def setup(self): RefBlade = self.options['RefBlade'] npts_coarse_power_curve = self.options['npts_coarse_power_curve'] npts_spline_power_curve = self.options['npts_spline_power_curve'] regulation_reg_II5 = self.options['regulation_reg_II5'] regulation_reg_III = self.options['regulation_reg_III'] flag_Cp_Ct_Cq_Tables = self.options['flag_Cp_Ct_Cq_Tables'] Analysis_Level = self.options['Analysis_Level'] FASTpref = self.options['FASTpref'] topLevelFlag = self.options['topLevelFlag'] rc_verbosity = self.options['rc_verbosity'] rc_tex_table = self.options['rc_tex_table'] rc_generate_plots = self.options['rc_generate_plots'] rc_show_plots = self.options['rc_show_plots'] rc_show_warnings = self.options['rc_show_warnings'] rc_discrete = self.options['rc_discrete'] user_update_routine = self.options['user_update_routine'] NPTS = len(RefBlade['pf']['s']) rotorIndeps = IndepVarComp() rotorIndeps.add_discrete_output('tiploss', True) rotorIndeps.add_discrete_output('hubloss', True) rotorIndeps.add_discrete_output('wakerotation', True) rotorIndeps.add_discrete_output('usecd', True) rotorIndeps.add_discrete_output( 'nSector', val=4, desc= 'number of sectors to divide rotor face into in computing thrust and power' ) self.add_subsystem('rotorIndeps', rotorIndeps, promotes=['*']) if topLevelFlag: sharedIndeps = IndepVarComp() sharedIndeps.add_output( 'lifetime', val=20.0, units='year', desc='project lifetime for fatigue analysis') sharedIndeps.add_output('hub_height', val=0.0, units='m') sharedIndeps.add_output('rho', val=1.225, units='kg/m**3') sharedIndeps.add_output('mu', val=1.81e-5, units='kg/(m*s)') sharedIndeps.add_output('shearExp', val=0.2) self.add_subsystem('sharedIndeps', sharedIndeps, promotes=['*']) # --- Rotor Aero & Power --- self.add_subsystem('rg', RotorGeometry( RefBlade=RefBlade, topLevelFlag=True, verbosity=rc_verbosity, tex_table=rc_tex_table, generate_plots=rc_generate_plots, show_plots=rc_show_plots, show_warnings=rc_show_warnings, discrete=rc_discrete, user_update_routine=user_update_routine), promotes=['*']) self.add_subsystem('ra', RotorAeroPower( RefBlade=RefBlade, npts_coarse_power_curve=npts_coarse_power_curve, npts_spline_power_curve=npts_spline_power_curve, regulation_reg_II5=regulation_reg_II5, regulation_reg_III=regulation_reg_III, flag_Cp_Ct_Cq_Tables=flag_Cp_Ct_Cq_Tables, topLevelFlag=False), promotes=['*']) self.add_subsystem( 'rs', RotorStructure(RefBlade=RefBlade, topLevelFlag=False, Analysis_Level=Analysis_Level), promotes=[ 'fst_vt_in', 'VfactorPC', 'turbulence_class', 'gust_stddev', 'pitch_extreme', 'azimuth_extreme', 'rstar_damage', 'Mxb_damage', 'Myb_damage', 'strain_ult_spar', 'strain_ult_te', 'm_damage', 'gamma_fatigue', 'gamma_freq', 'gamma_f', 'gamma_m', 'dynamic_amplification', 'azimuth_load180', 'azimuth_load0', 'azimuth_load120', 'azimuth_load240', 'nSector', 'rho', 'mu', 'shearExp', 'tiploss', 'hubloss', 'wakerotation', 'usecd', 'bladeLength', 'R', 'V_mean', 'chord', 'theta', 'precurve', 'presweep', 'Rhub', 'Rtip', 'r', 'r_in', 'airfoils_cl', 'airfoils_cd', 'airfoils_cm', 'airfoils_aoa', 'airfoils_Re', 'z', 'EA', 'EIxx', 'EIyy', 'EIxy', 'GJ', 'rhoA', 'rhoJ', 'x_ec', 'y_ec', 'Tw_iner', 'flap_iner', 'edge_iner', 'eps_crit_spar', 'eps_crit_te', 'xu_strain_spar', 'xl_strain_spar', 'yu_strain_spar', 'yl_strain_spar', 'xu_strain_te', 'xl_strain_te', 'yu_strain_te', 'yl_strain_te', 'precurveTip', 'presweepTip', 'precone', 'tilt', 'yaw', 'nBlades', 'downwind', 'control_tsr', 'control_pitch', 'lifetime', 'hub_height', 'mass_one_blade', 'mass_all_blades', 'I_all_blades', 'freq_pbeam', 'freq_distance', 'freq_curvefem', 'modes_coef_curvefem', 'tip_deflection', 'tip_position', 'ground_clearance', 'strainU_spar', 'strainL_spar', 'strainU_te', 'strainL_te', #'eps_crit_spar','eps_crit_te', 'root_bending_moment', 'Mxyz', 'damageU_spar', 'damageL_spar', 'damageU_te', 'damageL_te', 'delta_bladeLength_out', 'delta_precurve_sub_out', 'Fxyz_1', 'Fxyz_2', 'Fxyz_3', 'Fxyz_4', 'Fxyz_5', 'Fxyz_6', 'Mxyz_1', 'Mxyz_2', 'Mxyz_3', 'Mxyz_4', 'Mxyz_5', 'Mxyz_6', 'Fxyz_total', 'Mxyz_total', 'TotalCone', 'Pitch' ]) # self.add_subsystem('rc', RotorCost(RefBlade=RefBlade, verbosity=rc_verbosity), # promotes=['bladeLength','total_blade_cost','Rtip','Rhub','r','chord','le_location','materials','upperCS','lowerCS','websCS','profile']) self.add_subsystem('obj_cmp', ExecComp('obj = -AEP', AEP={ 'units': 'kW*h', 'value': 1000000.0 }, obj={'units': 'kW*h'}), promotes=['*']) # Connections between rotor_aero and rotor_structure self.connect('V_mean', 'wind.Uref') self.connect('wind_zvec', 'wind.z') self.connect('rated_V', ['rs.V_hub', 'rs.setuppc.Vrated']) self.connect('rated_Omega', [ 'rs.Omega', 'rs.aero_rated.Omega_load', 'rs.aero_rated_0.Omega_load', 'rs.aero_rated_120.Omega_load', 'rs.aero_rated_240.Omega_load' ]) self.connect('rated_pitch', 'rs.aero_rated.pitch_load') self.connect('V_extreme50', 'rs.aero_extrm.V_load') self.connect('V_extreme_full', 'rs.aero_extrm_forces.Uhub') self.connect('theta', 'rs.tip.theta', src_indices=[NPTS - 1]) # Connections to AeroelasticSE if Analysis_Level >= 1: self.add_subsystem( 'aeroelastic', FASTLoadCases(RefBlade=RefBlade, npts_coarse_power_curve=npts_coarse_power_curve, npts_spline_power_curve=npts_spline_power_curve, FASTpref=FASTpref), promotes=[ 'fst_vt_in', 'fst_vt_out', 'FASTpref_updated', 'r', 'le_location', 'chord', 'theta', 'precurve', 'shearExp', 'presweep', 'Rhub', 'Rtip', 'turbulence_class', 'turbine_class', 'V_R25', 'rho', 'mu', 'control_maxTS', 'control_maxOmega', 'hub_height', 'airfoils_cl', 'airfoils_cd', 'airfoils_cm', 'airfoils_aoa', 'airfoils_Re', 'airfoils_coord_x', 'airfoils_coord_y', 'rthick' ]) self.connect('rhoA', 'aeroelastic.beam:rhoA') self.connect('EIxx', 'aeroelastic.beam:EIxx') self.connect('EIyy', 'aeroelastic.beam:EIyy') self.connect('Tw_iner', 'aeroelastic.beam:Tw_iner') self.connect('modes_coef_curvefem', 'aeroelastic.modes_coef_curvefem') self.connect('rs.z_az', 'aeroelastic.z_az') self.connect('V', 'aeroelastic.U_init') self.connect('Omega', 'aeroelastic.Omega_init') self.connect('pitch', 'aeroelastic.pitch_init') self.connect('rated_V', 'aeroelastic.Vrated') self.connect('rs.gust.V_gust', 'aeroelastic.Vgust') self.connect('V_mean', 'aeroelastic.V_mean_iec') self.connect('machine_rating', 'aeroelastic.control_ratedPower') if Analysis_Level > 1: self.connect('aeroelastic.dx_defl', 'rs.tip.dx') self.connect('aeroelastic.dy_defl', 'rs.tip.dy') self.connect('aeroelastic.dz_defl', 'rs.tip.dz') self.connect('aeroelastic.loads_Px', 'rs.loads_strain.aeroloads_Px') self.connect('aeroelastic.loads_Py', 'rs.loads_strain.aeroloads_Py') self.connect('aeroelastic.loads_Pz', 'rs.loads_strain.aeroloads_Pz') self.connect('aeroelastic.loads_Omega', 'rs.loads_strain.aeroloads_Omega') self.connect('aeroelastic.loads_azimuth', 'rs.loads_strain.aeroloads_azimuth') self.connect('aeroelastic.loads_pitch', 'rs.loads_strain.aeroloads_pitch') self.connect('aeroelastic.root_bending_moment', 'rs.root_bending_moment_in') self.connect('aeroelastic.Mxyz', 'rs.Mxyz_in')
def setup(self): self.verbosity = self.options['verbosity'] if self.options['topLevelFlag']: sharedIndeps = IndepVarComp() sharedIndeps.add_output('machine_rating', units='kW', val=0.0) sharedIndeps.add_output('blade_mass', units='kg', val=0.0) sharedIndeps.add_output('hub_mass', units='kg', val=0.0) sharedIndeps.add_output('pitch_system_mass', units='kg', val=0.0) sharedIndeps.add_output('spinner_mass', units='kg', val=0.0) sharedIndeps.add_output('lss_mass', units='kg', val=0.0) sharedIndeps.add_output('bearings_mass', units='kg', val=0.0) sharedIndeps.add_output('gearbox_mass', units='kg', val=0.0) sharedIndeps.add_output('main_bearing_mass', units='kg', val=0.0) sharedIndeps.add_discrete_output('main_bearing_number', val=0) sharedIndeps.add_output('hss_mass', units='kg', val=0.0) sharedIndeps.add_output('generator_mass', units='kg', val=0.0) sharedIndeps.add_output('bedplate_mass', units='kg', val=0.0) sharedIndeps.add_output('yaw_mass', units='kg', val=0.0) sharedIndeps.add_output('vs_electronics_mass',units='kg', val=0.0) sharedIndeps.add_output('hvac_mass', units='kg', val=0.0) sharedIndeps.add_output('cover_mass', units='kg', val=0.0) sharedIndeps.add_output('platforms_mass', units='kg', val=0.0) sharedIndeps.add_output('transformer_mass', units='kg', val=0.0) sharedIndeps.add_output('tower_mass', units='kg', val=0.0) sharedIndeps.add_discrete_output('crane', val=False) self.add_subsystem('sharedIndeps', sharedIndeps, promotes=['*']) indeps = IndepVarComp() indeps.add_output('blade_mass_cost_coeff', units='USD/kg', val=14.6) indeps.add_output('hub_mass_cost_coeff', units='USD/kg', val=3.9) indeps.add_output('pitch_system_mass_cost_coeff', units='USD/kg', val=22.1) indeps.add_output('spinner_mass_cost_coeff', units='USD/kg', val=11.1) indeps.add_output('lss_mass_cost_coeff', units='USD/kg', val=11.9) indeps.add_output('bearings_mass_cost_coeff', units='USD/kg', val=4.5) indeps.add_output('gearbox_mass_cost_coeff', units='USD/kg', val=12.9) indeps.add_output('hss_mass_cost_coeff', units='USD/kg', val=6.8) indeps.add_output('generator_mass_cost_coeff', units='USD/kg', val=12.4) indeps.add_output('bedplate_mass_cost_coeff', units='USD/kg', val=2.9) indeps.add_output('yaw_mass_cost_coeff', units='USD/kg', val=8.3) indeps.add_output('vs_electronics_mass_cost_coeff',units='USD/kg', val=18.8) indeps.add_output('hvac_mass_cost_coeff', units='USD/kg', val=124.0) indeps.add_output('cover_mass_cost_coeff', units='USD/kg', val=5.7) indeps.add_output('elec_connec_machine_rating_cost_coeff',units='USD/kW', val=41.85) indeps.add_output('platforms_mass_cost_coeff', units='USD/kg', val=17.1) indeps.add_output('base_hardware_cost_coeff', units='USD/kg', val=0.7) indeps.add_output('transformer_mass_cost_coeff', units='USD/kg', val=18.8) indeps.add_output('tower_mass_cost_coeff', units='USD/kg', val=2.9) indeps.add_output('controls_machine_rating_cost_coeff', units='USD/kW', val=21.15) indeps.add_output('crane_cost', units='USD', val=12e3) indeps.add_output('hub_assemblyCostMultiplier', val=0.0) indeps.add_output('hub_overheadCostMultiplier', val=0.0) indeps.add_output('nacelle_assemblyCostMultiplier',val=0.0) indeps.add_output('nacelle_overheadCostMultiplier',val=0.0) indeps.add_output('tower_assemblyCostMultiplier', val=0.0) indeps.add_output('tower_overheadCostMultiplier', val=0.0) indeps.add_output('turbine_assemblyCostMultiplier',val=0.0) indeps.add_output('turbine_overheadCostMultiplier',val=0.0) indeps.add_output('hub_profitMultiplier', val=0.0) indeps.add_output('nacelle_profitMultiplier', val=0.0) indeps.add_output('tower_profitMultiplier', val=0.0) indeps.add_output('turbine_profitMultiplier', val=0.0) indeps.add_output('hub_transportMultiplier', val=0.0) indeps.add_output('nacelle_transportMultiplier', val=0.0) indeps.add_output('tower_transportMultiplier', val=0.0) indeps.add_output('turbine_transportMultiplier', val=0.0) self.add_subsystem('indeps', indeps, promotes=['*']) self.add_subsystem('blade_c' , BladeCost2015(), promotes=['*']) self.add_subsystem('hub_c' , HubCost2015(), promotes=['*']) self.add_subsystem('pitch_c' , PitchSystemCost2015(), promotes=['*']) self.add_subsystem('spinner_c' , SpinnerCost2015(), promotes=['*']) self.add_subsystem('hub_adder' , HubSystemCostAdder2015(),promotes=['*']) self.add_subsystem('rotor_adder' , RotorCostAdder2015(), promotes=['*']) self.add_subsystem('lss_c' , LowSpeedShaftCost2015(), promotes=['*']) self.add_subsystem('bearing_c' , BearingsCost2015(), promotes=['*']) self.add_subsystem('gearbox_c' , GearboxCost2015(), promotes=['*']) self.add_subsystem('hss_c' , HighSpeedSideCost2015(), promotes=['*']) self.add_subsystem('generator_c' , GeneratorCost2015(), promotes=['*']) self.add_subsystem('bedplate_c' , BedplateCost2015(), promotes=['*']) self.add_subsystem('yaw_c' , YawSystemCost2015(), promotes=['*']) self.add_subsystem('hvac_c' , HydraulicCoolingCost2015(), promotes=['*']) self.add_subsystem('controls_c' , ControlsCost2015(), promotes=['*']) self.add_subsystem('vs_c' , VariableSpeedElecCost2015(), promotes=['*']) self.add_subsystem('elec_c' , ElecConnecCost2015(), promotes=['*']) self.add_subsystem('cover_c' , NacelleCoverCost2015(), promotes=['*']) self.add_subsystem('other_c' , OtherMainframeCost2015(),promotes=['*']) self.add_subsystem('transformer_c' , TransformerCost2015(), promotes=['*']) self.add_subsystem('nacelle_adder' , NacelleSystemCostAdder2015(), promotes=['*']) self.add_subsystem('tower_c' , TowerCost2015(), promotes=['*']) self.add_subsystem('tower_adder' , TowerCostAdder2015(), promotes=['*']) self.add_subsystem('turbine_c' , TurbineCostAdder2015(), promotes=['*']) self.add_subsystem('outputs' , Outputs2Screen(verbosity=self.verbosity), promotes=['*'])
def setup(self): RefBlade = self.options['RefBlade'] Nsection_Tow = self.options['Nsection_Tow'] user_update_routine = self.options['user_update_routine'] if 'Analysis_Level' in self.options['FASTpref']: Analysis_Level = self.options['FASTpref']['Analysis_Level'] else: Analysis_Level = 0 # Define all input variables from all models myIndeps = IndepVarComp() myIndeps.add_discrete_output('crane', False) # Turbine Costs myIndeps.add_discrete_output('bearing_number', 0) # Tower and Frame3DD options myIndeps.add_output('project_lifetime', 0.0, units='yr') myIndeps.add_output('max_taper_ratio', 0.0) myIndeps.add_output('min_diameter_thickness_ratio', 0.0) # Environment myIndeps.add_output('wind_bottom_height', 0.0, units='m') myIndeps.add_output('wind_beta', 0.0, units='deg') myIndeps.add_output('cd_usr', -1.) # Environment Offshore myIndeps.add_output('offshore', True) myIndeps.add_output('water_depth', 0.0) myIndeps.add_output('wave_height', 0.0) myIndeps.add_output('wave_period', 0.0) myIndeps.add_output('mean_current_speed', 0.0) # Design standards myIndeps.add_output('gamma_b', 0.0) myIndeps.add_output('gamma_n', 0.0) # RNA myIndeps.add_discrete_output('rna_weightM', True) # Column myIndeps.add_output('morison_mass_coefficient', 2.0) myIndeps.add_output('material_density', 0.0, units='kg/m**3') myIndeps.add_output('E', 0.0, units='N/m**2') myIndeps.add_output('yield_stress', 0.0, units='N/m**2') # Pontoons myIndeps.add_output('G', 0.0, units='N/m**2') # LCOE myIndeps.add_output('labor_cost_rate', 0.0, units='USD/min') myIndeps.add_output('material_cost_rate', 0.0, units='USD/kg') myIndeps.add_output('painting_cost_rate', 0.0, units='USD/m**2') myIndeps.add_discrete_output('number_of_turbines', 0) myIndeps.add_output( 'annual_opex', 0.0, units='USD/kW/yr') # TODO: Replace with output connection myIndeps.add_output( 'bos_costs', 0.0, units='USD/kW') # TODO: Replace with output connection myIndeps.add_output('fixed_charge_rate', 0.0) myIndeps.add_output('wake_loss_factor', 0.0) myIndeps.add_output('overhang', 0.0, units='m') myIndeps.add_output('hub_cm', np.zeros(3), units='m') myIndeps.add_output('nac_cm', np.zeros(3), units='m') myIndeps.add_output('hub_I', np.zeros(6), units='kg*m**2') myIndeps.add_output('nac_I', np.zeros(6), units='kg*m**2') myIndeps.add_output('hub_mass', 0.0, units='kg') myIndeps.add_output('nac_mass', 0.0, units='kg') myIndeps.add_output('hss_mass', 0.0, units='kg') myIndeps.add_output('lss_mass', 0.0, units='kg') myIndeps.add_output('cover_mass', 0.0, units='kg') myIndeps.add_output('pitch_system_mass', 0.0, units='kg') myIndeps.add_output('platforms_mass', 0.0, units='kg') myIndeps.add_output('spinner_mass', 0.0, units='kg') myIndeps.add_output('transformer_mass', 0.0, units='kg') myIndeps.add_output('vs_electronics_mass', 0.0, units='kg') myIndeps.add_output('yaw_mass', 0.0, units='kg') myIndeps.add_output('gearbox_mass', 0.0, units='kg') myIndeps.add_output('generator_mass', 0.0, units='kg') myIndeps.add_output('bedplate_mass', 0.0, units='kg') myIndeps.add_output('main_bearing_mass', 0.0, units='kg') self.add_subsystem('myIndeps', myIndeps, promotes=['*']) # Add components self.add_subsystem('rotorse', RotorSE(RefBlade=RefBlade, npts_coarse_power_curve=20, npts_spline_power_curve=200, regulation_reg_II5=True, regulation_reg_III=True, Analysis_Level=Analysis_Level, FASTpref=self.options['FASTpref'], topLevelFlag=True, user_update_routine=user_update_routine), promotes=['*']) self.add_subsystem( 'rna', RNA(nLC=1), promotes=['hub_mass', 'nac_mass', 'nac_cm', 'hub_cm', 'tilt']) # Tower and substructure self.add_subsystem( 'tow', TowerSE(nLC=1, nPoints=Nsection_Tow + 1, nFull=5 * Nsection_Tow + 1, wind='PowerWind', topLevelFlag=False, monopile=True), promotes=[ 'water_density', 'water_viscosity', 'wave_beta', 'significant_wave_height', 'significant_wave_period', 'material_density', 'E', 'G', 'tower_section_height', 'tower_wall_thickness', 'tower_outer_diameter', 'tower_outfitting_factor', 'tower_buckling_length', 'transition_piece_mass', 'transition_piece_height', 'max_taper', 'min_d_to_t', 'rna_mass', 'rna_cg', 'rna_I', 'tower_add_gravity', 'tower_mass', 'tower_I_base', 'hub_height', 'foundation_height', 'monopile', 'soil_G', 'soil_nu', 'suctionpile_depth', 'gamma_f', 'gamma_m', 'gamma_b', 'gamma_n', 'gamma_fatigue', 'labor_cost_rate', 'material_cost_rate', 'painting_cost_rate', 'z_full', 'd_full', 't_full', 'DC', 'shear', 'geom', 'tower_force_discretization', 'nM', 'Mmethod', 'lump', 'tol', 'shift' ]) # Turbine constraints self.add_subsystem('tcons', TurbineConstraints(nFull=5 * Nsection_Tow + 1), promotes=['*']) # Turbine costs self.add_subsystem('tcost', Turbine_CostsSE_2015( verbosity=self.options['VerbosityCosts'], topLevelFlag=False), promotes=['*']) # LCOE Calculation self.add_subsystem( 'plantfinancese', PlantFinance(verbosity=self.options['VerbosityCosts']), promotes=['machine_rating', 'lcoe']) # Set up connections # Connections to DriveSE self.connect('Fxyz_total', 'rna.loads.F') self.connect('Mxyz_total', 'rna.loads.M') self.connect('mass_all_blades', 'rna.blades_mass') self.connect('I_all_blades', 'rna.blades_I') self.connect('material_density', 'tow.tower.rho') # Connections to TowerSE self.connect('rna.loads.top_F', 'tow.pre.rna_F') self.connect('rna.loads.top_M', 'tow.pre.rna_M') self.connect('rna.rna_I_TT', ['rna_I', 'tow.pre.mI']) self.connect('rna.rna_cm', ['rna_cg', 'tow.pre.mrho']) self.connect('rna.rna_mass', ['rna_mass', 'tow.pre.mass']) self.connect('rs.gust.V_gust', 'tow.wind.Uref') self.connect('wind_reference_height', ['tow.wind.zref', 'wind.zref']) # self.connect('wind_bottom_height', ['tow.wind.z0','tow.wave.z_surface', 'wind.z0']) # offshore self.connect('wind_bottom_height', ['tow.wind.z0', 'wind.z0']) self.connect('shearExp', ['tow.wind.shearExp']) # self.connect('morison_mass_coefficient','tow.cm') # offshore self.connect('yield_stress', 'tow.sigma_y') self.connect('max_taper_ratio', 'max_taper') self.connect('min_diameter_thickness_ratio', 'min_d_to_t') self.connect('rho', 'tow.windLoads.rho') self.connect('mu', 'tow.windLoads.mu') self.connect('wind_beta', 'tow.windLoads.beta') # Connections to TurbineConstraints self.connect('nBlades', 'blade_number') self.connect('control_maxOmega', 'rotor_omega') self.connect('tow.post.structural_frequencies', 'tower_freq') # Connections to TurbineCostSE self.connect('mass_one_blade', 'blade_mass') self.connect('total_blade_cost', 'blade_cost_external') # Connections to PlantFinanceSE self.connect('AEP', 'plantfinancese.turbine_aep') self.connect('turbine_cost_kW', 'plantfinancese.tcc_per_kW') self.connect('number_of_turbines', 'plantfinancese.turbine_number') self.connect('bos_costs', 'plantfinancese.bos_per_kW') self.connect('annual_opex', 'plantfinancese.opex_per_kW')
def setup(self): RefBlade = self.options['RefBlade'] topLevelFlag = self.options['topLevelFlag'] NINPUT = len(RefBlade['ctrl_pts']['r_in']) NAF = len(RefBlade['outer_shape_bem']['airfoil_position']['grid']) verbosity = self.options['verbosity'] tex_table = self.options['tex_table'] generate_plots = self.options['generate_plots'] show_plots = self.options['show_plots'] show_warnings = self.options['show_warnings'] discrete = self.options['discrete'] user_update_routine = self.options['user_update_routine'] # Independent variables that are unique to TowerSE if topLevelFlag: geomIndeps = IndepVarComp() geomIndeps.add_output('bladeLength', 0.0, units='m') geomIndeps.add_output('hubFraction', 0.0) geomIndeps.add_output('r_max_chord', 0.0) geomIndeps.add_output('chord_in', np.zeros(NINPUT), units='m') geomIndeps.add_output('theta_in', np.zeros(NINPUT), units='deg') geomIndeps.add_output('precurve_in', np.zeros(NINPUT), units='m') geomIndeps.add_output('presweep_in', np.zeros(NINPUT), units='m') # geomIndeps.add_output('precurveTip', 0.0, units='m') # geomIndeps.add_output('presweepTip', 0.0, units='m') geomIndeps.add_output('precone', 0.0, units='deg') geomIndeps.add_output('tilt', 0.0, units='deg') geomIndeps.add_output('yaw', 0.0, units='deg') geomIndeps.add_discrete_output('nBlades', 3) geomIndeps.add_discrete_output('downwind', False) geomIndeps.add_discrete_output('turbine_class', val='I', desc='IEC turbine class') geomIndeps.add_discrete_output('blade_in_overwrite', val={}, desc='IEC turbine class') geomIndeps.add_output( 'V_mean_overwrite', val=0.0, desc= 'optional overwrite value for mean velocity for using user defined CDFs' ) geomIndeps.add_output('airfoil_position', val=np.zeros(NAF)) geomIndeps.add_output('sparT_in', val=np.zeros(NINPUT), units='m', desc='spar cap thickness parameters') geomIndeps.add_output('teT_in', val=np.zeros(NINPUT), units='m', desc='trailing-edge thickness parameters') # geomIndeps.add_output('leT_in', val=np.zeros(NINPUT), units='m', desc='leading-edge thickness parameters') self.add_subsystem('geomIndeps', geomIndeps, promotes=['*']) # --- Rotor Definition --- self.add_subsystem('loc', Location(), promotes=['*']) self.add_subsystem('turbineclass', TurbineClass(), promotes=['*']) #self.add_subsystem('spline0', BladeGeometry(RefBlade)) self.add_subsystem('spline', BladeGeometry( RefBlade=RefBlade, verbosity=verbosity, tex_table=tex_table, generate_plots=generate_plots, show_plots=show_plots, show_warnings=show_warnings, discrete=discrete, user_update_routine=user_update_routine), promotes=['*']) self.add_subsystem('geom', CCBladeGeometry(NINPUT=NINPUT), promotes=[ 'precone', 'precurve_in', 'presweep_in', 'precurveTip', 'presweepTip', 'R', 'Rtip' ])
def setup(self): nLC = self.options['nLC'] nPoints = self.options['nPoints'] nFull = self.options['nFull'] # nDEL = self.options['nDEL'] wind = self.options['wind'] topLevelFlag = self.options['topLevelFlag'] self.monopile = self.options['monopile'] # Independent variables that are unique to TowerSE towerIndeps = IndepVarComp() #towerIndeps.add_output('tower_M_DEL', np.zeros(nDEL)) #towerIndeps.add_output('tower_z_DEL', np.zeros(nDEL), units='m') towerIndeps.add_output('tower_force_discretization', 5.0) towerIndeps.add_output('suctionpile_depth', 0.0, units='m') towerIndeps.add_output('soil_G', 0.0, units='N/m**2') towerIndeps.add_output('soil_nu', 0.0) towerIndeps.add_discrete_output('monopile', False) towerIndeps.add_discrete_output('tower_add_gravity', True) towerIndeps.add_discrete_output('shear', True) towerIndeps.add_discrete_output('geom', False) towerIndeps.add_discrete_output('nM', 2) towerIndeps.add_discrete_output('Mmethod', 1) towerIndeps.add_discrete_output('lump', 0) towerIndeps.add_output('tol', 1e-9) towerIndeps.add_output('shift', 0.0) towerIndeps.add_output('DC', 0.0) towerIndeps.add_output('water_density', 1025.0, units='kg/m**3') towerIndeps.add_output('water_viscosity', 8.9e-4, units='kg/m/s') towerIndeps.add_output('significant_wave_height', 0.0, units='m') towerIndeps.add_output('significant_wave_period', 0.0, units='s') towerIndeps.add_output('wave_beta', 0.0, units='deg') self.add_subsystem('towerIndeps', towerIndeps, promotes=['*']) # Independent variables that may be duplicated at higher levels of aggregation if topLevelFlag: sharedIndeps = IndepVarComp() sharedIndeps.add_output('air_density', 1.225, units='kg/m**3') sharedIndeps.add_output('air_viscosity', 1.81206e-5, units='kg/m/s') sharedIndeps.add_output('shearExp', 0.0) sharedIndeps.add_output('wind_reference_height', 0.0, units='m') sharedIndeps.add_output('wind_z0', 0.0, units='m') sharedIndeps.add_output('wind_beta', 0.0, units='deg') sharedIndeps.add_output('cd_usr', -1.) sharedIndeps.add_output('yaw', 0.0, units='deg') sharedIndeps.add_output('E', 0.0, units='N/m**2') sharedIndeps.add_output('G', 0.0, units='N/m**2') sharedIndeps.add_output('sigma_y', 0.0, units='N/m**2') sharedIndeps.add_output('rna_mass', 0.0, units='kg') sharedIndeps.add_output('rna_cg', np.zeros(3), units='m') sharedIndeps.add_output('rna_I', np.zeros(6), units='kg*m**2') sharedIndeps.add_output('gamma_f', 0.0) sharedIndeps.add_output('gamma_m', 0.0) sharedIndeps.add_output('gamma_n', 0.0) sharedIndeps.add_output('gamma_b', 0.0) sharedIndeps.add_output('gamma_fatigue', 0.0) sharedIndeps.add_output('life', 0.0) sharedIndeps.add_output('m_SN', 0.0) self.add_subsystem('sharedIndeps', sharedIndeps, promotes=['*']) self.add_subsystem('geom', TowerLeanSE(nPoints=nPoints, nFull=nFull, topLevelFlag=topLevelFlag), promotes=['*']) self.add_subsystem('props', CylindricalShellProperties(nFull=nFull)) self.add_subsystem('soil', TowerSoil()) # Connections for geometry and mass self.connect('d_full', 'props.d') self.connect('t_full', 'props.t') self.connect('d_full', 'soil.d0', src_indices=[0]) self.connect('suctionpile_depth', 'soil.depth') self.connect('soil_G', 'soil.G') self.connect('soil_nu', 'soil.nu') # Add in all Components that drive load cases # Note multiple load cases have to be handled by replicating components and not groups/assemblies. # Replicating Groups replicates the IndepVarComps which doesn't play nicely in OpenMDAO for iLC in range(nLC): lc = '' if nLC==1 else str(iLC+1) if wind is None or wind.lower() in ['power', 'powerwind', '']: self.add_subsystem('wind'+lc, PowerWind(nPoints=nFull)) elif wind.lower() == 'logwind': self.add_subsystem('wind'+lc, LogWind(nPoints=nFull)) else: raise ValueError('Unknown wind type, '+wind) self.add_subsystem('windLoads'+lc, CylinderWindDrag(nPoints=nFull), promotes=['cd_usr']) if self.monopile: self.add_subsystem('wave'+lc, LinearWaves(nPoints=nFull), promotes=['z_floor']) self.add_subsystem('waveLoads'+lc, CylinderWaveDrag(nPoints=nFull), promotes=['cm','cd_usr']) self.add_subsystem('distLoads'+lc, AeroHydroLoads(nPoints=nFull), promotes=['yaw']) self.add_subsystem('pre'+lc, TowerPreFrame(nFull=nFull), promotes=['monopile']) self.add_subsystem('tower'+lc, CylinderFrame3DD(npts=nFull, nK=1, nMass=1, nPL=1), promotes=['E','G','tol','Mmethod','geom','lump','shear', 'nM','shift','sigma_y']) self.add_subsystem('post'+lc, TowerPostFrame(nFull=nFull), promotes=['E','sigma_y','DC','life','m_SN', 'gamma_b','gamma_f','gamma_fatigue','gamma_m','gamma_n']) self.connect('z_full', ['wind'+lc+'.z', 'windLoads'+lc+'.z', 'distLoads'+lc+'.z', 'pre'+lc+'.z', 'tower'+lc+'.z', 'post'+lc+'.z']) self.connect('d_full', ['windLoads'+lc+'.d', 'tower'+lc+'.d', 'post'+lc+'.d']) if self.monopile: self.connect('z_full', ['wave'+lc+'.z', 'waveLoads'+lc+'.z']) self.connect('d_full', 'waveLoads'+lc+'.d') if topLevelFlag: self.connect('rna_mass', 'pre'+lc+'.mass') self.connect('rna_cg', 'pre'+lc+'.mrho') self.connect('rna_I', 'pre'+lc+'.mI') self.connect('material_density', 'tower'+lc+'.rho') self.connect('pre'+lc+'.kidx', 'tower'+lc+'.kidx') self.connect('pre'+lc+'.kx', 'tower'+lc+'.kx') self.connect('pre'+lc+'.ky', 'tower'+lc+'.ky') self.connect('pre'+lc+'.kz', 'tower'+lc+'.kz') self.connect('pre'+lc+'.ktx', 'tower'+lc+'.ktx') self.connect('pre'+lc+'.kty', 'tower'+lc+'.kty') self.connect('pre'+lc+'.ktz', 'tower'+lc+'.ktz') self.connect('pre'+lc+'.midx', 'tower'+lc+'.midx') self.connect('pre'+lc+'.m', 'tower'+lc+'.m') self.connect('pre'+lc+'.mIxx', 'tower'+lc+'.mIxx') self.connect('pre'+lc+'.mIyy', 'tower'+lc+'.mIyy') self.connect('pre'+lc+'.mIzz', 'tower'+lc+'.mIzz') self.connect('pre'+lc+'.mIxy', 'tower'+lc+'.mIxy') self.connect('pre'+lc+'.mIxz', 'tower'+lc+'.mIxz') self.connect('pre'+lc+'.mIyz', 'tower'+lc+'.mIyz') self.connect('pre'+lc+'.mrhox', 'tower'+lc+'.mrhox') self.connect('pre'+lc+'.mrhoy', 'tower'+lc+'.mrhoy') self.connect('pre'+lc+'.mrhoz', 'tower'+lc+'.mrhoz') self.connect('pre'+lc+'.plidx', 'tower'+lc+'.plidx') self.connect('pre'+lc+'.Fx', 'tower'+lc+'.Fx') self.connect('pre'+lc+'.Fy', 'tower'+lc+'.Fy') self.connect('pre'+lc+'.Fz', 'tower'+lc+'.Fz') self.connect('pre'+lc+'.Mxx', 'tower'+lc+'.Mxx') self.connect('pre'+lc+'.Myy', 'tower'+lc+'.Myy') self.connect('pre'+lc+'.Mzz', 'tower'+lc+'.Mzz') self.connect('tower_force_discretization', 'tower'+lc+'.dx') self.connect('tower_add_gravity', 'tower'+lc+'.addGravityLoadForExtraMass') self.connect('t_full', ['tower'+lc+'.t','post'+lc+'.t']) self.connect('soil.k', 'pre'+lc+'.k_monopile') self.connect('tower'+lc+'.f1', 'post'+lc+'.f1') self.connect('tower'+lc+'.f2', 'post'+lc+'.f2') self.connect('tower'+lc+'.Fz_out', 'post'+lc+'.Fz') self.connect('tower'+lc+'.Mxx_out', 'post'+lc+'.Mxx') self.connect('tower'+lc+'.Myy_out', 'post'+lc+'.Myy') self.connect('tower'+lc+'.axial_stress', 'post'+lc+'.axial_stress') self.connect('tower'+lc+'.shear_stress', 'post'+lc+'.shear_stress') self.connect('tower'+lc+'.hoop_stress_euro', 'post'+lc+'.hoop_stress') # connections to wind, wave if topLevelFlag: self.connect('wind_reference_height', 'wind'+lc+'.zref') self.connect('wind_z0', 'wind'+lc+'.z0') if self.monopile: self.connect('wind_z0', 'wave'+lc+'.z_surface') #self.connect('z_floor', 'waveLoads'+lc+'.wlevel') if wind=='PowerWind': self.connect('shearExp', 'wind'+lc+'.shearExp') # connections to windLoads1 self.connect('air_density', 'windLoads'+lc+'.rho') self.connect('air_viscosity', 'windLoads'+lc+'.mu') self.connect('wind_beta', 'windLoads'+lc+'.beta') if self.monopile: # connections to waveLoads1 self.connect('water_density', ['wave'+lc+'.rho', 'waveLoads'+lc+'.rho']) self.connect('water_viscosity', 'waveLoads'+lc+'.mu') self.connect('wave_beta', 'waveLoads'+lc+'.beta') self.connect('significant_wave_height', 'wave'+lc+'.hmax') self.connect('significant_wave_period', 'wave'+lc+'.T') self.connect('wind'+lc+'.U', 'windLoads'+lc+'.U') self.connect('wave'+lc+'.U', 'waveLoads'+lc+'.U') self.connect('wave'+lc+'.A', 'waveLoads'+lc+'.A') self.connect('wave'+lc+'.p', 'waveLoads'+lc+'.p') # connections to distLoads1 self.connect('windLoads'+lc+'.windLoads_Px', 'distLoads'+lc+'.windLoads_Px') self.connect('windLoads'+lc+'.windLoads_Py', 'distLoads'+lc+'.windLoads_Py') self.connect('windLoads'+lc+'.windLoads_Pz', 'distLoads'+lc+'.windLoads_Pz') self.connect('windLoads'+lc+'.windLoads_qdyn', 'distLoads'+lc+'.windLoads_qdyn') self.connect('windLoads'+lc+'.windLoads_beta', 'distLoads'+lc+'.windLoads_beta') #self.connect('windLoads'+lc+'.windLoads_Px0', 'distLoads'+lc+'.windLoads_Px0') #self.connect('windLoads'+lc+'.windLoads_Py0', 'distLoads'+lc+'.windLoads_Py0') #self.connect('windLoads'+lc+'.windLoads_Pz0', 'distLoads'+lc+'.windLoads_Pz0') #self.connect('windLoads'+lc+'.windLoads_qdyn0', 'distLoads'+lc+'.windLoads_qdyn0') #self.connect('windLoads'+lc+'.windLoads_beta0', 'distLoads'+lc+'.windLoads_beta0') self.connect('windLoads'+lc+'.windLoads_z', 'distLoads'+lc+'.windLoads_z') self.connect('windLoads'+lc+'.windLoads_d', 'distLoads'+lc+'.windLoads_d') if self.monopile: self.connect('waveLoads'+lc+'.waveLoads_Px', 'distLoads'+lc+'.waveLoads_Px') self.connect('waveLoads'+lc+'.waveLoads_Py', 'distLoads'+lc+'.waveLoads_Py') self.connect('waveLoads'+lc+'.waveLoads_Pz', 'distLoads'+lc+'.waveLoads_Pz') self.connect('waveLoads'+lc+'.waveLoads_pt', 'distLoads'+lc+'.waveLoads_qdyn') self.connect('waveLoads'+lc+'.waveLoads_beta', 'distLoads'+lc+'.waveLoads_beta') #self.connect('waveLoads'+lc+'.waveLoads_Px0', 'distLoads'+lc+'.waveLoads_Px0') #self.connect('waveLoads'+lc+'.waveLoads_Py0', 'distLoads'+lc+'.waveLoads_Py0') #self.connect('waveLoads'+lc+'.waveLoads_Pz0', 'distLoads'+lc+'.waveLoads_Pz0') #self.connect('waveLoads'+lc+'.waveLoads_qdyn0', 'distLoads'+lc+'.waveLoads_qdyn0') #self.connect('waveLoads'+lc+'.waveLoads_beta0', 'distLoads'+lc+'.waveLoads_beta0') self.connect('waveLoads'+lc+'.waveLoads_z', 'distLoads'+lc+'.waveLoads_z') self.connect('waveLoads'+lc+'.waveLoads_d', 'distLoads'+lc+'.waveLoads_d') # Tower connections self.connect('tower_buckling_length', ['tower'+lc+'.L_reinforced', 'post'+lc+'.L_reinforced']) #self.connect('tower_M_DEL', 'post'+lc+'.M_DEL') #self.connect('tower_z_DEL', 'post'+lc+'.z_DEL') self.connect('props.Az', 'tower'+lc+'.Az') self.connect('props.Asx', 'tower'+lc+'.Asx') self.connect('props.Asy', 'tower'+lc+'.Asy') self.connect('props.Jz', 'tower'+lc+'.Jz') self.connect('props.Ixx', 'tower'+lc+'.Ixx') self.connect('props.Iyy', 'tower'+lc+'.Iyy') self.connect('distLoads'+lc+'.Px', 'tower'+lc+'.Px') self.connect('distLoads'+lc+'.Py', 'tower'+lc+'.Py') self.connect('distLoads'+lc+'.Pz', 'tower'+lc+'.Pz') self.connect('distLoads'+lc+'.qdyn', 'tower'+lc+'.qdyn')
def main(): num_nodes = 1 num_blades = 10 num_radial = 15 num_cp = 6 af_filename = 'airfoils/mh117.dat' chord = 20. theta = 5.0 * np.pi / 180.0 pitch = 0. # Numbers taken from the Aviary group's study of the RVLT tiltwing # turboelectric concept vehicle. n_props = 4 hub_diameter = 30. # cm prop_diameter = 15 * 30.48 # 15 ft in cm c0 = np.sqrt(1.4 * 287.058 * 300.) # meters/second rho0 = 1.4 * 98600. / (c0 * c0) # kg/m^3 omega = 236. # rad/s # Find the thrust per rotor from the vehicle's mass. m_full = 6367 # kg g = 9.81 # m/s**2 thrust_vtol = 0.1 * m_full * g / n_props prob = Problem() comp = IndepVarComp() comp.add_discrete_output('B', val=num_blades) comp.add_output('rho', val=rho0, shape=num_nodes, units='kg/m**3') comp.add_output('mu', val=1., shape=num_nodes, units='N/m**2*s') comp.add_output('asound', val=c0, shape=num_nodes, units='m/s') comp.add_output('v', val=2., shape=num_nodes, units='m/s') comp.add_output('alpha', val=0., shape=num_nodes, units='rad') comp.add_output('incidence', val=0., shape=num_nodes, units='rad') comp.add_output('precone', val=0., units='deg') comp.add_output('hub_diameter', val=hub_diameter, shape=num_nodes, units='cm') comp.add_output('prop_diameter', val=prop_diameter, shape=num_nodes, units='cm') comp.add_output('pitch', val=pitch, shape=num_nodes, units='rad') comp.add_output('chord_dv', val=chord, shape=num_cp, units='cm') comp.add_output('theta_dv', val=theta, shape=num_cp, units='rad') comp.add_output('thrust_vtol', val=thrust_vtol, shape=num_nodes, units='N') prob.model.add_subsystem('indep_var_comp', comp, promotes=['*']) comp = GeometryGroup(num_nodes=num_nodes, num_cp=num_cp, num_radial=num_radial) prob.model.add_subsystem( 'geometry_group', comp, promotes_inputs=[ 'hub_diameter', 'prop_diameter', 'chord_dv', 'theta_dv', 'pitch' ], promotes_outputs=['radii', 'dradii', 'chord', 'theta']) balance_group = Group() comp = SimpleInflow(num_nodes=num_nodes, num_radial=num_radial) balance_group.add_subsystem( 'inflow_comp', comp, promotes_inputs=['v', 'omega', 'radii', 'precone'], promotes_outputs=['Vx', 'Vy']) comp = CCBladeGroup(num_nodes=num_nodes, num_radial=num_radial, num_blades=num_blades, af_filename=af_filename, turbine=False) balance_group.add_subsystem( 'ccblade_group', comp, promotes_inputs=[ 'B', 'radii', 'dradii', 'chord', 'theta', 'rho', 'mu', 'asound', 'v', 'precone', 'omega', 'Vx', 'Vy', 'precone', 'hub_diameter', 'prop_diameter' ], promotes_outputs=['thrust', 'torque', 'efficiency']) comp = BalanceComp() comp.add_balance( name='omega', eq_units='N', lhs_name='thrust', rhs_name='thrust_vtol', val=omega, units='rad/s', # lower=0., ) balance_group.add_subsystem('thrust_balance_comp', comp, promotes=['*']) balance_group.linear_solver = DirectSolver(assemble_jac=True) balance_group.nonlinear_solver = NewtonSolver(maxiter=50, iprint=2) balance_group.nonlinear_solver.options['solve_subsystems'] = True # prob.model.nonlinear_solver.linesearch = BoundsEnforceLS() balance_group.nonlinear_solver.options['atol'] = 1e-9 prob.model.add_subsystem('thrust_balance_group', balance_group, promotes=['*']) prob.setup() prob.final_setup() # Calculate the induced axial velocity at the rotor for hover, used for # non-diminsionalation. rho = prob.get_val('rho', units='kg/m**3')[0] hub_diameter = prob.get_val('hub_diameter', units='m')[0] prop_diameter = prob.get_val('prop_diameter', units='m')[0] thrust_vtol = prob.get_val('thrust_vtol', units='N')[0] A_rotor = 0.25 * np.pi * (prop_diameter**2 - hub_diameter**2) v_h = np.sqrt(thrust_vtol / (2 * rho * A_rotor)) # Climb: climb_velocity_nondim = np.linspace(0.1, 2., 10) induced_velocity_nondim = np.zeros_like(climb_velocity_nondim) for vc, vi in np.nditer([climb_velocity_nondim, induced_velocity_nondim], op_flags=[['readonly'], ['writeonly']]): # Run the model with the requested climb velocity. prob.set_val('v', vc * v_h, units='m/s') print(f"v = {prob.get_val('v', units='m/s')}") prob.run_model() # Calculate the area-weighted average induced velocity at the rotor. # Need the area of each blade section. radii = prob.get_val('radii', units='m') dradii = prob.get_val('dradii', units='m') dArea = 2 * np.pi * radii * dradii # Get the induced velocity at the rotor plane for each blade section. Vx = prob.get_val('Vx', units='m/s') a = prob.get_val('ccblade_group.ccblade_comp.a') # Get the area-weighted average of the induced velocity. vi[...] = np.sum(a * Vx * dArea / A_rotor) / v_h # Induced velocity from plain old momentum theory (for climb). induced_velocity_mt = (-0.5 * climb_velocity_nondim + np.sqrt((0.5 * climb_velocity_nondim)**2 + 1.)) fig, ax = plt.subplots() ax.plot(climb_velocity_nondim, -induced_velocity_nondim, label='CCBlade.jl (climb)') ax.plot(climb_velocity_nondim, induced_velocity_mt, label='Momentum Theory (climb)') # Descent: # climb_velocity_nondim = np.linspace(-3.5, -2.6, 10) climb_velocity_nondim = np.linspace(-5.0, -2.1, 10) induced_velocity_nondim = np.zeros_like(climb_velocity_nondim) for vc, vi in np.nditer([climb_velocity_nondim, induced_velocity_nondim], op_flags=[['readonly'], ['writeonly']]): # Run the model with the requested climb velocity. prob.set_val('v', vc * v_h, units='m/s') print(f"vc = {vc}, v = {prob.get_val('v', units='m/s')}") prob.run_model() # Calculate the area-weighted average induced velocity at the rotor. # Need the area of each blade section. radii = prob.get_val('radii', units='m') dradii = prob.get_val('dradii', units='m') dArea = 2 * np.pi * radii * dradii # Get the induced velocity at the rotor plane for each blade section. Vx = prob.get_val('Vx', units='m/s') a = prob.get_val('ccblade_group.ccblade_comp.a') # Get the area-weighted average of the induced velocity. vi[...] = np.sum(a * Vx * dArea / A_rotor) / v_h # Plot the induced velocity for descent. ax.plot(climb_velocity_nondim, -induced_velocity_nondim, label='CCBlade.jl (descent)') # Induced velocity from plain old momentum theory (for descent). induced_velocity_mt = (-0.5 * climb_velocity_nondim - np.sqrt((0.5 * climb_velocity_nondim)**2 - 1.)) ax.plot(climb_velocity_nondim, induced_velocity_mt, label='Momentum Theory (descent)') # Empirical region: climb_velocity_nondim = np.linspace(-1.9, -1.5, 5) induced_velocity_nondim = np.zeros_like(climb_velocity_nondim) for vc, vi in np.nditer([climb_velocity_nondim, induced_velocity_nondim], op_flags=[['readonly'], ['writeonly']]): # Run the model with the requested climb velocity. prob.set_val('v', vc * v_h, units='m/s') print(f"vc = {vc}, v = {prob.get_val('v', units='m/s')}") prob.run_model() # Calculate the area-weighted average induced velocity at the rotor. # Need the area of each blade section. radii = prob.get_val('radii', units='m') dradii = prob.get_val('dradii', units='m') dArea = 2 * np.pi * radii * dradii # Get the induced velocity at the rotor plane for each blade section. Vx = prob.get_val('Vx', units='m/s') a = prob.get_val('ccblade_group.ccblade_comp.a') # Get the area-weighted average of the induced velocity. vi[...] = np.sum(a * Vx * dArea / A_rotor) / v_h # Plot the induced velocity for the empirical region. ax.plot(climb_velocity_nondim, -induced_velocity_nondim, label='CCBlade.jl (empirical region)') ax.set_xlabel('Vc/vh') ax.set_ylabel('Vi/vh') ax.legend() fig.savefig('induced_velocity.png')