Skip to content

Add WaveTank module + additional C binding interface improvements #2735

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 49 commits into
base: dev-cbind
Choose a base branch
from

Conversation

rafmudaf
Copy link
Collaborator

@rafmudaf rafmudaf commented Apr 7, 2025

Add WaveTank module and C binding interface utilities and improvements

This pull request primarily focuses on the development of a module for driving a wave tank experimental setup coupling AeroDyn, InflowWind, MoorDyn, and SeaState to model the loads due to waves and current on a MHK turbine floating structure. To that end, the primary addition is the WaveTank module in the glue-codes/labview directory. A SeaState C-bindings interface is extended (starting from #2720) to include the full initialization sequence and the time marching simulation driven by the experiment controller (LabVIEW). To support the C binding development, I've also extended the new NWTC_C_Binding module (see #2720) with utilities for working with C and Fortran strings plus error handling.

This pull request depends on #2719 and #2720. Note that this pull request is a Draft. I will continue to update the PR description as I make more changes. I'll remove this line and change the status to "Ready for Review" when it's at a stable point.

C Bindings

Dealing with strings through the C interfaces is nuances, so I've introduced some tooling and patterns to make this more clear and consistent.

For context, a C-style string is represented in Fortran as CHARACTER(KIND=C_CHAR) :: ErrMsg_c(IntfStrLen). This is a character array of kind C_CHAR from the ISO_C_BINDING intrinsic module with one dimension of length IntfStrLen. This representation is different from the Fortran string, CHARACTER(IntfStrLen) :: ErrMsg, which is a string of length IntfStrLen (not an array). Importantly, C strings in Fortran must be terminated with C_NULL_CHAR from ISO_C_BINDING before being used by a function or subroutine expecting C-style strings: ErrMsg = " "//C_NULL_CHAR.

Since the C binding interfaces operate on both Fortran and C style strings, I've introduced the _C and _F suffix to the error message buffer variables and most other strings crossing the interface for any subroutines that have C bindings. The variable mapping and function is as follows:

Old var New var Description
ErrStat2 ErrStat_F2 Subroutine-local error
ErrStat ErrStat_F Module-global error
ErrStat_C ErrStat_C Error to be passed to the calling code

ErrStat_F2 should hold errors from individual commands, and then it should be incorporated into the module-global error with CALL SetErrStat( ErrStat_F2, ErrMsg_F2, ErrStat_F, ErrMsg_F, RoutineName ). Prior to returning control to the calling code, the _F error variables should be transferred to the _C variables with CALL SetErrStat_F2C(ErrStat_F,ErrMsg_F,ErrStat_C,ErrMsg_C).

An additional error handing utility is added, SetErrStat_C2C, to support glue code modules written in Fortran and combining C binding interfaces such as the WaveTank module. This subroutine expects a C-style error message string for both the local and global error message.

@rafmudaf rafmudaf force-pushed the dev-cbind-wavetank branch from 62ac9d6 to a712957 Compare April 7, 2025 20:33
@andrew-platt andrew-platt self-assigned this Apr 7, 2025
@andrew-platt andrew-platt added this to the v4.1.0 milestone Apr 7, 2025
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be included?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, these files are what make the files within a directory importable by the Python interpreter

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this go in r-test?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep it's coming soon. Just a heads up that this is very much in a draft stage. I just wanted to be able to write notes as I make changes. I've made note of this in the PR description, and I'll update the status when it's mostly complete.

Copy link
Collaborator

@andrew-platt andrew-platt Apr 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll hold off on reviewing further until the construction dust settles a bit more :)

character(*), intent(in) :: txt
if (errStat /= 0) then
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrew-platt Is it correct that this is checking whether errStat is 0? Where it's called above (line 342), the command is setting the error to ErrStat2. Since ErrStat is initialized to 0, I think this function would only correctly error when NumTurbines is incorrect since that's the only place that Failed() is called.

If this is indeed incorrect, I'm happy to rework it, but I just wanted to double check that I'm not misreading it.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is correct for Failed0(). We use this on allocations of arrays where a non-zero error status returned indicates failure to allocate.
For the Failed() routine, we use SetErrStat.

rafmudaf added 3 commits April 7, 2025 17:38
This allows for doing the geometric offset for MHK turbines; otherwise, the IC are set in Init but the geometric offsets must happen in preinit
@rafmudaf rafmudaf force-pushed the dev-cbind-wavetank branch from efe3c4a to fbff4b2 Compare April 14, 2025 14:54
if (Failed()) return
endif

!-------------------------------------------------
! Call the main subroutine MD_Init
!-------------------------------------------------
CALL MD_Init(InitInp, u(1), p, x(STATE_CURR), xd(STATE_CURR), z(STATE_CURR), other(STATE_CURR), y, m, dT_Global, InitOutData, ErrStat2, ErrMsg2); if (Failed()) return
CALL MD_Init(InitInp, u(1), p, x(STATE_CURR), xd(STATE_CURR), z(STATE_CURR), other(STATE_CURR), y, m, dT_Global, InitOutData, ErrStat_F2, ErrMsg_F2); if (Failed()) return

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add error checks here that ensure MD is only being run w/ one coupled body, unless we change MD c-bind to be more flexible

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to check the following are true:

p%nCpldBodies(1) = 1
p%nCpldRods(1) = 0
p%nCpldPoints(1) = 0

# Conflicts:
#	reg_tests/r-test
@deslaughter
Copy link
Collaborator

@rafmudaf Could you update the documentation for running the regression tests that use the pyOpenFAST module? It took me a bit to figure out that GitHub actions does pip install glue-codes/python/. and then executePythonRegressionCase.py imports it. Perhaps a better alternative would be to have executePythonRegressionCase.py add glue-codes/python/. to sys.path so it's always using the version directly from the repo. Sorry if this is the wrong place for this feedback, I figured this PR was related to #2720.

rafmudaf and others added 12 commits April 21, 2025 23:36
# Conflicts:
#	modules/aerodyn/src/AeroDyn_Inflow_C_Binding.f90
These commands within the module subroutines cause the Modern Fortran VS Code extension to have a fit and sometimes corrupt the generated Fortran modules. Since IMPLICIT NONE is declared at the module-global level, these aren’t required in the subroutines.
* ADI_c: set `OutputAccel` flag for IfW with MHK

* ADI cbind: pass the OutputAccel flag through AeroDyn_Inflow.f90

* AD driver: set OutputAccel flag for IfW

* Remove hard coded OutputAccel flag in favor of input file

---------

Co-authored-by: Rafael M Mudafort <[email protected]>
@rafmudaf rafmudaf force-pushed the dev-cbind-wavetank branch from 2bb9471 to 68ebcc1 Compare April 23, 2025 22:03
@rafmudaf rafmudaf force-pushed the dev-cbind-wavetank branch from f1c3125 to cf50376 Compare April 24, 2025 13:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants