Skip to content
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

Add a Python glue-code interface #962

Merged
merged 43 commits into from
May 6, 2022

Conversation

rafmudaf
Copy link
Collaborator

@rafmudaf rafmudaf commented Jan 7, 2022

Feature or improvement description
This pull request adds a Python interface to the OpenFAST glue code. It also includes a Python driver to test the interface. There are also changes to the FAST Library interface in FAST_Update and FAST_Sizes.

The change in FAST_Update is to support ending the simulation early similar to #930. However, the Python interface raises an error based on the error level from OpenFAST and ending early is not an error. To be more explicit with this feature, I added a variable EndSimulationEarly that the calling code can check and do what it needs to do while also handling errors.

The change to FAST_Sizes removes the requirement to use the ExternInitData structure and allows for retrieving the system-level TMax. Currently, the value of TMax given in FAST_Sizes overwrites the value provided in the input file. Here's a trace of the function calls from FAST_Sizes until FAST_init:

This pull request makes both TMax and ExternInitData optional in order to preserve that functionality while also allows a calling code to directly use the input file.

I've also added a new driver code written in C++ that replaces the older driver code written in C (FAST_Prog.c). In reality, all C-based driver codes are currently only used for testing. The functionality in the older C driver is already tested more extensively through the C++ API. The FAST_Library routines not dealing with the C++ API were not previously tested in the automated suite, so the new C++ driver tests those. Additionally, it adds test coverage for FAST_Library.h.

Impacted areas of the software
FAST_Library.f90
FAST_Library.h
FAST_SFunc.c
The rest are new files

Additional supporting information
Here are the API changes

FAST_Sizes

subroutine FAST_Sizes(iTurb, TMax, InitInpAry, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c,
    ErrStat_c, ErrMsg_c, ChannelNames_c) BIND (C, NAME='FAST_Sizes')

Changes:

  • Add tmax_c output argument
  • Remove TMax and InitInpAry required arguments and add same optional arguments
subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, tmax_c,
    ErrStat_c, ErrMsg_c, ChannelNames_c) BIND (C, NAME='FAST_Sizes')
subroutine FAST_Sizes(iTurb, InputFileName_c, AbortErrLev_c, NumOuts_c, dt_c, tmax_c,
    ErrStat_c, ErrMsg_c, ChannelNames_c, TMax, InitInpAry) BIND (C, NAME='FAST_Sizes')

FAST_Update

subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry,
    ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Update')

Add EndSimulationEarly output to become become

subroutine FAST_Update(iTurb, NumInputs_c, NumOutputs_c, InputAry, OutputAry, EndSimulationEarly,
    ErrStat_c, ErrMsg_c) BIND (C, NAME='FAST_Update')

Test results, if applicable
See the new actions "Interface Tests"

TODO

A couple of points that might be required to address are

  • What happens in TMax is provided but InitInpAry is not?
  • C header files do not support optional arguments as far as I know - UPDATE: NULL values are supported

Include a more explicit C string length variable
abort_error_level should be greater than 0 so that error_status of 0 doesn’t cause a false error
Rather than aborting the process completely
This is not a Python problem, but its a human eyes problem.
First call FAST_End to deallocate internal arrays and then call FAST_DeallocateTurbines to free up the Turbine array
Removes the requirement to pass TMax and InitInpAry since passing TMax overrides the input file value. This commit preserves this functionality, but makes it optional. The system TMax is also now returned so that calling-codes can determine how many time steps to loop over.
NOTE: this may break any codes using FAST_Library.h as that header does not support the optional arguments to FAST_Sizes
This is currently used during the linearization simulations with CalcSteady enabled. After do NLinTimes steps, the simluation should simply end.
This is currently already handled in FAST_Prog, and this commits adds the same behavior in FAST_Library
# Conflicts:
#	glue-codes/python/OpenFAST.py
Storing the error status on the class was causing it to be overwritting when doing the deinitialization routines. The error would be caught, but it would then report back Error 0: <empty string>.
This was checking for an error in the openfastlib but `fatal_error` is a function not an attribute so the if-statement was evaluating to True. In any case, the errors should be handled in the library.
Adds more of the exising OpenFAST regression tests. Only the tests that have dt and dt_out matching are compatible. The FAST_Library outputs values at each call to FAST_Update, but the output files from FAST_Prog are written at dt_out intervals. The Python interface would have to parse dt_out and export files similarly to match the existing regression test baselines.
@rafmudaf
Copy link
Collaborator Author

@bjonkman I've tried to fully describe the changes to FAST Library in the initial post, and I'm curious if you have any feedback here. I also made the corresponding changes to the Simulink interface, but I did not test those changes.

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented May 5, 2022

@gbarter This is finally tested and I think ready to go. Do you, @dzalkind, or @ptrbortolotti have any other suggestions on the Python interface?

@gbarter
Copy link
Contributor

gbarter commented May 6, 2022

Thanks, @rafmudaf ! The only thing I can think of is if we made local changes to the python interface in the WEIS-OpenFast here. At a first glance, it doesn't seem like it, but I'm not git-savvy enough to know how to do that diff across the forks and feature branches quickly.

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented May 6, 2022

I compared the python interface from the commit you linked and my latest. It looks like the only differences are my changes. @dzalkind would it help for us to look at the differences together?

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented May 6, 2022

Regarding the question in the initial post TMax, the functionality here is sufficient. TMax is specific in the input file and is read into FAST_ParameterType in FAST_Subs.FAST_Init.FAST_ReadPrimaryFile. After that, FAST_Init checks for whether the TMax optional argument was given, and if so p%TMax is overwritten.

In the pull request, the InitInpAry input argument can be used while TMax is gotten from the input file. TMax can also be provided via InitInpAry and this preserves the functionality prior to this pull request.

@rafmudaf
Copy link
Collaborator Author

rafmudaf commented May 6, 2022

I've added an error in the case where TMax is given to FAST_Sizes without InitInpAry. This adds clarity to the usage of FAST_Sizes. In order to support using TMax without InitInpAry, we would need to pass TMax to FAST_Subs outside of the ExternInitData structure. Since this is currently only used in the Simulink interface and in there both variables are given, there is no need to support this at the moment.

@rafmudaf rafmudaf merged commit 7c6d0aa into OpenFAST:dev May 6, 2022
@rafmudaf rafmudaf deleted the feature/python_driver branch May 6, 2022 20:09
@rafmudaf rafmudaf mentioned this pull request Jul 8, 2022
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants