From 1d77a260b41c64971acead808d3593ce52b56acf Mon Sep 17 00:00:00 2001 From: pibo Date: Wed, 11 Nov 2020 16:22:45 -0700 Subject: [PATCH 1/5] max blade root flapwise moment out of openfast --- weis/aeroelasticse/openmdao_openfast.py | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/weis/aeroelasticse/openmdao_openfast.py b/weis/aeroelasticse/openmdao_openfast.py index 6229bb0c3..01461b1c7 100644 --- a/weis/aeroelasticse/openmdao_openfast.py +++ b/weis/aeroelasticse/openmdao_openfast.py @@ -256,8 +256,10 @@ def setup(self): self.add_output('loads_pitch', val=0.0, units='deg', desc='pitch angle') self.add_output('loads_azimuth', val=0.0, units='deg', desc='azimuthal angle') - self.add_output('Fxyz', val=np.zeros(3), units='N') - self.add_output('Mxyz', val=np.zeros(3), units='N*m') + self.add_output('Fxyz', val=np.zeros(3), units='kN', desc = 'Maximum hub forces in the non rotating frame') + self.add_output('Mxyz', val=np.zeros(3), units='kN*m', desc = 'Maximum hub moments in the non rotating frame') + self.add_output('max_RootMyb', val=0.0, units='kN*m', desc = 'Maximum of the signals RootMyb1, RootMyb2, ... across all n blades representing the maximum blade root flapwise moment') + self.add_output('max_RootMyc', val=0.0, units='kN*m', desc = 'Maximum of the signals RootMyb1, RootMyb2, ... across all n blades representing the maximum blade root out of plane moment') self.add_output('C_miners_SC_SS', val=np.zeros((n_span, n_mat, 2)), desc="Miner's rule cummulative damage to Spar Cap, suction side") self.add_output('C_miners_SC_PS', val=np.zeros((n_span, n_mat, 2)), desc="Miner's rule cummulative damage to Spar Cap, pressure side") @@ -832,14 +834,15 @@ def post_process(self, FAST_Output, case_list, dlc_list, inputs, discrete_inputs outputs['loads_pitch'] = extreme_table[tip_max_chan][np.argmax(sum_stats[tip_max_chan]['max'])]['BldPitch1']['val'] outputs['loads_azimuth'] = extreme_table[tip_max_chan][np.argmax(sum_stats[tip_max_chan]['max'])]['Azimuth']['val'] - # # Determine blade with the maximum root moment - # defl_mag = [max(sum_stats['RootMc1']['max']), max(sum_stats['RootMc2']['max']), max(sum_stats['RootMc3']['max'])] - # if np.argmax(defl_mag) == 0: - # outputs['Mxyz'] = np.array(["RootMxc1", "RootMyc1", "RootMzc1"])*1.e3 - # if np.argmax(defl_mag) == 1: - # outputs['Mxyz'] = np.array(["RootMxc2", "RootMyc2", "RootMzc2"])*1.e3 - # if np.argmax(defl_mag) == 2: - # outputs['Mxyz'] = np.array(["RootMxc3", "RootMyc3", "RootMzc3"])*1.e3 + # Determine maximum root moment + if self.n_blades == 2: + blade_root_flap_moment = max([max(sum_stats['RootMyb1']['max']), max(sum_stats['RootMyb2']['max'])]) + blade_root_oop_moment = max([max(sum_stats['RootMyc1']['max']), max(sum_stats['RootMyc2']['max'])]) + else: + blade_root_flap_moment = max([max(sum_stats['RootMyb1']['max']), max(sum_stats['RootMyb2']['max']), max(sum_stats['RootMyb3']['max'])]) + blade_root_oop_moment = max([max(sum_stats['RootMyc1']['max']), max(sum_stats['RootMyc2']['max']), max(sum_stats['RootMyc3']['max'])]) + outputs['max_RootMyb'] = blade_root_flap_moment + outputs['max_RootMyc'] = blade_root_oop_moment ## Get hub momements and forces in the non-rotating frame outputs['Fxyz'] = np.array([extreme_table['LSShftF'][np.argmax(sum_stats['LSShftF']['max'])]['RotThrust']['val'], From 8a17720c7fe8449344a9390bdab4d54919726c3f Mon Sep 17 00:00:00 2001 From: pibo Date: Mon, 16 Nov 2020 13:40:39 -0700 Subject: [PATCH 2/5] P T Q M out of ccblade --- WISDEM/wisdem/ccblade/ccblade_component.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/WISDEM/wisdem/ccblade/ccblade_component.py b/WISDEM/wisdem/ccblade/ccblade_component.py index 8467d3c78..79c385a58 100644 --- a/WISDEM/wisdem/ccblade/ccblade_component.py +++ b/WISDEM/wisdem/ccblade/ccblade_component.py @@ -372,6 +372,10 @@ def setup(self): self.add_output('theta', val=np.zeros(n_span), units='rad', desc='Twist angle at each section (positive decreases angle of attack)') self.add_output('CP', val=0.0, desc='Rotor power coefficient') self.add_output('GenPwr',val=0.0, units='W', desc='Generator electrical power') + self.add_output('P', val=0.0, units='W', desc='Rotor aerodynamic power') + self.add_output('T', val=0.0, units='N*m', desc='Rotor aerodynamic thrust') + self.add_output('Q', val=0.0, units='N*m', desc='Rotor aerodynamic torque') + self.add_output('M', val=0.0, units='N*m', desc='Blade root flapwise moment') self.add_output('CM', val=0.0, desc='Blade flapwise moment coefficient') self.add_output('a', val=np.zeros(n_span), desc='Axial induction along blade span') self.add_output('ap', val=np.zeros(n_span), desc='Tangential induction along blade span') @@ -499,7 +503,7 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): myout, derivs = get_cp_cm.evaluate([inputs['Uhub']], [Omega], [inputs['pitch']], coefficients=True) - P, _, _, _, CP, CT, CQ, CM = [myout[key] for key in ['P','T','Q','M','CP','CT','CQ','CM']] + P, T, Q, M, CP, CT, CQ, CM = [myout[key] for key in ['P','T','Q','M','CP','CT','CQ','CM']] # if self.options['opt_options']['optimization_variables']['blade']['aero_shape']['twist']['flag']: get_cp_cm.induction = False @@ -513,6 +517,10 @@ def compute(self, inputs, outputs, discrete_inputs, discrete_outputs): outputs['CP'] = CP[0] outputs['CM'] = CM[0] outputs['GenPwr'] = P*inputs['gearbox_efficiency']*inputs['generator_efficiency'] + outputs['P'] = P + outputs['M'] = M + outputs['T'] = T + outputs['Q'] = Q outputs['a'] = loads['a'] outputs['ap'] = loads['ap'] outputs['alpha'] = loads['alpha'] From 58800dafd1745aa03fdb8ccd084647bd9488b812 Mon Sep 17 00:00:00 2001 From: pibo Date: Thu, 19 Nov 2020 11:48:23 -0700 Subject: [PATCH 3/5] stall margin from OF --- weis/aeroelasticse/openmdao_openfast.py | 33 +++++++++++++++++++++++++ weis/glue_code/glue_code.py | 13 ++++++---- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/weis/aeroelasticse/openmdao_openfast.py b/weis/aeroelasticse/openmdao_openfast.py index 01461b1c7..e0d138852 100644 --- a/weis/aeroelasticse/openmdao_openfast.py +++ b/weis/aeroelasticse/openmdao_openfast.py @@ -265,6 +265,9 @@ def setup(self): self.add_output('C_miners_SC_PS', val=np.zeros((n_span, n_mat, 2)), desc="Miner's rule cummulative damage to Spar Cap, pressure side") # self.add_output('C_miners_TE_SS', val=np.zeros((n_span, n_mat, 2)), desc="Miner's rule cummulative damage to Trailing-Edge reinforcement, suction side") # self.add_output('C_miners_TE_PS', val=np.zeros((n_span, n_mat, 2)), desc="Miner's rule cummulative damage to Trailing-Edge reinforcement, pressure side") + self.add_output('max_aoa', val=np.zeros(n_span), units='deg', desc='distributed angles of attack - max') + self.add_output('std_aoa', val=np.zeros(n_span), units='deg', desc='distributed angles of attack - std') + self.add_output('mean_aoa', val=np.zeros(n_span), units='deg', desc='distributed angles of attack - mean') self.add_discrete_output('fst_vt_out', val={}) @@ -539,10 +542,12 @@ def run_FAST(self, inputs, discrete_inputs, fst_vt): channels_out += ["Spn1MLyb1", "Spn2MLyb1", "Spn3MLyb1", "Spn4MLyb1", "Spn5MLyb1", "Spn6MLyb1", "Spn7MLyb1", "Spn8MLyb1", "Spn9MLyb1"] channels_out += ["RtAeroFxh", "RtAeroFyh", "RtAeroFzh"] channels_out += ["RotThrust", "LSShftFys", "LSShftFzs", "RotTorq", "LSSTipMys", "LSSTipMzs"] + channels_out += ["B1N1Alpha", "B1N2Alpha", "B1N3Alpha", "B1N4Alpha", "B1N5Alpha", "B1N6Alpha", "B1N7Alpha", "B1N8Alpha", "B1N9Alpha", "B2N1Alpha", "B2N2Alpha", "B2N3Alpha", "B2N4Alpha", "B2N5Alpha", "B2N6Alpha", "B2N7Alpha", "B2N8Alpha","B2N9Alpha"] if self.n_blades > 2: channels_out += ["TipDxc3", "TipDyc3", "TipDzc3", "RootMxc3", "RootMyc3", "RootMzc3", "TipDxb3", "TipDyb3", "TipDzb3", "RootMxb3", "RootMyb3", "RootMzb3", "RootFxc3", "RootFyc3", "RootFzc3", "RootFxb3", "RootFyb3", "RootFzb3", "BldPitch3"] channels_out += ["B3N1Fx", "B3N2Fx", "B3N3Fx", "B3N4Fx", "B3N5Fx", "B3N6Fx", "B3N7Fx", "B3N8Fx", "B3N9Fx", "B3N1Fy", "B3N2Fy", "B3N3Fy", "B3N4Fy", "B3N5Fy", "B3N6Fy", "B3N7Fy", "B3N8Fy", "B3N9Fy"] + channels_out += ["B3N1Alpha", "B3N2Alpha", "B3N3Alpha", "B3N4Alpha", "B3N5Alpha", "B3N6Alpha", "B3N7Alpha", "B3N8Alpha", "B3N9Alpha"] # Add additional options if ('channels_out',) in self.options['modeling_options']['openfast']['fst_settings']: @@ -852,6 +857,34 @@ def post_process(self, FAST_Output, case_list, dlc_list, inputs, discrete_inputs extreme_table['LSShftM'][np.argmax(sum_stats['LSShftM']['max'])]['LSSTipMys']['val'], extreme_table['LSShftM'][np.argmax(sum_stats['LSShftM']['max'])]['LSSTipMzs']['val']])*1.e3 + ## Post process aerodynamic data + # Angles of attack - max, std, mean + blade1_chans_aoa = ["B1N1Alpha", "B1N2Alpha", "B1N3Alpha", "B1N4Alpha", "B1N5Alpha", "B1N6Alpha", "B1N7Alpha", "B1N8Alpha", "B1N9Alpha"] + blade2_chans_aoa = ["B2N1Alpha", "B2N2Alpha", "B2N3Alpha", "B2N4Alpha", "B2N5Alpha", "B2N6Alpha", "B2N7Alpha", "B2N8Alpha", "B2N9Alpha"] + aoa_max_B1 = [np.max(sum_stats[var]['max']) for var in blade1_chans_aoa] + aoa_mean_B1 = [np.mean(sum_stats[var]['mean']) for var in blade1_chans_aoa] + aoa_std_B1 = [np.mean(sum_stats[var]['std']) for var in blade1_chans_aoa] + aoa_max_B2 = [np.max(sum_stats[var]['max']) for var in blade2_chans_aoa] + aoa_mean_B2 = [np.mean(sum_stats[var]['mean']) for var in blade2_chans_aoa] + aoa_std_B2 = [np.mean(sum_stats[var]['std']) for var in blade2_chans_aoa] + if self.n_blades == 2: + spline_aoa_max = PchipInterpolator(self.R_out, np.max([aoa_max_B1, aoa_max_B2], axis=0)) + spline_aoa_std = PchipInterpolator(self.R_out, np.mean([aoa_std_B1, aoa_std_B2], axis=0)) + spline_aoa_mean = PchipInterpolator(self.R_out, np.mean([aoa_mean_B1, aoa_mean_B2], axis=0)) + elif self.n_blades == 3: + blade3_chans_aoa = ["B3N1Alpha", "B3N2Alpha", "B3N3Alpha", "B3N4Alpha", "B3N5Alpha", "B3N6Alpha", "B3N7Alpha", "B3N8Alpha", "B3N9Alpha"] + aoa_max_B3 = [np.max(sum_stats[var]['max']) for var in blade3_chans_aoa] + aoa_mean_B3 = [np.mean(sum_stats[var]['mean']) for var in blade3_chans_aoa] + aoa_std_B3 = [np.mean(sum_stats[var]['std']) for var in blade3_chans_aoa] + spline_aoa_max = PchipInterpolator(self.R_out, np.max([aoa_max_B1, aoa_max_B2, aoa_max_B3], axis=0)) + spline_aoa_std = PchipInterpolator(self.R_out, np.mean([aoa_max_B1, aoa_std_B2, aoa_std_B3], axis=0)) + spline_aoa_mean = PchipInterpolator(self.R_out, np.mean([aoa_mean_B1, aoa_mean_B2, aoa_mean_B3], axis=0)) + else: + raise Exception('The calculations only support 2 or 3 bladed rotors') + outputs['max_aoa'] = spline_aoa_max(r) + outputs['std_aoa'] = spline_aoa_std(r) + outputs['mean_aoa'] = spline_aoa_mean(r) + if self.FASTpref['dlc_settings']['run_blade_fatigue']: # determine which dlc will be used for fatigue calculations, checks for dlc 1.2, then dlc 1.1 diff --git a/weis/glue_code/glue_code.py b/weis/glue_code/glue_code.py index f8b554f19..568c17eca 100644 --- a/weis/glue_code/glue_code.py +++ b/weis/glue_code/glue_code.py @@ -81,6 +81,7 @@ def setup(self): self.add_subsystem('freq_tower', TowerSE(modeling_options=modeling_options)) self.add_subsystem('sse_tune', ServoSE_ROSCO(modeling_options = modeling_options)) # Aero analysis self.add_subsystem('aeroelastic', FASTLoadCases(modeling_options = modeling_options, opt_options = opt_options)) + self.add_subsystem('stall_check_of', NoStallConstraint(modeling_options = modeling_options)) self.add_subsystem('rlds', RotorLoadsDeflStrainsWEIS(modeling_options = modeling_options, opt_options = opt_options, freq_run=False)) @@ -255,15 +256,17 @@ def setup(self): self.connect('configuration.turb_class', 'sse.gust.turbulence_class') # Connections to the stall check - self.connect('blade.outer_shape_bem.s', 'stall_check.s') - self.connect('airfoils.aoa', 'stall_check.airfoils_aoa') - self.connect('xf.cl_interp_flaps', 'stall_check.airfoils_cl') - self.connect('xf.cd_interp_flaps', 'stall_check.airfoils_cd') - self.connect('xf.cm_interp_flaps', 'stall_check.airfoils_cm') + self.connect('blade.outer_shape_bem.s', ['stall_check.s', 'stall_check_of.s']) + self.connect('airfoils.aoa', ['stall_check.airfoils_aoa', 'stall_check_of.airfoils_aoa']) + self.connect('xf.cl_interp_flaps', ['stall_check.airfoils_cl', 'stall_check_of.airfoils_cl']) + self.connect('xf.cd_interp_flaps', ['stall_check.airfoils_cd', 'stall_check_of.airfoils_cd']) + self.connect('xf.cm_interp_flaps', ['stall_check.airfoils_cm', 'stall_check_of.airfoils_cm']) if modeling_options['Analysis_Flags']['ServoSE']: self.connect('sse.powercurve.aoa_regII', 'stall_check.aoa_along_span') else: self.connect('ccblade.alpha', 'stall_check.aoa_along_span') + if modeling_options['Analysis_Flags']['OpenFAST']: + self.connect('aeroelastic.max_aoa', 'stall_check_of.aoa_along_span') if modeling_options['Analysis_Flags']['OpenFAST'] and modeling_options['Analysis_Flags']['ServoSE']: self.connect('sse.powercurve.rated_V', ['sse_tune.tune_rosco.v_rated']) From 16e5bac91db73f02e0c4f2171d111a97c18475d9 Mon Sep 17 00:00:00 2001 From: pibo Date: Mon, 23 Nov 2020 11:18:49 -0700 Subject: [PATCH 4/5] aeroelasticse call OLAF --- .../IEA-15-240-RWT-Monopile_ElastoDyn.dat | 2 +- .../IEA-15-240-RWT_AeroDyn15.dat | 135 ++++++++++++++++++ .../IEA-15-240-RWT_OLAF.dat | 42 ++++++ .../IEA-15-240-RWT_OLAF.fst | 60 ++++++++ examples/aeroelasticse/run_OLAF.py | 80 +++++++++++ weis/aeroelasticse/FAST_reader.py | 60 +++++++- weis/aeroelasticse/FAST_writer.py | 57 +++++++- 7 files changed, 428 insertions(+), 8 deletions(-) create mode 100644 examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_AeroDyn15.dat create mode 100644 examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat create mode 100644 examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.fst create mode 100644 examples/aeroelasticse/run_OLAF.py diff --git a/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_ElastoDyn.dat b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_ElastoDyn.dat index 2a3dfd8cd..83a1c1d0b 100644 --- a/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_ElastoDyn.dat +++ b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_ElastoDyn.dat @@ -107,7 +107,7 @@ False Furling - Read in additional model properties for fur "unused" FurlFile - Name of file containing furling properties (quoted string) [unused when Furling=False] ---------------------- TOWER --------------------------------------------------- 20 TwrNodes - Number of tower nodes used for analysis (-) -"IEA-15-240-RWT-Monopile_ElastoDyn_tower.dat" TwrFile - Name of file containing tower properties (quoted string) +"../IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_ElastoDyn_tower.dat" TwrFile - Name of file containing tower properties (quoted string) ---------------------- OUTPUT -------------------------------------------------- True SumPrint - Print summary data to ".sum" (flag) 1 OutFile - Switch to determine where output will be placed: {1: in module output file only; 2: in glue code output file only; 3: both} (currently unused) diff --git a/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_AeroDyn15.dat b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_AeroDyn15.dat new file mode 100644 index 000000000..b6d69ca18 --- /dev/null +++ b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_AeroDyn15.dat @@ -0,0 +1,135 @@ +------- AERODYN v15.03.* INPUT FILE ------------------------------------------------ +IEA 15 MW Offshore Reference Turbine +====== General Options ============================================================================ +False Echo - Echo the input to ".AD.ech"? (flag) +"default" DTAero - Time interval for aerodynamic calculations {or "default"} (s) +3 WakeMod - Type of wake/induction model (switch) {0=none, 1=BEMT} +1 AFAeroMod - Type of blade airfoil aerodynamics model (switch) {1=steady model, 2=Beddoes-Leishman unsteady model} [must be 1 when linearizing] +1 TwrPotent - Type tower influence on wind based on potential flow around the tower (switch) {0=none, 1=baseline potential flow, 2=potential flow with Bak correction} +False TwrShadow - Calculate tower influence on wind based on downstream tower shadow? (flag) +True TwrAero - Calculate tower aerodynamic loads? (flag) +False FrozenWake - Assume frozen wake during linearization? (flag) [used only when WakeMod=1 and when linearizing] +False CavitCheck - Perform cavitation check? (flag) TRUE will turn off unsteady aerodynamics +False CompAA - Flag to compute AeroAcoustics calculation [only used when WakeMod=1 or 2] +"AeroAcousticsInput.dat" AA_InputFile - Aeroacoustics input file +====== Environmental Conditions =================================================================== + 1.225000000000000e+00 AirDens - Air density (kg/m^3) + 1.479232653061225e-05 KinVisc - Kinematic air viscosity (m^2/s) + 3.350000000000000e+02 SpdSound - Speed of sound (m/s) + 1.035000000000000e+05 Patm - Atmospheric pressure (Pa) [used only when CavitCheck=True] + 1.700000000000000e+03 Pvap - Vapour pressure of fluid (Pa) [used only when CavitCheck=True] + 5.000000000000000e-01 FluidDepth - Water depth above mid-hub height (m) [used only when CavitCheck=True] +====== Blade-Element/Momentum Theory Options ====================================================== [used only when WakeMod=1] +2 SkewMod - Type of skewed-wake correction model (switch) {1=uncoupled, 2=Pitt/Peters, 3=coupled} [used only when WakeMod=1] +"default" SkewModFactor - Constant used in Pitt/Peters skewed wake model {or "default" is 15/32*pi} (-) [used only when SkewMod=2; unused when WakeMod=0] +True TipLoss - Use the Prandtl tip-loss model? (flag) [used only when WakeMod=1] +True HubLoss - Use the Prandtl hub-loss model? (flag) [used only when WakeMod=1] +True TanInd - Include tangential induction in BEMT calculations? (flag) [used only when WakeMod=1] +True AIDrag - Include the drag term in the axial-induction calculation? (flag) [used only when WakeMod=1] +True TIDrag - Include the drag term in the tangential-induction calculation? (flag) [used only when WakeMod=1 and TanInd=TRUE] +"Default" IndToler - Convergence tolerance for BEMT nonlinear solve residual equation {or "default"} (-) [used only when WakeMod=1] +500 MaxIter - Maximum number of iteration steps (-) [used only when WakeMod=1] +====== Dynamic Blade-Element/Momentum Theory Options ====================================================== [used only when WakeMod=1] +2 DBEMT_Mod - Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} (-) [used only when WakeMod=2] +2 tau1_const - Time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1] +====== OLAF -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options ================== [used only when WakeMod=3] +../IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat OLAFInputFileName - Input file for OLAF [used only when WakeMod=3] +====== Beddoes-Leishman Unsteady Airfoil Aerodynamics Options ===================================== [used only when AFAeroMod=2] +3 UAMod Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minemma/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2] +True FLookup Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files (flag) [used only when AFAeroMod=2] +====== Airfoil Information ========================================================================= +1 AFTabMod - Interpolation method for multiple airfoil tables {1=1D interpolation on AoA (first table only); 2=2D interpolation on AoA and Re; 3=2D interpolation on AoA and UserProp} (-) +1 InCol_Alfa - The column in the airfoil tables that contains the angle of attack (-) +2 InCol_Cl - The column in the airfoil tables that contains the lift coefficient (-) +3 InCol_Cd - The column in the airfoil tables that contains the drag coefficient (-) +4 InCol_Cm - The column in the airfoil tables that contains the pitching-moment coefficient; use zero if there is no Cm column (-) +0 InCol_Cpmin - The column in the airfoil tables that contains the Cpmin coefficient; use zero if there is no Cpmin column (-) +50 NumAFfiles - Number of airfoil files used (-) +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_00.dat" AFNames - Airfoil file names (NumAFfiles lines) (quoted strings) +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_01.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_02.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_03.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_04.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_05.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_06.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_07.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_08.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_09.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_10.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_11.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_12.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_13.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_14.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_15.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_16.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_17.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_18.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_19.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_20.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_21.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_22.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_23.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_24.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_25.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_26.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_27.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_28.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_29.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_30.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_31.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_32.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_33.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_34.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_35.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_36.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_37.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_38.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_39.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_40.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_41.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_42.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_43.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_44.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_45.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_46.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_47.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_48.dat" +"../IEA-15-240-RWT/Airfoils/IEA-15-240-RWT_AeroDyn15_Polar_49.dat" +====== Rotor/Blade Properties ===================================================================== +True UseBlCm - Include aerodynamic pitching moment in calculations? (flag) +"../IEA-15-240-RWT/IEA-15-240-RWT_AeroDyn15_blade.dat" ADBlFile(1) - Name of file containing distributed aerodynamic properties for Blade #1 (-) +"../IEA-15-240-RWT/IEA-15-240-RWT_AeroDyn15_blade.dat" ADBlFile(2) - Name of file containing distributed aerodynamic properties for Blade #2 (-) [unused if NumBl < 2] +"../IEA-15-240-RWT/IEA-15-240-RWT_AeroDyn15_blade.dat" ADBlFile(3) - Name of file containing distributed aerodynamic properties for Blade #3 (-) [unused if NumBl < 3] +====== Tower Influence and Aerodynamics ============================================================= [used only when TwrPotent/=0, TwrShadow=True, or TwrAero=True] +11 NumTwrNds - Number of tower nodes used in the analysis (-) [used only when TwrPotent/=0, TwrShadow=True, or TwrAero=True] +TwrElev TwrDiam TwrCd +(m) (m) (-) + 15. 10. 1. + 28. 10. 1. + 41. 9.926 1. + 54. 9.443 1. + 67. 8.833 1. + 80. 8.151 1. + 93. 7.39 1. + 106. 6.909 1. + 119. 6.748 1. + 132. 6.572 1. + 144.495 6.5 1. +====== Tower Influence and Aerodynamics ============================================================= [used only when TwrPotent/=0, TwrShadow=True, or TwrAero=True] +True SumPrint - Generate a summary file listing input options and interpolated properties to ".AD.sum"? (flag) +9 NBlOuts - Number of blade node outputs [0 - 9] (-) +1, 6, 11, 20, 30, 38, 43, 47, 50 BlOutNd - Blade nodes whose values will be output (-) +0 NTwOuts - Number of tower node outputs [0 - 9] (-) +1, 2, 3, 4, 5 TwOutNd - Tower nodes whose values will be output (-) + OutList - The next line(s) contains a list of output parameters. See OutListParameters.xlsx for a listing of available output channels, (-) +"RtAeroFxh" +"RtAeroFyh" +"RtAeroFzh" +"RtAeroMxh" +"RtAeroMyh" +"RtAeroMzh" +"RtVAvgxh" +"RtAeroCp" +"RtTSR" +END of input file (the word "END" must appear in the first 3 columns of this last OutList line) +--------------------------------------------------------------------------------------- diff --git a/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat new file mode 100644 index 000000000..bd43d3ba7 --- /dev/null +++ b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat @@ -0,0 +1,42 @@ +--------------------------- OLAF (cOnvecting LAgrangian Filaments) INPUT FILE ----------------- +Free wake input file for the Helix test case +--------------------------- GENERAL OPTIONS --------------------------------------------------- +5 IntMethod Integration method {5: Forward Euler 1st order, default: 5} (switch) +default DTfvw Time interval for wake propagation. {default: dtaero} (s) +99999 FreeWakeStart Time when wake is free. (-) value = always free. {default: 0.0} (s) +0.0 FullCircStart Time at which full circulation is reached. {default: 0.0} (s) +--------------------------- CIRCULATION SPECIFICATIONS ---------------------------------------- +1 CircSolvingMethod Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch) +0.00005 CircSolvConvCrit Convergence criteria {default: 0.001} [only if CircSolvingMethod=1] (-) +0.1 CircSolvRelaxation Relaxation factor {default: 0.1} [only if CircSolvingMethod=1] (-) +200 CircSolvMaxIter Maximum number of iterations for circulation solving {default: 30} (-) +"NA" PrescribedCircFile File containing prescribed circulation [only if CircSolvingMethod=3] (quoted string) +=============================================================================================== +--------------------------- WAKE OPTIONS ------------------------------------------------------ +------------------- WAKE EXTENT AND DISCRETIZATION -------------------------------------------- +100 nNWPanel Number of near-wake panels [integer] (-) +10 WakeLength Total wake distance [integer] (number of time steps) +default FreeWakeLength Wake length that is free [integer] (number of time steps) {default: WakeLength} +default FWShedVorticity Include shed vorticity in the far wake {default: false} +------------------- WAKE REGULARIZATIONS AND DIFFUSION ----------------------------------------- +0 DiffusionMethod Diffusion method to account for viscous effects {0: None, 1: Core Spreading, "default": 0} +0 RegDeterMethod Method to determine the regularization parameters {0: Manual, 1: Optimized, default: 0 } +2 RegFunction Viscous diffusion function {0: None, 1: Rankine, 2: LambOseen, 3: Vatistas, 4: Denominator, "default": 3} (switch) +1 WakeRegMethod Wake regularization method {1: Constant, 2: Stretching, 3: Age, default: 1} (switch) +0.0 WakeRegFactor Wake regularization factor (m) +0.0 WingRegFactor Wing regularization factor (m) +100 CoreSpreadEddyVisc Eddy viscosity in core spreading methods, typical values 1-1000 +------------------- WAKE TREATMENT OPTIONS --------------------------------------------------- +False TwrShadowOnWake Include tower flow disturbance effects on wake convection {default:false} [only if TwrPotent or TwrShadow] +0 ShearModel Shear Model {0: No treatment, 1: Mirrored vorticity, default: 0} +------------------- SPEEDUP OPTIONS ----------------------------------------------------------- +1 VelocityMethod Method to determine the velocity {1:Biot-Savart Segment, 2:Particle tree, default: 1} +1.5 TreeBranchFactor Branch radius fraction above which a multipole calculation is used {default: 2.0} [only if VelocityMethod=2] +1 PartPerSegment Number of particles per segment [only if VelocityMethod=2] +=============================================================================================== +--------------------------- OUTPUT OPTIONS --------------------------------------------------- +0 WrVTk Outputs Visualization Toolkit (VTK) (independent of .fst option) {0: NoVTK, 1: Write VTK at each time step} (flag) +1 nVTKBlades Number of blades for which VTK files are exported {0: No VTK per blade, n: VTK for blade 1 to n} (-) +1 VTKCoord Coordinate system used for VTK export. {1: Global, 2: Hub, "default": 1} +default VTK_fps Frame rate for VTK output (frames per second) {"all" for all glue code timesteps, "default" for all OLAF timesteps} [used only if WrVTK=1] +------------------------------------------------------------------------------------------------ diff --git a/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.fst b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.fst new file mode 100644 index 000000000..3f242af1d --- /dev/null +++ b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.fst @@ -0,0 +1,60 @@ +------- OpenFAST INPUT FILE ------------------------------------------- +IEA 15 MW offshore reference model monopile configuration +---------------------- SIMULATION CONTROL -------------------------------------- +True Echo - Echo input data to .ech (flag) +"FATAL" AbortLevel - Error level when simulation should abort (string) {"WARNING", "SEVERE", "FATAL"} +300.0 TMax - Total run time (s) +0.005 DT - Recommended module time step (s) +2 InterpOrder - Interpolation order for input/output time history (-) {1=linear, 2=quadratic} +0 NumCrctn - Number of correction iterations (-) {0=explicit calculation, i.e., no corrections} +99999.0 DT_UJac - Time between calls to get Jacobians (s) +1000000.0 UJacSclFact - Scaling factor used in Jacobians (-) +---------------------- FEATURE SWITCHES AND FLAGS ------------------------------ +1 CompElast - Compute structural dynamics (switch) {1=ElastoDyn; 2=ElastoDyn + BeamDyn for blades} +1 CompInflow - Compute inflow wind velocities (switch) {0=still air; 1=InflowWind; 2=external from OpenFOAM} +2 CompAero - Compute aerodynamic loads (switch) {0=None; 1=AeroDyn v14; 2=AeroDyn v15} +1 CompServo - Compute control and electrical-drive dynamics (switch) {0=None; 1=ServoDyn} +0 CompHydro - Compute hydrodynamic loads (switch) {0=None; 1=HydroDyn} +0 CompSub - Compute sub-structural dynamics (switch) {0=None; 1=SubDyn; 2=External Platform MCKF} +0 CompMooring - Compute mooring system (switch) {0=None; 1=MAP++; 2=FEAMooring; 3=MoorDyn; 4=OrcaFlex} +0 CompIce - Compute ice loads (switch) {0=None; 1=IceFloe; 2=IceDyn} +---------------------- INPUT FILES --------------------------------------------- +"../IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_ElastoDyn.dat" EDFile - Name of file containing ElastoDyn input parameters (quoted string) +"../IEA-15-240-RWT/IEA-15-240-RWT_BeamDyn.dat" BDBldFile(1) - Name of file containing BeamDyn input parameters for blade 1 (quoted string) +"../IEA-15-240-RWT/IEA-15-240-RWT_BeamDyn.dat" BDBldFile(2) - Name of file containing BeamDyn input parameters for blade 2 (quoted string) +"../IEA-15-240-RWT/IEA-15-240-RWT_BeamDyn.dat" BDBldFile(3) - Name of file containing BeamDyn input parameters for blade 3 (quoted string) +"../IEA-15-240-RWT/IEA-15-240-RWT_InflowFile.dat" InflowFile - Name of file containing inflow wind input parameters (quoted string) +"../IEA-15-240-RWT-OLAF/IEA-15-240-RWT_AeroDyn15.dat" AeroFile - Name of file containing aerodynamic input parameters (quoted string) +"../IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_ServoDyn.dat" ServoFile - Name of file containing control and electrical-drive input parameters (quoted string) +"../IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_HydroDyn.dat" HydroFile - Name of file containing hydrodynamic input parameters (quoted string) +"../IEA-15-240-RWT-Monopile/IEA-15-240-RWT-Monopile_SubDyn.dat" SubFile - Name of file containing sub-structural input parameters (quoted string) +"unused" MooringFile - Name of file containing mooring system input parameters (quoted string) +"unused" IceFile - Name of file containing ice input parameters (quoted string) +---------------------- OUTPUT -------------------------------------------------- +True SumPrint - Print summary data to ".sum" (flag) +10.0 SttsTime - Amount of time between screen status messages (s) +99999.0 ChkptTime - Amount of time between creating checkpoint files for potential restart (s) +"default" DT_Out - Time step for tabular output (s) (or "default") +0.0 TStart - Time to begin tabular output (s) +3 OutFileFmt - Format for tabular (time-marching) output file (switch) {1: text file [.out], 2: binary file [.outb], 3: both} +True TabDelim - Use tab delimiters in text tabular output file? (flag) {uses spaces if false} +"ES10.3E2" OutFmt - Format used for text tabular output, excluding the time channel. Resulting field should be 10 characters. (quoted string) +---------------------- LINEARIZATION ------------------------------------------- +False Linearize - Linearization analysis (flag) +False CalcSteady - Calculate a steady-state periodic operating point before linearization? [unused if Linearize=False] (flag) +3 TrimCase - Controller parameter to be trimmed {1:yaw; 2:torque; 3:pitch} [used only if CalcSteady=True] (-) +0.001 TrimTol - Tolerance for the rotational speed convergence [used only if CalcSteady=True] (-) +0.01 TrimGain - Proportional gain for the rotational speed error (>0) [used only if CalcSteady=True] (rad/(rad/s) for yaw or pitch; Nm/(rad/s) for torque) +0 Twr_Kdmp - Damping factor for the tower [used only if CalcSteady=True] (N/(m/s)) +0 Bld_Kdmp - Damping factor for the blades [used only if CalcSteady=True] (N/(m/s)) +2 NLinTimes - Number of times to linearize (-) [>=1] [unused if Linearize=False] +30.000000, 60.000000 LinTimes - List of times at which to linearize (s) [1 to NLinTimes] [used only when Linearize=True and CalcSteady=False] +1 LinInputs - Inputs included in linearization (switch) {0=none; 1=standard; 2=all module inputs (debug)} [unused if Linearize=False] +1 LinOutputs - Outputs included in linearization (switch) {0=none; 1=from OutList(s); 2=all module outputs (debug)} [unused if Linearize=False] +False LinOutJac - Include full Jacobians in linearization output (for debug) (flag) [unused if Linearize=False; used only if LinInputs=LinOutputs=2] +False LinOutMod - Write module-level linearization output files in addition to output for full system? (flag) [unused if Linearize=False] +---------------------- VISUALIZATION ------------------------------------------ +0 WrVTK - VTK visualization data output: (switch) {0=none; 1=initialization data only; 2=animation} +2 VTK_type - Type of VTK visualization data: (switch) {1=surfaces; 2=basic meshes (lines/points); 3=all meshes (debug)} [unused if WrVTK=0] +False VTK_fields - Write mesh fields to VTK data files? (flag) {true/false} [unused if WrVTK=0] +15.0 VTK_fps - Frame rate for VTK output (frames per second){will use closest integer multiple of DT} [used only if WrVTK=2] diff --git a/examples/aeroelasticse/run_OLAF.py b/examples/aeroelasticse/run_OLAF.py new file mode 100644 index 000000000..6dbc4f924 --- /dev/null +++ b/examples/aeroelasticse/run_OLAF.py @@ -0,0 +1,80 @@ +""" + +Example script to compute the steady-state performance in OpenFAST + +""" + + +from weis.aeroelasticse.runFAST_pywrapper import runFAST_pywrapper_batch +from weis.aeroelasticse.CaseGen_General import CaseGen_General +import numpy as np +import os, platform + +# Paths calling the standard modules of WEIS +fastBatch = runFAST_pywrapper_batch(FAST_ver='OpenFAST', dev_branch=True) +run_dir1 = os.path.dirname( os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) ) ) + os.sep +run_dir2 = os.path.dirname( os.path.dirname( os.path.realpath(__file__) ) ) + os.sep +fastBatch.FAST_directory = os.path.join(run_dir2, 'OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF') # Path to fst directory files +fastBatch.FAST_InputFile = 'IEA-15-240-RWT_OLAF.fst' # FAST input file (ext=.fst) +fastBatch.FAST_runDirectory = 'olaf/iea15mw' +fastBatch.debug_level = 2 + +# User settings +n_cores = 1 # Number of available cores +TMax = 1. # Length of wind grids and OpenFAST simulations, suggested 720 s +cut_in = 3. # Cut in wind speed +cut_out = 25. # Cut out wind speed +n_ws = 12 # Number of wind speed bins +wind_speeds = np.linspace(int(cut_in), int(cut_out), int(n_ws)) # Wind speeds to run OpenFAST at +Ttrans = max([0., TMax - 60.]) # Start of the transient for DLC with a transient, e.g. DLC 1.4 +TStart = max([0., TMax - 600.]) # Start of the recording of the channels of OpenFAST + +# Initial conditions for ElastoDyn +u_ref = np.arange(3.,26.) # Wind speed vector to specify the initial conditions +pitch_ref = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5058525323662666, 5.253759185225932, 7.50413344606208, 9.310153958810268, 10.8972969450052, 12.412247669440042, 13.883219268525659, 15.252012626933068, 16.53735488246438, 17.76456777500061, 18.953261878035104, 20.11055307762722, 21.238680277668898, 22.30705111326602, 23.455462501156205] # Pitch values in deg +omega_ref = [2.019140272160114, 2.8047214918577925, 3.594541645994511, 4.359025795823625, 5.1123509774611025, 5.855691196288371, 6.589281196735111, 7.312788026081227, 7.514186181824161, 7.54665511646938, 7.573823812448151, 7.600476033113538, 7.630243938880304, 7.638301051122195, 7.622050377183605, 7.612285710588359, 7.60743945212863, 7.605865650155881, 7.605792924227456, 7.6062185247519825, 7.607153933765292, 7.613179734210654, 7.606737845170748] # Rotor speeds in rpm +pitch_init = np.interp(wind_speeds, u_ref, pitch_ref) +omega_init = np.interp(wind_speeds, u_ref, omega_ref) + +# Settings passed to OpenFAST +case_inputs = {} +case_inputs[("Fst","TMax")] = {'vals':[TMax], 'group':0} +case_inputs[("Fst","DT")] = {'vals':[0.01], 'group':0} +case_inputs[("Fst","CompInflow")] = {'vals':[1], 'group':0} +case_inputs[("Fst","CompServo")] = {'vals':[1], 'group':0} +case_inputs[("Fst","OutFileFmt")] = {'vals':[1], 'group':0} +case_inputs[("Fst","DT_Out")] = {'vals':[0.02], 'group':0} +case_inputs[("ElastoDyn","GenDOF")] = {'vals':['True'], 'group':0} +case_inputs[("ServoDyn","PCMode")] = {'vals':[5], 'group':0} +case_inputs[("ServoDyn","VSContrl")] = {'vals':[5], 'group':0} +case_inputs[("AeroDyn15","WakeMod")] = {'vals':[3], 'group':0} +case_inputs[("AeroDyn15","AFAeroMod")] = {'vals':[1], 'group':0} +case_inputs[("InflowWind","WindType")] = {'vals':[1], 'group':0} +case_inputs[("InflowWind","HWindSpeed")]= {'vals': wind_speeds, 'group': 1} +case_inputs[("Fst","OutFileFmt")] = {'vals':[0], 'group':0} +case_inputs[("ElastoDyn","RotSpeed")] = {'vals': omega_init, 'group': 1} +case_inputs[("ElastoDyn","BlPitch1")] = {'vals': pitch_init, 'group': 1} +case_inputs[("ElastoDyn","BlPitch2")] = case_inputs[("ElastoDyn","BlPitch1")] +case_inputs[("ElastoDyn","BlPitch3")] = case_inputs[("ElastoDyn","BlPitch1")] + +# Find the controller +if platform.system() == 'Windows': + path2dll = os.path.join(run_dir1, 'local/lib/libdiscon.dll') +elif platform.system() == 'Darwin': + path2dll = os.path.join(run_dir1, 'local/lib/libdiscon.dylib') +else: + path2dll = os.path.join(run_dir1, 'local/lib/libdiscon.so') + +case_inputs[("ServoDyn","DLL_FileName")] = {'vals':[path2dll], 'group':0} + +# Generate the matrix of cases +case_list, case_name_list = CaseGen_General(case_inputs, dir_matrix=fastBatch.FAST_runDirectory, namebase='iea15mw') + +fastBatch.case_list = case_list +fastBatch.case_name_list = case_name_list + +# Run OpenFAST, either serially or sequentially +if n_cores == 1: + fastBatch.run_serial() +else: + fastBatch.run_multi(n_cores) \ No newline at end of file diff --git a/weis/aeroelasticse/FAST_reader.py b/weis/aeroelasticse/FAST_reader.py index 1b91b1ed3..05a94abea 100644 --- a/weis/aeroelasticse/FAST_reader.py +++ b/weis/aeroelasticse/FAST_reader.py @@ -525,6 +525,7 @@ def read_MainInput(self): self.fst_vt['Fst']['SubFile_path'] = os.path.split(self.fst_vt['Fst']['SubFile'])[0] self.fst_vt['Fst']['MooringFile_path'] = os.path.split(self.fst_vt['Fst']['MooringFile'])[0] self.fst_vt['Fst']['IceFile_path'] = os.path.split(self.fst_vt['Fst']['IceFile'])[0] + def read_ElastoDyn(self): # ElastoDyn v1.03 Input File # Currently no differences between FASTv8.16 and OpenFAST. @@ -784,7 +785,6 @@ def read_BeamDyn(self): self.read_BeamDynBlade() - def read_BeamDynBlade(self): # BeamDyn Blade @@ -1005,7 +1005,6 @@ def read_AeroDyn14Tower(self): self.fst_vt['AeroDynTower']['TwrRe'][i] = data[0] self.fst_vt['AeroDynTower']['TwrCD'][i,:] = data[1:] - def read_AeroDyn15(self): # AeroDyn v15.03 @@ -1123,6 +1122,10 @@ def read_AeroDyn15(self): self.read_AeroDyn15Blade() self.read_AeroDyn15Polar() self.read_AeroDyn15Coord() + if self.fst_vt['AeroDyn15']['WakeMod'] == 3: + if self.fst_vt['AeroDyn15']['AFAeroMod'] == 2: + raise Exception('OLAF is called with unsteady airfoil aerodynamics, but OLAF currently only supports AFAeroMod == 1') + self.read_AeroDyn15OLAF() def read_AeroDyn15Blade(self): # AeroDyn v5.00 Blade Definition File @@ -1267,6 +1270,56 @@ def read_AeroDyn15Coord(self): f.close() + def read_AeroDyn15OLAF(self): + + self.fst_vt['AeroDyn15']['OLAF'] = {} + olaf_filename = os.path.join(self.FAST_directory, self.fst_vt['AeroDyn15']['OLAFInputFileName']) + f = open(olaf_filename) + f.readline() + f.readline() + f.readline() + self.fst_vt['AeroDyn15']['OLAF']['IntMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['DTfvw'] = float_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['FreeWakeStart'] = float(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['FullCircStart'] = float(f.readline().split()[0]) + f.readline() + self.fst_vt['AeroDyn15']['OLAF']['CircSolvingMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['CircSolvConvCrit'] = float_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['CircSolvRelaxation'] = float_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['PrescribedCircFile'] = f.readline().split()[0] + f.readline() + f.readline() + f.readline() + self.fst_vt['AeroDyn15']['OLAF']['nNWPanel'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['WakeLength'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['FreeWakeLength'] = float_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['FWShedVorticity'] = float_read(f.readline().split()[0]) + f.readline() + self.fst_vt['AeroDyn15']['OLAF']['DiffusionMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['RegDeterMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['RegFunction'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['WakeRegMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['WakeRegFactor'] = float(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['WingRegFactor'] = float(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['CoreSpreadEddyVisc'] = int(f.readline().split()[0]) + f.readline() + self.fst_vt['AeroDyn15']['OLAF']['TwrShadowOnWake'] = bool_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['ShearModel'] = int(f.readline().split()[0]) + f.readline() + self.fst_vt['AeroDyn15']['OLAF']['VelocityMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['TreeBranchFactor']= float_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['PartPerSegment'] = int(f.readline().split()[0]) + f.readline() + f.readline() + self.fst_vt['AeroDyn15']['OLAF']['WrVTk'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['nVTKBlades'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['VTKCoord'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['VTK_fps'] = float_read(f.readline().split()[0]) + f.readline() + f.close() + + def read_ServoDyn(self): # ServoDyn v1.05 Input File # Currently no differences between FASTv8.16 and OpenFAST. @@ -1459,7 +1512,6 @@ def read_DISCON_in(self): else: del self.fst_vt['DISCON_in'] - def read_HydroDyn(self): # AeroDyn v2.03 @@ -2026,7 +2078,6 @@ def read_SubDyn(self): self.set_outlist(self.fst_vt['outlist']['SubDyn'], channel_list) data = f.readline() - def read_MAP(self): # MAP++ @@ -2079,7 +2130,6 @@ def read_MAP(self): f.readline() self.fst_vt['MAP']['Option'] = [str(val) for val in f.readline().strip().split()] - def read_MoorDyn(self): moordyn_file = os.path.normpath(os.path.join(self.FAST_directory, self.fst_vt['Fst']['MooringFile'])) diff --git a/weis/aeroelasticse/FAST_writer.py b/weis/aeroelasticse/FAST_writer.py index da5707e29..d1cf878c5 100644 --- a/weis/aeroelasticse/FAST_writer.py +++ b/weis/aeroelasticse/FAST_writer.py @@ -869,6 +869,9 @@ def write_AeroDyn15(self): if self.fst_vt['AeroDyn15']['af_data'][1][0]['NumCoords'] != 0: self.write_AeroDyn15Coord() + if self.fst_vt['AeroDyn15']['WakeMod'] == 3: + self.write_OLAF() + # Generate AeroDyn v15.03 input file self.fst_vt['Fst']['AeroFile'] = self.FAST_namingOut + '_AeroDyn15.dat' ad_file = os.path.join(self.FAST_runDirectory, self.fst_vt['Fst']['AeroFile']) @@ -912,7 +915,8 @@ def write_AeroDyn15(self): f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['DBEMT_Mod'], 'DBEMT_Mod', '- Type of dynamic BEMT (DBEMT) model {1=constant tau1, 2=time-dependent tau1} (-) [used only when WakeMod=2]\n')) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['tau1_const'], 'tau1_const', '- Time constant for DBEMT (s) [used only when WakeMod=2 and DBEMT_Mod=1]\n')) f.write('====== OLAF -- cOnvecting LAgrangian Filaments (Free Vortex Wake) Theory Options ================== [used only when WakeMod=3]\n') - f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAFInputFileName'], 'OLAFInputFileName', '- Input file for OLAF [used only when WakeMod=3]\n')) + olaf_file = self.FAST_namingOut + '_OLAF.dat' + f.write('{!s:<22} {:<11} {:}'.format(olaf_file, 'OLAFInputFileName', '- Input file for OLAF [used only when WakeMod=3]\n')) f.write('====== Beddoes-Leishman Unsteady Airfoil Aerodynamics Options ===================================== [used only when AFAeroMod=2]\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['UAMod'], 'UAMod', "Unsteady Aero Model Switch (switch) {1=Baseline model (Original), 2=Gonzalez's variant (changes in Cn,Cc,Cm), 3=Minemma/Pierce variant (changes in Cc and Cm)} [used only when AFAeroMod=2]\n")) f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['FLookup'], 'FLookup', "Flag to indicate whether a lookup for f' will be calculated (TRUE) or whether best-fit exponential equations will be used (FALSE); if FALSE S1-S4 must be provided in airfoil input files (flag) [used only when AFAeroMod=2]\n")) @@ -1145,7 +1149,56 @@ def write_AeroDyn15Coord(self): for row in coord: f.write(' '.join(['{: 2.14e}'.format(val) for val in row])+'\n') f.close() - + + def write_OLAF(self): + + olaf_file = os.path.join(self.FAST_runDirectory, self.FAST_namingOut + '_OLAF.dat') + f = open(olaf_file, 'w') + + f.write('--------------------------- OLAF (cOnvecting LAgrangian Filaments) INPUT FILE -----------------\n') + f.write('Free wake input file for the Helix test case\n') + f.write('--------------------------- GENERAL OPTIONS ---------------------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['IntMethod'], 'Integration method', '{5: Forward Euler 1st order, default: 5} (switch)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['DTfvw'], 'DTfvw method', 'Time interval for wake propagation. {default: dtaero} (s)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FreeWakeStart'], 'FreeWakeStart method', 'Time when wake is free. (-) value = always free. {default: 0.0} (s)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FullCircStart'], 'FullCircStart', 'Time at which full circulation is reached. {default: 0.0} (s)\n')) + f.write('--------------------------- CIRCULATION SPECIFICATIONS ----------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvingMethod'], 'CircSolvingMethod', 'Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvConvCrit'], 'CircSolvConvCrit', 'Convergence criteria {default: 0.001} [only if CircSolvingMethod=1] (-)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvRelaxation'], 'CircSolvRelaxation', 'Relaxation factor {default: 0.1} [only if CircSolvingMethod=1] (-)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'], 'CircSolvMaxIter', 'Maximum number of iterations for circulation solving {default: 30} (-)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['PrescribedCircFile'], 'PrescribedCircFile','File containing prescribed circulation [only if CircSolvingMethod=3] (quoted string)\n')) + f.write('===============================================================================================\n') + f.write('--------------------------- WAKE OPTIONS ------------------------------------------------------\n') + f.write('------------------- WAKE EXTENT AND DISCRETIZATION --------------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nNWPanel'], 'nNWPanel','Number of near-wake panels [integer] (-)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WakeLength'], 'WakeLength','Total wake distance [integer] (number of time steps)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FreeWakeLength'], 'FreeWakeLength','Wake length that is free [integer] (number of time steps) {default: WakeLength}\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FWShedVorticity'], 'FWShedVorticity','Include shed vorticity in the far wake {default: false}\n')) + f.write('------------------- WAKE REGULARIZATIONS AND DIFFUSION -----------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['DiffusionMethod'], 'DiffusionMethod','Diffusion method to account for viscous effects {0: None, 1: Core Spreading, "default": 0}\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['RegDeterMethod'], 'RegDeterMethod','Method to determine the regularization parameters {0: Manual, 1: Optimized, default: 0 }\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['RegFunction'], 'RegFunction','Viscous diffusion function {0: None, 1: Rankine, 2: LambOseen, 3: Vatistas, 4: Denominator, "default": 3} (switch)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WakeRegMethod'], 'WakeRegMethod','Wake regularization method {1: Constant, 2: Stretching, 3: Age, default: 1} (switch)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WakeRegFactor'], 'WakeRegFactor','Wake regularization factor (m)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WingRegFactor'], 'WingRegFactor','Wing regularization factor (m)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CoreSpreadEddyVisc'], 'CoreSpreadEddyVisc','Eddy viscosity in core spreading methods, typical values 1-1000\n')) + f.write('------------------- WAKE TREATMENT OPTIONS ---------------------------------------------------\n') + f.write('{!s:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['TwrShadowOnWake'], 'TwrShadowOnWake','Include tower flow disturbance effects on wake convection {default:false} [only if TwrPotent or TwrShadow]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['ShearModel'], 'ShearModel','Shear Model {0: No treatment, 1: Mirrored vorticity, default: 0}\n')) + f.write('------------------- SPEEDUP OPTIONS -----------------------------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['VelocityMethod'], 'VelocityMethod','Method to determine the velocity {1:Biot-Savart Segment, 2:Particle tree, default: 1}\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['TreeBranchFactor'], 'TreeBranchFactor','Branch radius fraction above which a multipole calculation is used {default: 2.0} [only if VelocityMethod=2]\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['PartPerSegment'], 'PartPerSegment','Number of particles per segment [only if VelocityMethod=2]\n')) + f.write('===============================================================================================\n') + f.write('--------------------------- OUTPUT OPTIONS ---------------------------------------------------\n') + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WrVTk'], 'WrVTk','Outputs Visualization Toolkit (VTK) (independent of .fst option) {0: NoVTK, 1: Write VTK at each time step} (flag)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nVTKBlades'], 'nVTKBlades','Number of blades for which VTK files are exported {0: No VTK per blade, n: VTK for blade 1 to n} (-)\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['VTKCoord'], 'VTKCoord','Coordinate system used for VTK export. {1: Global, 2: Hub, "default": 1}\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['VTK_fps'], 'VTK_fps','Frame rate for VTK output (frames per second) {"all" for all glue code timesteps, "default" for all OLAF timesteps} [used only if WrVTK=1]\n')) + f.write('------------------------------------------------------------------------------------------------\n') + + f.close() def write_ServoDyn(self): # ServoDyn v1.05 Input File From a7861ac14cd31ba0bcf15788368c3ee82fec3ec0 Mon Sep 17 00:00:00 2001 From: pibo Date: Mon, 23 Nov 2020 12:08:10 -0700 Subject: [PATCH 5/5] fix settings for WT simulation --- .../IEA-15-240-RWT_OLAF.dat | 30 +++++++++---------- weis/aeroelasticse/FAST_reader.py | 26 ++++++++-------- weis/aeroelasticse/FAST_writer.py | 8 ++--- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat index bd43d3ba7..37b4d1acb 100644 --- a/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat +++ b/examples/OpenFAST_models/IEA-15-240-RWT/IEA-15-240-RWT-OLAF/IEA-15-240-RWT_OLAF.dat @@ -1,36 +1,36 @@ --------------------------- OLAF (cOnvecting LAgrangian Filaments) INPUT FILE ----------------- Free wake input file for the Helix test case --------------------------- GENERAL OPTIONS --------------------------------------------------- -5 IntMethod Integration method {5: Forward Euler 1st order, default: 5} (switch) +default IntMethod Integration method {5: Forward Euler 1st order, default: 5} (switch) default DTfvw Time interval for wake propagation. {default: dtaero} (s) -99999 FreeWakeStart Time when wake is free. (-) value = always free. {default: 0.0} (s) -0.0 FullCircStart Time at which full circulation is reached. {default: 0.0} (s) +0.0 FreeWakeStart Time when wake is free. (-) value = always free. {default: 0.0} (s) +5.0 FullCircStart Time at which full circulation is reached. {default: 0.0} (s) --------------------------- CIRCULATION SPECIFICATIONS ---------------------------------------- -1 CircSolvingMethod Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch) -0.00005 CircSolvConvCrit Convergence criteria {default: 0.001} [only if CircSolvingMethod=1] (-) -0.1 CircSolvRelaxation Relaxation factor {default: 0.1} [only if CircSolvingMethod=1] (-) -200 CircSolvMaxIter Maximum number of iterations for circulation solving {default: 30} (-) +default CircSolvingMethod Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch) +default CircSolvConvCrit Convergence criteria {default: 0.001} [only if CircSolvingMethod=1] (-) +default CircSolvRelaxation Relaxation factor {default: 0.1} [only if CircSolvingMethod=1] (-) +default CircSolvMaxIter Maximum number of iterations for circulation solving {default: 30} (-) "NA" PrescribedCircFile File containing prescribed circulation [only if CircSolvingMethod=3] (quoted string) =============================================================================================== --------------------------- WAKE OPTIONS ------------------------------------------------------ ------------------- WAKE EXTENT AND DISCRETIZATION -------------------------------------------- -100 nNWPanel Number of near-wake panels [integer] (-) -10 WakeLength Total wake distance [integer] (number of time steps) -default FreeWakeLength Wake length that is free [integer] (number of time steps) {default: WakeLength} +600 nNWPanel Number of near-wake panels [integer] (-) +600 WakeLength Total wake distance [integer] (number of time steps) +400 FreeWakeLength Wake length that is free [integer] (number of time steps) {default: WakeLength} default FWShedVorticity Include shed vorticity in the far wake {default: false} ------------------- WAKE REGULARIZATIONS AND DIFFUSION ----------------------------------------- 0 DiffusionMethod Diffusion method to account for viscous effects {0: None, 1: Core Spreading, "default": 0} -0 RegDeterMethod Method to determine the regularization parameters {0: Manual, 1: Optimized, default: 0 } -2 RegFunction Viscous diffusion function {0: None, 1: Rankine, 2: LambOseen, 3: Vatistas, 4: Denominator, "default": 3} (switch) -1 WakeRegMethod Wake regularization method {1: Constant, 2: Stretching, 3: Age, default: 1} (switch) +1 RegDeterMethod Method to determine the regularization parameters {0: Manual, 1: Optimized, default: 0 } +3 RegFunction Viscous diffusion function {0: None, 1: Rankine, 2: LambOseen, 3: Vatistas, 4: Denominator, "default": 3} (switch) +3 WakeRegMethod Wake regularization method {1: Constant, 2: Stretching, 3: Age, default: 1} (switch) 0.0 WakeRegFactor Wake regularization factor (m) 0.0 WingRegFactor Wing regularization factor (m) -100 CoreSpreadEddyVisc Eddy viscosity in core spreading methods, typical values 1-1000 +1000 CoreSpreadEddyVisc Eddy viscosity in core spreading methods, typical values 1-1000 ------------------- WAKE TREATMENT OPTIONS --------------------------------------------------- False TwrShadowOnWake Include tower flow disturbance effects on wake convection {default:false} [only if TwrPotent or TwrShadow] 0 ShearModel Shear Model {0: No treatment, 1: Mirrored vorticity, default: 0} ------------------- SPEEDUP OPTIONS ----------------------------------------------------------- -1 VelocityMethod Method to determine the velocity {1:Biot-Savart Segment, 2:Particle tree, default: 1} +2 VelocityMethod Method to determine the velocity {1:Biot-Savart Segment, 2:Particle tree, default: 1} 1.5 TreeBranchFactor Branch radius fraction above which a multipole calculation is used {default: 2.0} [only if VelocityMethod=2] 1 PartPerSegment Number of particles per segment [only if VelocityMethod=2] =============================================================================================== diff --git a/weis/aeroelasticse/FAST_reader.py b/weis/aeroelasticse/FAST_reader.py index 05a94abea..54b14a08f 100644 --- a/weis/aeroelasticse/FAST_reader.py +++ b/weis/aeroelasticse/FAST_reader.py @@ -1278,43 +1278,43 @@ def read_AeroDyn15OLAF(self): f.readline() f.readline() f.readline() - self.fst_vt['AeroDyn15']['OLAF']['IntMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['IntMethod'] = int_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['DTfvw'] = float_read(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['FreeWakeStart'] = float(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['FullCircStart'] = float(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['FreeWakeStart'] = float_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['FullCircStart'] = float_read(f.readline().split()[0]) f.readline() - self.fst_vt['AeroDyn15']['OLAF']['CircSolvingMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['CircSolvingMethod'] = int_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['CircSolvConvCrit'] = float_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['CircSolvRelaxation'] = float_read(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'] = int_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['PrescribedCircFile'] = f.readline().split()[0] f.readline() f.readline() f.readline() self.fst_vt['AeroDyn15']['OLAF']['nNWPanel'] = int(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['WakeLength'] = int(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['FreeWakeLength'] = float_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['FreeWakeLength'] = int_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['FWShedVorticity'] = float_read(f.readline().split()[0]) f.readline() - self.fst_vt['AeroDyn15']['OLAF']['DiffusionMethod'] = int(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['RegDeterMethod'] = int(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['RegFunction'] = int(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['WakeRegMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['DiffusionMethod'] = int_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['RegDeterMethod'] = int_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['RegFunction'] = int_read(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['WakeRegMethod'] = int_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['WakeRegFactor'] = float(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['WingRegFactor'] = float(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['CoreSpreadEddyVisc'] = int(f.readline().split()[0]) f.readline() self.fst_vt['AeroDyn15']['OLAF']['TwrShadowOnWake'] = bool_read(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['ShearModel'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['ShearModel'] = int_read(f.readline().split()[0]) f.readline() - self.fst_vt['AeroDyn15']['OLAF']['VelocityMethod'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['VelocityMethod'] = int_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['TreeBranchFactor']= float_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['PartPerSegment'] = int(f.readline().split()[0]) f.readline() f.readline() self.fst_vt['AeroDyn15']['OLAF']['WrVTk'] = int(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['nVTKBlades'] = int(f.readline().split()[0]) - self.fst_vt['AeroDyn15']['OLAF']['VTKCoord'] = int(f.readline().split()[0]) + self.fst_vt['AeroDyn15']['OLAF']['VTKCoord'] = int_read(f.readline().split()[0]) self.fst_vt['AeroDyn15']['OLAF']['VTK_fps'] = float_read(f.readline().split()[0]) f.readline() f.close() diff --git a/weis/aeroelasticse/FAST_writer.py b/weis/aeroelasticse/FAST_writer.py index d1cf878c5..b97c6362c 100644 --- a/weis/aeroelasticse/FAST_writer.py +++ b/weis/aeroelasticse/FAST_writer.py @@ -1158,22 +1158,22 @@ def write_OLAF(self): f.write('--------------------------- OLAF (cOnvecting LAgrangian Filaments) INPUT FILE -----------------\n') f.write('Free wake input file for the Helix test case\n') f.write('--------------------------- GENERAL OPTIONS ---------------------------------------------------\n') - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['IntMethod'], 'Integration method', '{5: Forward Euler 1st order, default: 5} (switch)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['IntMethod'], 'Integration method', '{5: Forward Euler 1st order, default: 5} (switch)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['DTfvw'], 'DTfvw method', 'Time interval for wake propagation. {default: dtaero} (s)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FreeWakeStart'], 'FreeWakeStart method', 'Time when wake is free. (-) value = always free. {default: 0.0} (s)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FullCircStart'], 'FullCircStart', 'Time at which full circulation is reached. {default: 0.0} (s)\n')) f.write('--------------------------- CIRCULATION SPECIFICATIONS ----------------------------------------\n') - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvingMethod'], 'CircSolvingMethod', 'Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvingMethod'], 'CircSolvingMethod', 'Circulation solving method {1: Cl-Based, 2: No-Flow Through, 3: Prescribed, default: 1 }(switch)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvConvCrit'], 'CircSolvConvCrit', 'Convergence criteria {default: 0.001} [only if CircSolvingMethod=1] (-)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvRelaxation'], 'CircSolvRelaxation', 'Relaxation factor {default: 0.1} [only if CircSolvingMethod=1] (-)\n')) - f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'], 'CircSolvMaxIter', 'Maximum number of iterations for circulation solving {default: 30} (-)\n')) + f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['CircSolvMaxIter'], 'CircSolvMaxIter', 'Maximum number of iterations for circulation solving {default: 30} (-)\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['PrescribedCircFile'], 'PrescribedCircFile','File containing prescribed circulation [only if CircSolvingMethod=3] (quoted string)\n')) f.write('===============================================================================================\n') f.write('--------------------------- WAKE OPTIONS ------------------------------------------------------\n') f.write('------------------- WAKE EXTENT AND DISCRETIZATION --------------------------------------------\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['nNWPanel'], 'nNWPanel','Number of near-wake panels [integer] (-)\n')) f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['WakeLength'], 'WakeLength','Total wake distance [integer] (number of time steps)\n')) - f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FreeWakeLength'], 'FreeWakeLength','Wake length that is free [integer] (number of time steps) {default: WakeLength}\n')) + f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FreeWakeLength'], 'FreeWakeLength','Wake length that is free [integer] (number of time steps) {default: WakeLength}\n')) f.write('{:<22} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['FWShedVorticity'], 'FWShedVorticity','Include shed vorticity in the far wake {default: false}\n')) f.write('------------------- WAKE REGULARIZATIONS AND DIFFUSION -----------------------------------------\n') f.write('{:<22d} {:<11} {:}'.format(self.fst_vt['AeroDyn15']['OLAF']['DiffusionMethod'], 'DiffusionMethod','Diffusion method to account for viscous effects {0: None, 1: Core Spreading, "default": 0}\n'))