diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 8ca53c7fae..7d987072f8 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -225,9 +225,12 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut integer(IntKi) :: errStat2 ! temporary error status of the operation character(ErrMsgLen) :: errMsg2 ! temporary error message - type(AD_InputFile) :: InputFileData ! Data stored in the module's input file + type(FileInfoType) :: FileInfo_In !< The derived type for holding the full input file for parsing -- we may pass this in the future + type(AD_InputFile) :: InputFileData ! Data stored in the module's input file after parsing + character(1024) :: PriPath !< Primary path + character(1024) :: EchoFileName integer(IntKi) :: UnEcho ! Unit number for the echo file - + character(*), parameter :: RoutineName = 'AD_Init' @@ -245,27 +248,46 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut call DispNVD( AD_Ver ) - - p%NumBlades = InitInp%NumBlades ! need this before reading the AD input file so that we know how many blade files to read - !bjj: note that we haven't validated p%NumBlades before using it below! + + ! set a few parameters needed while reading the input file + call ValidateNumBlades( InitInp%NumBlades, ErrStat2, ErrMsg2 ) + if (Failed()) return; + p%NumBlades = InitInp%NumBlades p%RootName = TRIM(InitInp%RootName)//'.AD' - - ! Read the primary AeroDyn input file - call ReadInputFiles( InitInp%InputFile, InputFileData, interval, p%RootName, p%NumBlades, UnEcho, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if - - + + CALL GetPath( InitInp%InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. + + ! ----------------------------------------------------------------- + ! Read the primary AeroDyn input file, or copy from passed input + if (InitInp%UsePrimaryInputFile) then + ! Read the entire input file, minus any comment lines, into the FileInfo_In + ! data structure in memory for further processing. + call ProcessComFile( InitInp%InputFile, FileInfo_In, ErrStat2, ErrMsg2 ) + else + call NWTC_Library_CopyFileInfoType( InitInp%PassedPrimaryInputData, FileInfo_In, MESH_NEWCOPY, ErrStat2, ErrMsg2 ) + endif + if (Failed()) return; + + + ! For diagnostic purposes, the following can be used to display the contents + ! of the FileInfo_In data structure. + ! call Print_FileInfo_Struct( CU, FileInfo_In ) ! CU is the screen -- different number on different systems. + + ! Parse the FileInfo_In structure of data from the inputfile into the InitInp%InputFile structure + CALL ParsePrimaryFileInfo( PriPath, InitInp%InputFile, p%RootName, p%NumBlades, interval, FileInfo_In, InputFileData, UnEcho, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + + ! ----------------------------------------------------------------- + ! Read the AeroDyn blade files, or copy from passed input +!FIXME: add handling for passing of blade files and other types of files. + call ReadInputFiles( InitInp%InputFile, InputFileData, interval, p%RootName, p%NumBlades, UnEcho, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + ! Validate the inputs call ValidateInputData( InitInp, InputFileData, p%NumBlades, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + if (Failed()) return; !............................................................................................ ! Define parameters @@ -273,33 +295,20 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut ! Initialize AFI module (read Airfoil tables) call Init_AFIparams( InputFileData, p%AFI, UnEcho, p%NumBlades, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + if (Failed()) return; ! set the rest of the parameters call SetParameters( InitInp, InputFileData, p, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + if (Failed()) return; !............................................................................................ ! Define and initialize inputs here !............................................................................................ call Init_u( u, p, InputFileData, InitInp, errStat2, errMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + if (Failed()) return; - ! !............................................................................................ ! Initialize the BEMT module (also sets other variables for sub module) @@ -311,11 +320,7 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut if (p%WakeMod /= WakeMod_FVW) then call Init_BEMTmodule( InputFileData, u, m%BEMT_u(1), p, x%BEMT, xd%BEMT, z%BEMT, & OtherState%BEMT, m%BEMT_y, m%BEMT, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + if (Failed()) return; call BEMT_CopyInput( m%BEMT_u(1), m%BEMT_u(2), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) @@ -326,7 +331,7 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut !............................................................................................ if (p%CompAA) then call Init_AAmodule( InitInp, InputFileData, u, m%AA_u, p, x%AA, xd%AA, z%AA, OtherState%AA, m%AA_y, m%AA, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return; end if endif @@ -341,15 +346,11 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut if (.not. allocated(m%FVW_u)) Allocate(m%FVW_u(3)) !size(u))) call Init_FVWmodule( InputFileData, u, m%FVW_u(1), p, x%FVW, xd%FVW, z%FVW, & OtherState%FVW, m%FVW_y, m%FVW, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + if (Failed()) return; ! populate the rest of the FVW_u so that extrap-interp will work do i=2,3 !size(u) call FVW_CopyInput( m%FVW_u(1), m%FVW_u(i), MESH_NEWCOPY, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return; enddo endif @@ -358,11 +359,7 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut ! Define outputs here !............................................................................................ call Init_y(y, u, p, errStat2, errMsg2) ! do this after input meshes have been initialized - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - if (ErrStat >= AbortErrLev) then - call Cleanup() - return - end if + if (Failed()) return; !............................................................................................ @@ -372,20 +369,20 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut ! many states are in the BEMT module, which were initialized in BEMT_Init() call Init_MiscVars(m, p, u, y, errStat2, errMsg2) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return; !............................................................................................ ! Initialize other states !............................................................................................ ! The wake from FVW is stored in other states. This may not be the best place to put it! call Init_OtherStates(m, p, OtherState, errStat2, errMsg2) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return; !............................................................................................ ! Define initialization output here !............................................................................................ call AD_SetInitOut(p, InputFileData, InitOut, errStat2, errMsg2) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return; ! after setting InitOut variables, we really don't need the airfoil coordinates taking up ! space in AeroDyn @@ -401,7 +398,7 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut !............................................................................................ if (InitInp%Linearize) then call Init_Jacobian(InputFileData, p, u, y, m, InitOut, ErrStat2, ErrMsg2) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return; end if !............................................................................................ @@ -409,7 +406,7 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut !............................................................................................ if (InputFileData%SumPrint) then call AD_PrintSum( InputFileData, p, u, y, ErrStat2, ErrMsg2 ) - call SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return; end if !............................................................................................ @@ -423,11 +420,14 @@ subroutine AD_Init( InitInp, u, p, x, xd, z, OtherState, y, m, Interval, InitOut call Cleanup() contains + logical function Failed() + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + Failed = ErrStat >= AbortErrLev + if (Failed) call Cleanup() + end function Failed subroutine Cleanup() - CALL AD_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2 ) IF ( UnEcho > 0 ) CLOSE( UnEcho ) - end subroutine Cleanup end subroutine AD_Init @@ -1921,6 +1921,16 @@ subroutine SetOutputsFromFVW(u, p, OtherState, x, xd, m, y, ErrStat, ErrMsg) end subroutine SetOutputsFromFVW !---------------------------------------------------------------------------------------------------------------------------------- !> This routine validates the inputs from the AeroDyn input files. +SUBROUTINE ValidateNumBlades( NumBl, ErrStat, ErrMsg ) + integer(IntKi), intent(in) :: NumBl !< Number of blades + integer(IntKi), intent(out) :: ErrStat !< Error status + character(*), intent(out) :: ErrMsg !< Error message + ErrStat = ErrID_None + ErrMsg = '' + if (NumBl > MaxBl .or. NumBl < 1) call SetErrStat( ErrID_Fatal, 'Number of blades must be between 1 and '//trim(num2lstr(MaxBl))//'.', ErrStat, ErrMsg, 'ValidateNumBlades' ) +END SUBROUTINE ValidateNumBlades +!---------------------------------------------------------------------------------------------------------------------------------- +!> This routine validates the inputs from the AeroDyn input files. SUBROUTINE ValidateInputData( InitInp, InputFileData, NumBl, ErrStat, ErrMsg ) !.................................................................................................................................. @@ -1942,7 +1952,6 @@ SUBROUTINE ValidateInputData( InitInp, InputFileData, NumBl, ErrStat, ErrMsg ) ErrMsg = "" - if (NumBl > MaxBl .or. NumBl < 1) call SetErrStat( ErrID_Fatal, 'Number of blades must be between 1 and '//trim(num2lstr(MaxBl))//'.', ErrSTat, ErrMsg, RoutineName ) if (InputFileData%DTAero <= 0.0) call SetErrStat ( ErrID_Fatal, 'DTAero must be greater than zero.', ErrStat, ErrMsg, RoutineName ) if (InputFileData%WakeMod /= WakeMod_None .and. InputFileData%WakeMod /= WakeMod_BEMT .and. InputFileData%WakeMod /= WakeMod_DBEMT .and. InputFileData%WakeMod /= WakeMod_FVW) then call SetErrStat ( ErrID_Fatal, 'WakeMod must be '//trim(num2lstr(WakeMod_None))//' (none), '//trim(num2lstr(WakeMod_BEMT))//' (BEMT), '// & @@ -2154,6 +2163,7 @@ SUBROUTINE Init_AFIparams( InputFileData, p_AFI, UnEc, NumBl, ErrStat, ErrMsg ) AFI_InitInputs%InCol_Cl = InputFileData%InCol_Cl AFI_InitInputs%InCol_Cd = InputFileData%InCol_Cd AFI_InitInputs%InCol_Cm = InputFileData%InCol_Cm + IF (.not. InputFileData%UseBlCm) AFI_InitInputs%InCol_Cm = 0 ! Don't try to use Cm if flag set to false AFI_InitInputs%InCol_Cpmin = InputFileData%InCol_Cpmin AFI_InitInputs%AFTabMod = InputFileData%AFTabMod !AFITable_1 diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index 90465ed21e..619b2bd1bf 100644 --- a/modules/aerodyn/src/AeroDyn_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_IO.f90 @@ -1915,7 +1915,7 @@ SUBROUTINE ReadInputFiles( InputFileName, InputFileData, Default_DT, OutFileRoot CHARACTER(*), INTENT(IN) :: InputFileName ! Name of the input file CHARACTER(*), INTENT(IN) :: OutFileRoot ! The rootname of all the output files written by this routine. - TYPE(AD_InputFile), INTENT(OUT) :: InputFileData ! Data stored in the module's input file + TYPE(AD_InputFile), INTENT(INOUT) :: InputFileData ! Data stored in the module's input file INTEGER(IntKi), INTENT(OUT) :: UnEcho ! Unit number for the echo file INTEGER(IntKi), INTENT(IN) :: NumBlades ! Number of blades for this model @@ -1939,16 +1939,6 @@ SUBROUTINE ReadInputFiles( InputFileName, InputFileData, Default_DT, OutFileRoot UnEcho = -1 InputFileData%DTAero = Default_DT ! the glue code's suggested DT for the module (may be overwritten in ReadPrimaryFile()) - ! get the primary/platform input-file data - ! sets UnEcho, ADBlFile - - CALL ReadPrimaryFile( InputFileName, InputFileData, ADBlFile, OutFileRoot, UnEcho, ErrStat2, ErrMsg2 ) - CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName) - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - ! get the blade input-file data @@ -1959,8 +1949,9 @@ SUBROUTINE ReadInputFiles( InputFileName, InputFileData, Default_DT, OutFileRoot RETURN END IF +!FIXME: add options for passing the blade files. This routine will need restructuring to handle that. DO I=1,NumBlades - CALL ReadBladeInputs ( ADBlFile(I), InputFileData%BladeProps(I), UnEcho, ErrStat2, ErrMsg2 ) + CALL ReadBladeInputs ( InputFileData%ADBlFile(I), InputFileData%BladeProps(I), UnEcho, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2,ErrMsg2, ErrStat, ErrMsg, RoutineName//TRIM(':Blade')//TRIM(Num2LStr(I))) IF ( ErrStat >= AbortErrLev ) THEN CALL Cleanup() @@ -1985,621 +1976,354 @@ END SUBROUTINE Cleanup END SUBROUTINE ReadInputFiles !---------------------------------------------------------------------------------------------------------------------------------- -SUBROUTINE ReadPrimaryFile( InputFile, InputFileData, ADBlFile, OutFileRoot, UnEc, ErrStat, ErrMsg ) -! This routine reads in the primary AeroDyn input file and places the values it reads in the InputFileData structure. -! It opens and prints to an echo file if requested. -!.................................................................................................................................. - - - implicit none +!> This routine parses the input file data stored in FileInfo_In and places it in the InputFileData structure for validating. +SUBROUTINE ParsePrimaryFileInfo( PriPath, InputFile, RootName, NumBlades, interval, FileInfo_In, InputFileData, UnEc, ErrStat, ErrMsg ) + implicit none ! Passed variables - integer(IntKi), intent(out) :: UnEc ! I/O unit for echo file. If > 0, file is open for writing. - integer(IntKi), intent(out) :: ErrStat ! Error status - - character(*), intent(out) :: ADBlFile(MaxBl) ! name of the files containing blade inputs - character(*), intent(in) :: InputFile ! Name of the file containing the primary input data - character(*), intent(out) :: ErrMsg ! Error message - character(*), intent(in) :: OutFileRoot ! The rootname of the echo file, possibly opened in this routine + character(*), intent(in ) :: PriPath !< primary path + CHARACTER(*), intent(in ) :: InputFile !< Name of the file containing the primary input data + CHARACTER(*), intent(in ) :: RootName !< The rootname of the echo file, possibly opened in this routine + integer(IntKi), intent(in ) :: NumBlades !< Number of blades we expect -- from InitInp + real(DBKi), intent(in ) :: interval !< timestep + type(AD_InputFile), intent(inout) :: InputFileData !< All the data in the AD15 primary input file + type(FileInfoType), intent(in ) :: FileInfo_In !< The derived type for holding the file information. + integer(IntKi), intent( out) :: UnEc !< The local unit number for this module's echo file + integer(IntKi), intent( out) :: ErrStat !< Error status + CHARACTER(ErrMsgLen), intent( out) :: ErrMsg !< Error message - type(AD_InputFile), intent(inout) :: InputFileData ! All the data in the AeroDyn input file - ! Local variables: - real(ReKi) :: TmpAry(3) ! array to help read tower properties table - integer(IntKi) :: I ! loop counter - integer(IntKi) :: UnIn ! Unit number for reading file - - integer(IntKi) :: ErrStat2, IOS ! Temporary Error status - logical :: Echo ! Determines if an echo file should be written - character(ErrMsgLen) :: ErrMsg2 ! Temporary Error message - character(ErrMsgLen) :: ErrMsg_NoAllBldNdOuts ! Temporary Error message - character(1024) :: PriPath ! Path name of the primary file - character(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents - character(200) :: Line ! Temporary storage of a line from the input file (to compare with "default") - character(*), parameter :: RoutineName = 'ReadPrimaryFile' - - - ! Initialize some variables: - ErrStat = ErrID_None - ErrMsg = "" - - UnEc = -1 - Echo = .FALSE. - CALL GetPath( InputFile, PriPath ) ! Input files will be relative to the path where the primary input file is located. - - - CALL AllocAry( InputFileData%OutList, MaxOutPts, "Outlist", ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Allocate array for holding the list of node outputs - CALL AllocAry( InputFileData%BldNd_OutList, BldNd_MaxOutPts, "BldNd_Outlist", ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Get an available unit number for the file. - - CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Open the Primary input file. - - CALL OpenFInpFile ( UnIn, InputFile, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - - - ! Read the lines up/including to the "Echo" simulation control variable - ! If echo is FALSE, don't write these lines to the echo file. - ! If Echo is TRUE, rewind and write on the second try. - - I = 1 !set the number of times we've read the file - DO - !----------- HEADER ------------------------------------------------------------- - - CALL ReadCom( UnIn, InputFile, 'File header: Module Version (line 1)', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL ReadStr( UnIn, InputFile, FTitle, 'FTitle', 'File Header: File Description (line 2)', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - - !----------- GENERAL OPTIONS ---------------------------------------------------- - - CALL ReadCom( UnIn, InputFile, 'Section Header: General Options', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Echo - Echo input to ".AD.ech". - - CALL ReadVar( UnIn, InputFile, Echo, 'Echo', 'Echo flag', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - - IF (.NOT. Echo .OR. I > 1) EXIT !exit this loop - - ! Otherwise, open the echo file, then rewind the input file and echo everything we've read - - I = I + 1 ! make sure we do this only once (increment counter that says how many times we've read this file) - - CALL OpenEcho ( UnEc, TRIM(OutFileRoot)//'.ech', ErrStat2, ErrMsg2, AD_Ver ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - IF ( UnEc > 0 ) WRITE (UnEc,'(/,A,/)') 'Data from '//TRIM(AD_Ver%Name)//' primary input file "'//TRIM( InputFile )//'":' - - REWIND( UnIn, IOSTAT=ErrStat2 ) - IF (ErrStat2 /= 0_IntKi ) THEN - CALL SetErrStat( ErrID_Fatal, 'Error rewinding file "'//TRIM(InputFile)//'".', ErrStat, ErrMsg, RoutineName ) - CALL Cleanup() - RETURN - END IF - - END DO - - IF (NWTC_VerboseLevel == NWTC_Verbose) THEN - CALL WrScr( ' Heading of the '//TRIM(AD_Ver%Name)//' input file: ' ) - CALL WrScr( ' '//TRIM( FTitle ) ) - END IF - - - ! DTAero - Time interval for aerodynamic calculations {or default} (s): - Line = "" - CALL ReadVar( UnIn, InputFile, Line, "DTAero", "Time interval for aerodynamic calculations {or default} (s)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL Conv2UC( Line ) - IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the value already stored in InputFileData%DTAero - READ( Line, *, IOSTAT=IOS) InputFileData%DTAero - CALL CheckIOS ( IOS, InputFile, 'DTAero', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - END IF - - ! WakeMod - Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW} (-): - CALL ReadVar( UnIn, InputFile, InputFileData%WakeMod, "WakeMod", "Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW} (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! AFAeroMod - Type of airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model} (-): - CALL ReadVar( UnIn, InputFile, InputFileData%AFAeroMod, "AFAeroMod", "Type of airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model} (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! TwrPotent - Type tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} (switch) : - CALL ReadVar( UnIn, InputFile, InputFileData%TwrPotent, "TwrPotent", "Type tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! TwrShadow - Calculate tower influence on wind based on downstream tower shadow? (flag) : - CALL ReadVar( UnIn, InputFile, InputFileData%TwrShadow, "TwrShadow", "Calculate tower influence on wind based on downstream tower shadow? (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! TwrAero - Calculate tower aerodynamic loads? (flag): - CALL ReadVar( UnIn, InputFile, InputFileData%TwrAero, "TwrAero", "Calculate tower aerodynamic loads? (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! FrozenWake - Assume frozen wake during linearization? (flag): - CALL ReadVar( UnIn, InputFile, InputFileData%FrozenWake, "FrozenWake", "Assume frozen wake during linearization? (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - - ! CavitCheck - Perform cavitation check? (flag): - CALL ReadVar( UnIn, InputFile, InputFileData%CavitCheck, "CavitCheck", "Perform cavitation check? (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! AddedMass - Include added mass effects? (flag): -! CALL ReadVar( UnIn, InputFile, InputFileData%AddedMass, "AddedMass", "Include added mass effects? (flag)", ErrStat2, ErrMsg2, UnEc) - ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! CompAA - Compute AeroAcoustics? (flag): - CALL ReadVar( UnIn, InputFile, InputFileData%CompAA, "CompAA", "Compute AeroAcoustics? (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! AA_Inputfile - CALL ReadVar ( UnIn, InputFile, InputFileData%AA_InputFile, "AA_Inputfile", "AeroAcoustics Input filename", ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( PathIsRelative( InputFileData%AA_InputFile ) ) InputFileData%AA_InputFile = TRIM(PriPath)//TRIM(InputFileData%AA_InputFile) - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !----------- ENVIRONMENTAL CONDITIONS ------------------------------------------- - CALL ReadCom( UnIn, InputFile, 'Section Header: Environmental Conditions', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! AirDens - Air density (kg/m^3): - CALL ReadVar( UnIn, InputFile, InputFileData%AirDens, "AirDens", "Air density (kg/m^3)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! KinVisc - Kinematic air viscosity (m^2/s): - CALL ReadVar( UnIn, InputFile, InputFileData%KinVisc, "KinVisc", "Kinematic air viscosity (m^2/s)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! SpdSound - Speed of sound (m/s): - CALL ReadVar( UnIn, InputFile, InputFileData%SpdSound, "SpdSound", "Speed of sound (m/s)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Patm - Atmospheric pressure (Pa): - CALL ReadVar( UnIn, InputFile, InputFileData%Patm, "Patm", "Atmospheric pressure (Pa)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - - ! Pvap - Vapour pressure of fluid (Pa): - CALL ReadVar( UnIn, InputFile, InputFileData%Pvap, "Pvap", "Vapour pressure of fluid (Pa)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! FluidDepth - Water depth above mid-hub height (m) - used for caviation check: - CALL ReadVar( UnIn, InputFile, InputFileData%FluidDepth, "FluidDepth", "Water depth above mid-hub height (MHK only, for cavitation check) (m)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !----------- BLADE-ELEMENT/MOMENTUM THEORY OPTIONS ------------------------------ - CALL ReadCom( UnIn, InputFile, 'Section Header: Blade-Element/Momentum Theory Options', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! SkewMod - Type of skewed-wake correction model {1=uncoupled, 2=Pitt/Peters, 3=coupled} (-) [unused when WakeMod={0|3}]: - CALL ReadVar( UnIn, InputFile, InputFileData%SkewMod, "SkewMod", "Type of skewed-wake correction model {1=uncoupled, 2=Pitt/Peters, 3=coupled} (-) [unused when WakeMod={0|3}]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! SkewModFactor - Constant used in Pitt/Peters skewed wake model {or default is 15/32*pi} (-) [used only when WakeMod/={0|3} and SkewMod=2]: - Line = "" - CALL ReadVar( UnIn, InputFile, Line, "SkewModFactor", "Constant used in Pitt/Peters skewed wake model {or default} (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL Conv2UC( Line ) - IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise use the default value 15.0_ReKi * pi / 32.0_ReKi - READ( Line, *, IOSTAT=IOS) InputFileData%SkewModFactor - CALL CheckIOS ( IOS, InputFile, 'SkewModFactor', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) - ELSE - InputFileData%SkewModFactor = 15.0_ReKi * pi / 32.0_ReKi - END IF - - - ! TipLoss - Use the Prandtl tip-loss model? (flag) [unused when WakeMod={0|3}]: - CALL ReadVar( UnIn, InputFile, InputFileData%TipLoss, "TipLoss", "Use the Prandtl tip-loss model? (flag) [unused when WakeMod={0|3}]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! HubLoss - Use the Prandtl hub-loss model? (flag) [unused when WakeMod={0|3}]: - CALL ReadVar( UnIn, InputFile, InputFileData%HubLoss, "HubLoss", "Use the Prandtl hub-loss model? (flag) [unused when WakeMod={0|3}]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! TanInd - Include tangential induction in BEMT calculations? (flag) [unused when WakeMod={0|3}]: - CALL ReadVar( UnIn, InputFile, InputFileData%TanInd, "TanInd", "Include tangential induction in BEMT calculations? (flag) [unused when WakeMod={0|3}]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! AIDrag - Include the drag term in the axial-induction calculation? (flag) [unused when WakeMod={0|3}]: - CALL ReadVar( UnIn, InputFile, InputFileData%AIDrag, "AIDrag", "Include the drag term in the axial-induction calculation? (flag) [unused when WakeMod={0|3}]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! TIDrag - Include the drag term in the tangential-induction calculation? (flag) [unused when WakeMod={0|3} or TanInd=FALSE]: - CALL ReadVar( UnIn, InputFile, InputFileData%TIDrag, "TIDrag", "Include the drag term in the tangential-induction calculation? (flag) [unused when WakeMod={0|3} or TanInd=FALSE]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! IndToler - Convergence tolerance for BEM induction factors (or "default"] (-) [unused when WakeMod={0|3}]: - Line = "" - CALL ReadVar( UnIn, InputFile, Line, "IndToler", "Convergence tolerance for BEM induction factors (-) [unused when WakeMod={0|3}]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - CALL Conv2UC( Line ) - IF ( INDEX(Line, "DEFAULT" ) /= 1 ) THEN ! If it's not "default", read this variable; otherwise set the value based on ReKi precision - READ( Line, *, IOSTAT=IOS) InputFileData%IndToler - CALL CheckIOS ( IOS, InputFile, 'IndToler', NumType, ErrStat2, ErrMsg2 ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - else - if (ReKi==SiKi) then - InputFileData%IndToler = 5E-5 - else - InputFileData%IndToler = 5D-10 - end if - END IF - - - ! MaxIter - Maximum number of iteration steps [unused when WakeMod={0|3}] (-): - CALL ReadVar( UnIn, InputFile, InputFileData%MaxIter, "MaxIter", "Maximum number of iteration steps (-) [unused when WakeMod={0|3}]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - - !----------- DYNAMIC BLADE-ELEMENT/MOMENTUM THEORY OPTIONS ------------------------------ - CALL ReadCom( UnIn, InputFile, 'Section Header: Dynamic Blade-Element/Momentum Theory Options', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! DBEMT_Mod - Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} (-): - CALL ReadVar( UnIn, InputFile, InputFileData%DBEMT_Mod, "DBEMT_Mod", "Type of dynamic BEMT (DBEMT) model {0=none, 1=constant tau1, 2=time-dependent tau1} (-) [used only when WakeMod=2]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! tau1_const - time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1]: - CALL ReadVar( UnIn, InputFile, InputFileData%tau1_const, "tau1_const", "time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1]", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - - !----------- FREE VORTEX WAKE (FVW) THEORY OPTIONS ------------------------------ - CALL ReadCom( UnIn, InputFile, 'Section Header: Free Vortex Wake (FVW) Theory Options', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + integer(IntKi) :: i !< generic counter + integer(IntKi) :: ErrStat2, IOS !< Temporary Error status + character(ErrMsgLen) :: ErrMsg2 !< Temporary Error message + character(ErrMsgLen) :: ErrMsg_NoAllBldNdOuts + integer(IntKi) :: CurLine !< current entry in FileInfo_In%Lines array + real(ReKi) :: TmpRe3(3) !< temporary 3 number array for reading values in - CALL ReadVar ( UnIn, InputFile, InputFileData%FVWFileName, 'FVWFile', 'FVW input file name', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( PathIsRelative( InputFileData%FVWFileName ) ) InputFileData%FVWFileName = TRIM(PriPath)//TRIM(InputFileData%FVWFileName) + character(1024) :: FTitle ! "File Title": the 2nd line of the input file, which contains a description of its contents + character(*), parameter :: RoutineName = 'ParsePrimaryFileInfo' + ! Initialization + ErrStat = 0 + ErrMsg = "" + UnEc = -1 ! Echo file unit. >0 when used - !----------- BEDDOES-LEISHMAN UNSTEADY AIRFOIL AERODYNAMICS OPTIONS ------------- - CALL ReadCom( UnIn, InputFile, 'Section Header: Beddoes-Leishman Unsteady Airfoil Aerodynamics Options', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! UAMod - Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAreoMod=2] (-): - CALL ReadVar( UnIn, InputFile, InputFileData%UAMod, "UAMod", "Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAreoMod=2] (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! FLookup - Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files [used only when AFAreoMod=2] (flag): - CALL ReadVar( UnIn, InputFile, InputFileData%FLookup, "FLookup", "Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files [used only when AFAreoMod=2] (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! UACutout - Angle-of-attack beyond which unsteady aerodynamics are disabled (deg) -! CALL ReadVar( UnIn, InputFile, InputFileData%UACutout, "UACutout", "Angle-of-attack beyond which unsteady aerodynamics are disabled (deg)", ErrStat2, ErrMsg2, UnEc) -! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !----------- AIRFOIL INFORMATION ------------------------------------------------ - CALL ReadCom( UnIn, InputFile, 'Section Header: Airfoil Information', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ! AFTabMod - Interpolation method for multiple airfoil tables (-): - CALL ReadVar( UnIn, InputFile, InputFileData%AFTabMod, "AFTabMod", "Interpolation method for multiple airfoil tables (-)", ErrStat2, ErrMsg2, UnEc) + CALL AllocAry( InputFileData%OutList, MaxOutPts, "Outlist", ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - ! InCol_Alfa - The column in the airfoil tables that contains the angle of attack (-): - CALL ReadVar( UnIn, InputFile, InputFileData%InCol_Alfa, "InCol_Alfa", "The column in the airfoil tables that contains the angle of attack (-)", ErrStat2, ErrMsg2, UnEc) + ! Allocate array for holding the list of node outputs + CALL AllocAry( InputFileData%BldNd_OutList, BldNd_MaxOutPts, "BldNd_Outlist", ErrStat2, ErrMsg2 ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - ! InCol_Cl - The column in the airfoil tables that contains the lift coefficient (-): - CALL ReadVar( UnIn, InputFile, InputFileData%InCol_Cl, "InCol_Cl", "The column in the airfoil tables that contains the lift coefficient (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - ! InCol_Cd - The column in the airfoil tables that contains the drag coefficient (-): - CALL ReadVar( UnIn, InputFile, InputFileData%InCol_Cd, "InCol_Cd", "The column in the airfoil tables that contains the drag coefficient (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN + !------------------------------------------------------------------------------------------------- + ! General settings + !------------------------------------------------------------------------------------------------- - ! InCol_Cm - The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column (-): - CALL ReadVar( UnIn, InputFile, InputFileData%InCol_Cm, "InCol_Cm", "The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN + CurLine = 4 ! Skip the first three lines as they are known to be header lines and separators + call ParseVar( FileInfo_In, CurLine, 'Echo', InputFileData%Echo, ErrStat2, ErrMsg2 ) + if (Failed()) return; + + if ( InputFileData%Echo ) then + CALL OpenEcho ( UnEc, TRIM(RootName)//'.ech', ErrStat2, ErrMsg2 ) + if (Failed()) return; + WRITE(UnEc, '(A)') 'Echo file for AeroDyn 15 primary input file: '//trim(InputFile) + ! Write the first three lines into the echo file + WRITE(UnEc, '(A)') FileInfo_In%Lines(1) + WRITE(UnEc, '(A)') FileInfo_In%Lines(2) + WRITE(UnEc, '(A)') FileInfo_In%Lines(3) + + CurLine = 4 + call ParseVar( FileInfo_In, CurLine, 'Echo', InputFileData%Echo, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + endif - ! InCol_Cpmin - The column in the airfoil tables that contains the drag coefficient; use zero if there is no Cpmin column (-): - CALL ReadVar( UnIn, InputFile, InputFileData%InCol_Cpmin, "InCol_Cpmin", "The column in the airfoil tables that contains the drag coefficient; use zero if there is no Cpmin column (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - - ! NumAFfiles - Number of airfoil files used (-): - CALL ReadVar( UnIn, InputFile, InputFileData%NumAFfiles, "NumAFfiles", "Number of airfoil files used (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN + ! DTAero - Time interval for aerodynamic calculations {or default} (s): + call ParseVarWDefault ( FileInfo_In, CurLine, "DTAero", InputFileData%DTAero, interval, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! WakeMod - Type of wake/induction model (switch) {0=none, 1=BEMT, 2=DBEMT, 3=OLAF} [WakeMod cannot be 2 or 3 when linearizing] + call ParseVar( FileInfo_In, CurLine, "WakeMod", InputFileData%WakeMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! AFAeroMod - Type of blade airfoil aerodynamics model (switch) {1=steady model, 2=Beddoes-Leishman unsteady model} [AFAeroMod must be 1 when linearizing] + call ParseVar( FileInfo_In, CurLine, "AFAeroMod", InputFileData%AFAeroMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TwrPotent - Type tower influence on wind based on potential flow around the tower (switch) {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} + call ParseVar( FileInfo_In, CurLine, "TwrPotent", InputFileData%TwrPotent, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TwrShadow - Calculate tower influence on wind based on downstream tower shadow? (flag) + call ParseVar( FileInfo_In, CurLine, "TwrShadow", InputFileData%TwrShadow, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TwrAero - Calculate tower aerodynamic loads? (flag) + call ParseVar( FileInfo_In, CurLine, "TwrAero", InputFileData%TwrAero, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! FrozenWake - Assume frozen wake during linearization? (flag) [used only when WakeMod=1 and when linearizing] + call ParseVar( FileInfo_In, CurLine, "FrozenWake", InputFileData%FrozenWake, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! CavitCheck - Perform cavitation check? (flag) [AFAeroMod must be 1 when CavitCheck=true] + call ParseVar( FileInfo_In, CurLine, "CavitCheck", InputFileData%CavitCheck, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! CompAA - Flag to compute AeroAcoustics calculation [only used when WakeMod=1 or 2] + call ParseVar( FileInfo_In, CurLine, "CompAA", InputFileData%CompAA, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! AA_InputFile - Aeroacoustics input file + call ParseVar( FileInfo_In, CurLine, "AA_InputFile", InputFileData%AA_InputFile, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%AA_InputFile ) ) InputFileData%AA_InputFile = TRIM(PriPath)//TRIM(InputFileData%AA_InputFile) + + !====== Environmental Conditions =================================================================== + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! AirDens - Air density (kg/m^3) + call ParseVar( FileInfo_In, CurLine, "AirDens", InputFileData%AirDens, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! KinVisc - Kinematic air viscosity (m^2/s) + call ParseVar( FileInfo_In, CurLine, "KinVisc", InputFileData%KinVisc, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! SpdSound - Speed of sound (m/s) + call ParseVar( FileInfo_In, CurLine, "SpdSound", InputFileData%SpdSound, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Patm - Atmospheric pressure (Pa) [used only when CavitCheck=True] + call ParseVar( FileInfo_In, CurLine, "Patm", InputFileData%Patm, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Pvap - Vapour pressure of fluid (Pa) [used only when CavitCheck=True] + call ParseVar( FileInfo_In, CurLine, "Pvap", InputFileData%Pvap, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! FluidDepth - Water depth above mid-hub height (m) [used only when CavitCheck=True] + call ParseVar( FileInfo_In, CurLine, "FluidDepth", InputFileData%FluidDepth, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== Blade-Element/Momentum Theory Options ====================================================== [unused when WakeMod=0 or 3] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! SkewMod - Type of skewed-wake correction model (switch) {1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "SkewMod", InputFileData%SkewMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! SkewModFactor - Constant used in Pitt/Peters skewed wake model {or "default" is 15/32*pi} (-) [used only when SkewMod=2; unused when WakeMod=0 or 3] + call ParseVarWDefault( FileInfo_In, CurLine, "SkewModFactor", InputFileData%SkewModFactor, (15.0_ReKi * pi / 32.0_ReKi), ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TipLoss - Use the Prandtl tip-loss model? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "TipLoss", InputFileData%TipLoss, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! HubLoss - Use the Prandtl hub-loss model? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "HubLoss", InputFileData%HubLoss, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TanInd - Include tangential induction in BEMT calculations? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "TanInd", InputFileData%TanInd, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! AIDrag - Include the drag term in the axial-induction calculation? (flag) [unused when WakeMod=0 or 3] + call ParseVar( FileInfo_In, CurLine, "AIDrag", InputFileData%AIDrag, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! TIDrag - Include the drag term in the tangential-induction calculation? (flag) [unused when WakeMod=0,3 or TanInd=FALSE] + call ParseVar( FileInfo_In, CurLine, "TIDrag", InputFileData%TIDrag, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! IndToler - Convergence tolerance for BEMT nonlinear solve residual equation {or "default"} (-) [unused when WakeMod=0 or 3] + if (ReKi==SiKi) then + call ParseVarWDefault( FileInfo_In, CurLine, "IndToler", InputFileData%IndToler, real(5E-5,ReKi), ErrStat2, ErrMsg2, UnEc ) + else + call ParseVarWDefault( FileInfo_In, CurLine, "IndToler", InputFileData%IndToler, real(5D-10,ReKi), ErrStat2, ErrMsg2, UnEc ) + end if + if (Failed()) return + ! MaxIter - Maximum number of iteration steps (-) [unused when WakeMod=0] + call ParseVar( FileInfo_In, CurLine, "MaxIter", InputFileData%MaxIter, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== Dynamic Blade-Element/Momentum Theory Options ============================================== [used only when WakeMod=2] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! DBEMT_Mod - Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} (-) [used only when WakeMod=2] + call ParseVar( FileInfo_In, CurLine, "DBEMT_Mod", InputFileData%DBEMT_Mod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! tau1_const - Time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1] + call ParseVar( FileInfo_In, CurLine, "tau1_const", InputFileData%tau1_const, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== OLAF -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options ================== [used only when WakeMod=3] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! OLAFInputFileName - Input file for OLAF [used only when WakeMod=3] + call ParseVar( FileInfo_In, CurLine, "OLAFInputFileName", InputFileData%FVWFileName, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%FVWFileName ) ) InputFileData%FVWFileName = TRIM(PriPath)//TRIM(InputFileData%FVWFileName) + + !====== Beddoes-Leishman Unsteady Airfoil Aerodynamics Options ===================================== [used only when AFAeroMod=2] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! UAMod - Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2] + call ParseVar( FileInfo_In, CurLine, "UAMod", InputFileData%UAMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! FLookup - Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files (flag) [used only when AFAeroMod=2] + call ParseVar( FileInfo_In, CurLine, "FLookup", InputFileData%FLookup, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + !====== Airfoil Information ========================================================================= + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! AFTabMod - Interpolation method for multiple airfoil tables {1=1D interpolation on AoA (first table only); 2=2D interpolation on AoA and Re; 3=2D interpolation on AoA and UserProp} (-) + call ParseVar( FileInfo_In, CurLine, "AFTabMod", InputFileData%AFTabMod, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Alfa - The column in the airfoil tables that contains the angle of attack (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Alfa", InputFileData%InCol_Alfa, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cl - The column in the airfoil tables that contains the lift coefficient (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cl", InputFileData%InCol_Cl, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cd - The column in the airfoil tables that contains the drag coefficient (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cd", InputFileData%InCol_Cd, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cm - The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cm", InputFileData%InCol_Cm, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! InCol_Cpmin - The column in the airfoil tables that contains the Cpmin coefficient; use zero if there is no Cpmin column (-) + call ParseVar( FileInfo_In, CurLine, "InCol_Cpmin", InputFileData%InCol_Cpmin, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! NumAFfiles - Number of airfoil files used (-) + call ParseVar( FileInfo_In, CurLine, "NumAFfiles", InputFileData%NumAFfiles, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return ! Allocate space to hold AFNames ALLOCATE( InputFileData%AFNames(InputFileData%NumAFfiles), STAT=ErrStat2) IF (ErrStat2 /= 0 ) THEN CALL SetErrStat( ErrID_Fatal, "Error allocating AFNames.", ErrStat, ErrMsg, RoutineName) - CALL Cleanup() RETURN END IF - - ! AFNames - Airfoil file names (NumAFfiles lines) (quoted strings): - DO I = 1,InputFileData%NumAFfiles - CALL ReadVar ( UnIn, InputFile, InputFileData%AFNames(I), 'AFNames('//TRIM(Num2Lstr(I))//')', 'Airfoil '//TRIM(Num2Lstr(I))//' file name', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + ! AFNames - Airfoil file names (NumAFfiles lines) (quoted strings): -- NOTE: this line may not have a keyname with it + DO I = 1,InputFileData%NumAFfiles ! ParseChVar allows empty keynames. + call ParseChVar( FileInfo_In, CurLine, "", InputFileData%AFNames(I), ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return IF ( PathIsRelative( InputFileData%AFNames(I) ) ) InputFileData%AFNames(I) = TRIM(PriPath)//TRIM(InputFileData%AFNames(I)) - END DO - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !----------- ROTOR/BLADE PROPERTIES -------------------------------------------- - CALL ReadCom( UnIn, InputFile, 'Section Header: Rotor/Blade Properties', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! UseBlCm - Include aerodynamic pitching moment in calculations? (flag): - CALL ReadVar( UnIn, InputFile, InputFileData%UseBlCm, "UseBlCm", "Include aerodynamic pitching moment in calculations? (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN - IF (.not. InputFileData%UseBlCm) InputFileData%InCol_Cm = 0 ! don't use cm column is UseBlCm is false - - ! ! NumBlNds - Number of blade nodes used in the analysis (-): - !CALL ReadVar( UnIn, InputFile, InputFileData%NumBlNds, "NumBlNds", "Number of blade nodes used in the analysis (-)", ErrStat2, ErrMsg2, UnEc) - ! CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - ! IF ( ErrStat >= AbortErrLev ) RETURN - - ! ADBlFile - Names of files containing distributed aerodynamic properties for each blade (see AD_BladeInputFile type): - DO I = 1,size(ADBlFile) - CALL ReadVar ( UnIn, InputFile, ADBlFile(I), 'ADBlFile('//TRIM(Num2Lstr(I))//')', 'Name of file containing distributed aerodynamic properties for blade '//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( PathIsRelative( ADBlFile(I) ) ) ADBlFile(I) = TRIM(PriPath)//TRIM(ADBlFile(I)) - END DO - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !----------- TOWER INFLUENCE AND AERODYNAMICS ---------------------------------- - CALL ReadCom( UnIn, InputFile, 'Section Header: Tower Influence and Aerodynamics', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! NumTwrNds - Number of tower nodes used in the analysis (-): - CALL ReadVar( UnIn, InputFile, InputFileData%NumTwrNds, "NumTwrNds", "Number of tower nodes used in the analysis (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN + END DO - - !....... tower properties ................... - CALL ReadCom( UnIn, InputFile, 'Section Header: Tower Property Channels', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - CALL ReadCom( UnIn, InputFile, 'Section Header: Tower Property Units', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! allocate space for tower inputs: + !====== Rotor/Blade Properties ===================================================================== + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! UseBlCm - Include aerodynamic pitching moment in calculations? (flag) + call ParseVar( FileInfo_In, CurLine, "UseBlCm", InputFileData%UseBlCm, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Allocate space for AD blade file names -- MaxBl is usually set to 3, but if we specify more blades, this will work still. + call AllocAry( InputFileData%ADBlFile, max(MaxBl,NumBlades), 'ADBlFile', ErrStat2, ErrMsg2) + if (Failed()) return + do I =1,size(InputFileData%ADBlFile) ! We expect MaxBl blade file lines. We may want to revisit this idea later if we allow more thn 3 blades + call ParseVar( FileInfo_In, CurLine, "", InputFileData%ADBlFile(i), ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + IF ( PathIsRelative( InputFileData%ADBlFile(I) ) ) InputFileData%ADBlFile(I) = TRIM(PriPath)//TRIM(InputFileData%ADBlFile(I)) + enddo + + !====== Tower Influence and Aerodynamics ============================================================= [used only when TwrPotent/=0, TwrShadow=True, or TwrAero=True] + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! NumTwrNds - Number of tower nodes used in the analysis (-) [used only when TwrPotent/=0, TwrShadow=True, or TwrAero=True] + call ParseVar( FileInfo_In, CurLine, "NumTwrNds", InputFileData%NumTwrNds, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + !TwrElev TwrDiam TwrCd + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Tower Table Header: '//FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + !(m) (m) (-) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') 'Tower Table Header: '//FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! Allocate space for tower table CALL AllocAry( InputFileData%TwrElev, InputFileData%NumTwrNds, 'TwrElev', ErrStat2, ErrMsg2) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return CALL AllocAry( InputFileData%TwrDiam, InputFileData%NumTwrNds, 'TwrDiam', ErrStat2, ErrMsg2) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) + if (Failed()) return CALL AllocAry( InputFileData%TwrCd, InputFileData%NumTwrNds, 'TwrCd', ErrStat2, ErrMsg2) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Return on error if we didn't allocate space for the next inputs - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - DO I=1,InputFileData%NumTwrNds - call ReadAry ( UnIn, InputFile, TmpAry, 3, 'TwrNds', 'Properties for tower node ' & - //trim( Int2LStr( I ) )//'.', errStat2, errMsg2, UnEc ) - call setErrStat( errStat2, ErrMsg2 , errStat, ErrMsg , RoutineName ) - - InputFileData%TwrElev(I) = TmpAry( 1) - InputFileData%TwrDiam(I) = TmpAry( 2) - InputFileData%TwrCd(I) = TmpAry( 3) - END DO - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !----------- OUTPUTS ----------------------------------------------------------- - CALL ReadCom( UnIn, InputFile, 'Section Header: Outputs', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! SumPrint - Generate a summary file listing input options and interpolated properties to .AD.sum? (flag): - CALL ReadVar( UnIn, InputFile, InputFileData%SumPrint, "SumPrint", "Generate a summary file listing input options and interpolated properties to .AD.sum? (flag)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! NBlOuts - Number of blade node outputs [0 - 9] (-): - CALL ReadVar( UnIn, InputFile, InputFileData%NBlOuts, "NBlOuts", "Number of blade node outputs [0 - 9] (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - IF ( InputFileData%NBlOuts > SIZE(InputFileData%BlOutNd) ) THEN - CALL SetErrStat( ErrID_Warn, ' Warning: number of blade output nodes exceeds '//& - TRIM(Num2LStr(SIZE(InputFileData%BlOutNd))) //'.', ErrStat, ErrMsg, RoutineName ) - InputFileData%NBlOuts = SIZE(InputFileData%BlOutNd) - END IF - + if (Failed()) return + + do I=1,InputFileData%NumTwrNds + call ParseAry ( FileInfo_In, CurLine, 'Properties for tower node '//trim( Int2LStr( I ) )//'.', TmpRe3, 3, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; + InputFileData%TwrElev(I) = TmpRe3( 1) + InputFileData%TwrDiam(I) = TmpRe3( 2) + InputFileData%TwrCd(I) = TmpRe3( 3) + end do + + !====== Outputs ==================================================================================== + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + ! SumPrint - Generate a summary file listing input options and interpolated properties to ".AD.sum"? (flag) + call ParseVar( FileInfo_In, CurLine, "SumPrint", InputFileData%SumPrint, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + + ! NBlOuts - Number of blade node outputs [0 - 9] (-) + call ParseVar( FileInfo_In, CurLine, "NBlOuts", InputFileData%NBlOuts, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Make sure we don't try to read in more than will fit in the pre-allocated BlOutNd array + if ( InputFileData%NBlOuts > SIZE(InputFileData%BlOutNd) ) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: number of blade output nodes exceeds '//& + TRIM(Num2LStr(SIZE(InputFileData%BlOutNd))) //'.', ErrStat, ErrMsg, RoutineName ) + InputFileData%NBlOuts = SIZE(InputFileData%BlOutNd) + endif ! BlOutNd - Blade nodes whose values will be output (-): - CALL ReadAry( UnIn, InputFile, InputFileData%BlOutNd, InputFileData%NBlOuts, "BlOutNd", "Blade nodes whose values will be output (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! NTwOuts - Number of tower node outputs [0 - 9] (-): - CALL ReadVar( UnIn, InputFile, InputFileData%NTwOuts, "NTwOuts", "Number of tower node outputs [0 - 9] (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - IF ( InputFileData%NTwOuts > SIZE(InputFileData%TwOutNd) ) THEN - CALL SetErrStat( ErrID_Warn, ' Warning: number of tower output nodes exceeds '//& - TRIM(Num2LStr(SIZE(InputFileData%TwOutNd))) //'.', ErrStat, ErrMsg, RoutineName ) - InputFileData%NTwOuts = SIZE(InputFileData%TwOutNd) - END IF - + call ParseAry( FileInfo_In, CurLine, "BlOutNd", InputFileData%BlOutNd, InputFileData%NBlOuts, ErrStat2, ErrMsg2, UnEc) + + ! NTwOuts - Number of blade node outputs [0 - 9] (-) + call ParseVar( FileInfo_In, CurLine, "NTwOuts", InputFileData%NTwOuts, ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return + ! Make sure we don't try to read in more than will fit in the pre-allocated TwOutNd array + if ( InputFileData%NTwOuts > SIZE(InputFileData%TwOutNd) ) THEN + CALL SetErrStat( ErrID_Warn, ' Warning: number of blade output nodes exceeds '//& + TRIM(Num2LStr(SIZE(InputFileData%TwOutNd))) //'.', ErrStat, ErrMsg, RoutineName ) + InputFileData%NTwOuts = SIZE(InputFileData%TwOutNd) + endif ! TwOutNd - Tower nodes whose values will be output (-): - CALL ReadAry( UnIn, InputFile, InputFileData%TwOutNd, InputFileData%NTwOuts, "TwOutNd", "Tower nodes whose values will be output (-)", ErrStat2, ErrMsg2, UnEc) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !----------- OUTLIST ----------------------------------------------------------- - CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - - ! OutList - List of user-requested output channels (-): - CALL ReadOutputList ( UnIn, InputFile, InputFileData%OutList, InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library - CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - + call ParseAry( FileInfo_In, CurLine, "TwOutNd", InputFileData%TwOutNd, InputFileData%NTwOuts, ErrStat2, ErrMsg2, UnEc) - ! Return on error at end of section - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - - !---------------------- END OF FILE ----------------------------------------- + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + call ReadOutputListFromFileInfo( FileInfo_In, CurLine, InputFileData%OutList, & + InputFileData%NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) + if (Failed()) return; - - - !----------- OUTLIST ----------------------------------------------------------- + !====== Nodal Outputs ============================================================================== ! In case there is something ill-formed in the additional nodal outputs section, we will simply ignore it. - ErrMsg_NoAllBldNdOuts='Nodal output section of AeroDyn input file not found or improperly formatted.' - - !----------- OUTLIST for BldNd ----------------------------------------------------------- - CALL ReadCom( UnIn, InputFile, 'Section Header: OutList for Blade node channels', ErrStat2, ErrMsg2, UnEc ) - IF ( ErrStat2 >= AbortErrLev ) THEN - InputFileData%BldNd_BladesOut = 0 - InputFileData%BldNd_NumOuts = 0 - call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) - CALL Cleanup() - RETURN - ENDIF + ! Expecting at least 5 more lines in the input file for this section + if (FileInfo_In%NumLines < CurLine + 5) then + ErrStat2 = ErrID_Fatal + ErrMsg2 = '' + if (FailedNodal()) return; + endif + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 - ! Number of blade nodes to output: will modify this at some point for arrays + ! BldNd_BladesOut - Number of blades to output all node information at. Up to number of blades on turbine. (-) ! TODO: In a future release, allow this to be an array of N blade numbers (change BldNd_BladesOut to an array if we do that). ! Will likely require reading this line in as a string (BldNd_BladesOut_Str) and parsing it - CALL ReadVar( UnIn, InputFile, InputFileData%BldNd_BladesOut, 'BldNd_BladesOut', 'Which blades to output node data on.'//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ) - IF ( ErrStat2 >= AbortErrLev ) THEN - InputFileData%BldNd_BladesOut = 0 - InputFileData%BldNd_NumOuts = 0 - call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) - CALL Cleanup() - RETURN - ENDIF - - - ! Which blades to output for: will add this at some point + call ParseVar( FileInfo_In, CurLine, "BldNd_BladesOut", InputFileData%BldNd_BladesOut, ErrStat2, ErrMsg2, UnEc ) + if (FailedNodal()) return + ! BldNd_BlOutNd - Future feature will allow selecting a portion of the nodes to output. Not implemented yet. (-) ! TODO: Parse this string into an array of nodes to output at (one idea is to set an array of boolean to T/F for which nodes to output). At present, we ignore it entirely. - CALL ReadVar( UnIn, InputFile, InputFileData%BldNd_BlOutNd_Str, 'BldNd_BlOutNd_Str', 'Which nodes to output node data on.'//TRIM(Num2Lstr(I)), ErrStat2, ErrMsg2, UnEc ) - IF ( ErrStat2 >= AbortErrLev ) THEN - InputFileData%BldNd_BladesOut = 0 - InputFileData%BldNd_NumOuts = 0 - call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) - CALL Cleanup() - RETURN - ENDIF + call ParseVar( FileInfo_In, CurLine, "BldNd_BlOutNd", InputFileData%BldNd_BlOutNd_Str, ErrStat2, ErrMsg2, UnEc ) + if (FailedNodal()) return + ! OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) + if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo + CurLine = CurLine + 1 + call ReadOutputListFromFileInfo( FileInfo_In, CurLine, InputFileData%BldNd_OutList, & + InputFileData%BldNd_NumOuts, 'BldNd_OutList', "List of user-requested output nodal channel groups", ErrStat2, ErrMsg2, UnEc ) + if (FailedNodal()) return; - ! Section header for outlist - CALL ReadCom( UnIn, InputFile, 'Section Header: OutList', ErrStat2, ErrMsg2, UnEc ) - IF ( ErrStat2 >= AbortErrLev ) THEN - InputFileData%BldNd_BladesOut = 0 - InputFileData%BldNd_NumOuts = 0 - call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) - CALL Cleanup() - RETURN - ENDIF - - - ! OutList - List of user-requested output channels at each node(-): - CALL ReadOutputList ( UnIn, InputFile, InputFileData%BldNd_OutList, InputFileData%BldNd_NumOuts, 'OutList', "List of user-requested output channels", ErrStat2, ErrMsg2, UnEc ) ! Routine in NWTC Subroutine Library - IF ( ErrStat2 >= AbortErrLev ) THEN - InputFileData%BldNd_BladesOut = 0 - InputFileData%BldNd_NumOuts = 0 - call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) - CALL Cleanup() - RETURN - ENDIF - - - - !---------------------- END OF FILE ----------------------------------------- - - CALL Cleanup( ) RETURN - - CONTAINS - !............................................................................................................................... - SUBROUTINE Cleanup() - ! This subroutine cleans up any local variables and closes input files - !............................................................................................................................... - - IF (UnIn > 0) CLOSE ( UnIn ) - - END SUBROUTINE Cleanup - !............................................................................................................................... -END SUBROUTINE ReadPrimaryFile + !------------------------------------------------------------------------------------------------- + logical function Failed() + CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, 'ParsePrimaryFileInfo' ) + Failed = ErrStat >= AbortErrLev + if (Failed) then + if (UnEc > -1_IntKi) CLOSE( UnEc ) + endif + end function Failed + logical function FailedNodal() + ErrMsg_NoAllBldNdOuts='AD15 Nodal Outputs: Nodal output section of AeroDyn input file not found or improperly formatted. Skipping nodal outputs.' + if (ErrStat2 >= AbortErrLev ) then + InputFileData%BldNd_BladesOut = 0 + InputFileData%BldNd_NumOuts = 0 + call wrscr( trim(ErrMsg_NoAllBldNdOuts) ) + endif + FailedNodal = ErrStat2 >= AbortErrLev + end function FailedNodal + !------------------------------------------------------------------------------------------------- +END SUBROUTINE ParsePrimaryFileInfo !---------------------------------------------------------------------------------------------------------------------------------- SUBROUTINE ReadBladeInputs ( ADBlFile, BladeKInputFileData, UnEc, ErrStat, ErrMsg ) ! This routine reads a blade input file. diff --git a/modules/aerodyn/src/AeroDyn_Registry.txt b/modules/aerodyn/src/AeroDyn_Registry.txt index 563b6cf202..839c329bf2 100644 --- a/modules/aerodyn/src/AeroDyn_Registry.txt +++ b/modules/aerodyn/src/AeroDyn_Registry.txt @@ -42,6 +42,10 @@ typedef ^ InitInputType ReKi HubPosition {3} - - "X-Y-Z reference position of hu typedef ^ InitInputType R8Ki HubOrientation {3}{3} - - "DCM reference orientation of hub" - typedef ^ InitInputType ReKi BladeRootPosition {:}{:} - - "X-Y-Z reference position of each blade root (3 x NumBlades)" m typedef ^ InitInputType R8Ki BladeRootOrientation {:}{:}{:} - - "DCM reference orientation of blade roots (3x3 x NumBlades)" - +typedef ^ InitInputType LOGICAL UsePrimaryInputFile - .TRUE. - "Read input file instead of passed data" - +typedef ^ InitInputType FileInfoType PassedPrimaryInputData - - - "Primary input file as FileInfoType (set by driver/glue code)" - + + # This is data defined in the Input File for this module (or could otherwise be passed in) # ..... Blade Input file data ..................................................................................................... @@ -77,6 +81,7 @@ typedef ^ InitOutputType ReKi TwrDiam {:} - - "Diameter of tower at node" m # ..... Input file data ........................................................................................................... # ..... Primary Input file data ................................................................................................... +typedef ^ AD_InputFile Logical Echo - - - "Echo input file to echo file" - typedef ^ AD_InputFile DbKi DTAero - - - "Time interval for aerodynamic calculations {or "default"}" s typedef ^ AD_InputFile IntKi WakeMod - - - "Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW}" - typedef ^ AD_InputFile IntKi AFAeroMod - - - "Type of blade airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model}" - @@ -87,6 +92,7 @@ typedef ^ AD_InputFile Logical FrozenWake - - - "Flag that tells this module it typedef ^ AD_InputFile Logical CavitCheck - - - "Flag that tells us if we want to check for cavitation" - typedef ^ AD_InputFile Logical CompAA - - - "Compute AeroAcoustic noise" flag typedef ^ AD_InputFile CHARACTER(1024) AA_InputFile - - - "AeroAcoustics input file name" "quoted strings" +typedef ^ AD_InputFile CHARACTER(1024) ADBlFile {:} - - "AD blade file (NumBl filenames)" "quoted strings" typedef ^ AD_InputFile ReKi AirDens - - - "Air density" kg/m^3 typedef ^ AD_InputFile ReKi KinVisc - - - "Kinematic air viscosity" m^2/s typedef ^ AD_InputFile ReKi Patm - - - "Atmospheric pressure" Pa diff --git a/modules/aerodyn/src/AeroDyn_Types.f90 b/modules/aerodyn/src/AeroDyn_Types.f90 index 28487fc89c..79872caedc 100644 --- a/modules/aerodyn/src/AeroDyn_Types.f90 +++ b/modules/aerodyn/src/AeroDyn_Types.f90 @@ -60,6 +60,8 @@ MODULE AeroDyn_Types REAL(R8Ki) , DIMENSION(1:3,1:3) :: HubOrientation !< DCM reference orientation of hub [-] REAL(ReKi) , DIMENSION(:,:), ALLOCATABLE :: BladeRootPosition !< X-Y-Z reference position of each blade root (3 x NumBlades) [m] REAL(R8Ki) , DIMENSION(:,:,:), ALLOCATABLE :: BladeRootOrientation !< DCM reference orientation of blade roots (3x3 x NumBlades) [-] + LOGICAL :: UsePrimaryInputFile = .TRUE. !< Read input file instead of passed data [-] + TYPE(FileInfoType) :: PassedPrimaryInputData !< Primary input file as FileInfoType (set by driver/glue code) [-] END TYPE AD_InitInputType ! ======================= ! ========= AD_BladePropsType ======= @@ -101,6 +103,7 @@ MODULE AeroDyn_Types ! ======================= ! ========= AD_InputFile ======= TYPE, PUBLIC :: AD_InputFile + LOGICAL :: Echo !< Echo input file to echo file [-] REAL(DbKi) :: DTAero !< Time interval for aerodynamic calculations {or "default"} [s] INTEGER(IntKi) :: WakeMod !< Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW} [-] INTEGER(IntKi) :: AFAeroMod !< Type of blade airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model} [-] @@ -111,6 +114,7 @@ MODULE AeroDyn_Types LOGICAL :: CavitCheck !< Flag that tells us if we want to check for cavitation [-] LOGICAL :: CompAA !< Compute AeroAcoustic noise [flag] CHARACTER(1024) :: AA_InputFile !< AeroAcoustics input file name [quoted strings] + CHARACTER(1024) , DIMENSION(:), ALLOCATABLE :: ADBlFile !< AD blade file (NumBl filenames) [quoted strings] REAL(ReKi) :: AirDens !< Air density [kg/m^3] REAL(ReKi) :: KinVisc !< Kinematic air viscosity [m^2/s] REAL(ReKi) :: Patm !< Atmospheric pressure [Pa] @@ -338,6 +342,10 @@ SUBROUTINE AD_CopyInitInput( SrcInitInputData, DstInitInputData, CtrlCode, ErrSt END IF DstInitInputData%BladeRootOrientation = SrcInitInputData%BladeRootOrientation ENDIF + DstInitInputData%UsePrimaryInputFile = SrcInitInputData%UsePrimaryInputFile + CALL NWTC_Library_Copyfileinfotype( SrcInitInputData%PassedPrimaryInputData, DstInitInputData%PassedPrimaryInputData, CtrlCode, ErrStat2, ErrMsg2 ) + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg,RoutineName) + IF (ErrStat>=AbortErrLev) RETURN END SUBROUTINE AD_CopyInitInput SUBROUTINE AD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) @@ -355,6 +363,7 @@ SUBROUTINE AD_DestroyInitInput( InitInputData, ErrStat, ErrMsg ) IF (ALLOCATED(InitInputData%BladeRootOrientation)) THEN DEALLOCATE(InitInputData%BladeRootOrientation) ENDIF + CALL NWTC_Library_Destroyfileinfotype( InitInputData%PassedPrimaryInputData, ErrStat, ErrMsg ) END SUBROUTINE AD_DestroyInitInput SUBROUTINE AD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg, SizeOnly ) @@ -409,6 +418,25 @@ SUBROUTINE AD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 2*3 ! BladeRootOrientation upper/lower bounds for each dimension Db_BufSz = Db_BufSz + SIZE(InData%BladeRootOrientation) ! BladeRootOrientation END IF + Int_BufSz = Int_BufSz + 1 ! UsePrimaryInputFile + ! Allocate buffers for subtypes, if any (we'll get sizes from these) + Int_BufSz = Int_BufSz + 3 ! PassedPrimaryInputData: size of buffers for each call to pack subtype + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedPrimaryInputData, ErrStat2, ErrMsg2, .TRUE. ) ! PassedPrimaryInputData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN ! PassedPrimaryInputData + Re_BufSz = Re_BufSz + SIZE( Re_Buf ) + DEALLOCATE(Re_Buf) + END IF + IF(ALLOCATED(Db_Buf)) THEN ! PassedPrimaryInputData + Db_BufSz = Db_BufSz + SIZE( Db_Buf ) + DEALLOCATE(Db_Buf) + END IF + IF(ALLOCATED(Int_Buf)) THEN ! PassedPrimaryInputData + Int_BufSz = Int_BufSz + SIZE( Int_Buf ) + DEALLOCATE(Int_Buf) + END IF IF ( Re_BufSz .GT. 0 ) THEN ALLOCATE( ReKiBuf( Re_BufSz ), STAT=ErrStat2 ) IF (ErrStat2 /= 0) THEN @@ -505,6 +533,36 @@ SUBROUTINE AD_PackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg END DO END DO END IF + IntKiBuf(Int_Xferred) = TRANSFER(InData%UsePrimaryInputFile, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 + CALL NWTC_Library_Packfileinfotype( Re_Buf, Db_Buf, Int_Buf, InData%PassedPrimaryInputData, ErrStat2, ErrMsg2, OnlySize ) ! PassedPrimaryInputData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Re_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Re_Buf) > 0) ReKiBuf( Re_Xferred:Re_Xferred+SIZE(Re_Buf)-1 ) = Re_Buf + Re_Xferred = Re_Xferred + SIZE(Re_Buf) + DEALLOCATE(Re_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Db_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Db_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Db_Buf) > 0) DbKiBuf( Db_Xferred:Db_Xferred+SIZE(Db_Buf)-1 ) = Db_Buf + Db_Xferred = Db_Xferred + SIZE(Db_Buf) + DEALLOCATE(Db_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF + IF(ALLOCATED(Int_Buf)) THEN + IntKiBuf( Int_Xferred ) = SIZE(Int_Buf); Int_Xferred = Int_Xferred + 1 + IF (SIZE(Int_Buf) > 0) IntKiBuf( Int_Xferred:Int_Xferred+SIZE(Int_Buf)-1 ) = Int_Buf + Int_Xferred = Int_Xferred + SIZE(Int_Buf) + DEALLOCATE(Int_Buf) + ELSE + IntKiBuf( Int_Xferred ) = 0; Int_Xferred = Int_Xferred + 1 + ENDIF END SUBROUTINE AD_PackInitInput SUBROUTINE AD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, ErrMsg ) @@ -618,6 +676,48 @@ SUBROUTINE AD_UnPackInitInput( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err END DO END DO END IF + OutData%UsePrimaryInputFile = TRANSFER(IntKiBuf(Int_Xferred), OutData%UsePrimaryInputFile) + Int_Xferred = Int_Xferred + 1 + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Re_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Re_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Re_Buf = ReKiBuf( Re_Xferred:Re_Xferred+Buf_size-1 ) + Re_Xferred = Re_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Db_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Db_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Db_Buf = DbKiBuf( Db_Xferred:Db_Xferred+Buf_size-1 ) + Db_Xferred = Db_Xferred + Buf_size + END IF + Buf_size=IntKiBuf( Int_Xferred ) + Int_Xferred = Int_Xferred + 1 + IF(Buf_size > 0) THEN + ALLOCATE(Int_Buf(Buf_size),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating Int_Buf.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + Int_Buf = IntKiBuf( Int_Xferred:Int_Xferred+Buf_size-1 ) + Int_Xferred = Int_Xferred + Buf_size + END IF + CALL NWTC_Library_Unpackfileinfotype( Re_Buf, Db_Buf, Int_Buf, OutData%PassedPrimaryInputData, ErrStat2, ErrMsg2 ) ! PassedPrimaryInputData + CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) + IF (ErrStat >= AbortErrLev) RETURN + + IF(ALLOCATED(Re_Buf )) DEALLOCATE(Re_Buf ) + IF(ALLOCATED(Db_Buf )) DEALLOCATE(Db_Buf ) + IF(ALLOCATED(Int_Buf)) DEALLOCATE(Int_Buf) END SUBROUTINE AD_UnPackInitInput SUBROUTINE AD_CopyBladePropsType( SrcBladePropsTypeData, DstBladePropsTypeData, CtrlCode, ErrStat, ErrMsg ) @@ -2492,6 +2592,7 @@ SUBROUTINE AD_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrSt ! ErrStat = ErrID_None ErrMsg = "" + DstInputFileData%Echo = SrcInputFileData%Echo DstInputFileData%DTAero = SrcInputFileData%DTAero DstInputFileData%WakeMod = SrcInputFileData%WakeMod DstInputFileData%AFAeroMod = SrcInputFileData%AFAeroMod @@ -2502,6 +2603,18 @@ SUBROUTINE AD_CopyInputFile( SrcInputFileData, DstInputFileData, CtrlCode, ErrSt DstInputFileData%CavitCheck = SrcInputFileData%CavitCheck DstInputFileData%CompAA = SrcInputFileData%CompAA DstInputFileData%AA_InputFile = SrcInputFileData%AA_InputFile +IF (ALLOCATED(SrcInputFileData%ADBlFile)) THEN + i1_l = LBOUND(SrcInputFileData%ADBlFile,1) + i1_u = UBOUND(SrcInputFileData%ADBlFile,1) + IF (.NOT. ALLOCATED(DstInputFileData%ADBlFile)) THEN + ALLOCATE(DstInputFileData%ADBlFile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating DstInputFileData%ADBlFile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + END IF + DstInputFileData%ADBlFile = SrcInputFileData%ADBlFile +ENDIF DstInputFileData%AirDens = SrcInputFileData%AirDens DstInputFileData%KinVisc = SrcInputFileData%KinVisc DstInputFileData%Patm = SrcInputFileData%Patm @@ -2639,6 +2752,9 @@ SUBROUTINE AD_DestroyInputFile( InputFileData, ErrStat, ErrMsg ) ! ErrStat = ErrID_None ErrMsg = "" +IF (ALLOCATED(InputFileData%ADBlFile)) THEN + DEALLOCATE(InputFileData%ADBlFile) +ENDIF IF (ALLOCATED(InputFileData%AFNames)) THEN DEALLOCATE(InputFileData%AFNames) ENDIF @@ -2700,6 +2816,7 @@ SUBROUTINE AD_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Re_BufSz = 0 Db_BufSz = 0 Int_BufSz = 0 + Int_BufSz = Int_BufSz + 1 ! Echo Db_BufSz = Db_BufSz + 1 ! DTAero Int_BufSz = Int_BufSz + 1 ! WakeMod Int_BufSz = Int_BufSz + 1 ! AFAeroMod @@ -2710,6 +2827,11 @@ SUBROUTINE AD_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Int_BufSz = Int_BufSz + 1 ! CavitCheck Int_BufSz = Int_BufSz + 1 ! CompAA Int_BufSz = Int_BufSz + 1*LEN(InData%AA_InputFile) ! AA_InputFile + Int_BufSz = Int_BufSz + 1 ! ADBlFile allocated yes/no + IF ( ALLOCATED(InData%ADBlFile) ) THEN + Int_BufSz = Int_BufSz + 2*1 ! ADBlFile upper/lower bounds for each dimension + Int_BufSz = Int_BufSz + SIZE(InData%ADBlFile)*LEN(InData%ADBlFile) ! ADBlFile + END IF Re_BufSz = Re_BufSz + 1 ! AirDens Re_BufSz = Re_BufSz + 1 ! KinVisc Re_BufSz = Re_BufSz + 1 ! Patm @@ -2829,6 +2951,8 @@ SUBROUTINE AD_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg Db_Xferred = 1 Int_Xferred = 1 + IntKiBuf(Int_Xferred) = TRANSFER(InData%Echo, IntKiBuf(1)) + Int_Xferred = Int_Xferred + 1 DbKiBuf(Db_Xferred) = InData%DTAero Db_Xferred = Db_Xferred + 1 IntKiBuf(Int_Xferred) = InData%WakeMod @@ -2851,6 +2975,23 @@ SUBROUTINE AD_PackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Indata, ErrStat, ErrMsg IntKiBuf(Int_Xferred) = ICHAR(InData%AA_InputFile(I:I), IntKi) Int_Xferred = Int_Xferred + 1 END DO ! I + IF ( .NOT. ALLOCATED(InData%ADBlFile) ) THEN + IntKiBuf( Int_Xferred ) = 0 + Int_Xferred = Int_Xferred + 1 + ELSE + IntKiBuf( Int_Xferred ) = 1 + Int_Xferred = Int_Xferred + 1 + IntKiBuf( Int_Xferred ) = LBOUND(InData%ADBlFile,1) + IntKiBuf( Int_Xferred + 1) = UBOUND(InData%ADBlFile,1) + Int_Xferred = Int_Xferred + 2 + + DO i1 = LBOUND(InData%ADBlFile,1), UBOUND(InData%ADBlFile,1) + DO I = 1, LEN(InData%ADBlFile) + IntKiBuf(Int_Xferred) = ICHAR(InData%ADBlFile(i1)(I:I), IntKi) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF ReKiBuf(Re_Xferred) = InData%AirDens Re_Xferred = Re_Xferred + 1 ReKiBuf(Re_Xferred) = InData%KinVisc @@ -3101,6 +3242,8 @@ SUBROUTINE AD_UnPackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err Re_Xferred = 1 Db_Xferred = 1 Int_Xferred = 1 + OutData%Echo = TRANSFER(IntKiBuf(Int_Xferred), OutData%Echo) + Int_Xferred = Int_Xferred + 1 OutData%DTAero = DbKiBuf(Db_Xferred) Db_Xferred = Db_Xferred + 1 OutData%WakeMod = IntKiBuf(Int_Xferred) @@ -3123,6 +3266,26 @@ SUBROUTINE AD_UnPackInputFile( ReKiBuf, DbKiBuf, IntKiBuf, Outdata, ErrStat, Err OutData%AA_InputFile(I:I) = CHAR(IntKiBuf(Int_Xferred)) Int_Xferred = Int_Xferred + 1 END DO ! I + IF ( IntKiBuf( Int_Xferred ) == 0 ) THEN ! ADBlFile not allocated + Int_Xferred = Int_Xferred + 1 + ELSE + Int_Xferred = Int_Xferred + 1 + i1_l = IntKiBuf( Int_Xferred ) + i1_u = IntKiBuf( Int_Xferred + 1) + Int_Xferred = Int_Xferred + 2 + IF (ALLOCATED(OutData%ADBlFile)) DEALLOCATE(OutData%ADBlFile) + ALLOCATE(OutData%ADBlFile(i1_l:i1_u),STAT=ErrStat2) + IF (ErrStat2 /= 0) THEN + CALL SetErrStat(ErrID_Fatal, 'Error allocating OutData%ADBlFile.', ErrStat, ErrMsg,RoutineName) + RETURN + END IF + DO i1 = LBOUND(OutData%ADBlFile,1), UBOUND(OutData%ADBlFile,1) + DO I = 1, LEN(OutData%ADBlFile) + OutData%ADBlFile(i1)(I:I) = CHAR(IntKiBuf(Int_Xferred)) + Int_Xferred = Int_Xferred + 1 + END DO ! I + END DO + END IF OutData%AirDens = ReKiBuf(Re_Xferred) Re_Xferred = Re_Xferred + 1 OutData%KinVisc = ReKiBuf(Re_Xferred) diff --git a/modules/aerodyn/src/FVW.f90 b/modules/aerodyn/src/FVW.f90 index 3e1cd6912d..4a984e362f 100644 --- a/modules/aerodyn/src/FVW.f90 +++ b/modules/aerodyn/src/FVW.f90 @@ -467,7 +467,7 @@ end subroutine FVW_ToString !> This routine is called at the end of the simulation. subroutine FVW_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) - type(FVW_InputType), intent(inout) :: u(:) !< System inputs + type(FVW_InputType),allocatable, intent(inout) :: u(:) !< System inputs type(FVW_ParameterType), intent(inout) :: p !< Parameters type(FVW_ContinuousStateType), intent(inout) :: x !< Continuous states type(FVW_DiscreteStateType), intent(inout) :: xd !< Discrete states @@ -486,9 +486,11 @@ subroutine FVW_End( u, p, x, xd, z, OtherState, y, m, ErrStat, ErrMsg ) ! Place any last minute operations or calculations here: ! Close files here: ! Destroy the input data: - do i=1,size(u) - call FVW_DestroyInput( u(i), ErrStat, ErrMsg ) - enddo + if (allocated(u)) then + do i=1,size(u) + call FVW_DestroyInput( u(i), ErrStat, ErrMsg ) + enddo + endif ! Destroy the parameter data: call FVW_DestroyParam( p, ErrStat, ErrMsg ) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 394a66ad45..0c7e15d299 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -1697,28 +1697,40 @@ SUBROUTINE ChkParseData ( Words, ExpVarName, FileName, FileLineNum, NameIndx, Er CALL Conv2UC ( ExpUCVarName ) - ! See which word is the variable name. Generate an error if it is neither. - ! If it is the first word, check to make sure the second word is not empty. - - IF ( TRIM( FndUCVarName ) == TRIM( ExpUCVarName ) ) THEN - NameIndx = 1 - IF ( LEN_TRIM( Words(2) ) == 0 ) THEN - CALL ExitThisRoutine ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "'//TRIM( FileName ) & - //'".'//NewLine//' >> The variable "'//TRIM( Words(1) )//'" was not assigned a value on line #' & - //TRIM( Num2LStr( FileLineNum ) )//'.' ) - RETURN - ENDIF + ! Allow for an empty variable name to be passed. This occurs when we have + ! multiple lines of items that may not have variable keys associated. In + ! this case, we will assume the first word has the value and return that. + ! Otherwise, we will check which is the variable keyname. + IF ( LEN_TRIM(ExpVarName) == 0 ) THEN + ! There isn't actually a variable name passed in, but this satisfies the + ! logic for retrieving the value in the calling routine + NameIndx = 2 + ELSE - FndUCVarName = Words(2) - CALL Conv2UC ( FndUCVarName ) + ! See which word is the variable name. Generate an error if it is neither. + ! If it is the first word, check to make sure the second word is not empty. + IF ( TRIM( FndUCVarName ) == TRIM( ExpUCVarName ) ) THEN - NameIndx = 2 + NameIndx = 1 + IF ( LEN_TRIM( Words(2) ) == 0 ) THEN + CALL ExitThisRoutine ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "'//TRIM( FileName ) & + //'".'//NewLine//' >> The variable "'//TRIM( Words(1) )//'" was not assigned a value on line #' & + //TRIM( Num2LStr( FileLineNum ) )//'.' ) + RETURN + ENDIF ELSE - CALL ExitThisRoutine ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "'//TRIM( FileName ) & - //'".'//NewLine//' >> The variable "'//TRIM( ExpVarName )//'" was not found on line #' & - //TRIM( Num2LStr( FileLineNum ) )//'.' ) - RETURN + FndUCVarName = Words(2) + CALL Conv2UC ( FndUCVarName ) + IF ( TRIM( FndUCVarName ) == TRIM( ExpUCVarName ) ) THEN + NameIndx = 2 + ELSE + CALL ExitThisRoutine ( ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data from "'//TRIM( FileName ) & + //'".'//NewLine//' >> The variable "'//TRIM( ExpVarName )//'" was not found on line #' & + //TRIM( Num2LStr( FileLineNum ) )//'.' ) + RETURN + ENDIF ENDIF + ENDIF @@ -3454,7 +3466,7 @@ SUBROUTINE ParseChVar ( FileInfo, LineNum, ExpVarName, Var, ErrStat, ErrMsg, UnE CALL GetWords ( FileInfo%Lines(LineNum), Words, 2 ) ! Read the first two words in Line. - IF ( Words(2) == '' ) THEN + IF ( Words(2) == '' .and. (LEN_TRIM(ExpVarName) > 0) ) THEN CALL SetErrStat ( ErrID_Fatal, 'A fatal error occurred when parsing data from "' & //TRIM( FileInfo%FileList(FileInfo%FileIndx(LineNum)) )//'".'//NewLine// & ' >> The variable "'//TRIM( ExpVarName )//'" was not assigned valid string value on line #' & diff --git a/reg_tests/r-test b/reg_tests/r-test index 851aa03a0f..e245f1b18f 160000 --- a/reg_tests/r-test +++ b/reg_tests/r-test @@ -1 +1 @@ -Subproject commit 851aa03a0f141bebfd35b275726d1421081f8494 +Subproject commit e245f1b18fafbaac421fdd7c103861cd4ff1df8f