From 5e22baa5cf7b53b333bed49f0c7fa47764680ab2 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Wed, 13 Oct 2021 11:22:31 -0600 Subject: [PATCH 1/9] Update comments in example AD airfoil files --- .../aerodyn/examples/ad_airfoil_example.dat | 81 ++++++++++--------- .../aerodyn/examples/ad_polar_example.dat | 77 +++++++++--------- 2 files changed, 83 insertions(+), 75 deletions(-) diff --git a/docs/source/user/aerodyn/examples/ad_airfoil_example.dat b/docs/source/user/aerodyn/examples/ad_airfoil_example.dat index 6a61476439..5a6159b439 100644 --- a/docs/source/user/aerodyn/examples/ad_airfoil_example.dat +++ b/docs/source/user/aerodyn/examples/ad_airfoil_example.dat @@ -4,6 +4,7 @@ ! ------------------------------------------------------------------------------ "DEFAULT" InterpOrd ! Interpolation order to use for quasi-steady table lookup {1=linear; 3=cubic spline; "default"} [default=1] ! ------------------------------------------------------------------------------ +! 0.30 RelThickness ! The non-dimensional thickness of the airfoil (thickness/chord) [only used if UAMod=7] [default=0.2] (-) 1 NonDimArea ! The non-dimensional area of the airfoil (area/chord^2) (set to 1.0 if unsure or unneeded) 67 NumCoords ! The number of coordinates in the airfoil shape file (including an extra coordinate for airfoil reference). ! ......... x-y coordinates are next if NumCoords > 0 ............. @@ -79,51 +80,53 @@ 0.996141 0.000290 1.000000 0.000000 ! ------------------------------------------------------------------------------ -"unused" BL_file ! The file name including the boundary layer characteristics of the profile. Ignored if the aeroacoustic module is not called. +"unused" BL_file ! The file name including the boundary layer characteristics of the profile. Unused if the aeroacoustic module is not called. 1 NumTabs ! Number of airfoil tables in this file. ! ------------------------------------------------------------------------------ ! data for table 1 ! ------------------------------------------------------------------------------ 0.75 Re ! Reynolds number in millions 0 UserProp ! User property (control) setting -true InclUAdata ! Is unsteady aerodynamics data included in this table? If TRUE, then include UA coefficients below this line -!........................................ - -0.38 alpha0 ! 0-lift angle of attack, depends on airfoil. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data - 15.3 alpha1 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA>alpha0. (deg) ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data - -15.3 alpha2 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - -11.324 S2 ! Constant in the f curve best-fit for AOA> alpha1; by definition it depends on the airfoil. [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - 18.269 S3 ! Constant in the f curve best-fit for alpha2<=AOA< alpha0; by definition it depends on the airfoil. [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - -11.324 S4 ! Constant in the f curve best-fit for AOA< alpha2; by definition it depends on the airfoil. [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - 1.9408 Cn1 ! Critical value of C0n at leading edge separation. It should be extracted from airfoil data at a given Mach and Reynolds number. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data - -0.8 Cn2 ! As Cn1 for negative AOAs. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data -"Default" St_sh ! Strouhal's shedding frequency constant. [default = 0.19; unused when UAMod = 4 or 5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value - 0.0016 Cd0 ! 2D drag coefficient value at 0-lift. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data - -0.0328 Cm0 ! 2D pitching moment coefficient about 1/4-chord location, at 0-lift, positive if nose up. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data - 0 k0 ! Constant in the \hat(x)_cp curve best-fit; = (\hat(x)_AC-0.25). [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - 0 k1 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - 0 k2 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - 0 k3 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 - 0 k1_hat ! Constant in the expression of Cc due to leading edge vortex effects. [ignored if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 -"Default" x_cp_bar ! Constant in the expression of \hat(x)_cp^v. [ignored if UAMod<>1, default = 0.2] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value -"DEFAULT" UACutout ! Angle of attack above which unsteady aerodynamics are disabled (deg). [Specifying the string "Default" sets UACutout to 45 degrees] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value -"DEFAULT" UACutout_delta ! Delta angle of attack below UACutout where unsteady aerodynamics begin to turn off (blend with steady solution) (deg) [Specifying the string "Default" sets UACutout_delta to 5 degrees] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value -"DEFAULT" filtCutOff ! Reduced frequency cut-off for low-pass filtering the AoA input to UA, as well as the 1st and 2nd derivatives (-) [default = 0.5; unused when UAMod = 4 or 5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value -!........................................ +True InclUAdata ! Is unsteady aerodynamics data included in this table? If TRUE, then include UA coefficients below this line. Any missing coefficients will be calculated internally. +!........................................ > start of UA coefficients included only when InclUAdata=TRUE +!Note: If any of the following lines are missing, they will be calculated internally (they must be read in the following order, though) + -0.38 alpha0 ! 0-lift angle of attack, depends on airfoil. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + 15.3 alpha1 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA>alpha0. (deg) [unused when UAMod=4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + -15.3 alpha2 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + -11.324 S2 ! Constant in the f curve best-fit for AOA> alpha1; by definition it depends on the airfoil. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 18.269 S3 ! Constant in the f curve best-fit for alpha2<=AOA< alpha0; by definition it depends on the airfoil. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + -11.324 S4 ! Constant in the f curve best-fit for AOA< alpha2; by definition it depends on the airfoil. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 1.9408 Cn1 ! Critical value of C0n at leading edge separation. It should be extracted from airfoil data at a given Mach and Reynolds number. [unused when UAMod=4] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + -0.8 Cn2 ! As Cn1 for negative AOAs. [unused when UAMod=4] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data +"Default" St_sh ! Strouhal's shedding frequency constant. [default = 0.19; unused when UAMod = 4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value + 0.0016 Cd0 ! 2D drag coefficient value at 0-lift. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + -0.0328 Cm0 ! 2D pitching moment coefficient about 1/4-chord location, at 0-lift, positive if nose up. [unused when UAMod = 4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + 0 k0 ! Constant in the \hat(x)_cp curve best-fit; = (\hat(x)_AC-0.25). [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k1 ! Constant in the \hat(x)_cp curve best-fit. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k2 ! Constant in the \hat(x)_cp curve best-fit. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k3 ! Constant in the \hat(x)_cp curve best-fit. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k1_hat ! Constant in the expression of Cc due to leading edge vortex effects. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 +"Default" x_cp_bar ! Constant in the expression of \hat(x)_cp^v. [unused if UAMod<>1, default = 0.2] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +"DEFAULT" UACutout ! Angle of attack above which unsteady aerodynamics are disabled (deg). [Default = 45 degrees] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +"DEFAULT" UACutout_delta ! Delta angle of attack below UACutout where unsteady aerodynamics begin to turn off/blend with steady solution (deg) [Default = 5 degrees] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +"DEFAULT" filtCutOff ! Reduced frequency cut-off for low-pass filtering the AoA input to UA, as well as the 1st and 2nd derivatives (-) [default = 0.5; unused when UAMod = 4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +!........................................ < end of UA coefficients included only when InclUAdata=TRUE ! Table of aerodynamics coefficients 63 NumAlf ! Number of data lines in the following table ! Alpha Cl Cd Cm diff --git a/docs/source/user/aerodyn/examples/ad_polar_example.dat b/docs/source/user/aerodyn/examples/ad_polar_example.dat index 174deb0272..a2c9db8799 100644 --- a/docs/source/user/aerodyn/examples/ad_polar_example.dat +++ b/docs/source/user/aerodyn/examples/ad_polar_example.dat @@ -7,48 +7,53 @@ 0.30 RelThickness - ! The non-dimensional thickness of the airfoil (thickness/chord) [only used if UAMod=7] [default=0.2] (-) 1 NonDimArea ! The non-dimensional area of the airfoil (area/chord^2) (set to 1.0 if unsure or unneeded) @"DU30_A17_coords.txt" NumCoords ! The number of coordinates in the airfoil shape file. Set to zero if coordinates not included. -"unused" BL_file ! The file name including the boundary layer characteristics of the profile. Ignored if the aeroacoustic module is not called. +"unused" BL_file ! The file name including the boundary layer characteristics of the profile. Unused if the aeroacoustic module is not called. 1 NumTabs ! Number of airfoil tables in this file. ! ------------------------------------------------------------------------------ ! data for table 1 ! ------------------------------------------------------------------------------ 0.75 Re ! Reynolds number in millions 0 UserProp ! User property (control) setting -True InclUAdata ! Is unsteady aerodynamics data included in this table? If TRUE, then include 30 UA coefficients below this line -!........................................ - -2.2 alpha0 ! 0-lift angle of attack, depends on airfoil. - 9 alpha1 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA>alpha0. (deg) - -9 alpha2 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA1] - 0 S2 ! Constant in the f curve best-fit for AOA> alpha1; by definition it depends on the airfoil. [ignored if UAMod<>1] - 0 S3 ! Constant in the f curve best-fit for alpha2<=AOA< alpha0; by definition it depends on the airfoil. [ignored if UAMod<>1] - 0 S4 ! Constant in the f curve best-fit for AOA< alpha2; by definition it depends on the airfoil. [ignored if UAMod<>1] - 1.449 Cn1 ! Critical value of C0n at leading edge separation. It should be extracted from airfoil data at a given Mach and Reynolds number. It can be calculated from the static value of Cn at either the break in the pitching moment or the loss of chord force at the onset of stall. It is close to the condition of maximum lift of the airfoil at low Mach numbers. - -0.6138 Cn2 ! As Cn1 for negative AOAs. - 0.19 St_sh ! Strouhal's shedding frequency constant. [default = 0.19] - 0.008 Cd0 ! 2D drag coefficient value at 0-lift. - -0.09 Cm0 ! 2D pitching moment coefficient about 1/4-chord location, at 0-lift, positive if nose up. [If the aerodynamics coefficients table does not include a column for Cm, this needs to be set to 0.0] - 0 k0 ! Constant in the \hat(x)_cp curve best-fit; = (\hat(x)_AC-0.25). [ignored if UAMod<>1] - 0 k1 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] - 0 k2 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] - 0 k3 ! Constant in the \hat(x)_cp curve best-fit. [ignored if UAMod<>1] - 0 k1_hat ! Constant in the expression of Cc due to leading edge vortex effects. [ignored if UAMod<>1] - 0.2 x_cp_bar ! Constant in the expression of \hat(x)_cp^v. [ignored if UAMod<>1, default = 0.2] -"DEFAULT" UACutout ! Angle of attack above which unsteady aerodynamics are disabled (deg). [Specifying the string "Default" sets UACutout to 45 degrees] -"DEFAULT" filtCutOff ! Reduced frequency cut-off for low-pass filtering the AoA input to UA, as well as the 1st and 2nd derivatives (-) [default = 0.5] -!........................................ +True InclUAdata ! Is unsteady aerodynamics data included in this table? If TRUE, then include UA coefficients below this line. Any missing coefficients will be calculated internally. +!........................................ > start of UA coefficients included only when InclUAdata=TRUE +!Note: If any of the following lines are missing, they will be calculated internally (they must be read in the following order, though) + -2.2 alpha0 ! 0-lift angle of attack, depends on airfoil. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + 9 alpha1 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA>alpha0. (deg) [unused when UAMod=4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + -9 alpha2 ! Angle of attack at f=0.7, (approximately the stall angle) for AOA1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 S2 ! Constant in the f curve best-fit for AOA> alpha1; by definition it depends on the airfoil. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 S3 ! Constant in the f curve best-fit for alpha2<=AOA< alpha0; by definition it depends on the airfoil. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 S4 ! Constant in the f curve best-fit for AOA< alpha2; by definition it depends on the airfoil. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 1.449 Cn1 ! Critical value of C0n at leading edge separation. It should be extracted from airfoil data at a given Mach and Reynolds number. [unused when UAMod=4] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + -0.6138 Cn2 ! As Cn1 for negative AOAs. [unused when UAMod=4] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + 0.19 St_sh ! Strouhal's shedding frequency constant. [default = 0.19; unused when UAMod = 4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value + 0.008 Cd0 ! 2D drag coefficient value at 0-lift. ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + -0.09 Cm0 ! 2D pitching moment coefficient about 1/4-chord location, at 0-lift, positive if nose up. [unused when UAMod = 4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be calculated from the polar data + 0 k0 ! Constant in the \hat(x)_cp curve best-fit; = (\hat(x)_AC-0.25). [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k1 ! Constant in the \hat(x)_cp curve best-fit. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k2 ! Constant in the \hat(x)_cp curve best-fit. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k3 ! Constant in the \hat(x)_cp curve best-fit. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0 k1_hat ! Constant in the expression of Cc due to leading edge vortex effects. [unused if UAMod<>1] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to 0 + 0.2 x_cp_bar ! Constant in the expression of \hat(x)_cp^v. [unused if UAMod<>1, default = 0.2] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +"DEFAULT" UACutout ! Angle of attack above which unsteady aerodynamics are disabled (deg). [Default = 45 degrees] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +"DEFAULT" UACutout_delta ! Delta angle of attack below UACutout where unsteady aerodynamics begin to turn off/blend with steady solution (deg) [Default = 5 degrees] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +"DEFAULT" filtCutOff ! Reduced frequency cut-off for low-pass filtering the AoA input to UA, as well as the 1st and 2nd derivatives (-) [default = 0.5; unused when UAMod = 4|5] ! THIS IS AN OPTIONAL LINE; if omitted, it will be set to its default value +!........................................ < end of UA coefficients included only when InclUAdata=TRUE ! Table of aerodynamics coefficients 143 NumAlf ! Number of data lines in the following table ! Alpha Cl Cd Cm From f43093efbcdbb310d4482cae19213d03bd969209 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Wed, 13 Oct 2021 11:30:48 -0600 Subject: [PATCH 2/9] AD: update error handling --- modules/aerodyn/src/AeroDyn_Driver.f90 | 1 + modules/aerodyn/src/AeroDyn_Driver_Subs.f90 | 35 ++++++++++++++------- modules/aerodyn/src/AeroDyn_IO.f90 | 10 +++--- modules/aerodyn/src/BEMT.f90 | 3 ++ 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn_Driver.f90 b/modules/aerodyn/src/AeroDyn_Driver.f90 index 486277a180..42202c4d8c 100644 --- a/modules/aerodyn/src/AeroDyn_Driver.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver.f90 @@ -38,6 +38,7 @@ program AeroDyn_Driver CALL CPU_TIME ( UsrTime1 ) ! Initial time (this zeros the start time when used as a MATLAB function) UsrTime1 = MAX( 0.0_ReKi, UsrTime1 ) ! CPU_TIME: If a meaningful time cannot be returned, a processor-dependent negative value is returned + dat%initialized=.false. call dvr_Init(dat%dvr, dat%AD, dat%IW, dat%errStat, dat%errMsg); call CheckError() do iCase= 1,dat%dvr%numCases diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 index 9c67fdb7f6..c7b3f9971c 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -140,7 +140,7 @@ subroutine Dvr_InitCase(iCase, dvr, AD, IW, errStat, errMsg ) dvr%WT(1)%hub%motionType = idHubMotionConstant ! NOTE: we change it back after validate inputs.. dvr%WT(1)%bld(:)%motionType = idBldMotionConstant ! Change if needed else if (dvr%analysisType==idAnalysisCombi) then - print*,'------------------------------------------------------------------------------' + call WrScr('------------------------------------------------------------------------------') call WrScr('Running combined case '//trim(num2lstr(iCase))//'/'//trim(num2lstr(dvr%numCases))) ! Set time dvr%dT = dvr%Cases(iCase)%dT @@ -200,12 +200,12 @@ subroutine Dvr_InitCase(iCase, dvr, AD, IW, errStat, errMsg ) ! Copy AD input here because tower is modified in ADMeshMap do j = 2, numInp - call AD_CopyInput (AD%u(1), AD%u(j), MESH_NEWCOPY, errStat2, errMsg2) + call AD_CopyInput (AD%u(1), AD%u(j), MESH_NEWCOPY, errStat2, errMsg2); if(Failed()) return end do ! Compute driver outputs at t=0 - call Set_Mesh_Motion(0,dvr,errStat,errMsg) + call Set_Mesh_Motion(0,dvr,errStat2,errMsg2); if(Failed()) return ! --- Initial AD inputs AD%inputTime = -999 @@ -216,13 +216,13 @@ subroutine Dvr_InitCase(iCase, dvr, AD, IW, errStat, errMsg ) ! --- Initialize outputs call Dvr_InitializeOutputs(dvr%numTurbines, dvr%out, dvr%numSteps, errStat2, errMsg2); if(Failed()) return - call Dvr_CalcOutputDriver(dvr, IW%y, errStat, errMsg) + call Dvr_CalcOutputDriver(dvr, IW%y, errStat2, errMsg2); if(Failed()) return ! --- Initialize VTK if (dvr%out%WrVTK>0) then dvr%out%n_VTKTime = 1 dvr%out%VTKRefPoint = (/0.0_SiKi, 0.0_SiKi, 0.0_SiKi /) - call SetVTKParameters(dvr%out, dvr, InitOutData_AD, AD, errStat2, errMsg2) + call SetVTKParameters(dvr%out, dvr, InitOutData_AD, AD, errStat2, errMsg2); if(Failed()) return endif call cleanUp() @@ -920,8 +920,9 @@ subroutine Set_Mesh_Motion(nt,dvr,errStat,errMsg) wt%nac%yawSpeed = nacMotion(2) wt%nac%yawAcc = nacMotion(3) else - print*,'Unknown nac motion type, should never happen' - STOP + ErrMsg2='Unknown nac motion type; should never happen.' + ErrStat2 = ErrID_FATAL + if(Failed()) return endif theta(3) = wt%nac%yaw orientation_loc = EulerConstruct(theta) @@ -1221,7 +1222,7 @@ end subroutine AD_InputSolve_IfW !> Read the driver input file subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) character(*), intent( in ) :: fileName - type(Dvr_SimData), target, intent( out ) :: dvr + type(Dvr_SimData), target, intent( out ) :: dvr integer, intent( out ) :: errStat ! returns a non-zero value when an error occurs character(*), intent( out ) :: errMsg ! Error message if errStat /= ErrID_None ! Local variables @@ -1269,7 +1270,7 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) endif call ParseVar(FileInfo_In, CurLine, "analysisType", dvr%analysisType, errStat2, errMsg2, unEc); if (Failed()) return - call ParseVar(FileInfo_In, CurLine, "tMax" , dvr%tMax , errStat2, errMsg2, unEc); if (Failed()) return + call ParseVar(FileInfo_In, CurLine, "tMax" , dvr%tMax , errStat2, errMsg2, unEc); if (Failed()) return call ParseVar(FileInfo_In, CurLine, "dt" , dvr%dt , errStat2, errMsg2, unEc); if (Failed()) return call ParseVar(FileInfo_In, CurLine, "AeroFile" , dvr%AD_InputFile, errStat2, errMsg2, unEc); if (Failed()) return @@ -1296,7 +1297,12 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) ! --- Turbines call ParseCom(FileInfo_In, CurLine, Line, errStat2, errMsg2, unEc); if (Failed()) return call ParseVar(FileInfo_In, CurLine, "numTurbines", dvr%numTurbines, errStat2, errMsg2, unEc); if (Failed()) return - allocate(dvr%WT(dvr%numTurbines)) + allocate(dvr%WT(dvr%numTurbines), stat=ErrStat2) + if (ErrStat2 /=0) then + ErrStat2=ErrID_Fatal + ErrMsg2="Error allocating dvr%WT." + if(Failed()) return + end if do iWT=1,dvr%numTurbines wt => dvr%WT(iWT) @@ -1348,7 +1354,7 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) call ParseAry(FileInfo_In, CurLine, 'baseOriginInit'//sWT , wt%originInit, 3 , errStat2, errMsg2, unEc); if(Failed()) return call ParseAry(FileInfo_In, CurLine, 'baseOrientationInit'//sWT, wt%orientationInit, 3 , errStat2, errMsg2, unEc); if(Failed()) return call ParseVar(FileInfo_In, CurLine, 'hasTower'//sWT , wt%hasTower , errStat2, errMsg2, unEc); if(Failed()) return - call ParseVar(FileInfo_In, CurLine, 'HAWTprojection'//sWT , wt%HAWTprojection , errStat2, errMsg2, unEc); if(Failed()) return + call ParseVar(FileInfo_In, CurLine, 'HAWTprojection'//sWT , wt%HAWTprojection , errStat2, errMsg2, unEc); if(Failed()) return call ParseAry(FileInfo_In, CurLine, 'twrOrigin_t'//sWT , wt%twr%origin_t, 3 , errStat2, errMsg2, unEc); if(Failed()) return call ParseAry(FileInfo_In, CurLine, 'nacOrigin_t'//sWT , wt%nac%origin_t, 3 , errStat2, errMsg2, unEc); if(Failed()) return call ParseAry(FileInfo_In, CurLine, 'hubOrigin_n'//sWT , wt%hub%origin_n, 3 , errStat2, errMsg2, unEc); if(Failed()) return @@ -1358,7 +1364,12 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) ! Blades call ParseCom(FileInfo_In, CurLine, Line, errStat2, errMsg2, unEc); if(Failed()) return call ParseVar(FileInfo_In, CurLine, 'numBlades'//sWT , wt%numBlades, errStat2, errMsg2, unEc); if(Failed()) return - allocate(wt%bld(wt%numBlades)) + allocate(wt%bld(wt%numBlades), stat=ErrStat2) + if (errStat2 /= 0) then + ErrStat2=ErrID_Fatal + ErrMsg2 = "Error allocating wt%bld" + if(Failed()) return + end if wt%bld(:)%pitch = myNaN do iB=1,wt%numBlades sBld = '('//trim(num2lstr(iWT))//'_'//trim(num2lstr(iB))//')' diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index 1e9906dbdb..5739a50616 100644 --- a/modules/aerodyn/src/AeroDyn_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_IO.f90 @@ -2530,11 +2530,6 @@ SUBROUTINE ReadBladeInputs ( ADBlFile, BladeKInputFileData, UnEc, ErrStat, ErrMs ErrStat = ErrID_None ErrMsg = "" UnIn = -1 - - ! Allocate space for these variables - - - CALL GetNewUnit( UnIn, ErrStat2, ErrMsg2 ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) @@ -2564,7 +2559,10 @@ SUBROUTINE ReadBladeInputs ( ADBlFile, BladeKInputFileData, UnEc, ErrStat, ErrMs ! NumBlNds - Number of blade nodes used in the analysis (-): CALL ReadVar( UnIn, ADBlFile, BladeKInputFileData%NumBlNds, "NumBlNds", "Number of blade nodes used in the analysis (-)", ErrStat2, ErrMsg2, UnEc) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) RETURN + IF ( ErrStat>= AbortErrLev ) THEN + CALL Cleanup() + RETURN + END IF CALL ReadCom ( UnIn, ADBlFile, 'Table header: names', ErrStat2, ErrMsg2, UnEc ) CALL SetErrStat(ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName) diff --git a/modules/aerodyn/src/BEMT.f90 b/modules/aerodyn/src/BEMT.f90 index 3ad8fabc58..379ec70d06 100644 --- a/modules/aerodyn/src/BEMT.f90 +++ b/modules/aerodyn/src/BEMT.f90 @@ -682,6 +682,7 @@ subroutine BEMT_ReInit(p,x,xd,z,OtherState,misc,ErrStat,ErrMsg) end if else + OtherState%ValidPhi = .false. misc%AxInduction = 0.0_ReKi misc%TanInduction = 0.0_ReKi end if @@ -1210,6 +1211,7 @@ subroutine BEMT_CalcOutput( t, u, p, x, xd, z, OtherState, AFInfo, y, m, errStat !!#endif y%phi = z%phi ! set this before possibly calling UpdatePhi() because phi is intent(inout) in the solve + m%ValidPhi = OtherState%ValidPhi ! set this so that we don't overwrite OtherSTate%ValidPhi !............................................................................................................................... ! if we haven't initialized z%phi, we want to get a better guess as to what the actual values of phi are: @@ -1545,6 +1547,7 @@ subroutine BEMT_CalcContStateDeriv( t, u, p, x, xd, z, OtherState, m, dxdt, AFIn m%phi = z%phi ! set this before possibly calling InitPhi() because phi is intent(inout) in the solve + m%ValidPhi = OtherState%ValidPhi ! set this so that we don't overwrite OtherSTate%ValidPhi !............................................................................................................................... ! THIS IS CALLED ONLY DURING LINEARIZATION, where we want to treat z%phi as an implied input, thus we need to recalculate phi From 94fc94c40ec29a1403521057154b3532e0271a39 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Wed, 13 Oct 2021 11:36:25 -0600 Subject: [PATCH 3/9] AD: replace instances of `Array(:)%Field` with loops: `Array(i)%Field` This type of syntax caused issues in some version of gfortran long ago: https://github.com/old-NWTC/NWTC_Library/commit/976d9bd7d787a52ab3d01a10344eb3b924b2a0e5#diff-9cf80e40ecf0eacb20ef6f7042888d47defca409fb3c4bb7e972be47e93c2e6f Maybe this helps with https://github.com/OpenFAST/openfast/issues/841? --- modules/aerodyn/src/AeroDyn.f90 | 5 +- modules/aerodyn/src/AeroDyn_Driver_Subs.f90 | 53 +++++++++++++++------ modules/aerodyn/src/FVW.f90 | 5 +- modules/nwtc-library/src/ModMesh.f90 | 1 + 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 91aa7fb096..9857197341 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -2869,7 +2869,10 @@ SUBROUTINE Init_OLAF( InputFileData, u_AD, u, p, x, xd, z, OtherState, m, ErrSta InitInp%DTaero = p%DT ! NOTE: FVW can run a lower timestep internally ! Allocate wings - nWings = sum(p%rotors(:)%numBlades) + nWings = 0 + do iR=1,size(p%rotors) + nWings = nWings + p%rotors(iR)%numBlades + end do allocate(InitInp%W(nWings) , STAT = ErrStat2); ErrMsg2='Allocate W'; if(Failed()) return allocate(InitInp%WingsMesh(nWings), STAT = ErrStat2); ErrMsg2='Allocate Wings Mesh'; if(Failed()) return diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 index c7b3f9971c..9da3aa0c85 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -138,7 +138,9 @@ subroutine Dvr_InitCase(iCase, dvr, AD, IW, errStat, errMsg ) dvr%WT(1)%motionType = idBldMotionConstant dvr%WT(1)%nac%motionType = idNacMotionConstant dvr%WT(1)%hub%motionType = idHubMotionConstant ! NOTE: we change it back after validate inputs.. - dvr%WT(1)%bld(:)%motionType = idBldMotionConstant ! Change if needed + do j=1,size(dvr%WT(1)%bld) + dvr%WT(1)%bld(j)%motionType = idBldMotionConstant ! Change if needed + end do else if (dvr%analysisType==idAnalysisCombi) then call WrScr('------------------------------------------------------------------------------') call WrScr('Running combined case '//trim(num2lstr(iCase))//'/'//trim(num2lstr(dvr%numCases))) @@ -853,7 +855,9 @@ subroutine Set_Mesh_Motion(nt,dvr,errStat,errMsg) dvr%PLexp = timeState(2) !! Set motion at this time dvr%WT(1)%hub%rotSpeed = timeState(3) ! rad/s - dvr%WT(1)%bld(:)%pitch = timeState(4) ! rad + do j=1,size(dvr%WT(1)%bld) + dvr%WT(1)%bld(j)%pitch = timeState(4) ! rad + end do dvr%WT(1)%nac%yaw = timeState(5) ! rad ! Getting previous RotSpeed value by interpolation timePrev = (nt-1) * dvr%dt @@ -1340,8 +1344,8 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) ! blades allocate(wt%bld(wt%numBlades)) - wt%bld(:)%pitch = myNaN do iB=1,wt%numBlades + wt%bld(iB)%pitch = myNaN wt%bld(iB)%origin_h(1:3) = 0.0_ReKi wt%bld(iB)%orientation_h(1) = (iB-1)*(2._ReKi*Pi)/wt%numBlades wt%bld(iB)%orientation_h(2) = precone @@ -1370,8 +1374,9 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) ErrMsg2 = "Error allocating wt%bld" if(Failed()) return end if - wt%bld(:)%pitch = myNaN + do iB=1,wt%numBlades + wt%bld(iB)%pitch = myNaN sBld = '('//trim(num2lstr(iWT))//'_'//trim(num2lstr(iB))//')' call ParseAry(FileInfo_In, CurLine, 'bldOrigin_h'//sBld , wt%bld(iB)%origin_h, 3, errStat2, errMsg2, unEc); if(Failed()) return enddo @@ -1469,8 +1474,8 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) ! Blade motion call ParseVar(FileInfo_In, CurLine, 'bldMotionType'//sWT, bldMotionType, errStat2, errMsg2, unEc); if(Failed()) return - wt%bld(:)%motionType=bldMotionType do iB=1,wt%numBlades + wt%bld(iB)%motionType=bldMotionType sBld = '('//trim(num2lstr(iWT))//'_'//trim(num2lstr(iB))//')' call ParseVar(FileInfo_In, CurLine, 'bldPitch'//sBld , wt%bld(iB)%pitch, errStat2, errMsg2, unEc); if(Failed()) return wt%bld(iB)%pitch = wt%bld(iB)%pitch*Pi/180_ReKi ! to rad @@ -1491,8 +1496,10 @@ subroutine Dvr_ReadInputFile(fileName, dvr, errStat, errMsg ) enddo else ! Replacing with default motion if AnalysisType is not Regular, shouldbe overriden later - wt%bld(:)%motionType = idBldMotionConstant - wt%bld(:)%pitch = myNan + do iB=1,size(wt%bld) + wt%bld(iB)%motionType = idBldMotionConstant + wt%bld(iB)%pitch = myNan + end do endif endif ! numBlade>0 endif ! BASIC/ADVANCED rotor definition @@ -1593,6 +1600,8 @@ subroutine setSimpleMotion(wt, rotSpeed, bldPitch, nacYaw, DOF, amplitude, frequ integer(IntKi), intent(in ) :: DOF ! 0<: None, 1:surge, ... 6: yaw real(ReKi), intent(in ) :: amplitude ! m or rad real(ReKi), intent(in ) :: frequency ! Hz + + integer :: i wt%degreeofFreedom = DOF wt%amplitude = amplitude wt%frequency = frequency * 2 *pi ! Hz to rad/s @@ -1600,8 +1609,12 @@ subroutine setSimpleMotion(wt, rotSpeed, bldPitch, nacYaw, DOF, amplitude, frequ wt%nac%yaw = nacYaw* PI /180._ReKi ! deg 2 rad wt%hub%motionType = idHubMotionConstant wt%hub%rotSpeed = rotSpeed*RPM2RPS ! rpm 2 rad/s - wt%bld(:)%motionType = idBldMotionConstant - wt%bld(:)%pitch = bldPitch * Pi /180._ReKi ! deg 2 rad + if (allocated(wt%bld)) then + do i=1,size(wt%bld) + wt%bld(i)%motionType = idBldMotionConstant + wt%bld(i)%pitch = bldPitch * Pi /180._ReKi ! deg 2 rad + end do + end if end subroutine setSimpleMotion @@ -1761,7 +1774,10 @@ subroutine Dvr_InitializeDriverOutputs(dvr, errStat, errMsg) errStat = ErrID_None errMsg = '' - maxNumBlades=maxval(dvr%WT(:)%numBlades) + maxNumBlades = 0 + do iWT=1,size(dvr%WT) + maxNumBlades= max(maxNumBlades, dvr%WT(iWT)%numBlades) + end do ! --- Allocate driver-level outputs dvr%out%nDvrOutputs = 1+ 4 + 6 + 3 + 1*maxNumBlades ! @@ -1830,7 +1846,12 @@ subroutine Dvr_CalcOutputDriver(dvr, y_Ifw, errStat, errMsg) real(ReKi), pointer :: arr(:) errStat = ErrID_None errMsg = '' - + + maxNumBlades = 0 + do iWT=1,size(dvr%WT) + maxNumBlades= max(maxNumBlades, dvr%WT(iWT)%numBlades) + end do + do iWT = 1, dvr%numTurbines if (dvr%wt(iWT)%numBlades >0 ) then ! TODO, export for tower only arr => dvr%wt(iWT)%WriteOutput @@ -1855,7 +1876,7 @@ subroutine Dvr_CalcOutputDriver(dvr, y_Ifw, errStat, errMsg) arr(k) = dvr%WT(iWT)%nac%yaw*R2D ; k=k+1 ! yaw [deg] arr(k) = modulo(real(dvr%WT(iWT)%hub%azimuth+(dvr%dt * dvr%WT(iWT)%hub%rotSpeed)*R2D, ReKi), 360.0_ReKi); k=k+1 ! azimuth [deg], stored at nt-1 arr(k) = dvr%WT(iWT)%hub%rotSpeed*RPS2RPM; k=k+1 ! rotspeed [rpm] - do j=1,maxval(dvr%WT(:)%numBlades) + do j=1,maxNumBlades if (j<=dvr%WT(iWT)%numBlades) then arr(k) = dvr%WT(iWT)%bld(j)%pitch*R2D ! pitch [deg] else @@ -2101,8 +2122,12 @@ SUBROUTINE SetVTKParameters(p_FAST, dvr, InitOutData_AD, AD, ErrStat, ErrMsg) ! Get radius for ground (blade length + hub radius): GroundRad = MaxBladeLength + MaxTwrLength+ p_FAST%VTKHubRad ! write the ground or seabed reference polygon: - RefPoint(1) = sum(dvr%WT(:)%originInit(1)) / dvr%numTurbines - RefPoint(2) = sum(dvr%WT(:)%originInit(2)) / dvr%numTurbines + RefPoint(1:2) = dvr%WT(1)%originInit(1:2) + do iWT=2,dvr%numTurbines + RefPoint(1:2) = RefPoint(1:2) + dvr%WT(iWT)%originInit(1:2) + end do + RefPoint(1:2) = RefPoint(1:2) / dvr%numTurbines + RefPoint(3) = 0.0_ReKi RefLengths = GroundRad + sqrt((WorldBoxMax(1)-WorldBoxMin(1))**2 + (WorldBoxMax(2)-WorldBoxMin(2))**2) call WrVTK_Ground (RefPoint, RefLengths, trim(p_FAST%VTK_OutFileRoot) // '.GroundSurface', ErrStat2, ErrMsg2 ) diff --git a/modules/aerodyn/src/FVW.f90 b/modules/aerodyn/src/FVW.f90 index cff5842fe3..fec204bdda 100644 --- a/modules/aerodyn/src/FVW.f90 +++ b/modules/aerodyn/src/FVW.f90 @@ -450,7 +450,10 @@ SUBROUTINE FVW_SetParametersFromInputs( InitInp, p, ErrStat, ErrMsg ) enddo ! --- Distributing wings to rotors - p%nRotors = maxval(p%W(:)%iRotor) + p%nRotors = p%W(1)%iRotor + do iW=2,p%nWings + p%nRotors = max(p%nRotors,p%W(iW)%iRotor) + end do ! Count number of blades per rotor call AllocAry(nBldPerRot, p%nRotors , 'nBldPerRot', ErrStat2, ErrMsg2);call SetErrStat(ErrStat2, ErrMsg2, ErrStat,ErrMsg,RoutineName); nBldPerRot=0 diff --git a/modules/nwtc-library/src/ModMesh.f90 b/modules/nwtc-library/src/ModMesh.f90 index a38dfdd723..9c386cf531 100644 --- a/modules/nwtc-library/src/ModMesh.f90 +++ b/modules/nwtc-library/src/ModMesh.f90 @@ -2329,6 +2329,7 @@ SUBROUTINE MeshCommit( Mesh, ErrStat, ErrMess ) RETURN ! Early return ENDIF + !bjj: Not sure Mesh%ElemTable(:)%nelem can be used on all versions of gfortran IF ( ALL( Mesh%ElemTable(:)%nelem /= SUM(Mesh%ElemTable(:)%nelem ) ) ) THEN ErrStat = ErrID_Fatal ErrMess = "MeshCommit: a mesh can have only one type of element." From e4c8337f5bc808f5f55eb761f8efe542e0ef6732 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Mon, 11 Oct 2021 14:03:08 -0600 Subject: [PATCH 4/9] docs: Fix some typos also added `alt` keyword to figures to avoid warnings in VSCode previewer --- docs/source/user/aerodyn/appendix.rst | 5 ++++- docs/source/user/aerodyn/input.rst | 16 ++++++++++------ docs/source/user/beamdyn/input_files.rst | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/docs/source/user/aerodyn/appendix.rst b/docs/source/user/aerodyn/appendix.rst index 9404802837..daf271e5f6 100644 --- a/docs/source/user/aerodyn/appendix.rst +++ b/docs/source/user/aerodyn/appendix.rst @@ -34,8 +34,9 @@ The file is organized into several functional sections. Each section correspond The input file begins with two lines of header information which is for your use, but is not used by the software. 4) Airfoil Data Input File - + :download:`(profile data) `: + :download:`(profile coordinates) `: The airfoil data input files themselves (one for each airfoil) include tables containing coefficients of lift force, drag force, and pitching moment versus AoA, as well as UA model parameters. In these files, any line whose first non-blank character is an exclamation point (!) is ignored (for inserting comment lines). The non-comment lines should appear within the file in order, but comment lines may be intermixed as desired for reading clarity. @@ -59,6 +60,7 @@ The local tower coordinate system is shown in :numref:`ad_tower_geom` and the lo .. figure:: figs/ad_blade_local_cs.png :width: 80% :align: center + :alt: ad_blade_local_cs.png AeroDyn Local Blade Coordinate System (Looking Toward the Tip, from the Root) – l: Lift, d: Drag, m: Pitching, x: Normal (to Plane), @@ -70,5 +72,6 @@ The local tower coordinate system is shown in :numref:`ad_tower_geom` and the lo .. figure:: figs/ad_output_channel.pdf :width: 500px :align: center + :alt: ad_output_channel.pdf AeroDyn Output Channel List diff --git a/docs/source/user/aerodyn/input.rst b/docs/source/user/aerodyn/input.rst index 432b5e07bd..bbe9d3e5b3 100644 --- a/docs/source/user/aerodyn/input.rst +++ b/docs/source/user/aerodyn/input.rst @@ -45,7 +45,7 @@ This name should be in quotations and can contain an absolute path or a relative path. The TURBINE DATA section defines the AeroDyn-required turbine geometry -for a rigid turbine, see Figure 1. ``NumBlades`` specifies the number +for a rigid turbine, see :numref:`ad_driver_geom`. ``NumBlades`` specifies the number of blades; only one-, two-, or three-bladed rotors are permitted. ``HubRad`` specifies the radius to the blade root from the center-of-rotation along the (possibly preconed) blade-pitch axis; @@ -74,9 +74,12 @@ for text output, excluding the time channel. The resulting field should be 10 characters, but AeroDyn does not check ``OutFmt`` for validity. If you want a sound generated on program exit, set ``Beep`` to true. +.. _ad_driver_geom: + .. figure:: figs/ad_driver_geom.png :width: 60% :align: center + :alt: ad_driver_geom.png AeroDyn Driver Turbine Geometry @@ -425,9 +428,9 @@ wind fluctuation. ``TwrElev`` must be entered in monotonically increasing order—from the lowest (tower-base) to the highest (tower-top) elevation. Values of ``TwrTI`` between 0.05 and 0.4 are recommended. Values larger than 0.4 up to 1 will trigger a warning -that the results will need to be interpretted carefully, but the code +that the results will need to be interpreted carefully, but the code will allow such values for scientific investigation purposes. -See :numref:`fig:TwrGeom`. +See :numref:`ad_tower_geom`. .. _AD-Outputs: @@ -468,8 +471,8 @@ quantities are actually output at these nodes. .. figure:: figs/ad_tower_geom.png :width: 60% - :name: fig:TwrGeom :align: center + :alt: ad_tower_geom.png AeroDyn Tower Geometry @@ -510,7 +513,7 @@ moment versus AoA, as well as UA model parameters. In these files, any line whose first non-blank character is an exclamation point (!) is ignored (for inserting comment lines). The non-comment lines should appear within the file in order, but comment lines may be intermixed as -desired for reading clarity. A sample airfoil data input file is given +desired for reading clarity. A sample airfoil data input file is given in :numref:`ad_appendix`. ``InterpOrd`` is the order the static airfoil data is interpolated @@ -525,7 +528,7 @@ if the keyword ``DEFAULT`` is entered in place of a numerical value, ``RelThickness`` is the non-dimensional thickness of the airfoil (thickness over chord ratio), expressed as a fraction (not a percentage), typically between 0.1 and 1. -The parameter is currently used when `UAMod=7`, but might be used more in the future. +The parameter is currently used when ``UAMod=7``, but might be used more in the future. The default value of 0.2 if provided for convenience. ``NonDimArea`` is the nondimensional airfoil area (normalized by the @@ -832,6 +835,7 @@ See :numref:`ad_blade_geom`. Twist is shown in :numref:`ad_blade_local_cs` of :n .. figure:: figs/ad_blade_geom.png :width: 90% :align: center + :alt: ad_blade_geom.png AeroDyn Blade Geometry – Left: Side View; Right: Front View (Looking Downwind) diff --git a/docs/source/user/beamdyn/input_files.rst b/docs/source/user/beamdyn/input_files.rst index f5802607ef..2982145b09 100644 --- a/docs/source/user/beamdyn/input_files.rst +++ b/docs/source/user/beamdyn/input_files.rst @@ -371,7 +371,7 @@ The structural twist angle is also following the IEC standard which is defined as the twist about the negative :math:`Z_l` axis. The key points are entered sequentially (from the root to tip) and there should be a total of ``kp_total`` lines for BeamDyn to read in the information, -after two header lines. Please refer to Figure :numref:`blade-geometry` for +after two header lines. Please refer to :numref:`blade-geometry` for more details on the blade geometry definition. .. _blade-geometry: From 8f91c6fa5a4de91f315f47f2704809761363d044 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Mon, 18 Oct 2021 14:08:55 -0600 Subject: [PATCH 5/9] AD: fix some error handling --- modules/aerodyn/src/AeroDyn_Driver_Subs.f90 | 12 ++++++------ modules/aerodyn/src/AeroDyn_IO.f90 | 2 ++ modules/aerodyn/src/AirfoilInfo.f90 | 21 +++++++++++---------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 index 9da3aa0c85..5f119d059e 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -622,21 +622,21 @@ subroutine Init_Meshes(dvr, errStat, errMsg) !CALL Eye(R_gl2wt, errStat2, errMsg2) R_gl2wt = EulerConstruct( wt%orientationInit ) ! global 2 base at t = 0 (constant) orientation = R_gl2wt - call CreatePointMesh(wt%ptMesh, pos, orientation, errStat2, errMsg2); if(Failed())return + + !bjj: Inspector consistently gives "Invalid Memory Access" errors here on the allocation of wt%ptMesh%RotationVel in MeshCreate. I haven't yet figured out why. + call CreatePointMesh(wt%ptMesh, pos, orientation, errStat2, errMsg2); if(Failed()) return ! Tower if (wt%hasTower) then pos = wt%ptMesh%Position(:,1) + matmul(transpose(R_gl2wt), wt%twr%origin_t) orientation = R_gl2wt - call CreatePointMesh(wt%twr%ptMesh, pos, orientation, errStat2, errMsg2); if(Failed())return - if(Failed())return + call CreatePointMesh(wt%twr%ptMesh, pos, orientation, errStat2, errMsg2); if(Failed()) return endif ! Nacelle pos = wt%ptMesh%Position(:,1) + matmul(transpose(R_gl2wt), wt%nac%origin_t) orientation = R_gl2wt ! Yaw? - call CreatePointMesh(wt%nac%ptMesh, pos, orientation, errStat2, errMsg2); if(Failed())return - if(Failed())return + call CreatePointMesh(wt%nac%ptMesh, pos, orientation, errStat2, errMsg2); if(Failed()) return ! Hub R_nac2gl = transpose(wt%nac%ptMesh%RefOrientation(:,:,1)) @@ -790,7 +790,7 @@ end subroutine Init_ADMeshMap !---------------------------------------------------------------------------------------------------------------------------------- !> subroutine CreatePointMesh(mesh, posInit, orientInit, errStat, errMsg) - type(MeshType), intent(out) :: mesh + type(MeshType), intent(inout) :: mesh real(ReKi), intent(in ) :: PosInit(3) !< Xi,Yi,Zi, coordinates of node real(R8Ki), intent(in ) :: orientInit(3,3) !< Orientation (direction cosine matrix) of node; identity by default integer(IntKi) , intent(out) :: errStat ! Status of error message diff --git a/modules/aerodyn/src/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index 5739a50616..5ef80b9e87 100644 --- a/modules/aerodyn/src/AeroDyn_IO.f90 +++ b/modules/aerodyn/src/AeroDyn_IO.f90 @@ -2435,6 +2435,7 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InputFile, RootName, NumBlades, interv endif ! BlOutNd - Blade nodes whose values will be output (-): call ParseAry( FileInfo_In, CurLine, "BlOutNd", InputFileData%BlOutNd, InputFileData%NBlOuts, ErrStat2, ErrMsg2, UnEc) + if (Failed()) return ! NTwOuts - Number of blade node outputs [0 - 9] (-) call ParseVar( FileInfo_In, CurLine, "NTwOuts", InputFileData%NTwOuts, ErrStat2, ErrMsg2, UnEc ) @@ -2447,6 +2448,7 @@ SUBROUTINE ParsePrimaryFileInfo( PriPath, InputFile, RootName, NumBlades, interv endif ! TwOutNd - Tower nodes whose values will be output (-): call ParseAry( FileInfo_In, CurLine, "TwOutNd", InputFileData%TwOutNd, InputFileData%NTwOuts, ErrStat2, ErrMsg2, UnEc) + if (Failed()) return if ( InputFileData%Echo ) WRITE(UnEc, '(A)') FileInfo_In%Lines(CurLine) ! Write section break to echo CurLine = CurLine + 1 diff --git a/modules/aerodyn/src/AirfoilInfo.f90 b/modules/aerodyn/src/AirfoilInfo.f90 index 87d82bb807..cc96479a3a 100644 --- a/modules/aerodyn/src/AirfoilInfo.f90 +++ b/modules/aerodyn/src/AirfoilInfo.f90 @@ -391,7 +391,6 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) CHARACTER(*), PARAMETER :: RoutineName = 'ReadAFfile' CHARACTER(10) :: defaultStr CHARACTER(1024) :: PriPath - CHARACTER(1024) :: sLine TYPE (AFI_UA_BL_Default_Type), ALLOCATABLE :: CalcDefaults(:) ! Whether to calculate default values for the UA parameters @@ -423,17 +422,19 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) CALL ParseVarWDefault ( FileInfo, CurLine, 'InterpOrd', p%InterpOrd, DefaultInterpOrd, ErrStat2, ErrMsg2, UnEc ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - + IF (ErrStat >= AbortErrLev) THEN + CALL Cleanup() + RETURN + END IF + ! RelThickness, default is 0.2 if user doesn't know it, only used for Boing-Vertol UA model = 7 - sLine = FileInfo%Lines(CurLine) - call Conv2UC(sLine) ! to uppercase - if (index(sLine, 'RELTHICKNESS')>1) then - CALL ParseVarWDefault ( FileInfo, CurLine, 'RelThickness', p%RelThickness, 0.2_ReKi, ErrStat2, ErrMsg2, UnEc ) + CALL ParseVarWDefault ( FileInfo, CurLine, 'RelThickness', p%RelThickness, 0.2_ReKi, ErrStat2, ErrMsg2, UnEc ) + if (ErrStat2 >= AbortErrLev) then ! if the line is missing, set RelThickness = -1 and move on... + p%RelThickness=-1 ! To trigger an error + !call WrScr('Skipping. RelThickness not found on line 7 of Profile file: '//trim(InitInp%FileName) ) + else CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - else - p%RelThickness=-1 ! To trigger an error - !call WrScr('Skipping. RelThickness not found on line 7 of Profile file: '//trim(InitInp%FileName) ) - endif + endif ! NonDimArea is currently unused by AirfoilInfo or codes using AirfoilInfo. GJH 9/13/2017 From 8e9c079e31d2cc1ac0f918288f98bdc745f85648 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Mon, 18 Oct 2021 20:18:40 -0600 Subject: [PATCH 6/9] AD: destroy arrays in FileInfo type after use Also, don't save variables for ProcessCom (initialize in declaration statement = SAVE) --- modules/aerodyn/src/AeroDyn.f90 | 1 + modules/aerodyn/src/AeroDyn_Driver_Subs.f90 | 1 + modules/nwtc-library/src/NWTC_IO.f90 | 27 +++++++++++++++------ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 9857197341..14b8ed1920 100644 --- a/modules/aerodyn/src/AeroDyn.f90 +++ b/modules/aerodyn/src/AeroDyn.f90 @@ -471,6 +471,7 @@ end function Failed subroutine Cleanup() CALL AD_DestroyInputFile( InputFileData, ErrStat2, ErrMsg2 ) + CALL NWTC_Library_Destroyfileinfotype(FileInfo_In, ErrStat2, ErrMsg2) IF ( UnEcho > 0 ) CLOSE( UnEcho ) end subroutine Cleanup diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 index 5f119d059e..e571f91e3f 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -1581,6 +1581,7 @@ end function Check subroutine CleanUp() if (UnIn>0) close(UnIn) if (UnEc>0) close(UnEc) + CALL NWTC_Library_Destroyfileinfotype(FileInfo_In, ErrStat2, ErrMsg2) end subroutine cleanup logical function Failed() diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index e90b142a86..29e4212229 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -3884,7 +3884,7 @@ SUBROUTINE ParseInclInfo ( InclInfo, RelativePathFileName, FileName, RangeBeg, R IF ( DashLoc > 0 ) THEN ! Must be in the form of "-". - READ (Words(1)(:DashLoc-1),*,IOSTAT=ErrStatLcl) RangeBeg ! Parse the first number as the beginning fo the range. + READ (Words(1)(:DashLoc-1),*,IOSTAT=ErrStatLcl) RangeBeg ! Parse the first number as the beginning of the range. IF ( ErrStatLcl /= 0 ) THEN CALL SetErrStat(ErrID_Fatal,'Fatal error for an incorrectly formatted include-file line range.',ErrStat,ErrMsg,RoutineName) RETURN @@ -4670,13 +4670,13 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) ! Local declarations. - INTEGER(IntKi) :: AryInd = 0 ! The index into the FileInfo arrays. There is no data in the arrays at the start. - INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. - INTEGER(IntKi) :: FileIndx = 1 ! The index into the FileInfo%FileList array. Start with the first file in the list. - INTEGER(IntKi) :: RangeBeg = 1 ! The first line in a range of lines to be included from a file. - INTEGER(IntKi) :: RangeEnd = 0 ! The last line in a range of lines to be included from a file. Zero to read to the end of the file. + INTEGER(IntKi) :: AryInd ! The index into the FileInfo arrays. There is no data in the arrays at the start. + INTEGER(IntKi) :: ErrStatLcl ! Error status local to this routine. + INTEGER(IntKi) :: FileIndx ! The index into the FileInfo%FileList array. Start with the first file in the list. + INTEGER(IntKi) :: RangeBeg ! The first line in a range of lines to be included from a file. + INTEGER(IntKi) :: RangeEnd ! The last line in a range of lines to be included from a file. Zero to read to the end of the file. - INTEGER :: File = 0 ! Index into the arrays. + INTEGER :: File ! Index into the arrays. CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'ProcessComFile' @@ -4684,6 +4684,7 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) TYPE (FNlist_Type), POINTER :: FirstFile ! The first file in the linked list (TopFile). TYPE (FNlist_Type), POINTER :: LastFile ! The last file in the linked list. + ! Scan the file, and it's included files, to determine how many lines will be kept and generate ! a linked list of the different files. @@ -4691,6 +4692,7 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) ErrStat = ErrID_None ErrMsg = "" + ALLOCATE ( FirstFile ) !bjj: fix me , IOStat=ErrStatLcl2 LastFile => FirstFile @@ -4765,9 +4767,18 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) ENDIF + if ( FileInfo%NumLines < 1) then + CALL SetErrStat( ErrID_Fatal, 'No data found in '//trim(TopFileName)//'.' , ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + end if + ! Read the file and save all but the comments. AryInd = 0 + FileIndx = 1 ! The index into the FileInfo%FileList array. Start with the first file in the list. + RangeBeg = 1 ! The first line in a range of lines to be included from a file. + RangeEnd = 0 ! The last line in a range of lines to be included from a file. Zero to read to the end of the file. CALL ReadComFile ( FileInfo, FileIndx, AryInd, RangeBeg, RangeEnd, ErrStatLcl, ErrMsg2 ) CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( ErrStatLcl >= AbortErrLev ) THEN @@ -4775,7 +4786,7 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) RETURN ENDIF - CALL Cleanup() + CALL Cleanup() RETURN !======================================================================= From 6df975ec8b0c14bbcace35c37fc59049f5b02967 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Wed, 20 Oct 2021 12:53:32 -0600 Subject: [PATCH 7/9] docs: fix some typos/spelling errors --- docs/source/user/aerodyn-aeroacoustics/index.rst | 2 +- docs/source/user/aerodyn-olaf/index.rst | 2 +- docs/source/user/aerodyn/driver.rst | 2 +- docs/source/user/input_file_overview.rst | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/user/aerodyn-aeroacoustics/index.rst b/docs/source/user/aerodyn-aeroacoustics/index.rst index c6fd838d9b..52c66c9866 100644 --- a/docs/source/user/aerodyn-aeroacoustics/index.rst +++ b/docs/source/user/aerodyn-aeroacoustics/index.rst @@ -13,7 +13,7 @@ Aeroacoustics Noise Model of OpenFAST fully open source and publicly available, is based on work performed over the past three decades. Frequency-based models for turbulent inflow; turbulent boundary layer – trailing edge; laminar boundary layer - –vortex shedding; tip vortex; and trailing edge bluntness – vortex + – vortex shedding; tip vortex; and trailing edge bluntness – vortex shedding noise mechanisms are included. A simple directivity model is also included. diff --git a/docs/source/user/aerodyn-olaf/index.rst b/docs/source/user/aerodyn-olaf/index.rst index e706234e7e..2c9595743a 100644 --- a/docs/source/user/aerodyn-olaf/index.rst +++ b/docs/source/user/aerodyn-olaf/index.rst @@ -12,7 +12,7 @@ OLAF User's Guide and Theory Manual (Free Vortex Wake in AeroDyn15) releases are issued and as needed to provide further information on advancements or modifications to the software. - The documentaiton here was derived from the OLAF users manual by K. Shaler, + The documentation here was derived from the OLAF users manual by K. Shaler, E. Branlard, and A. Platt. (`https://www.nrel.gov/docs/fy20osti/75959.pdf `_) diff --git a/docs/source/user/aerodyn/driver.rst b/docs/source/user/aerodyn/driver.rst index af645d8a1c..f281e04daa 100644 --- a/docs/source/user/aerodyn/driver.rst +++ b/docs/source/user/aerodyn/driver.rst @@ -9,7 +9,7 @@ A standalone AeroDyn driver is provided to perform aerodynamic simulations of ri undergoing rigid body motion (fixed, sinusoidal, or arbitrary). The standalone AeroDyn driver code improves on the functionality previously available in the separate wind turbine rotor-performance tool WT\_Perf. -The driver alo supports turbine configurations that are not currently supported by OpenFAST. +The driver also supports turbine configurations that are not currently supported by OpenFAST. Examples of applications are: diff --git a/docs/source/user/input_file_overview.rst b/docs/source/user/input_file_overview.rst index 06bd428d0f..9a5d75ce4d 100644 --- a/docs/source/user/input_file_overview.rst +++ b/docs/source/user/input_file_overview.rst @@ -15,7 +15,7 @@ Value column input files ------------------------ Only the first column in a *value column* based input file is read. This is the -historical format used by OpenFAST and it's predecessors (the keyword was often +historical format used by OpenFAST and its predecessors (the keyword was often referenced in the source code and documentation, but OpenFAST did not process the keyword or description). Everything after the first value read is simply ignored by the code. This allowed the user to keep From 872ef692a4eda0316afb65a796040b6119366671 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Thu, 21 Oct 2021 11:25:33 -0600 Subject: [PATCH 8/9] Added more error handling --- modules/aerodyn/src/AeroDyn_Driver_Subs.f90 | 1 + modules/nwtc-library/src/NWTC_IO.f90 | 48 +++++++++++++++------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 index e571f91e3f..423533f146 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -802,6 +802,7 @@ subroutine CreatePointMesh(mesh, posInit, orientInit, errStat, errMsg) call MeshCreate(mesh, COMPONENT_INPUT, 1, errStat2, errMsg2, Orientation=.true., TranslationDisp=.true., TranslationVel=.true., RotationVel=.true., TranslationAcc=.true., RotationAcc=.true.) call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'CreatePointMesh') + if (ErrStat >= AbortErrLev) return call MeshPositionNode(mesh, 1, posInit, errStat2, errMsg2, orientInit); call SetErrStat(errStat2, errMsg2, errStat, errMsg, 'CreatePointMesh') diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index 29e4212229..11f718931b 100644 --- a/modules/nwtc-library/src/NWTC_IO.f90 +++ b/modules/nwtc-library/src/NWTC_IO.f90 @@ -3364,10 +3364,10 @@ subroutine Print_FileInfo_Struct( U, FileInfo ) endif write(U,*) ' %NumLines (integer): ',FileInfo%NumLines write(U,*) ' %NumFiles (integer): ',FileInfo%NumFiles - write(U,*) ' %FileList (array of strings): ',size(FileInfo%FileList) - write(U,*) ' %FileIndx (array of integer): ',size(FileInfo%FileIndx) - write(U,*) ' %FileLine (array of integer): ',size(FileInfo%FileLine) - write(U,*) ' %Lines (array of strings): ',size(FileInfo%Lines ) + write(U,*) ' %FileList (array of strings): ',size(FileInfo%FileList) ! SIZE(array) will produce an error on some compilers if array not allocated + write(U,*) ' %FileIndx (array of integer): ',size(FileInfo%FileIndx) ! SIZE(array) will produce an error on some compilers if array not allocated + write(U,*) ' %FileLine (array of integer): ',size(FileInfo%FileLine) ! SIZE(array) will produce an error on some compilers if array not allocated + write(U,*) ' %Lines (array of strings): ',size(FileInfo%Lines ) ! SIZE(array) will produce an error on some compilers if array not allocated if (allocated(FileInfo%FileList)) then write(U,*) ' list of files read:' write(U,*) ' FileIdx FileName' @@ -4728,7 +4728,6 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) RETURN ENDIF - ! Copy the linked list of file names into the FileList array. ! This MUST be done before calling ReadComFile. @@ -4773,6 +4772,9 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) RETURN end if + ! initialize this, just in case + FileInfo%FileIndx = 1 + ! Read the file and save all but the comments. AryInd = 0 @@ -4786,6 +4788,12 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) RETURN ENDIF + IF ( AryInd /= FileInfo%NumLines ) THEN ! This would happen if there is a mis-match between ScanComFile and ReadComFile + CALL SetErrStat( ErrID_Fatal, "Error processing files: number of lines read does not match array size.", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + CALL Cleanup() RETURN @@ -5227,17 +5235,18 @@ RECURSIVE SUBROUTINE ReadComFile ( FileInfo, FileIndx, AryInd, StartLine, LastLi ErrMsg = "" ! Open the input file. - + IF ( FileIndx > SIZE(FileInfo%FileList ) ) THEN + CALL SetErrStat( ErrID_Fatal, "Error processing file: Invalid FileIndx.", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF + CALL GetNewUnit ( UnIn, ErrStatLcl, ErrMsg2 ) CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) CALL OpenFInpFile ( UnIn, FileInfo%FileList(FileIndx), ErrStatLcl, ErrMsg2 ) CALL SetErrStat( ErrStatLcl, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - IF ( ErrStat >= AbortErrLev ) THEN - CALL Cleanup() - RETURN - END IF - + IF ( ErrStat >= AbortErrLev ) RETURN ! Skip the beginning of the file, if requested. @@ -5296,7 +5305,7 @@ RECURSIVE SUBROUTINE ReadComFile ( FileInfo, FileIndx, AryInd, StartLine, LastLi ErrStatLcl = 0 ! Which file in the prestored list is the new one? - + NewIndx = 0 DO File=1,FileInfo%NumFiles IF ( TRIM( FileInfo%FileList(File) ) == TRIM( IncFileName ) ) THEN NewIndx = File @@ -5304,6 +5313,11 @@ RECURSIVE SUBROUTINE ReadComFile ( FileInfo, FileIndx, AryInd, StartLine, LastLi ENDIF ! ( TRIM( FileInfo%FileList(File) ) == TRIM( Line(2:) ) ) ENDDO ! File + IF (NewIndx < 1) THEN ! This would happen if there is a mis-match between ScanComFile and ReadComFile + CALL SetErrStat( ErrID_Fatal, "Error processing file: "//TRIM(IncFileName)//"is not in the pre-stored list.", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF ! Let's recursively process this new file. @@ -5319,6 +5333,16 @@ RECURSIVE SUBROUTINE ReadComFile ( FileInfo, FileIndx, AryInd, StartLine, LastLi ! Not a file name. Add this line to stack. + + IF ( AryInd >= FileInfo%NumLines ) THEN ! This would happen if there is a mis-match between ScanComFile and ReadComFile + CALL SetErrStat( ErrID_Fatal, "Error processing file: Too many data lines.", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + ELSE IF (AryInd < 0) THEN + CALL SetErrStat( ErrID_Fatal, "Error processing file: Invalid AryInd.", ErrStat, ErrMsg, RoutineName ) + CALL Cleanup() + RETURN + END IF AryInd = AryInd + 1 FileInfo%FileLine(AryInd) = FileLine From bbb38dd72f536c4c08fc38a203d65d1bb3ec6827 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Thu, 21 Oct 2021 12:08:41 -0600 Subject: [PATCH 9/9] update docs --- docs/source/user/aerodyn/bibliography.bib | 8 -------- docs/source/user/aerodyn/theory_ua.rst | 4 +++- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/docs/source/user/aerodyn/bibliography.bib b/docs/source/user/aerodyn/bibliography.bib index 9f2880db14..65913f77f5 100644 --- a/docs/source/user/aerodyn/bibliography.bib +++ b/docs/source/user/aerodyn/bibliography.bib @@ -61,14 +61,6 @@ @techreport{Hansen:2004 address={Roskilde, Denmark} } -@techreport{Bladed:manual, - title = {Bladed Theory Manual version 4.8}, - author = {DNV GL}, - year = {2016}, - institution={DNV-GL - Energy}, - address={Bristol, UK} -} - @article{Oye:1991, author = {S. {\O}ye}, diff --git a/docs/source/user/aerodyn/theory_ua.rst b/docs/source/user/aerodyn/theory_ua.rst index e4f535aec6..5522e42da6 100644 --- a/docs/source/user/aerodyn/theory_ua.rst +++ b/docs/source/user/aerodyn/theory_ua.rst @@ -233,7 +233,9 @@ with: Beddoes-Leishman 5-states model (UAMod=5) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The 5-states (incompressible) dynamic stall model is described in the Bladed Theory Manual :cite:`ad-Bladed:manual` and enabled using ``UAMod=5``. The model uses :math:`C_n` and :math:`C_c` as main physical quantities. +The 5-states (incompressible) dynamic stall model is similar to the Beddoes-Leishman 4-states model (UAMod=4), but +adds a 5th state to represent vortex generation. +It is enabled using ``UAMod=5``. The model uses :math:`C_n` and :math:`C_c` as main physical quantities. Linearization of the model will be available in the future.