Skip to content

Commit 22848f9

Browse files
authored
Merge pull request #2720 from rafmudaf/dev-cbind
Adds first pass SeaState C Binding interface
2 parents e46b9ad + b6c808d commit 22848f9

File tree

18 files changed

+1262
-36
lines changed

18 files changed

+1262
-36
lines changed

glue-codes/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11

22
add_subdirectory(openfast)
3+
add_subdirectory(labview)
34

45
if(BUILD_OPENFAST_CPP_API)
56
add_subdirectory(openfast-cpp)

glue-codes/labview/CMakeLists.txt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#
2+
# Copyright 2025 National Renewable Energy Laboratory
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
#
16+
17+
add_library(wavetanktestinglib SHARED
18+
src/WaveTank.f90
19+
)
20+
target_link_libraries(wavetanktestinglib aerodyn_inflow_c_binding moordyn_c_binding seastate_c_binding nwtclibs versioninfolib)
21+
if(APPLE OR UNIX)
22+
target_compile_definitions(wavetanktestinglib PRIVATE IMPLICIT_DLLEXPORT)
23+
endif()
24+
25+
install(TARGETS wavetanktestinglib
26+
EXPORT "${CMAKE_PROJECT_NAME}Libraries"
27+
RUNTIME DESTINATION bin
28+
LIBRARY DESTINATION lib
29+
ARCHIVE DESTINATION lib)
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
2+
MODULE WaveTankTesting
3+
4+
USE ISO_C_BINDING
5+
USE NWTC_Library
6+
! USE Precision
7+
USE MoorDyn_C
8+
USE SeaState_C_Binding
9+
USE NWTC_C_Binding, ONLY: IntfStrLen, SetErr
10+
11+
IMPLICIT NONE
12+
SAVE
13+
14+
PUBLIC :: WaveTank_Init
15+
16+
REAL(C_DOUBLE) :: dt_c = 0.01_C_DOUBLE ! 100 hertz
17+
REAL(C_FLOAT) :: g_c = 9.8065_C_FLOAT
18+
REAL(C_FLOAT) :: rho_c = 1025.0_C_FLOAT
19+
REAL(C_FLOAT) :: depth_c = 200.0_C_FLOAT
20+
REAL(C_FLOAT), DIMENSION(6) :: ptfminit_c = 0.0_C_FLOAT
21+
INTEGER(C_INT) :: interporder_c = 2 ! 1: linear (uses two time steps) or 2: quadratic (uses three time steps)
22+
23+
INTEGER(C_INT) :: N_CAMERA_POINTS
24+
25+
INTEGER(C_INT) :: load_period = 20 ! seconds
26+
27+
CONTAINS
28+
29+
SUBROUTINE SetErrStat_C(ErrStatLocal, ErrMessLocal, ErrStatGlobal, ErrMessGlobal, RoutineName)
30+
31+
INTEGER(C_INT), INTENT(IN ) :: ErrStatLocal ! Error status of the operation
32+
CHARACTER(*, KIND=C_CHAR), INTENT(IN ) :: ErrMessLocal ! Error message if ErrStat /= ErrID_None
33+
INTEGER(C_INT), INTENT(INOUT) :: ErrStatGlobal ! Error status of the operation
34+
CHARACTER(KIND=C_CHAR), INTENT(INOUT) :: ErrMessGlobal ! Error message if ErrStat /= ErrID_None
35+
CHARACTER(*), INTENT(IN ) :: RoutineName ! Name of the routine error occurred in
36+
37+
IF ( ErrStatLocal == ErrID_None ) RETURN
38+
39+
IF (ErrStatGlobal /= ErrID_None) ErrMessGlobal = TRIM(ErrMessGlobal)//new_line('a')
40+
ErrMessGlobal = TRIM(ErrMessGlobal)//TRIM(RoutineName)//':'//TRIM(ErrMessLocal)
41+
ErrStatGlobal = MAX(ErrStatGlobal,ErrStatLocal)
42+
43+
END SUBROUTINE
44+
45+
SUBROUTINE WaveTank_Init( &
46+
MD_InputFile_c, &
47+
SS_InputFile_c, &
48+
AD_InputFile_c, &
49+
IfW_InputFile_c, &
50+
n_camera_points_c, &
51+
ErrStat_c, &
52+
ErrMsg_c &
53+
) BIND (C, NAME='WaveTank_Init')
54+
#ifndef IMPLICIT_DLLEXPORT
55+
!DEC$ ATTRIBUTES DLLEXPORT :: WaveTank_Init
56+
!GCC$ ATTRIBUTES DLLEXPORT :: WaveTank_Init
57+
#endif
58+
59+
IMPLICIT NONE
60+
61+
CHARACTER(KIND=C_CHAR), INTENT(IN ), TARGET :: MD_InputFile_c(IntfStrLen)
62+
CHARACTER(KIND=C_CHAR), INTENT(IN ), TARGET :: SS_InputFile_c(IntfStrLen)
63+
CHARACTER(KIND=C_CHAR), INTENT(IN ), TARGET :: AD_InputFile_c(IntfStrLen)
64+
CHARACTER(KIND=C_CHAR), INTENT(IN ), TARGET :: IfW_InputFile_c(IntfStrLen)
65+
INTEGER(C_INT), INTENT(IN ) :: n_camera_points_c
66+
INTEGER(C_INT), INTENT( OUT) :: ErrStat_C
67+
CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_C(ErrMsgLen_C)
68+
69+
! Local variables
70+
integer(c_int) :: numchannels_c
71+
character(kind=c_char) :: outputchannelnames_c(100000)
72+
character(kind=c_char) :: outputchannelunits_c(100000)
73+
integer(c_int) :: input_file_passed = 0 ! We're passing paths to input files rather than input strings for all modules
74+
! character(kind=c_char), pointer :: filestring_c(IntfStrLen) ! Point to input file path input argument
75+
76+
print *, MD_InputFile_c
77+
print *, SS_InputFile_c
78+
print *, AD_InputFile_c
79+
print *, IfW_InputFile_c
80+
81+
N_CAMERA_POINTS = n_camera_points_c
82+
83+
! filestring_c => MD_InputFile_c
84+
! call MD_C_Init( &
85+
! input_file_passed, &
86+
! filestring_c, &
87+
! IntfStrLen, &
88+
! dt_c, &
89+
! g_c, &
90+
! rho_c, &
91+
! depth_c, &
92+
! ptfminit_c, &
93+
! interporder_c, &
94+
! numchannels_c, &
95+
! outputchannelnames_c, &
96+
! outputchannelunits_c, &
97+
! ErrStat_C, ErrMsg_C &
98+
! )
99+
100+
! call ADI_C_Init( &
101+
! ADinputFilePassed, & ! integer(c_int), intent(in ) :: ADinputFilePassed !< Write VTK outputs [0: none, 1: init only, 2: animation]
102+
! ADinputFileString_C, & ! type(c_ptr), intent(in ) :: ADinputFileString_C !< Input file as a single string with lines deliniated by C_NULL_CHAR
103+
! ADinputFileStringLength_C, & ! integer(c_int), intent(in ) :: ADinputFileStringLength_C !< lenght of the input file string
104+
! IfWinputFilePassed, & ! integer(c_int), intent(in ) :: IfWinputFilePassed !< Write VTK outputs [0: none, 1: init only, 2: animation]
105+
! IfWinputFileString_C, & ! type(c_ptr), intent(in ) :: IfWinputFileString_C !< Input file as a single string with lines deliniated by C_NULL_CHAR
106+
! IfWinputFileStringLength_C, & ! integer(c_int), intent(in ) :: IfWinputFileStringLength_C !< lenght of the input file string
107+
! OutRootName_C, & ! character(kind=c_char), intent(in ) :: OutRootName_C(IntfStrLen) !< Root name to use for echo files and other
108+
! OutVTKDir_C, & ! character(kind=c_char), intent(in ) :: OutVTKDir_C(IntfStrLen) !< Directory to put all vtk output
109+
! gravity_C, & ! real(c_float), intent(in ) :: gravity_C !< Gravitational acceleration (m/s^2)
110+
! defFldDens_C, & ! real(c_float), intent(in ) :: defFldDens_C !< Air density (kg/m^3)
111+
! defKinVisc_C, & ! real(c_float), intent(in ) :: defKinVisc_C !< Kinematic viscosity of working fluid (m^2/s)
112+
! defSpdSound_C, & ! real(c_float), intent(in ) :: defSpdSound_C !< Speed of sound in working fluid (m/s)
113+
! defPatm_C, & ! real(c_float), intent(in ) :: defPatm_C !< Atmospheric pressure (Pa) [used only for an MHK turbine cavitation check]
114+
! defPvap_C, & ! real(c_float), intent(in ) :: defPvap_C !< Vapour pressure of working fluid (Pa) [used only for an MHK turbine cavitation check]
115+
! WtrDpth_C, & ! real(c_float), intent(in ) :: WtrDpth_C !< Water depth (m)
116+
! MSL2SWL_C, & ! real(c_float), intent(in ) :: MSL2SWL_C !< Offset between still-water level and mean sea level (m) [positive upward]
117+
! InterpOrder_C, & ! integer(c_int), intent(in ) :: InterpOrder_C !< Interpolation order to use (must be 1 or 2)
118+
! DT_C, & ! real(c_double), intent(in ) :: DT_C !< Timestep used with AD for stepping forward from t to t+dt. Must be constant.
119+
! TMax_C, & ! real(c_double), intent(in ) :: TMax_C !< Maximum time for simulation
120+
! storeHHVel, & ! integer(c_int), intent(in ) :: storeHHVel !< Store hub height time series from IfW
121+
! WrVTK_in, & ! integer(c_int), intent(in ) :: WrVTK_in !< Write VTK outputs [0: none, 1: init only, 2: animation]
122+
! WrVTK_inType, & ! integer(c_int), intent(in ) :: WrVTK_inType !< Write VTK outputs as [1: surface, 2: lines, 3: both]
123+
! WrVTK_inDT, & ! real(c_double), intent(in ) :: WrVTK_inDT !< Timestep between VTK writes
124+
! VTKNacDim_in, & ! real(c_float), intent(in ) :: VTKNacDim_in(6) !< Nacelle dimension passed in for VTK surface rendering [0,y0,z0,Lx,Ly,Lz] (m)
125+
! VTKHubRad_in, & ! real(c_float), intent(in ) :: VTKHubrad_in !< Hub radius for VTK surface rendering
126+
! wrOuts_C, &
127+
! DT_Outs_C, &
128+
! NumChannels_C, &
129+
! OutputChannelNames_C, &
130+
! OutputChannelUnits_C, &
131+
! ErrStat_C, ErrMsg_C &
132+
! )
133+
134+
135+
! ! Input file info
136+
! integer(c_int), intent(in ) :: ADinputFilePassed !< Write VTK outputs [0: none, 1: init only, 2: animation]
137+
! type(c_ptr), intent(in ) :: ADinputFileString_C !< Input file as a single string with lines deliniated by C_NULL_CHAR
138+
! integer(c_int), intent(in ) :: ADinputFileStringLength_C !< lenght of the input file string
139+
! integer(c_int), intent(in ) :: IfWinputFilePassed !< Write VTK outputs [0: none, 1: init only, 2: animation]
140+
! type(c_ptr), intent(in ) :: IfWinputFileString_C !< Input file as a single string with lines deliniated by C_NULL_CHAR
141+
! integer(c_int), intent(in ) :: IfWinputFileStringLength_C !< lenght of the input file string
142+
! character(kind=c_char), intent(in ) :: OutRootName_C(IntfStrLen) !< Root name to use for echo files and other
143+
! character(kind=c_char), intent(in ) :: OutVTKDir_C(IntfStrLen) !< Directory to put all vtk output
144+
! ! Environmental
145+
! real(c_float), intent(in ) :: gravity_C !< Gravitational acceleration (m/s^2)
146+
! real(c_float), intent(in ) :: defFldDens_C !< Air density (kg/m^3)
147+
! real(c_float), intent(in ) :: defKinVisc_C !< Kinematic viscosity of working fluid (m^2/s)
148+
! real(c_float), intent(in ) :: defSpdSound_C !< Speed of sound in working fluid (m/s)
149+
! real(c_float), intent(in ) :: defPatm_C !< Atmospheric pressure (Pa) [used only for an MHK turbine cavitation check]
150+
! real(c_float), intent(in ) :: defPvap_C !< Vapour pressure of working fluid (Pa) [used only for an MHK turbine cavitation check]
151+
! real(c_float), intent(in ) :: WtrDpth_C !< Water depth (m)
152+
! real(c_float), intent(in ) :: MSL2SWL_C !< Offset between still-water level and mean sea level (m) [positive upward]
153+
! ! Interpolation
154+
! integer(c_int), intent(in ) :: InterpOrder_C !< Interpolation order to use (must be 1 or 2)
155+
! ! Time
156+
! real(c_double), intent(in ) :: DT_C !< Timestep used with AD for stepping forward from t to t+dt. Must be constant.
157+
! real(c_double), intent(in ) :: TMax_C !< Maximum time for simulation
158+
! ! Flags
159+
! integer(c_int), intent(in ) :: storeHHVel !< Store hub height time series from IfW
160+
! ! VTK
161+
! integer(c_int), intent(in ) :: WrVTK_in !< Write VTK outputs [0: none, 1: init only, 2: animation]
162+
! integer(c_int), intent(in ) :: WrVTK_inType !< Write VTK outputs as [1: surface, 2: lines, 3: both]
163+
! real(c_double), intent(in ) :: WrVTK_inDT !< Timestep between VTK writes
164+
! real(c_float), intent(in ) :: VTKNacDim_in(6) !< Nacelle dimension passed in for VTK surface rendering [0,y0,z0,Lx,Ly,Lz] (m)
165+
! real(c_float), intent(in ) :: VTKHubrad_in !< Hub radius for VTK surface rendering
166+
! integer(c_int), intent(in ) :: wrOuts_C !< Write ADI output file
167+
! real(c_double), intent(in ) :: DT_Outs_C !< Timestep to write output file from ADI
168+
! ! Output
169+
! integer(c_int), intent( out) :: NumChannels_C !< Number of output channels requested from the input file
170+
! character(kind=c_char), intent( out) :: OutputChannelNames_C(ChanLen*MaxADIOutputs+1) !< NOTE: if MaxADIOutputs is sufficiently large, we may overrun the buffer on the Python side.
171+
! character(kind=c_char), intent( out) :: OutputChannelUnits_C(ChanLen*MaxADIOutputs+1)
172+
! integer(c_int), intent( out) :: ErrStat_C !< Error status
173+
! character(kind=c_char), intent( out) :: ErrMsg_C(ErrMsgLen_C) !< Error message (C_NULL_CHAR terminated)
174+
175+
! Set compiler flag for Labview
176+
! Cmpl4LV = .TRUE.
177+
178+
END SUBROUTINE WaveTank_Init
179+
180+
! delta_time, &
181+
SUBROUTINE WaveTank_CalcOutput( &
182+
frame_number, &
183+
positions_x, &
184+
positions_y, &
185+
positions_z, &
186+
rotation_matrix, &
187+
loads, &
188+
ErrStat_c, &
189+
ErrMsg_c &
190+
) BIND (C, NAME='WaveTank_CalcOutput')
191+
#ifndef IMPLICIT_DLLEXPORT
192+
!DEC$ ATTRIBUTES DLLEXPORT :: WaveTank_CalcOutput
193+
!GCC$ ATTRIBUTES DLLEXPORT :: WaveTank_CalcOutput
194+
#endif
195+
196+
IMPLICIT NONE
197+
198+
! INTEGER(C_INT) :: delta_time
199+
INTEGER(C_INT) :: frame_number
200+
REAL(C_FLOAT), INTENT(IN ) :: positions_x(N_CAMERA_POINTS)
201+
REAL(C_FLOAT), INTENT(IN ) :: positions_y(N_CAMERA_POINTS)
202+
REAL(C_FLOAT), INTENT(IN ) :: positions_z(N_CAMERA_POINTS)
203+
REAL(C_FLOAT), INTENT(IN ) :: rotation_matrix(9)
204+
REAL(C_FLOAT), INTENT( OUT) :: loads(N_CAMERA_POINTS)
205+
INTEGER(C_INT), INTENT( OUT) :: ErrStat_C
206+
CHARACTER(KIND=C_CHAR), INTENT( OUT) :: ErrMsg_C(ErrMsgLen_C)
207+
208+
INTEGER :: i
209+
210+
IF ( MOD(frame_number / load_period, 2) == 0 ) THEN
211+
loads = -1.0
212+
ELSE
213+
loads = 1.0
214+
ENDIF
215+
216+
END SUBROUTINE
217+
218+
SUBROUTINE WaveTank_End() bind (C, NAME="WaveTank_End")
219+
220+
221+
IMPLICIT NONE
222+
223+
224+
225+
226+
END SUBROUTINE
227+
228+
end module WaveTankTesting

0 commit comments

Comments
 (0)