From 51a5faeb8eda8d016ae6b5f144d8021546d25e08 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Sat, 13 Nov 2021 17:45:18 -0700 Subject: [PATCH 1/3] UA/AFI: Fix calculation of default Cd0, alphaUpper, and alphaLower Also remove unused comments + fix some of the UA/AFI documentation --- docs/source/user/aerodyn/input.rst | 19 ++++--- glue-codes/fast-farm/src/FAST_Farm_IO.f90 | 2 +- modules/aerodyn/src/AirfoilInfo.f90 | 60 ++++++++++------------- modules/turbsim/src/TSsubs.f90 | 7 --- 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/docs/source/user/aerodyn/input.rst b/docs/source/user/aerodyn/input.rst index 32c1e993e..176388d3b 100644 --- a/docs/source/user/aerodyn/input.rst +++ b/docs/source/user/aerodyn/input.rst @@ -238,7 +238,8 @@ value, *f’*, will be calculated. When ``FLookup`` is set to TRUE, *f’* is determined via a lookup into the static lift-force coefficient and drag-force coefficient data. **Using best-fit exponential equations (``FLookup = FALSE``) is not yet available, so ``FLookup`` must be -``TRUE`` in this version of AeroDyn.** Note, ``FLookup`` is not used when ``UAMod=5``. +``TRUE`` in this version of AeroDyn.** Note, ``FLookup`` is not used +when ``UAMod=4`` or ``UAMod=5``. ``UAStartRad`` is the starting rotor radius where dynamic stall will be turned on. Enter a number between 0 and 1, representing a fraction of rotor radius, @@ -434,6 +435,7 @@ The default value of 0.2 if provided for convenience. ``NonDimArea`` is the nondimensional airfoil area (normalized by the local ``BlChord`` squared), but is currently unused by AeroDyn. + ``NumCoords`` is the number of points to define the exterior shape of the airfoil, plus one point to define the aerodynamic center, and determines the number of rows in the subsequent table; ``NumCoords`` @@ -449,6 +451,7 @@ used by OpenFAST for blade surface visualization when enabled. ``BL_file`` is the name of the file containing boundary-layer characteristics of the profile. It is ignored if the aeroacoustic module is not used. +This parameter may also be omitted from the file if the aeroacoustic module is not used. Specify the number of Reynolds number- or aerodynamic-control setting-dependent tables of data for the given airfoil via the @@ -472,18 +475,22 @@ or calculating it based on the polar coefficient data in the airfoil table: - ``alpha1`` specifies the AoA (in degrees) larger than ``alpha0`` for which *f* equals 0.7; approximately the positive stall angle; + This parameter is used when ``flookup=false`` and when determining + a default value of ``Cn1``. - ``alpha2`` specifies the AoA (in degrees) less than ``alpha0`` for which *f* equals 0.7; approximately the negative stall angle; + This parameter is used when ``flookup=false`` and when determining + a default value of ``Cn2``. - ``alphaUpper`` specifies the AoA (in degrees) of the upper boundary of - fully-attached region of the cn or cl curve. It is used to - compute the separation function when ``UAMod=5``. + fully-attached region of the cn or cl curve. It is used to + compute the separation function when ``UAMod=5``. - ``alphaLower`` specifies the AoA (in degrees) of the lower boundary of - fully-attached region of the cn or cl curve. It is used to - compute the separation function when ``UAMod=5``. (The separation function - will have a value of 1 between ``alphaUpper`` and ``alphaLower``.) + fully-attached region of the cn or cl curve. It is used to + compute the separation function when ``UAMod=5``. (The separation function + will have a value of 1 between ``alphaUpper`` and ``alphaLower``.) - ``eta_e`` is the recovery factor and typically has a value in the range [0.85 to 0.95] for ``UAMod = 1``; if the keyword ``DEFAULT`` is diff --git a/glue-codes/fast-farm/src/FAST_Farm_IO.f90 b/glue-codes/fast-farm/src/FAST_Farm_IO.f90 index c31bc708b..92c914c71 100644 --- a/glue-codes/fast-farm/src/FAST_Farm_IO.f90 +++ b/glue-codes/fast-farm/src/FAST_Farm_IO.f90 @@ -11064,7 +11064,7 @@ SUBROUTINE WriteFarmOutputToFile( t_global, farm, ErrStat, ErrMsg ) REAL(DbKi) :: OutTime ! Used to determine if output should be generated at this simulation time INTEGER(IntKi) :: ErrStat2 CHARACTER(ErrMsgLen) :: ErrMSg2 - CHARACTER(*), PARAMETER :: RoutineName = 'WriteOutputToFile' + CHARACTER(*), PARAMETER :: RoutineName = 'WriteFarmOutputToFile' CHARACTER(200) :: Frmt ! A string to hold a format specifier CHARACTER(farm%p%TChanLen) :: TmpStr ! temporary string to print the time output as text CHARACTER(ChanLen) :: TmpStr2 ! temporary string to print the output as text diff --git a/modules/aerodyn/src/AirfoilInfo.f90 b/modules/aerodyn/src/AirfoilInfo.f90 index cc96479a3..7ac829fe0 100644 --- a/modules/aerodyn/src/AirfoilInfo.f90 +++ b/modules/aerodyn/src/AirfoilInfo.f90 @@ -37,7 +37,7 @@ MODULE AirfoilInfo TYPE(ProgDesc), PARAMETER :: AFI_Ver = ProgDesc( 'AirfoilInfo', '', '') ! The name, version, and date of AirfoilInfo. -integer, parameter :: MaxNumAFCoeffs = 7 !cl,cd,cm,cpMin, UA:f_st, FullySeparate, FullyAttached + integer, parameter :: MaxNumAFCoeffs = 7 !cl,cd,cm,cpMin, UA:f_st, FullySeparate, FullyAttached CONTAINS @@ -385,7 +385,7 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) TYPE (FileInfoType) :: FileInfo ! The derived type for holding the file information. INTEGER(IntKi) :: NumCoefsTab ! The number of aerodynamic coefficients to be stored. - INTEGER(IntKi) :: DefaultInterpOrd ! value of default interp order + INTEGER(IntKi), parameter :: DefaultInterpOrd = 1 ! value of default interp order INTEGER(IntKi) :: ErrStat2 ! Error status local to this routine. CHARACTER(ErrMsgLen) :: ErrMsg2 CHARACTER(*), PARAMETER :: RoutineName = 'ReadAFfile' @@ -397,7 +397,7 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) ErrStat = ErrID_None ErrMsg = "" defaultStr = "" - + ! Getting parent folder of airfoils data (e.g. "Arifoils/") CALL GetPath( InitInp%FileName, PriPath ) @@ -417,9 +417,6 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) CurLine = 1 - ! Default to linear interpolation - DefaultInterpOrd = 1 - CALL ParseVarWDefault ( FileInfo, CurLine, 'InterpOrd', p%InterpOrd, DefaultInterpOrd, ErrStat2, ErrMsg2, UnEc ) CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF (ErrStat >= AbortErrLev) THEN @@ -434,8 +431,8 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) !call WrScr('Skipping. RelThickness not found on line 7 of Profile file: '//trim(InitInp%FileName) ) else CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) - endif - + end if + ! NonDimArea is currently unused by AirfoilInfo or codes using AirfoilInfo. GJH 9/13/2017 CALL ParseVar ( FileInfo, CurLine, 'NonDimArea', p%NonDimArea, ErrStat2, ErrMsg2, UnEc ) @@ -480,15 +477,12 @@ SUBROUTINE ReadAFfile ( InitInp, NumCoefsIn, p, ErrStat, ErrMsg, UnEc ) ENDDO ! Row ENDIF - + ! Reading Boundary layer file for aeroacoustics CALL ParseVar ( FileInfo, CurLine, 'BL_file' , p%BL_file , ErrStat2, ErrMsg2, UnEc ) IF (ErrStat2 >= AbortErrLev) p%BL_file = "NOT_SET_IN_AIRFOIL_FILE" !CALL SetErrStat( ErrStat2, ErrMsg2, ErrStat, ErrMsg, RoutineName ) IF ( PathIsRelative( p%BL_file ) ) p%BL_file=trim(PriPath)//trim(p%BL_file) - - ! How many columns do we need to read in the input and how many total coefficients will be used? - ! How many columns do we need to read in the input and how many total coefficients will be used? @@ -859,8 +853,10 @@ SUBROUTINE CalculateUACoeffs(CalcDefaults,p,ColCl,ColCd,ColCm,ColUAf,UA_f_cn) REAL(ReKi) :: slope REAL(ReKi) , PARAMETER :: CnSlopeThreshold = 0.90; REAL(ReKi) , PARAMETER :: fAtCriticalCn = 0.7; + REAL(ReKi) :: LimitAlphaRange + LimitAlphaRange = 20.0_ReKi * D2R ! range we're limiting our equations to (in radians) col_fs = ColUAf + 1 @@ -905,7 +901,7 @@ SUBROUTINE CalculateUACoeffs(CalcDefaults,p,ColCl,ColCd,ColCm,ColUAf,UA_f_cn) ! Calculate based on airfoil polar: !------------------------------------- ! if Cd is constant, does this cause issues??? - iCdMin = minloc(p%Coefs(:,ColCd),DIM=1) + iCdMin = minloc(p%Coefs(:,ColCd),DIM=1, MASK=abs(p%alpha)<=LimitAlphaRange) if (CalcDefaults%Cd0) p%UA_BL%Cd0 = p%Coefs(iCdMin,ColCd) alphaAtCdMin = p%alpha(iCdMin) @@ -929,7 +925,8 @@ SUBROUTINE CalculateUACoeffs(CalcDefaults,p,ColCl,ColCd,ColCm,ColUAf,UA_f_cn) CnSlopeAtCdMin = InterpStp( alphaAtCdMin, alpha_, CnSlope_, iLow, p%NumAlf-1 ) !find alphaUpper (using smoothed Cn values): - iHigh = minloc( abs( alpha_ - 20.0_ReKi*D2R ),DIM=1 ) ! we can limit this to ~20 degrees + iHigh = minloc( alpha_ ,DIM=1, MASK=alpha_ >= LimitAlphaRange ) ! we can limit this to ~20 degrees + iHigh2 = iHigh if (CalcDefaults%alphaUpper) then if (iHighiCdMin) iLow = 1 maxCnSlope = CnSlopeAtCdMin - iLow2 = min(iCdMin, p%NumAlf-1) + iLow2 = min(iHigh2-1, iCdMin-1, p%NumAlf-1) - do Row = min(iCdMin, p%NumAlf-1) ,iLow,-1 + do Row = min(iHigh2-1, iCdMin-1, p%NumAlf-1) ,iLow,-1 iLow2 = Row if (CnSlope_(Row) > maxCnSlope) then maxCnSlope = CnSlope_(Row); end if + + if ( CnSlope_(Row) < CnSlopeThreshold*maxCnSlope ) exit end do @@ -1020,7 +1018,7 @@ SUBROUTINE CalculateUACoeffs(CalcDefaults,p,ColCl,ColCd,ColCm,ColUAf,UA_f_cn) p%Coefs(:,col_fa) = 0.0_ReKi call ComputeUASeparationFunction_zero(p, ColUAf, p%Coefs(:,ColCl)) ! just to initialize these values... UA will turn off without using them else - + do Row=1,p%NumAlf if (EqualRealNos( p%alpha(Row), p%UA_BL%alpha0)) then @@ -1030,7 +1028,7 @@ SUBROUTINE CalculateUACoeffs(CalcDefaults,p,ColCl,ColCd,ColCm,ColUAf,UA_f_cn) cl_ratio = p%Coefs(Row,ColCl) / ( p%UA_BL%c_lalpha*(p%alpha(Row) - p%UA_BL%alpha0)) cl_ratio = max(0.0_ReKi, cl_ratio) - + f_st = ( 2.0_ReKi * sqrt(cl_ratio) - 1.0_ReKi )**2 if (f_st < 1.0_ReKi) then @@ -1052,7 +1050,7 @@ SUBROUTINE CalculateUACoeffs(CalcDefaults,p,ColCl,ColCd,ColCm,ColUAf,UA_f_cn) ! Compute variables to help x3 state with +/-180-degree wrap-around issues ! and make sure that the separation function is monotonic before iLow and after iHigh: call ComputeUASeparationFunction_zero(p, ColUAf, p%Coefs(:,ColCl)) ! this was comparing with alpha0, but now we compaer with alphaUpper and alphaLower - + ! Ensuring everything is in harmony do Row=1,p%NumAlf @@ -1072,7 +1070,7 @@ SUBROUTINE CalculateUACoeffs(CalcDefaults,p,ColCl,ColCd,ColCm,ColUAf,UA_f_cn) end if ! c_lalpha == 0 - + else call ComputeUASeparationFunction(p, ColUAf, cn) @@ -1201,11 +1199,7 @@ SUBROUTINE ComputeUASeparationFunction(p, ColUAf, cn_cl) iLow = p%NumAlf - 1 ! we can't have IndLower > IndUpper, so fix it here. end if ! figure out which side of iLow to compute the slope later: - if (p%UA_BL%alphaLower < p%alpha(iLow) .and. iLow > 1) then - iLow_2= iLow - 1 - else - iLow_2 = iLow + 1 - end if + iLow_2 = iLow + 1 iLow_1 = iLow ! get value @@ -1226,13 +1220,9 @@ SUBROUTINE ComputeUASeparationFunction(p, ColUAf, cn_cl) end if end if ! figure out which side of iHigh to compute the slope later: - if (p%UA_BL%alphaUpper < p%alpha(iHigh) .or. iHigh == p%NumAlf) then - iHigh_2= iHigh - 1 - else - iHigh_2 = iHigh + 1 - end if + iHigh_2= iHigh - 1 iHigh_1 = iHigh - + p%UA_BL%c_alphaUpper = InterpStp( p%UA_BL%alphaUpper, p%alpha, cn_cl, iHigh, p%NumAlf ) !------------------------------------------------ @@ -1609,6 +1599,10 @@ subroutine AFI_ComputeAirfoilCoefs( AOA, Re, UserProp, p, AFI_interp, errStat, e call AFI_ComputeAirfoilCoefs2D( AOA, UserProp, p, AFI_interp, errStat, errMsg ) end if + ! put some limits on the separation function: + AFI_interp%f_st = min( max( AFI_interp%f_st, 0.0_ReKi), 1.0_ReKi) ! separation function + + end subroutine AFI_ComputeAirfoilCoefs !---------------------------------------------------------------------------------------------------------------------------------- diff --git a/modules/turbsim/src/TSsubs.f90 b/modules/turbsim/src/TSsubs.f90 index f8b50992f..ebb48b81a 100644 --- a/modules/turbsim/src/TSsubs.f90 +++ b/modules/turbsim/src/TSsubs.f90 @@ -650,16 +650,9 @@ SUBROUTINE CalcFourierCoeffs_API( p, U, PhaseAngles, S, V, TRH, ErrStat, ErrMsg DO J=max(1, p%usr%NPoints),p%grid%NPoints DO I=J,p%grid%NPoints -!mlb: THis is where to look for the error. - -!mlb TEMP_Y=Coef_AlphaY*p%grid%Freq(IFreq)**Coef_RY*(Dist_Y(Indx)/Coef_1)**Coef_QY*(Dist_Z12(Indx)/Coef_2)**(-0.5*Coef_PY) -!mlb TEMP_Z=Coef_AlphaZ*p%grid%Freq(IFreq)**Coef_RZ*(Dist_Z(Indx)/Coef_1)**Coef_QZ*(Dist_Z12(Indx)/Coef_2)**(-0.5*Coef_PZ) - -!dist_x is zero, so we ignore it here (i.e., A_X = 0) A_Y = Alpha(2) * (p%grid%Freq(IFreq)**rc(2)) * ((Dist_Y(Indx)/Coef_1)**qc(2)) * (z_g(Indx)**(-pc(2))) A_Z = Alpha(3) * (p%grid%Freq(IFreq)**rc(3)) * ((Dist_Z(Indx)/Coef_1)**qc(3)) * (z_g(Indx)**(-pc(3))) -!mlb TRH(Indx)=EXP(-Coef_1*SQRT(TEMP_Y**2+TEMP_Z**2)/U0_1HR) TRH(Indx)=EXP(- Coef_1 * SQRT(A_Y**2 + A_Z**2) / p%met%URef) Indx = Indx + 1 From c5307062c80eed350f0f482c59f14f91830ff8c6 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Sat, 13 Nov 2021 18:09:04 -0700 Subject: [PATCH 2/3] Remove hard-coded version numbers/dates on modules --- glue-codes/fast-farm/src/FASTWrapper.f90 | 2 +- glue-codes/fast-farm/src/FAST_Farm_IO.f90 | 2 +- modules/aerodyn/src/AeroAcoustics_IO.f90 | 2 +- modules/feamooring/src/FEAM.f90 | 2 +- modules/icedyn/src/IceDyn.f90 | 2 +- modules/icefloe/src/interfaces/FAST/IceFloe.f90 | 2 +- modules/moordyn/src/MoorDyn.f90 | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/glue-codes/fast-farm/src/FASTWrapper.f90 b/glue-codes/fast-farm/src/FASTWrapper.f90 index ad3c27558..2a922ed67 100644 --- a/glue-codes/fast-farm/src/FASTWrapper.f90 +++ b/glue-codes/fast-farm/src/FASTWrapper.f90 @@ -33,7 +33,7 @@ MODULE FASTWrapper PRIVATE - TYPE(ProgDesc), PARAMETER :: FWrap_Ver = ProgDesc( 'FASTWrapper', 'v1.00.00', '7-Feb-2017' ) !< module date/version information + TYPE(ProgDesc), PARAMETER :: FWrap_Ver = ProgDesc( 'FASTWrapper', '', '' ) !< module date/version information REAL(DbKi), PARAMETER :: t_initial = 0.0_DbKi ! Initial time diff --git a/glue-codes/fast-farm/src/FAST_Farm_IO.f90 b/glue-codes/fast-farm/src/FAST_Farm_IO.f90 index 92c914c71..27a30607e 100644 --- a/glue-codes/fast-farm/src/FAST_Farm_IO.f90 +++ b/glue-codes/fast-farm/src/FAST_Farm_IO.f90 @@ -6,7 +6,7 @@ module FAST_Farm_IO IMPLICIT NONE ! The maximum number of output channels which can be output by the code. INTEGER(IntKi), PARAMETER :: Farm_MaxOutPts = 9423 -TYPE(ProgDesc), PARAMETER :: Farm_Ver = ProgDesc( 'FAST.Farm', 'v0.01.02a-jmj', '04-Jul-2017' ) !< module date/version information +TYPE(ProgDesc), PARAMETER :: Farm_Ver = ProgDesc( 'FAST.Farm', '', '' ) !< module date/version information ! =================================================================================================== ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" ! using the parameters listed in the "OutListParameters3.xlsx" Excel file. Any changes to these diff --git a/modules/aerodyn/src/AeroAcoustics_IO.f90 b/modules/aerodyn/src/AeroAcoustics_IO.f90 index 1fde6bc86..cbb1666d5 100644 --- a/modules/aerodyn/src/AeroAcoustics_IO.f90 +++ b/modules/aerodyn/src/AeroAcoustics_IO.f90 @@ -8,7 +8,7 @@ MODULE AeroAcoustics_IO implicit none - type(ProgDesc), parameter :: AA_Ver = ProgDesc( 'AeroAcoustics', 'v1.00.00', '18-Aug-2016' ) + type(ProgDesc), parameter :: AA_Ver = ProgDesc( 'AeroAcoustics', '', '' ) character(*), parameter :: AA_Nickname = 'AA' diff --git a/modules/feamooring/src/FEAM.f90 b/modules/feamooring/src/FEAM.f90 index 7402e939f..f1e541e6e 100644 --- a/modules/feamooring/src/FEAM.f90 +++ b/modules/feamooring/src/FEAM.f90 @@ -25,7 +25,7 @@ MODULE FEAMooring PRIVATE - TYPE(ProgDesc), PARAMETER :: FEAM_Ver = ProgDesc( 'FEAMooring', 'v1.02.01', '23-Jul-2016' ) + TYPE(ProgDesc), PARAMETER :: FEAM_Ver = ProgDesc( 'FEAMooring', '', '' ) ! ===================================================================================================" ! NOTE: The following lines of code were generated by a Matlab script called "Write_ChckOutLst.m" diff --git a/modules/icedyn/src/IceDyn.f90 b/modules/icedyn/src/IceDyn.f90 index 64ed3f375..454777b03 100644 --- a/modules/icedyn/src/IceDyn.f90 +++ b/modules/icedyn/src/IceDyn.f90 @@ -37,7 +37,7 @@ MODULE IceDyn PRIVATE - TYPE(ProgDesc), PARAMETER :: IceD_Ver = ProgDesc( 'IceDyn', 'v1.02.01', '23-Jul-2016' ) + TYPE(ProgDesc), PARAMETER :: IceD_Ver = ProgDesc( 'IceDyn', '', '' ) ! ..... Public Subroutines ................................................................................................... diff --git a/modules/icefloe/src/interfaces/FAST/IceFloe.f90 b/modules/icefloe/src/interfaces/FAST/IceFloe.f90 index 5f447efdb..f257ddeb6 100644 --- a/modules/icefloe/src/interfaces/FAST/IceFloe.f90 +++ b/modules/icefloe/src/interfaces/FAST/IceFloe.f90 @@ -54,7 +54,7 @@ MODULE IceFloe PRIVATE - TYPE(ProgDesc), PARAMETER :: IceFloe_Ver = ProgDesc( 'IceFloe', 'v1.01.01', '23-Jul-2016' ) + TYPE(ProgDesc), PARAMETER :: IceFloe_Ver = ProgDesc( 'IceFloe', '', '' ) ! ..... Public Subroutines ................................................................................................... diff --git a/modules/moordyn/src/MoorDyn.f90 b/modules/moordyn/src/MoorDyn.f90 index 4d1accbd5..be03841bb 100644 --- a/modules/moordyn/src/MoorDyn.f90 +++ b/modules/moordyn/src/MoorDyn.f90 @@ -27,7 +27,7 @@ MODULE MoorDyn PRIVATE - TYPE(ProgDesc), PARAMETER :: MD_ProgDesc = ProgDesc( 'MoorDyn', 'v1.01.02F', '8-Apr-2016' ) + TYPE(ProgDesc), PARAMETER :: MD_ProgDesc = ProgDesc( 'MoorDyn', '', '' ) PUBLIC :: MD_Init From ad0c22aaa5bfbec52f2040072dad8e6f4606f316 Mon Sep 17 00:00:00 2001 From: Bonnie Jonkman Date: Tue, 16 Nov 2021 14:45:02 -0700 Subject: [PATCH 3/3] Update UA documentation for default AFI parameters --- docs/source/user/aerodyn/theory_ua.rst | 89 ++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/docs/source/user/aerodyn/theory_ua.rst b/docs/source/user/aerodyn/theory_ua.rst index 5522e42da..7c66917bb 100644 --- a/docs/source/user/aerodyn/theory_ua.rst +++ b/docs/source/user/aerodyn/theory_ua.rst @@ -139,7 +139,29 @@ as the function reaches :math:`0` on both sides of :math:`\alpha_0`, then :math:`f_s^{st}` is kept at the constant value :math:`0`. +**Note that for UAMod=5, a different separation function is formed.** +We define an offset for the :math:`C_n` function, ``cn_offset``, where +:math:`C_{n,offset}=\frac{C_n\left(\alpha^{Lower}\right)+C_n\left(\alpha^{Upper}\right)}{2}`. Then, the separation function +is a value between 0 and 1, given by the following equation: + +.. math:: + + f_s^{st}(\alpha) = \left[ 2 \max\left\{\frac{1}{4} , \sqrt{\frac{C_n^{st}(\alpha) - C_{n,offset}}{C_n^{fullyAttached}(\alpha)-C_{n,offset}}} \right\} -1 \right]^2 + +with the fully-attached :math:`C_n` curve defined as :math:`C_n` between :math:`alpha^{Lower}` and :math:`alpha^{Upper}` and linear functions outside of that range: + +.. math:: + + C_n^{fullyAttached}(\alpha) = \begin{cases} C_n\left(\alpha^{Upper}\right) + C_n^{slope}\left(\alpha^{Upper}\right) \cdot \left(\alpha-\alpha^{Upper}\right) & \alpha>\alpha^{Upper} \\ + C_n(\alpha) & \alpha^{Lower}<=\alpha<=\alpha^{Upper} \\ + C_n\left(\alpha^{Lower}\right) + C_n^{slope}\left(\alpha^{Lower}\right) \cdot \left(\alpha-\alpha^{Lower}\right) & \alpha<\alpha^{Lower} \end{cases} + +Note that to avoid numerical issues at the :math:`\pm180` degree boundary, this function changes slope when the separation function is 0 above :math:`alpha^{Upper}` and below :math:`alpha^{Lower}`. +This allow the fully-attached linear sections to be periodic and avoid numerical issues with large magnitudes of angle of attack. + + **Inviscid and fully separated lift coefficient:** + The inviscid lift coefficient is :math:`C_{l,\text{inv}}= C_{l,\alpha} (\alpha-\alpha_0)`. The fully separated lift coefficient may @@ -465,6 +487,7 @@ Inputs See :numref:`ad_ua_inputs` for a description of the inputs necessary in the AeroDyn primary file (e.g. ``UAMod``) See :numref:`airfoil_data_input_file` for a more comprehensive description of all the inputs present in the profile input file. +Their default values are described in :numref:`UA_AFI_defaults` See :numref:`ua_notations` for a list of notations and definitions specific to unsteady aerodynamic inputs. @@ -472,6 +495,71 @@ An example of profile data (containing some of the unsteady aerodynamic paramete :download:`(here) `. +.. _UA_AFI_defaults: + +Calculating Default Airfoil Coefficients +---------------------------------------- + +The default value for ``cd0`` is the minimum value of the :math:`C_d` curve between :math:`\pm20` degrees angle of attack. +:math:`\alpha_{c_{d0}}` is defined to be the angle of attack where ``cd0`` occurs. + +After computing ``cd0``, the :math:`C_n` curve is computed by + +.. math:: + C_{n}(\alpha) = C_l(\alpha) \cos\alpha + \left(C_d(\alpha) - c_{d0}\right) \sin\alpha + +The slope of the :math:`C_n` curve is computed as follows: + +.. math:: + C_{n}^{Slope}\left(\frac{\alpha_{i+1} + \alpha_i}{2}\right) = \frac{C_n(\alpha_{i+1}) - C_n(\alpha_i)}{\alpha_{i+1} - \alpha_i} + +:math:`C_{n,smooth}^{Slope}` is a smoothed version of :math:`C_{n}^{Slope}`, calculated using a triweight kernel with a window of 2 degrees. + + +.. math:: + C_{l}^{Slope}\left(\frac{\alpha_{i+1} + \alpha_i}{2}\right) = \frac{C_l(\alpha_{i+1}) - C_l(\alpha_i)}{\alpha_{i+1} - \alpha_i} + + +Using :math:`C_{n,smooth}^{Slope}`, ``alphaUpper`` and ``alphaLower`` are computed: + +``alphaUpper`` is the smallest angle of attack value between :math:`\alpha_{c_{d0}}` and 20 degrees where the :math:`C_{n,smooth}^{Slope}` curve has started to decrease to 90% of its maximum slope. + +.. math:: + C_{n,smooth}^{Slope}\left(\alpha^{Upper}\right) < 0.9 \max_{\alpha \in \left[\alpha_{c_{d0}}, \alpha^{Upper}\right]} C_{n,smooth}^{Slope}\left( \alpha \right) + + +``alphaLower`` is the largest angle of attack value between -20 degrees and :math:`\alpha_{c_{d0}}` where the :math:`C_{n,smooth}^{Slope}` curve has started to decrease to 90% of its maximum slope. + +.. math:: + C_{n,smooth}^{Slope}\left(\alpha^{Lower}\right) < 0.9 \max_{\alpha \in \left[\alpha^{Lower}, \alpha_{c_{d0}}\right]} C_{n,smooth}^{Slope}\left( \alpha \right) + +``Cn1`` is the value of :math:`C_n(\alpha)` at the smallest value of :math:`\alpha` where :math:`\alpha >= \alpha^{Upper}` and the separation function, :math:`f_{st}(\alpha)` = 0.7. + +``Cn2`` is the value of :math:`C_n(\alpha)` at the largest value of :math:`\alpha` where :math:`\alpha <= \alpha^{Lower}` and the separation function, :math:`f_{st}(\alpha)` = 0.7. + +``Cn_offset`` is the average value of the :math:`C_n` curve at ``alphaUpper`` and ``alphaLower``: + +.. math:: + C_{n}^{offset} = \frac{C_n\left(\alpha^{Lower}\right) + C_n\left(\alpha^{Upper}\right)}{2} + +``C_nalpha`` is defined as the maximum slope of the smoothed :math:`C_n` curve, :math:`C_{n,smooth}^{Slope}` between :math:`\pm20` degrees angle of attack. + +``C_lalpha`` is defined as the maximum slope of the (un-smoothed) :math:`C_l` curve, :math:`C_{l}^{Slope}` between :math:`\pm20` degrees angle of attack. + +The default ``alpha0`` is computed as the zero-crossing of a line with a slope equal to ``C_lalpha`` that goes through the :math:`C_l` curve at :math:`\alpha = \frac{\alpha^{Upper} + \alpha^{Lower}}{2}` + +.. math:: + \alpha_0 = \frac{\alpha^{Upper} + \alpha^{Lower}}{2} - \frac{C_l\left(\frac{\alpha^{Upper} + \alpha^{Lower}}{2}\right) }{C_{l,\alpha}} + +``Cm0`` is the value of the :math:`C_m` curve at ``alpha0``: :math:`C_{m,0} = C_m\left(\alpha_0\right)`. If the :math:`C_m` polar values have not been included, :math:`C_{m,0} =0`. + +``alpha1`` is the angle of attack above ``alphaUpper`` where the separation function, :math:`f_s^{st}` is 0.7. + +``alpha2`` is the angle of attack below ``alphaLower`` where the separation function, :math:`f_s^{st}` is 0.7. + +``Cn1`` is the value of the :math:`C_n` curve at ``alpha1``. + +``Cn2`` is the value of the :math:`C_n` curve at ``alpha2``. @@ -485,6 +573,7 @@ To activate these outputs with `cmake`, compile using ``-DCMAKE_Fortran_FLAGS="- + Driver ------