@@ -32,26 +32,39 @@ MODULE InflowWind_C_BINDING
3232 PUBLIC :: IfW_C_CalcOutput
3333 PUBLIC :: IfW_C_End
3434
35+ !- -----------------------------------------------------------------------------------
3536 ! Version info for display
3637 type (ProgDesc), parameter :: version = ProgDesc( ' InflowWind library' , ' ' , ' ' )
3738
38- ! Accessible to all routines inside module
39- TYPE (InflowWind_InputType) , SAVE :: InputData ! < Inputs to InflowWind
40- TYPE (InflowWind_InitInputType) , SAVE :: InitInp
41- TYPE (InflowWind_InitOutputType) , SAVE :: InitOutData ! < Initial output data -- Names, units, and version info.
42- TYPE (InflowWind_ParameterType) , SAVE :: p ! < Parameters
43- TYPE (InflowWind_ContinuousStateType) , SAVE :: ContStates ! < Initial continuous states
44- TYPE (InflowWind_DiscreteStateType) , SAVE :: DiscStates ! < Initial discrete states
45- TYPE (InflowWind_ConstraintStateType) , SAVE :: ConstrStates ! < Constraint states at Time
46- TYPE (InflowWind_OtherStateType) , SAVE :: OtherStates ! < Initial other/optimization states
47- TYPE (InflowWind_OutputType) , SAVE :: y ! < Initial output (outputs are not calculated; only the output mesh is initialized)
48- TYPE (InflowWind_MiscVarType) , SAVE :: m ! < Misc variables for optimization (not copied in glue code)
49-
50- ! This must exactly match the value in the Python interface. We are not using the variable 'ErrMsgLen'
51- ! so that we avoid issues if ErrMsgLen changes in the NWTC Library. If the value of ErrMsgLen does change
52- ! in the NWTC Library, ErrMsgLen_C (and the equivalent value in the Python interface) can be updated
53- ! to be equivalent to ErrMsgLen + 1, but the logic exists to correctly handle different lengths of the strings
54- integer (IntKi), parameter :: ErrMsgLen_C= 1025 ! Numerical equivalent of ErrMsgLen + 1
39+ !- -----------------------------------------------------------------------------------
40+ ! Debugging: DebugLevel -- passed at PreInit
41+ ! 0 - none
42+ ! 1 - some summary info
43+ ! 2 - above + all position/orientation info
44+ ! 3 - above + input files (if direct passed)
45+ ! 4 - above + meshes
46+ integer (IntKi) :: DebugLevel = 0
47+
48+ !- -----------------------------------------------------------------------------------
49+ ! Primary IfW data derived types
50+ type (InflowWind_InputType) :: InputData ! < Inputs to InflowWind
51+ type (InflowWind_InitInputType) :: InitInp
52+ type (InflowWind_InitOutputType) :: InitOutData ! < Initial output data -- Names, units, and version info.
53+ type (InflowWind_ParameterType) :: p ! < Parameters
54+ type (InflowWind_ContinuousStateType) :: ContStates ! < Initial continuous states
55+ type (InflowWind_DiscreteStateType) :: DiscStates ! < Initial discrete states
56+ type (InflowWind_ConstraintStateType) :: ConstrStates ! < Constraint states at Time
57+ type (InflowWind_OtherStateType) :: OtherStates ! < Initial other/optimization states
58+ type (InflowWind_OutputType) :: y ! < Initial output (outputs are not calculated; only the output mesh is initialized)
59+ type (InflowWind_MiscVarType) :: m ! < Misc variables for optimization (not copied in glue code)
60+
61+ !- -----------------------------------------------------------------------------------
62+ ! Error handling
63+ ! This must exactly match the value in the python-lib. If ErrMsgLen changes at
64+ ! some point in the nwtc-library, this should be updated, but the logic exists
65+ ! to correctly handle different lengths of the strings
66+ integer (IntKi), parameter :: ErrMsgLen_C = 1025
67+ integer (IntKi), parameter :: IntfStrLen = 1025 ! length of other strings through the C interface
5568
5669
5770
@@ -78,35 +91,39 @@ end subroutine SetErr
7891! ===============================================================================================================
7992!- -------------------------------------------- IFW INIT --------------------------------------------------------
8093! ===============================================================================================================
81- SUBROUTINE IfW_C_Init (InputFileString_C , InputFileStringLength_C , InputUniformString_C , InputUniformStringLength_C , NumWindPts_C , DT_C , NumChannels_C , OutputChannelNames_C , OutputChannelUnits_C , ErrStat_C , ErrMsg_C ) BIND (C, NAME= ' IfW_C_Init' )
94+ SUBROUTINE IfW_C_Init (IfWinputFilePassed , IfWinputFileString_C , IfWinputFileStringLength_C , OutRootName_C , &
95+ NumWindPts_C , DT_C , DebugLevel_in , NumChannels_C , OutputChannelNames_C , OutputChannelUnits_C , &
96+ ErrStat_C , ErrMsg_C ) BIND (C, NAME= ' IfW_C_Init' )
8297 IMPLICIT NONE
8398#ifndef IMPLICIT_DLLEXPORT
8499! DEC$ ATTRIBUTES DLLEXPORT :: IfW_C_Init
85100! GCC$ ATTRIBUTES DLLEXPORT :: IfW_C_Init
86101#endif
87- TYPE (C_PTR) , INTENT (IN ) :: InputFileString_C
88- INTEGER (C_INT) , INTENT (IN ) :: InputFileStringLength_C
89- TYPE (C_PTR) , INTENT (IN ) :: InputUniformString_C
90- INTEGER (C_INT) , INTENT (IN ) :: InputUniformStringLength_C
91- INTEGER (C_INT) , INTENT (IN ) :: NumWindPts_C
92- REAL (C_DOUBLE) , INTENT (IN ) :: DT_C
93- INTEGER (C_INT) , INTENT ( OUT ) :: NumChannels_C
94- CHARACTER (KIND= C_CHAR) , INTENT ( OUT ) :: OutputChannelNames_C(ChanLen* MaxOutPts+1 )
95- CHARACTER (KIND= C_CHAR) , INTENT ( OUT ) :: OutputChannelUnits_C(ChanLen* MaxOutPts+1 )
96- INTEGER (C_INT) , INTENT ( OUT ) :: ErrStat_C
97- CHARACTER (KIND= C_CHAR) , INTENT ( OUT ) :: ErrMsg_C(ErrMsgLen_C)
98-
99- ! Local Variables
100- CHARACTER (kind= C_char, len= InputFileStringLength_C), POINTER :: InputFileString ! < Input file as a single string with NULL chracter separating lines
101- CHARACTER (kind= C_char, len= InputUniformStringLength_C), POINTER :: UniformFileString ! < Input file as a single string with NULL chracter separating lines -- Uniform wind file
102-
103- REAL (DbKi) :: TimeInterval
104- INTEGER :: ErrStat ! < aggregated error message
105- CHARACTER (ErrMsgLen) :: ErrMsg ! < aggregated error message
106- INTEGER :: ErrStat2 ! < temporary error status from a call
107- CHARACTER (ErrMsgLen) :: ErrMsg2 ! < temporary error message from a call
108- INTEGER :: i,j,k
109- character (* ), parameter :: RoutineName = ' IfW_C_Init' ! < for error handling
102+ integer (c_int), intent (in ) :: IfWinputFilePassed ! < Write VTK outputs [0: none, 1: init only, 2: animation]
103+ type (c_ptr), intent (in ) :: IfWinputFileString_C ! < Input file as a single string with lines deliniated by C_NULL_CHAR
104+ integer (c_int), intent (in ) :: IfWinputFileStringLength_C ! < lenght of the input file string
105+ character (kind= c_char), intent (in ) :: OutRootName_C(IntfStrLen) ! < Root name to use for echo files and other
106+ integer (c_int), intent (in ) :: NumWindPts_C
107+ real (c_double), intent (in ) :: DT_C
108+ integer (c_int), intent (in ) :: DebugLevel_in
109+ integer (c_int), intent ( out ) :: NumChannels_C
110+ character (kind= c_char), intent ( out ) :: OutputChannelNames_C(ChanLen* MaxOutPts+1 )
111+ character (kind= c_char), intent ( out ) :: OutputChannelUnits_C(ChanLen* MaxOutPts+1 )
112+ integer (c_int), intent ( out ) :: ErrStat_C
113+ character (kind= c_char), intent ( out ) :: ErrMsg_C(ErrMsgLen_C)
114+
115+ ! local variables
116+ character (IntfStrLen) :: OutRootName ! < Root name to use for echo files and other
117+ character (IntfStrLen) :: TmpFileName ! < Temporary file name if not passing AD or IfW input file contents directly
118+ character (kind= c_char, len= IfWinputFileStringLength_C), pointer :: IfWinputFileString ! < Input file as a single string with NULL chracter separating lines
119+
120+ real (DbKi) :: TimeInterval
121+ integer :: ErrStat ! < aggregated error message
122+ character (ErrMsgLen) :: ErrMsg ! < aggregated error message
123+ integer :: ErrStat2 ! < temporary error status from a call
124+ character (ErrMsgLen) :: ErrMsg2 ! < temporary error message from a call
125+ integer :: i,j,k
126+ character (* ), parameter :: RoutineName = ' IfW_C_Init' ! < for error handling
110127
111128 ! Initialize error handling
112129 ErrStat = ErrID_None
@@ -116,26 +133,65 @@ SUBROUTINE IfW_C_Init(InputFileString_C, InputFileStringLength_C, InputUniformSt
116133 CALL DispCopyrightLicense( version% Name )
117134 CALL DispCompileRuntimeInfo( version% Name )
118135
136+
137+ ! interface debugging
138+ DebugLevel = int (DebugLevel_in,IntKi)
139+
140+ ! Input files
141+ OutRootName = TRANSFER ( OutRootName_C, OutRootName )
142+ i = INDEX (OutRootName,C_NULL_CHAR) - 1 ! if this has a c null character at the end...
143+ if ( i > 0 ) OutRootName = OutRootName(1 :I) ! remove it
144+
145+ ! if non-zero, show all passed data here. Then check valid values
146+ if (DebugLevel /= 0_IntKi ) then
147+ call WrScr(" Interface debugging level " // trim (Num2Lstr(DebugLevel))// " requested." )
148+ call ShowPassedData()
149+ endif
150+ ! check valid debug level
151+ if (DebugLevel < 0_IntKi ) then
152+ ErrStat2 = ErrID_Fatal
153+ ErrMsg2 = " Interface debug level must be 0 or greater" // NewLine// &
154+ " 0 - none" // NewLine// &
155+ " 1 - some summary info and variables passed through interface" // NewLine// &
156+ " 2 - above + all position/orientation info" // NewLine// &
157+ " 3 - above + input files (if direct passed)" // NewLine// &
158+ " 4 - above + meshes"
159+ if (Failed()) return ;
160+ endif
161+
162+ ! For debugging the interface:
163+ if (DebugLevel > 0 ) then
164+ call ShowPassedData()
165+ endif
166+
119167 ! Get fortran pointer to C_NULL_CHAR deliniated input file as a string
120- CALL C_F_pointer(InputFileString_C, InputFileString)
121- CALL C_F_pointer(InputUniformString_C, UniformFileString)
122-
123- ! Store string-inputs as type FileInfoType within InflowWind_InitInputType
124- CALL InitFileInfo(InputFileString, InitInp% PassedFileInfo, ErrStat2, ErrMsg2); if (Failed()) return
125- InitInp% FilePassingMethod = 1_IntKi ! read file and pass as FileInfoType structure
126-
127- ! store Uniform File strings if they are non-zero sized
128- if (len (UniformFileString) > 1 ) then
129- CALL InitFileInfo(UniformFileString, InitInp% WindType2Info, ErrStat2, ErrMsg2); if (Failed()) return
130- InitInp% WindType2UseInputFile = .FALSE.
131- else ! Default to reading from disk
132- InitInp% WindType2UseInputFile = .TRUE.
168+ CALL C_F_pointer(IfWinputFileString_C, IfWinputFileString)
169+
170+ ! Format IfW input file contents
171+ if (IfWinputFilePassed== 1_c_int ) then
172+ InitInp% FilePassingMethod = 1_IntKi ! Don't try to read an input -- use passed data instead (blades and AF tables not passed) using FileInfoType
173+ InitInp% InputFileName = " passed_ifw_file" ! not actually used
174+ call InitFileInfo(IfWinputFileString, InitInp% PassedFileInfo, ErrStat2, ErrMsg2); if (Failed()) return
175+ else
176+ InitInp% FilePassingMethod = 0_IntKi ! Read input info from a primary input file
177+ i = min (IntfStrLen,IfWinputFileStringLength_C)
178+ TmpFileName = ' '
179+ TmpFileName(1 :i) = IfWinputFileString(1 :i)
180+ i = INDEX (TmpFileName,C_NULL_CHAR) - 1 ! if this has a c null character at the end...
181+ if ( i > 0 ) TmpFileName = TmpFileName(1 :I) ! remove it
182+ InitInp% InputFileName = TmpFileName
183+ endif
184+
185+ ! For diagnostic purposes, the following can be used to display the contents
186+ ! of the InFileInfo data structure.
187+ ! CU is the screen -- system dependent.
188+ if (DebugLevel >= 3 ) then
189+ if (IfWinputFilePassed== 1_c_int ) call Print_FileInfo_Struct( CU, InitInp% PassedFileInfo )
133190 endif
134191
135192 ! Set other inputs for calling InflowWind_Init
136- InitInp% NumWindPoints = NumWindPts_C
137- InitInp% InputFileName = " passed_ifw_file" ! dummy
138- InitInp% RootName = " ifwRoot" ! used for making echo files
193+ InitInp% NumWindPoints = int (NumWindPts_C, IntKi)
194+ InitInp% RootName = OutRootName ! used for making echo files
139195 TimeInterval = REAL (DT_C, DbKi)
140196
141197 ! Call the main subroutine InflowWind_Init - only need InitInp and TimeInterval as inputs, the rest are set by InflowWind_Init
@@ -174,6 +230,30 @@ logical function Failed()
174230 end function Failed
175231 subroutine Cleanup () ! NOTE: we are ignoring any error reporting from here
176232 end subroutine Cleanup
233+
234+ ! > This subroutine prints out all the variables that are passed in. Use this only
235+ ! ! for debugging the interface on the Fortran side.
236+ subroutine ShowPassedData ()
237+ character (1 ) :: TmpFlag
238+ integer :: i,j
239+ call WrSCr(" " )
240+ call WrScr(" -----------------------------------------------------------" )
241+ call WrScr(" Interface debugging: Variables passed in through interface" )
242+ call WrScr(" ADI_C_Init" )
243+ call WrScr(" --------------------------------------------------------" )
244+ call WrScr(" FileInfo" )
245+ TmpFlag= " F" ; if (IfWinputFilePassed== 1_c_int ) TmpFlag= " T"
246+ call WrScr(" IfWinputFilePassed_C " // TmpFlag )
247+ call WrScr(" IfWinputFileString_C (ptr addr)" // trim (Num2LStr(LOC(IfWinputFileString_C))) )
248+ call WrScr(" IfWinputFileStringLength_C " // trim (Num2LStr( IfWinputFileStringLength_C )) )
249+ call WrScr(" OutRootName " // trim (OutRootName) )
250+ call WrScr(" Input variables" )
251+ call WrScr(" NumWindPts_C " // trim (Num2LStr( NumWindPts_C)) )
252+ call WrScr(" Time variables" )
253+ call WrScr(" DT_C " // trim (Num2LStr( DT_C )) )
254+ call WrScr(" -----------------------------------------------------------" )
255+ end subroutine ShowPassedData
256+
177257END SUBROUTINE IfW_C_Init
178258
179259! ===============================================================================================================
0 commit comments