From d6a10ea820615af739c4190ebdd9f71ab8917684 Mon Sep 17 00:00:00 2001 From: Emmanuel Branlard Date: Thu, 30 Nov 2023 14:14:09 -0700 Subject: [PATCH] AD: Starting new input file format --- modules/aerodyn/src/AeroDyn_Driver.f90 | 12 +-- modules/aerodyn/src/AeroDyn_IO.f90 | 113 +++++++++++++++++++++-- modules/aerodyn/src/AeroDyn_Registry.txt | 15 ++- modules/aerodyn/src/AeroDyn_Types.f90 | 35 ++++++- modules/nwtc-library/src/NWTC_IO.f90 | 18 +++- 5 files changed, 166 insertions(+), 27 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn_Driver.f90 b/modules/aerodyn/src/AeroDyn_Driver.f90 index fdc343249c..076f0a4bcc 100644 --- a/modules/aerodyn/src/AeroDyn_Driver.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver.f90 @@ -52,24 +52,24 @@ program AeroDyn_Driver ! Init of time estimator t_global=0.0_DbKi t_final=dat%dvr%numSteps*dat%dvr%dt - if (dat%dvr%analysisType/=idAnalysisCombi) then + !if (dat%dvr%analysisType/=idAnalysisCombi) then call SimStatus_FirstTime( TiLstPrn, PrevClockTime, SimStrtTime, UsrTime2, t_global, t_final ) - endif + !endif ! One time loop do nt = 1, dat%dvr%numSteps call Dvr_TimeStep(nt, dat%dvr, dat%ADI, dat%FED, dat%errStat, dat%errMsg); call CheckError() ! Time update to screen t_global=nt*dat%dvr%dt - if (dat%dvr%analysisType/=idAnalysisCombi) then + !if (dat%dvr%analysisType/=idAnalysisCombi) then if (mod( nt + 1, 10 )==0) call SimStatus(TiLstPrn, PrevClockTime, t_global, t_final) - endif + !endif end do !nt=1,numSteps - if (dat%dvr%analysisType/=idAnalysisCombi) then + !if (dat%dvr%analysisType/=idAnalysisCombi) then ! display runtime to screen call RunTimes(StrtTime, UsrTime1, SimStrtTime, UsrTime2, t_global) - endif + !endif call Dvr_EndCase(dat%dvr, dat%ADI, dat%initialized, dat%errStat, dat%errMsg); call CheckError() diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index f0224d871d..3c9e46e5ba 100644 --- a/modules/aerodyn/src/AeroDyn_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_IO.f90 @@ -659,6 +659,7 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade integer(IntKi) :: CurLine !< current entry in FileInfo_In%Lines array real(ReKi) :: TmpRe5(5) !< temporary 8 number array for reading values in character(1024) :: sDummy !< temporary string + logical :: frozenWakeProvided, AFAeroModProvided, isLegalComment !< Temporary for legacy purposes character(*), parameter :: RoutineName = 'ParsePrimaryFileInfo' @@ -703,12 +704,11 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade ! 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] + ! WakeMod - Type of wake/induction model (switch) {0=none, 1=BEMT, 2=TBD, 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 + AFAeroModProvided = legacyInputPresent('AFAeroMod', CurLine, ErrStat2, ErrMsg2, 'UAMod=0 (AFAeroMod=1), UAMod>1 (AFAeroMod=2)') ! TwrPotent - Type of 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 @@ -718,9 +718,9 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade ! 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] + ! 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 + frozenWakeProvided = legacyInputPresent('FrozenWake', Curline, ErrStat2, ErrMsg2, 'DBEMTMod=-1 (FrozenWake=True), DBEMTMod>-1 (FrozenWake=False)') ! 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 @@ -788,11 +788,21 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade ! MaxIter - Maximum number of iteration steps (-) [unused when WakeMod=0] call ParseVar( FileInfo_In, CurLine, "MaxIter", InputFileData%MaxIter, ErrStat2, ErrMsg2, UnEc ) if (Failed()) return + ! --- Shear + call ParseCom (FileInfo_in, CurLine, sDummy, errStat2, errMsg2, UnEc, isLegalComment); + if (newInputAbsent('Comment line `--- Shear`', CurLine, errStat2, errMsg2)) then + ! pass + else + call ParseVar( FileInfo_In, CurLine, "SectAvg" , InputFileData%SectAvg, ErrStat2, ErrMsg2, UnEc ); if (Failed()) return + call ParseVar( FileInfo_In, CurLine, "SectAvgWeighting", InputFileData%SA_Weighting, ErrStat2, ErrMsg2, UnEc ); if (Failed()) return + call ParseVar( FileInfo_In, CurLine, "SectAvgNPoints" , InputFileData%SA_nPerSec, ErrStat2, ErrMsg2, UnEc ); if (Failed()) return + endif + !====== 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 ParseCom (FileInfo_in, CurLine, sDummy, errStat2, errMsg2, UnEc, isLegalComment); if (Failed()) return + + ! 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] @@ -1021,6 +1031,45 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade if (InputFileData%BldNd_BladesOut <= 0) InputFileData%BldNd_NumOuts = 0 + !====== Legacy logic to match old and new input files ================================================ + ! NOTE: remove me in future release + if (frozenWakeProvided) then + if (InputFileData%FrozenWake) then + call WrScr(' FrozenWake=True -> Setting DBEMT_Mod=-1') + ! InputFileData%DBEMT_Mod =-1 + else + call WrScr(' FrozenWake=False -> Not changing DBEMT_Mod') + endif + endif + if (AFAeroModProvided) then + if (InputFileData%AFAeroMod==1) then + call WrScr(' AFAeroMod=1 -> Setting UAMod=0') + ! InputFileData%UAMod=0 + else if (InputFileData%AFAeroMod==1) then + call WrScr(' AFAeroMod=2 -> Not changing DBEMT_Mod') + else + call LegacyAbort('AFAeroMod should be 1 or 2'); return + endif + endif + + !====== Summary of new AeroDyn options =============================================================== + ! NOTE: remove me in future release + call WrScr('-------------- New AeroDyn inputs (with new meaning):') + write (*,'(A20,I0)') 'WakeMod: ' , InputFileData%WakeMod + write (*,'(A20,L0)') 'SectAvg: ' , InputFileData%SectAvg + write (*,'(A20,I0)') 'SectAvgWeighting: ', InputFileData%SA_Weighting + write (*,'(A20,I0)') 'SectAvgNPoints: ', InputFileData%SA_nPerSec + write (*,'(A20,I0)') 'DBEMT_Mod:' , InputFileData%DBEMT_Mod + write (*,'(A20,I0)') 'SkewMod: ' , InputFileData%SkewMod + write (*,'(A20,L0)') 'SkewMomCorr:' , InputFileData%SkewMomCorr + write (*,'(A20,I0)') 'SkewRedistrMod:' , InputFileData%SkewRedistrMod + write (*,'(A20,L0)') 'AoA34: ' , InputFileData%AoA34 + write (*,'(A20,I0)') 'UAMod: ' , InputFileData%UAMod + call WrScr('-------------- Old AeroDyn inputs:') + write (*,'(A20,I0)') 'AFAeroMod:', InputFileData%AFAeroMod + write (*,'(A20,L0)') 'FrozenWake:', InputFileData%FrozenWake + call WrScr('------------------------------------------------------') + !====== Advanced Options ============================================================================= if ((CurLine) >= size(FileInfo_In%Lines)) RETURN @@ -1047,6 +1096,8 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InitInp, InputFile, RootName, NumBlade endif enddo + + RETURN CONTAINS !------------------------------------------------------------------------------------------------- @@ -1074,6 +1125,48 @@ subroutine LegacyWarning(Message) call WrScr('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!') end subroutine LegacyWarning !------------------------------------------------------------------------------------------------- + subroutine LegacyAbort(Message) + character(len=*), intent(in) :: Message + call SetErrStat( ErrID_Fatal, Message, ErrStat, ErrMsg, 'ParsePrimaryFileInfo' ) + end subroutine LegacyAbort + !------------------------------------------------------------------------------------------------- + logical function legacyInputPresent(varName, iLine, errStat, errMsg, varNameSubs) + character(len=*), intent(in ) :: varName !< Variable being read + integer(IntKi), intent(in ) :: iLine !< Line number + integer(IntKi), intent(inout) :: errStat !< Error status + character(ErrMsgLen), intent(inout) :: errMsg !< Error message + character(len=*), optional, intent(in ) :: varNameSubs !< Substituted variable + legacyInputPresent = errStat == ErrID_None + if (legacyInputPresent) then + if (present(varNameSubs)) then + call LegacyWarning('Input '//trim(varName)//' has now been removed.'//NewLine//'Replaced by: '//trim(varNameSubs)//'.') + else + call LegacyWarning('Input '//trim(varName)//' has now been removed.') + endif + else + ! We are actually happy, this input should indeed not be present. + endif + ! We erase the error no matter what + errStat = ErrID_None + errMsg = '' + end function legacyInputPresent + !------------------------------------------------------------------------------------------------- + logical function newInputAbsent(varName, iLine, errStat, errMsg, varNameSubs) + character(len=*), intent(in ) :: varName !< Variable being read + integer(IntKi), intent(in ) :: iLine !< Line number + integer(IntKi), intent(inout) :: errStat !< Error status + character(ErrMsgLen), intent(inout) :: errMsg !< Error message + character(len=*), optional, intent(in ) :: varNameSubs !< Substituted variable + newInputAbsent = errStat == ErrID_Fatal + if (newInputAbsent) then + call LegacyWarning('Input '//trim(varName)//' should be present on line '//trim(num2lstr(iLine))//'.') + else + ! We are happy + endif + ! We erase the error + errStat = ErrID_None + errMsg = '' + end function newInputAbsent END SUBROUTINE ParsePrimaryFileInfo !---------------------------------------------------------------------------------------------------------------------------------- SUBROUTINE ReadBladeInputs ( ADBlFile, BladeKInputFileData, AeroProjMod, UnEc, ErrStat, ErrMsg ) diff --git a/modules/aerodyn/src/AeroDyn_Registry.txt b/modules/aerodyn/src/AeroDyn_Registry.txt index 461a65c56b..c209d24a5d 100644 --- a/modules/aerodyn/src/AeroDyn_Registry.txt +++ b/modules/aerodyn/src/AeroDyn_Registry.txt @@ -166,6 +166,7 @@ typedef ^ RotInputFile TFinInputFileType TFin - - - "Input file 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 BEMMod - - - "Type of BEM model {1=legacy NoSweepPitchTwist, 2=polar grid}" - typedef ^ AD_InputFile IntKi AFAeroMod - - - "Type of blade airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model}" - typedef ^ AD_InputFile IntKi TwrPotent - - - "Type of tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction}" - typedef ^ AD_InputFile IntKi TwrShadow - - - "Type of tower influence on wind based on downstream tower shadow {0=none, 1=Powles model, 2=Eames model}" - @@ -181,7 +182,9 @@ typedef ^ AD_InputFile ReKi KinVisc - - - "Kinematic air viscosity" m^2/s typedef ^ AD_InputFile ReKi Patm - - - "Atmospheric pressure" Pa typedef ^ AD_InputFile ReKi Pvap - - - "Vapour pressure" Pa typedef ^ AD_InputFile ReKi SpdSound - - - "Speed of sound" m/s -typedef ^ AD_InputFile IntKi SkewMod - - - "Type of skewed-wake correction model {0=orthogonal, 1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0]" - +typedef ^ AD_InputFile IntKi SkewMod - - - "Select skew model {0=No skew model at all, -1=Throw away non-normal component for linearization, 1=Glauert skew model}" - +typedef ^ AD_InputFile Logical SkewMomCorr - - - "Turn the skew momentum correction on or off [used only when SkewMod=1]" - +typedef ^ AD_InputFile IntKi SkewRedistrMod - - - "Type of skewed-wake correction model (switch) {0=no redistribution, 1=Glauert/Pitt/Peters, 2=Vortex Cylinder} [unsed only when SkewMod=1]" - typedef ^ AD_InputFile ReKi SkewModFactor - - - "Constant used in Pitt/Peters skewed wake model (default is 15*pi/32)" - typedef ^ AD_InputFile LOGICAL TipLoss - - - "Use the Prandtl tip-loss model? [unused when WakeMod=0]" flag typedef ^ AD_InputFile LOGICAL HubLoss - - - "Use the Prandtl hub-loss model? [unused when WakeMod=0]" flag @@ -190,11 +193,13 @@ typedef ^ AD_InputFile LOGICAL AIDrag - - - "Include the drag term in the axial- typedef ^ AD_InputFile LOGICAL TIDrag - - - "Include the drag term in the tangential-induction calculation? [unused when WakeMod=0 or TanInd=FALSE]" flag typedef ^ AD_InputFile ReKi IndToler - - - "Convergence tolerance for BEM induction factors [unused when WakeMod=0]" - typedef ^ AD_InputFile ReKi MaxIter - - - "Maximum number of iteration steps [unused when WakeMod=0]" - -typedef ^ AD_InputFile Logical SectAvg - - False "Use Sector average for BEM inflow velocity calculation" - +typedef ^ AD_InputFile Logical SectAvg - - False "Use Sector average for BEM inflow velocity calculation (flag)" - +typedef ^ ^ IntKi SA_Weighting - - 1 "Sector Average - Weighting function for sector average {1=Uniform, 2=Impulse, } within a 360/nB sector centered on the blade (switch) [used only when SectAvg=True]" - typedef ^ ^ ReKi SA_PsiBwd - -60 - "Sector Average - Backard Azimuth (<0)" deg typedef ^ ^ ReKi SA_PsiFwd - 60 - "Sector Average - Forward Azimuth (>0)" deg -typedef ^ ^ IntKi SA_nPerSec - 11 - "Sector Average - Number of points per sectors (>1)" - -typedef ^ ^ IntKi 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]" - +typedef ^ ^ IntKi SA_nPerSec - 11 - "Sector average - Number of points per sectors (-) [used only when SectAvg=True]" - +typedef ^ ^ IntKi AoA34 - - - "Sample the angle of attack (AoA) at the 3/4 chord or the AC point {default=True} [always used]" - +typedef ^ ^ IntKi UAMod - - - "Unsteady Aero Model Switch (switch) {0=Quasi-steady (no UA), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)}" - typedef ^ AD_InputFile LOGICAL 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 AFAeroMod=2]" flag typedef ^ AD_InputFile ReKi InCol_Alfa - - - "The column in the airfoil tables that contains the angle of attack" - typedef ^ AD_InputFile ReKi InCol_Cl - - - "The column in the airfoil tables that contains the lift coefficient" - @@ -215,7 +220,7 @@ typedef ^ AD_InputFile IntKi TwOutNd {9} - - "Tower nodes whose values will be o typedef ^ AD_InputFile IntKi NumOuts - - - "Number of parameters in the output list (number of outputs requested)" - typedef ^ AD_InputFile CHARACTER(ChanLen) OutList {:} - - "List of user-requested output channels" - typedef ^ AD_InputFile ReKi tau1_const - - - "time constant for DBEMT [used only when WakeMod=2 and DBEMT_Mod/=2]" s -typedef ^ AD_InputFile IntKi DBEMT_Mod - - - "Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1}" - +typedef ^ AD_InputFile IntKi DBEMT_Mod - - - "Type of dynamic BEMT (DBEMT) model {0=No Dynamic Wake, -1=Frozen Wake for linearization, 1=constant tau1, 2=time-dependent tau1, 3=constant tau1 with continuous formulation} (-) [used only when WakeMod=1]" - typedef ^ AD_InputFile IntKi BldNd_NumOuts - - - "Number of requested output channels per blade node (AD_AllBldNdOuts)" - typedef ^ AD_InputFile CHARACTER(ChanLen) BldNd_OutList {:} - - "List of user-requested output channels (AD_AllBldNdOuts)" - #typedef ^ AD_InputFile IntKi BldNd_BlOutNd {:} - - "The blade nodes to actually output (AD_AllBldNdOuts)" - diff --git a/modules/aerodyn/src/AeroDyn_Types.f90 b/modules/aerodyn/src/AeroDyn_Types.f90 index 3a6c7c1412..f27a4c8853 100644 --- a/modules/aerodyn/src/AeroDyn_Types.f90 +++ b/modules/aerodyn/src/AeroDyn_Types.f90 @@ -194,6 +194,7 @@ MODULE AeroDyn_Types LOGICAL :: Echo = .false. !< Echo input file to echo file [-] REAL(DbKi) :: DTAero = 0.0_R8Ki !< Time interval for aerodynamic calculations {or "default"} [s] INTEGER(IntKi) :: WakeMod = 0_IntKi !< Type of wake/induction model {0=none, 1=BEMT, 2=DBEMT, 3=FVW} [-] + INTEGER(IntKi) :: BEMMod = 0_IntKi !< Type of BEM model {1=legacy NoSweepPitchTwist, 2=polar grid} [-] INTEGER(IntKi) :: AFAeroMod = 0_IntKi !< Type of blade airfoil aerodynamics model {1=steady model, 2=Beddoes-Leishman unsteady model} [-] INTEGER(IntKi) :: TwrPotent = 0_IntKi !< Type of tower influence on wind based on potential flow around the tower {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} [-] INTEGER(IntKi) :: TwrShadow = 0_IntKi !< Type of tower influence on wind based on downstream tower shadow {0=none, 1=Powles model, 2=Eames model} [-] @@ -209,7 +210,9 @@ MODULE AeroDyn_Types REAL(ReKi) :: Patm = 0.0_ReKi !< Atmospheric pressure [Pa] REAL(ReKi) :: Pvap = 0.0_ReKi !< Vapour pressure [Pa] REAL(ReKi) :: SpdSound = 0.0_ReKi !< Speed of sound [m/s] - INTEGER(IntKi) :: SkewMod = 0_IntKi !< Type of skewed-wake correction model {0=orthogonal, 1=uncoupled, 2=Pitt/Peters, 3=coupled} [unused when WakeMod=0] [-] + INTEGER(IntKi) :: SkewMod = 0_IntKi !< Select skew model {0=No skew model at all, -1=Throw away non-normal component for linearization, 1=Glauert skew model} [-] + LOGICAL :: SkewMomCorr = .false. !< Turn the skew momentum correction on or off [used only when SkewMod=1] [-] + INTEGER(IntKi) :: SkewRedistrMod = 0_IntKi !< Type of skewed-wake correction model (switch) {0=no redistribution, 1=Glauert/Pitt/Peters, 2=Vortex Cylinder} [unsed only when SkewMod=1] [-] REAL(ReKi) :: SkewModFactor = 0.0_ReKi !< Constant used in Pitt/Peters skewed wake model (default is 15*pi/32) [-] LOGICAL :: TipLoss = .false. !< Use the Prandtl tip-loss model? [unused when WakeMod=0] [flag] LOGICAL :: HubLoss = .false. !< Use the Prandtl hub-loss model? [unused when WakeMod=0] [flag] @@ -218,11 +221,13 @@ MODULE AeroDyn_Types LOGICAL :: TIDrag = .false. !< Include the drag term in the tangential-induction calculation? [unused when WakeMod=0 or TanInd=FALSE] [flag] REAL(ReKi) :: IndToler = 0.0_ReKi !< Convergence tolerance for BEM induction factors [unused when WakeMod=0] [-] REAL(ReKi) :: MaxIter = 0.0_ReKi !< Maximum number of iteration steps [unused when WakeMod=0] [-] - LOGICAL :: SectAvg = .false. !< Use Sector average for BEM inflow velocity calculation [-] + LOGICAL :: SectAvg = .false. !< Use Sector average for BEM inflow velocity calculation (flag) [-] + INTEGER(IntKi) :: SA_Weighting = 0_IntKi !< Sector Average - Weighting function for sector average {1=Uniform, 2=Impulse, } within a 360/nB sector centered on the blade (switch) [used only when SectAvg=True] [-] REAL(ReKi) :: SA_PsiBwd = -60 !< Sector Average - Backard Azimuth (<0) [deg] REAL(ReKi) :: SA_PsiFwd = 60 !< Sector Average - Forward Azimuth (>0) [deg] - INTEGER(IntKi) :: SA_nPerSec = 11 !< Sector Average - Number of points per sectors (>1) [-] - INTEGER(IntKi) :: UAMod = 0_IntKi !< 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] [-] + INTEGER(IntKi) :: SA_nPerSec = 11 !< Sector average - Number of points per sectors (-) [used only when SectAvg=True] [-] + INTEGER(IntKi) :: AoA34 = 0_IntKi !< Sample the angle of attack (AoA) at the 3/4 chord or the AC point {default=True} [always used] [-] + INTEGER(IntKi) :: UAMod = 0_IntKi !< Unsteady Aero Model Switch (switch) {0=Quasi-steady (no UA), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minnema/Pierce variant (changes in Cc and Cm)} [-] LOGICAL :: FLookup = .false. !< 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 AFAeroMod=2] [flag] REAL(ReKi) :: InCol_Alfa = 0.0_ReKi !< The column in the airfoil tables that contains the angle of attack [-] REAL(ReKi) :: InCol_Cl = 0.0_ReKi !< The column in the airfoil tables that contains the lift coefficient [-] @@ -242,7 +247,7 @@ MODULE AeroDyn_Types INTEGER(IntKi) :: NumOuts = 0_IntKi !< Number of parameters in the output list (number of outputs requested) [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: OutList !< List of user-requested output channels [-] REAL(ReKi) :: tau1_const = 0.0_ReKi !< time constant for DBEMT [used only when WakeMod=2 and DBEMT_Mod/=2] [s] - INTEGER(IntKi) :: DBEMT_Mod = 0_IntKi !< Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} [-] + INTEGER(IntKi) :: DBEMT_Mod = 0_IntKi !< Type of dynamic BEMT (DBEMT) model {0=No Dynamic Wake, -1=Frozen Wake for linearization, 1=constant tau1, 2=time-dependent tau1, 3=constant tau1 with continuous formulation} (-) [used only when WakeMod=1] [-] INTEGER(IntKi) :: BldNd_NumOuts = 0_IntKi !< Number of requested output channels per blade node (AD_AllBldNdOuts) [-] CHARACTER(ChanLen) , DIMENSION(:), ALLOCATABLE :: BldNd_OutList !< List of user-requested output channels (AD_AllBldNdOuts) [-] CHARACTER(1024) :: BldNd_BlOutNd_Str !< String to parse for the blade nodes to actually output (AD_AllBldNdOuts) [-] @@ -2578,6 +2583,7 @@ subroutine AD_CopyInputFile(SrcInputFileData, DstInputFileData, CtrlCode, ErrSta DstInputFileData%Echo = SrcInputFileData%Echo DstInputFileData%DTAero = SrcInputFileData%DTAero DstInputFileData%WakeMod = SrcInputFileData%WakeMod + DstInputFileData%BEMMod = SrcInputFileData%BEMMod DstInputFileData%AFAeroMod = SrcInputFileData%AFAeroMod DstInputFileData%TwrPotent = SrcInputFileData%TwrPotent DstInputFileData%TwrShadow = SrcInputFileData%TwrShadow @@ -2605,6 +2611,8 @@ subroutine AD_CopyInputFile(SrcInputFileData, DstInputFileData, CtrlCode, ErrSta DstInputFileData%Pvap = SrcInputFileData%Pvap DstInputFileData%SpdSound = SrcInputFileData%SpdSound DstInputFileData%SkewMod = SrcInputFileData%SkewMod + DstInputFileData%SkewMomCorr = SrcInputFileData%SkewMomCorr + DstInputFileData%SkewRedistrMod = SrcInputFileData%SkewRedistrMod DstInputFileData%SkewModFactor = SrcInputFileData%SkewModFactor DstInputFileData%TipLoss = SrcInputFileData%TipLoss DstInputFileData%HubLoss = SrcInputFileData%HubLoss @@ -2614,9 +2622,11 @@ subroutine AD_CopyInputFile(SrcInputFileData, DstInputFileData, CtrlCode, ErrSta DstInputFileData%IndToler = SrcInputFileData%IndToler DstInputFileData%MaxIter = SrcInputFileData%MaxIter DstInputFileData%SectAvg = SrcInputFileData%SectAvg + DstInputFileData%SA_Weighting = SrcInputFileData%SA_Weighting DstInputFileData%SA_PsiBwd = SrcInputFileData%SA_PsiBwd DstInputFileData%SA_PsiFwd = SrcInputFileData%SA_PsiFwd DstInputFileData%SA_nPerSec = SrcInputFileData%SA_nPerSec + DstInputFileData%AoA34 = SrcInputFileData%AoA34 DstInputFileData%UAMod = SrcInputFileData%UAMod DstInputFileData%FLookup = SrcInputFileData%FLookup DstInputFileData%InCol_Alfa = SrcInputFileData%InCol_Alfa @@ -2739,6 +2749,7 @@ subroutine AD_PackInputFile(Buf, Indata) call RegPack(Buf, InData%Echo) call RegPack(Buf, InData%DTAero) call RegPack(Buf, InData%WakeMod) + call RegPack(Buf, InData%BEMMod) call RegPack(Buf, InData%AFAeroMod) call RegPack(Buf, InData%TwrPotent) call RegPack(Buf, InData%TwrShadow) @@ -2759,6 +2770,8 @@ subroutine AD_PackInputFile(Buf, Indata) call RegPack(Buf, InData%Pvap) call RegPack(Buf, InData%SpdSound) call RegPack(Buf, InData%SkewMod) + call RegPack(Buf, InData%SkewMomCorr) + call RegPack(Buf, InData%SkewRedistrMod) call RegPack(Buf, InData%SkewModFactor) call RegPack(Buf, InData%TipLoss) call RegPack(Buf, InData%HubLoss) @@ -2768,9 +2781,11 @@ subroutine AD_PackInputFile(Buf, Indata) call RegPack(Buf, InData%IndToler) call RegPack(Buf, InData%MaxIter) call RegPack(Buf, InData%SectAvg) + call RegPack(Buf, InData%SA_Weighting) call RegPack(Buf, InData%SA_PsiBwd) call RegPack(Buf, InData%SA_PsiFwd) call RegPack(Buf, InData%SA_nPerSec) + call RegPack(Buf, InData%AoA34) call RegPack(Buf, InData%UAMod) call RegPack(Buf, InData%FLookup) call RegPack(Buf, InData%InCol_Alfa) @@ -2837,6 +2852,8 @@ subroutine AD_UnPackInputFile(Buf, OutData) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%WakeMod) if (RegCheckErr(Buf, RoutineName)) return + call RegUnpack(Buf, OutData%BEMMod) + if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%AFAeroMod) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%TwrPotent) @@ -2881,6 +2898,10 @@ subroutine AD_UnPackInputFile(Buf, OutData) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%SkewMod) if (RegCheckErr(Buf, RoutineName)) return + call RegUnpack(Buf, OutData%SkewMomCorr) + if (RegCheckErr(Buf, RoutineName)) return + call RegUnpack(Buf, OutData%SkewRedistrMod) + if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%SkewModFactor) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%TipLoss) @@ -2899,12 +2920,16 @@ subroutine AD_UnPackInputFile(Buf, OutData) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%SectAvg) if (RegCheckErr(Buf, RoutineName)) return + call RegUnpack(Buf, OutData%SA_Weighting) + if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%SA_PsiBwd) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%SA_PsiFwd) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%SA_nPerSec) if (RegCheckErr(Buf, RoutineName)) return + call RegUnpack(Buf, OutData%AoA34) + if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%UAMod) if (RegCheckErr(Buf, RoutineName)) return call RegUnpack(Buf, OutData%FLookup) diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 25d317c68d..945d6fc40a 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -2925,7 +2925,7 @@ SUBROUTINE ParseChAry ( FileInfo, LineNum, AryName, Ary, AryLen, ErrStat, ErrMsg END SUBROUTINE ParseChAry !======================================================================= !> This subroutine parses a comment line - SUBROUTINE ParseCom ( FileInfo, LineNum, Var, ErrStat, ErrMsg, UnEc ) + SUBROUTINE ParseCom ( FileInfo, LineNum, Var, ErrStat, ErrMsg, UnEc, IsLegalComment ) ! Arguments declarations. INTEGER(IntKi), INTENT(OUT) :: ErrStat !< The error status. @@ -2934,6 +2934,7 @@ SUBROUTINE ParseCom ( FileInfo, LineNum, Var, ErrStat, ErrMsg, UnEc ) CHARACTER(*), INTENT(OUT) :: Var !< The variable to receive the comment CHARACTER(*), INTENT(OUT) :: ErrMsg !< The error message, if ErrStat /= 0. TYPE (FileInfoType), INTENT(IN) :: FileInfo !< The derived type for holding the file information. + LOGICAL, OPTIONAL, INTENT(INOUT) :: IsLegalComment !< True if the comment is a "legal" comment line starting with '---' or '==='. NOTE: We have too many options, we need to be more strict!!!! CHARACTER(*), PARAMETER :: RoutineName = 'ParseCom' ErrStat=ErrID_None @@ -2961,6 +2962,21 @@ SUBROUTINE ParseCom ( FileInfo, LineNum, Var, ErrStat, ErrMsg, UnEc ) END IF LineNum = LineNum + 1 + IF (PRESENT(IsLegalComment) ) then + if (len(Var)<=3) then + IsLegalComment=.False. + else + ! Here, we are talking about comments in the input file that are "expected to be there" + IsLegalComment = (Var(1:3)=='---') .or. (Var(1:3)=='===') + endif + if (.not.IsLegalComment) then + call SetErrStat(ErrID_Fatal, NewLine//' >> A fatal error occurred when parsing data.'//NewLine// & + ' >> The comment line did not start with `---` or `===`. LineNum='// & + trim(num2lstr(LineNum))//'; NumLines='//trim(num2lstr(size(FileInfo%Lines))) & + , ErrStat, ErrMsg, RoutineName ) + endif + END IF + END SUBROUTINE ParseCom !=======================================================================