Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,12 @@ vs-build/
#Simulink cache files
varcache
*.slxc

# old repo for zmq pr
/RealTimeFAST
/cJSON

# simulation output files
*.out
*.outb
*.pkl.gz
19 changes: 19 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cff-version: 1.0.0
message: "If you use this software, please cite it as below."
authors:
- family-names: Schena
given-names: Lorenzo
- family-names: Branlard
given-names: Emmanuel
- family-names: Jonkman
given-names: Jason
- family-names: Platt
given-names: Andrew
- family-names: Slaughter
given-names: Derek
title: "Real time OpenFAST communication"
version: 1.0
identifiers:
- type: url
- url: "https://github.com/lorenzoschena/openfast/"
date-released: 2024-02-01
39 changes: 39 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,42 @@
OpenFAST ZMQ PR
========
OpenFAST with ZMQ for interfacing with other applications, developed at NREL during my research stay (2023-11 - 2024 - 01).


Requirements
----
```
cJSON
ZMQ
```

Main changes in this PR
----

- Added ZMQ connection capabilities to OpenFAST:
- PUB-SUB connection to receive solved variables from OpenFAST at runtime (all `y_FAST` is available)
- REQ-REP to interact with OpenFAST at runtime (eg. pitch control, wind speed, etc).
- Modified input files to include ZMQ parameters
- Added Python routines and tests to interface with OpenFAST (to be moved to `openfast-toolbox`?)

The folder `zmq_python_toolbox` contains the Python routines to interact with OpenFAST via ZMQ.

- `ex01` shows how to subscribe to a PUB-SUB socket from OpenFAST and how to receive the data.
- `ex02` shows how to interact with OpenFAST via REQ-REP sockets.
- `ex03` shows how to interact with OpenFAST using both sockets at the same time.


Updates
---------
- Added end of simulation message to ZMQ, so that receiver can know when the simulation is over and
detach from the ZMQ connection (close the socket). Currently, EOF signals are zeros, to keep float format. (`line 5649`)
- Added warning if user passes wind speed at runtime, as it will trigger Inflow Wind to use the steady model around the rotor disk (`line 3580`)
- Added variables `ZmqInDT` and `ZmqOutDT` to the input file, to set the time step for the ZMQ connection (`line 3586` - `line 3641`)
- Added variable check in input: if Zmq does not recognize one requested output, it will display it (not stopping the simulation) (`line 2500` - `line 2506`)
- Added units to the ZMQ output variables (`line 2517`)


========
OpenFAST
========

Expand Down
24 changes: 24 additions & 0 deletions modules/openfast-library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,35 @@ add_library(openfast_postlib STATIC
src/FAST_Solver.f90
src/FAST_SS_Subs.f90
src/FAST_SS_Solver.f90
src/zmq_client.c
)

target_link_libraries(openfast_postlib openfast_prelib extinflowlib scfastlib)
target_include_directories(openfast_postlib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
)

# Specify the include directories for ZeroMQ and cJSON
include_directories(
/opt/homebrew/Cellar/zeromq/4.3.5_1/include
/opt/homebrew/Cellar/cjson/1.7.18/include
${CMAKE_CURRENT_SOURCE_DIR}/src
)

# Specify the library directories for ZeroMQ and cJSON
link_directories(
/opt/homebrew/Cellar/zeromq/4.3.5_1/lib
/opt/homebrew/Cellar/cjson/1.7.18/lib
)

target_link_libraries(openfast_postlib
openfast_prelib
# foamfastlib
scfastlib
/opt/homebrew/Cellar/zeromq/4.3.5_1/lib/libzmq.dylib
/opt/homebrew/Cellar/cjson/1.7.18/lib/libcjson.dylib
)

set_target_properties(openfast_postlib PROPERTIES PUBLIC_HEADER src/FAST_Library.h)

# OpenFAST Library static (openfast, FAST.Farm, Simulink)
Expand Down
15 changes: 15 additions & 0 deletions modules/openfast-library/src/FAST_Registry.txt
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,21 @@ typedef ^ FAST_ParameterType ReKi WS_TSR {:} - - "List of WindSpeed or TSRs (dep
typedef ^ FAST_ParameterType ReKi Pitch {:} - - "List of pitch angles for aeromap generation" "(rad)"
typedef ^ FAST_ParameterType IntKi GearBox_index - - - "Index to gearbox rotation in state array (for steady-state calculations)" -

# ................................................... ZMQ PROTOCOL ...........................................................
typedef ^ FAST_ParameterType LOGICAL ZmqOn - .false. - "zmq activation flag" -
typedef ^ FAST_ParameterType CHARACTER(1024) ZmqInAddress - - - "address for ZMQ REQ-REP protocol" -
typedef ^ FAST_ParameterType IntKi ZmqInNbr - - - "number of ZMQ REQ-REP channels" -
typedef ^ FAST_ParameterType CHARACTER(ChanLen) ZmqInChannels {:} - - "address for ZMQ REQ-REP protocol" -
typedef ^ FAST_ParameterType ReKi ZmqInChannelsAry {:} - - "array to pass ZMQ PUB-SUB protocol" -
typedef ^ FAST_ParameterType ReKi ZmqInDT - - - "time step for in communication, FAST will keep it constant in between (sample & hold), default is same DT of simulation"
typedef ^ FAST_ParameterType CHARACTER(1024) ZmqOutAddress - - - "address for ZMQ PUB-SUB protocol" -
typedef ^ FAST_ParameterType IntKi ZmqOutNbr - - - "number of ZMQ PUB-SUB channels" -
typedef ^ FAST_ParameterType CHARACTER(ChanLen) ZmqOutChannels {:} - - "variables to pass ZMQ PUB-SUB protocol" -
typedef ^ FAST_ParameterType DbKi ZmqOutDT - - - "time step for out communication, FAST will keep it constant in between (sample & hold), default is same DT of simulation"
typedef ^ FAST_ParameterType IntKi ZmqOutChnlsIdx {:} - - "indexes of channels to be broadcasted" -
typedef ^ FAST_ParameterType CHARACTER(ChanLen) ZmqOutChannelsNames {:} - - "names for ZMQ PUB-SUB protocol" -
typedef ^ FAST_ParameterType ReKi ZmqOutChannelsAry {:} - - "array to pass ZMQ PUB-SUB protocol" -
# ............................................................................................................................

# SAVED OPERATING POINT DATA FOR VTKLIN (visualization of mode shapes from linearization analysis)
# ..... IceDyn OP data .......................................................................................................
Expand Down
11 changes: 7 additions & 4 deletions modules/openfast-library/src/FAST_SS_Subs.f90
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@ SUBROUTINE FAST_SteadyState_T( Turbine, ErrStat, ErrMsg )
CHARACTER(*), INTENT( OUT) :: ErrMsg !< Error message if ErrStat /= ErrID_None

CALL FAST_SteadyState( Turbine%p_FAST, Turbine%y_FAST, Turbine%m_FAST, &
Turbine%ED, Turbine%BD, Turbine%AD, Turbine%MeshMapData, ErrStat, ErrMsg )
Turbine%ED, Turbine%BD, Turbine%AD, Turbine%MeshMapData, Turbine%TurbID, ErrStat, ErrMsg )

END SUBROUTINE FAST_SteadyState_T
!----------------------------------------------------------------------------------------------------------------------------------
!> This routine takes data from n_t_global and gets values at n_t_global + 1
SUBROUTINE FAST_SteadyState(p_FAST, y_FAST, m_FAST, ED, BD, AD, MeshMapData, ErrStat, ErrMsg )
SUBROUTINE FAST_SteadyState(p_FAST, y_FAST, m_FAST, ED, BD, AD, MeshMapData, TurbID, ErrStat, ErrMsg )

TYPE(FAST_ParameterType), INTENT(IN ) :: p_FAST !< Parameters for the glue code
TYPE(FAST_OutputFileType),INTENT(INOUT) :: y_FAST !< Output variables for the glue code
Expand All @@ -172,9 +172,11 @@ SUBROUTINE FAST_SteadyState(p_FAST, y_FAST, m_FAST, ED, BD, AD, MeshMapData, Err
CHARACTER(ErrMsgLen) :: ErrMSg2
TYPE(IceD_OutputType), ALLOCATABLE :: y_IceD (:) !< IceDyn outputs (WriteOutput values are subset)
CHARACTER(MaxWrScrLen), PARAMETER :: BlankLine = " "
INTEGER(IntKi), INTENT(INOUT) :: TurbID

CHARACTER(*), PARAMETER :: RoutineName = 'FAST_SteadyState'

LOGICAL :: NeedSendZmq = .false. ! de activating it for now in ss subs

ErrStat = ErrID_None
ErrMsg = ""

Expand Down Expand Up @@ -244,7 +246,8 @@ SUBROUTINE FAST_SteadyState(p_FAST, y_FAST, m_FAST, ED, BD, AD, MeshMapData, Err

CALL WrOutputLine( n_global, p_FAST, y_FAST, UnusedAry, UnusedAry, ED%y%WriteOutput, &
AD%y, UnusedAry, UnusedAry, UnusedAry, UnusedAry, UnusedAry, UnusedAry, &
UnusedAry, UnusedAry, UnusedAry, UnusedAry, y_IceD, BD%y, ErrStat2, ErrMsg2 )
UnusedAry, UnusedAry, UnusedAry, UnusedAry, y_IceD, BD%y, &
p_FAST%ZmqOutChannelsAry, TurbID, NeedSendZmq, ErrStat2, ErrMsg2 )

call SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName)
if (ErrStat >= AbortErrLev) then
Expand Down
Loading