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/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/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/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/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 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/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. 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: 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 diff --git a/modules/aerodyn/src/AeroDyn.f90 b/modules/aerodyn/src/AeroDyn.f90 index 91aa7fb096..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 @@ -2869,7 +2870,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.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..423533f146 100644 --- a/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 +++ b/modules/aerodyn/src/AeroDyn_Driver_Subs.f90 @@ -138,9 +138,11 @@ 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 - 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 +202,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 +218,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() @@ -620,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)) @@ -788,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 @@ -800,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') @@ -853,7 +856,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 @@ -920,8 +925,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 +1227,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 +1275,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 +1302,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) @@ -1334,8 +1345,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 @@ -1348,7 +1359,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,9 +1369,15 @@ 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)) - wt%bld(:)%pitch = myNaN + allocate(wt%bld(wt%numBlades), stat=ErrStat2) + if (errStat2 /= 0) then + ErrStat2=ErrID_Fatal + ErrMsg2 = "Error allocating wt%bld" + if(Failed()) return + end if + 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 @@ -1458,8 +1475,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 @@ -1480,8 +1497,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 @@ -1563,6 +1582,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() @@ -1582,6 +1602,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 @@ -1589,8 +1611,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 @@ -1750,7 +1776,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 ! @@ -1819,7 +1848,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 @@ -1844,7 +1878,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 @@ -2090,8 +2124,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/AeroDyn_IO.f90 b/modules/aerodyn/src/AeroDyn_IO.f90 index 1e9906dbdb..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 @@ -2530,11 +2532,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 +2561,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/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 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 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." diff --git a/modules/nwtc-library/src/NWTC_IO.f90 b/modules/nwtc-library/src/NWTC_IO.f90 index e90b142a86..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' @@ -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 @@ -4726,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. @@ -4765,9 +4766,21 @@ 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 + + ! initialize this, just in case + FileInfo%FileIndx = 1 + ! 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 +4788,13 @@ SUBROUTINE ProcessComFile ( TopFileName, FileInfo, ErrStat, ErrMsg ) RETURN ENDIF - CALL Cleanup() + 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 !======================================================================= @@ -5216,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. @@ -5285,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 @@ -5293,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. @@ -5308,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