def setup(self): RefBlade = self.options['RefBlade'] Nsection_Tow = self.options['Nsection_Tow'] 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.) # 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) 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=False, Analysis_Level=Analysis_Level, FASTpref=self.options['FASTpref'], topLevelFlag=True), promotes=['*']) self.add_subsystem('drive', DriveSE(debug=False, number_of_main_bearings=1, topLevelFlag=False), promotes=[ 'machine_rating', 'overhang', 'hub_mass', 'bedplate_mass', 'gearbox_mass', 'generator_mass', 'hss_mass', 'hvac_mass', 'lss_mass', 'cover_mass', 'pitch_system_mass', 'platforms_mass', 'spinner_mass', 'transformer_mass', 'vs_electronics_mass', 'yaw_mass' ]) # Tower and substructure self.add_subsystem( 'tow', TowerSE(nLC=1, nPoints=Nsection_Tow + 1, nFull=5 * Nsection_Tow + 1, wind='PowerWind', topLevelFlag=False), 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', 'max_taper', 'min_d_to_t', 'rna_mass', 'rna_cg', 'rna_I', '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('diameter', 'drive.rotor_diameter') self.connect('rated_Q', 'drive.rotor_torque') self.connect('rated_Omega', 'drive.rotor_rpm') self.connect('Fxyz_total', 'drive.Fxyz') self.connect('Mxyz_total', 'drive.Mxyz') self.connect('I_all_blades', 'drive.blades_I') self.connect('mass_one_blade', 'drive.blade_mass') self.connect('chord', 'drive.blade_root_diameter', src_indices=[0]) self.connect('Rtip', 'drive.blade_length', src_indices=[0]) self.connect('drivetrainEff', 'drive.drivetrain_efficiency', src_indices=[0]) self.connect('tower_outer_diameter', 'drive.tower_top_diameter', src_indices=[-1]) self.connect('material_density', 'tow.tower.rho') # Connections to TowerSE self.connect('drive.top_F', 'tow.pre.rna_F') self.connect('drive.top_M', 'tow.pre.rna_M') self.connect('drive.rna_I_TT', ['rna_I', 'tow.pre.mI']) self.connect('drive.rna_cm', ['rna_cg', 'tow.pre.mrho']) self.connect('drive.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', 'drive.number_of_blades']) 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('drive.mainBearing.mb_mass', 'main_bearing_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): modeling_options = self.options["modeling_options"] opt_options = self.options["opt_options"] self.add_subsystem("wt", WT_RNTA(modeling_options=modeling_options, opt_options=opt_options), promotes=["*"]) if modeling_options["BOS"]["flag"]: if modeling_options["flags"]["offshore"]: self.add_subsystem( "orbit", Orbit(floating=modeling_options["flags"] ["floating_platform"])) else: self.add_subsystem("landbosse", LandBOSSE()) if modeling_options["flags"]["blade"]: self.add_subsystem( "financese", PlantFinance( verbosity=modeling_options["General"]["verbosity"])) self.add_subsystem( "outputs_2_screen", Outputs_2_Screen(modeling_options=modeling_options, opt_options=opt_options)) if opt_options["opt_flag"] and opt_options["recorder"]["flag"]: self.add_subsystem("conv_plots", Convergence_Trends_Opt(opt_options=opt_options)) # BOS inputs if modeling_options["BOS"]["flag"]: if modeling_options["flags"]["offshore"]: # Inputs into ORBIT self.connect("configuration.rated_power", "orbit.turbine_rating") self.connect("env.water_depth", "orbit.site_depth") self.connect("costs.turbine_number", "orbit.number_of_turbines") self.connect("configuration.n_blades", "orbit.number_of_blades") self.connect("assembly.hub_height", "orbit.hub_height") self.connect("assembly.rotor_diameter", "orbit.turbine_rotor_diameter") self.connect("towerse.tower_mass", "orbit.tower_mass") if modeling_options["flags"]["monopile"]: self.connect("towerse.monopile_mass", "orbit.monopile_mass") self.connect("towerse.monopile_length", "orbit.monopile_length") self.connect("monopile.transition_piece_mass", "orbit.transition_piece_mass") self.connect("monopile.diameter", "orbit.monopile_diameter", src_indices=[0]) else: self.connect("mooring.n_lines", "orbit.num_mooring_lines") self.connect("mooring.line_mass", "orbit.mooring_line_mass", src_indices=[0]) self.connect("mooring.line_diameter", "orbit.mooring_line_diameter", src_indices=[0]) self.connect("mooring.unstretched_length", "orbit.mooring_line_length", src_indices=[0]) self.connect("mooring.anchor_mass", "orbit.anchor_mass") self.connect("re.precomp.blade_mass", "orbit.blade_mass") self.connect("tcc.turbine_cost_kW", "orbit.turbine_capex") if modeling_options["flags"]["nacelle"]: self.connect("drivese.nacelle_mass", "orbit.nacelle_mass") self.connect("wt_class.V_mean", "orbit.site_mean_windspeed") self.connect("rp.powercurve.rated_V", "orbit.turbine_rated_windspeed") self.connect("bos.plant_turbine_spacing", "orbit.plant_turbine_spacing") self.connect("bos.plant_row_spacing", "orbit.plant_row_spacing") self.connect("bos.commissioning_pct", "orbit.commissioning_pct") self.connect("bos.decommissioning_pct", "orbit.decommissioning_pct") self.connect("bos.distance_to_substation", "orbit.plant_substation_distance") self.connect("bos.distance_to_interconnection", "orbit.interconnection_distance") self.connect("bos.site_distance", "orbit.site_distance") self.connect("bos.distance_to_landfall", "orbit.site_distance_to_landfall") self.connect("bos.port_cost_per_month", "orbit.port_cost_per_month") self.connect("bos.site_auction_price", "orbit.site_auction_price") self.connect("bos.site_assessment_plan_cost", "orbit.site_assessment_plan_cost") self.connect("bos.site_assessment_cost", "orbit.site_assessment_cost") self.connect("bos.construction_operations_plan_cost", "orbit.construction_operations_plan_cost") self.connect("bos.boem_review_cost", "orbit.boem_review_cost") self.connect("bos.design_install_plan_cost", "orbit.design_install_plan_cost") else: # Inputs into LandBOSSE self.connect("assembly.hub_height", "landbosse.hub_height_meters") self.connect("costs.turbine_number", "landbosse.num_turbines") self.connect("configuration.rated_power", "landbosse.turbine_rating_MW") self.connect("env.shear_exp", "landbosse.wind_shear_exponent") self.connect("assembly.rotor_diameter", "landbosse.rotor_diameter_m") self.connect("configuration.n_blades", "landbosse.number_of_blades") if modeling_options["flags"]["blade"]: self.connect("rp.powercurve.rated_T", "landbosse.rated_thrust_N") self.connect("towerse.tower_mass", "landbosse.tower_mass") if modeling_options["flags"]["nacelle"]: self.connect("drivese.nacelle_mass", "landbosse.nacelle_mass") self.connect("drivese.hub_system_mass", "landbosse.hub_mass") self.connect("re.precomp.blade_mass", "landbosse.blade_mass") self.connect("tower_grid.foundation_height", "landbosse.foundation_height") self.connect("bos.plant_turbine_spacing", "landbosse.turbine_spacing_rotor_diameters") self.connect("bos.plant_row_spacing", "landbosse.row_spacing_rotor_diameters") self.connect("bos.commissioning_pct", "landbosse.commissioning_pct") self.connect("bos.decommissioning_pct", "landbosse.decommissioning_pct") self.connect("bos.distance_to_substation", "landbosse.trench_len_to_substation_km") self.connect("bos.distance_to_interconnection", "landbosse.distance_to_interconnect_mi") self.connect("bos.interconnect_voltage", "landbosse.interconnect_voltage_kV") # Inputs to plantfinancese from wt group if modeling_options["flags"]["blade"]: self.connect("rp.AEP", "financese.turbine_aep") self.connect("tcc.turbine_cost_kW", "financese.tcc_per_kW") if modeling_options["flags"]["bos"]: if modeling_options["flags"]["offshore"]: self.connect("orbit.total_capex_kW", "financese.bos_per_kW") else: self.connect("landbosse.bos_capex_kW", "financese.bos_per_kW") else: self.connect("costs.bos_per_kW", "financese.bos_per_kW") # Inputs to plantfinancese from input yaml if modeling_options["flags"]["control"]: self.connect("configuration.rated_power", "financese.machine_rating") self.connect("costs.turbine_number", "financese.turbine_number") self.connect("costs.opex_per_kW", "financese.opex_per_kW") self.connect("costs.offset_tcc_per_kW", "financese.offset_tcc_per_kW") self.connect("costs.wake_loss_factor", "financese.wake_loss_factor") self.connect("costs.fixed_charge_rate", "financese.fixed_charge_rate") # Connections to outputs to screen if modeling_options["flags"]["blade"]: self.connect("rp.AEP", "outputs_2_screen.aep") self.connect("financese.lcoe", "outputs_2_screen.lcoe") self.connect("re.precomp.blade_mass", "outputs_2_screen.blade_mass") self.connect("rs.tip_pos.tip_deflection", "outputs_2_screen.tip_deflection")
#!/usr/bin/env python3 # Import the libraries import openmdao.api as om from wisdem.plant_financese.plant_finance import PlantFinance # Initialize the OpenMDAO instance prob = om.Problem() prob.model = PlantFinance() prob.setup() # Set variable inputs with intended units prob.set_val("machine_rating", 2.32e3, units="kW") prob.set_val("tcc_per_kW", 1093, units="USD/kW") prob.set_val("turbine_number", 87) prob.set_val("opex_per_kW", 43.56, units="USD/kW/yr") prob.set_val("fixed_charge_rate", 0.079216644) prob.set_val("bos_per_kW", 517.0, units="USD/kW") prob.set_val("wake_loss_factor", 0.15) prob.set_val("turbine_aep", 9915.95e3, units="kW*h") # Run the model once prob.run_model() # Print all inputs and outputs to the screen prob.model.list_inputs(units=True) prob.model.list_outputs(units=True)
def setup(self): modeling_options = self.options['modeling_options'] opt_options = self.options['opt_options'] self.add_subsystem('wt', WT_RNTA(modeling_options=modeling_options, opt_options=opt_options), promotes=['*']) if modeling_options['flags']['bos']: if modeling_options['offshore']: self.add_subsystem('orbit', Orbit()) else: self.add_subsystem('landbosse', LandBOSSE()) self.add_subsystem( 'financese', PlantFinance(verbosity=modeling_options['general']['verbosity'])) # Post-processing self.add_subsystem( 'outputs_2_screen', Outputs_2_Screen(modeling_options=modeling_options, opt_options=opt_options)) if opt_options['opt_flag']: self.add_subsystem('conv_plots', Convergence_Trends_Opt(opt_options=opt_options)) # BOS inputs if modeling_options['flags']['bos']: if modeling_options['offshore']: # Inputs into ORBIT self.connect('control.rated_power', 'orbit.turbine_rating') self.connect('env.water_depth', 'orbit.site_depth') self.connect('costs.turbine_number', 'orbit.number_of_turbines') self.connect('configuration.n_blades', 'orbit.number_of_blades') self.connect('assembly.hub_height', 'orbit.hub_height') self.connect('assembly.rotor_diameter', 'orbit.turbine_rotor_diameter') self.connect('towerse.tower_mass', 'orbit.tower_mass') self.connect('towerse.monopile_mass', 'orbit.monopile_mass') self.connect('towerse.monopile_length', 'orbit.monopile_length') self.connect('monopile.transition_piece_mass', 'orbit.transition_piece_mass') self.connect('elastic.precomp.blade_mass', 'orbit.blade_mass') self.connect('tcc.turbine_cost_kW', 'orbit.turbine_capex') self.connect('drivese.nacelle_mass', 'orbit.nacelle_mass') self.connect('monopile.diameter', 'orbit.monopile_diameter', src_indices=[0]) self.connect('wt_class.V_mean', 'orbit.site_mean_windspeed') self.connect('sse.powercurve.rated_V', 'orbit.turbine_rated_windspeed') self.connect('bos.plant_turbine_spacing', 'orbit.plant_turbine_spacing') self.connect('bos.plant_row_spacing', 'orbit.plant_row_spacing') self.connect('bos.commissioning_pct', 'orbit.commissioning_pct') self.connect('bos.decommissioning_pct', 'orbit.decommissioning_pct') self.connect('bos.distance_to_substation', 'orbit.plant_substation_distance') self.connect('bos.distance_to_interconnection', 'orbit.interconnection_distance') self.connect('bos.site_distance', 'orbit.site_distance') self.connect('bos.distance_to_landfall', 'orbit.site_distance_to_landfall') self.connect('bos.port_cost_per_month', 'orbit.port_cost_per_month') self.connect('bos.site_auction_price', 'orbit.site_auction_price') self.connect('bos.site_assessment_plan_cost', 'orbit.site_assessment_plan_cost') self.connect('bos.site_assessment_cost', 'orbit.site_assessment_cost') self.connect('bos.construction_operations_plan_cost', 'orbit.construction_operations_plan_cost') self.connect('bos.boem_review_cost', 'orbit.boem_review_cost') self.connect('bos.design_install_plan_cost', 'orbit.design_install_plan_cost') else: # Inputs into LandBOSSE self.connect('assembly.hub_height', 'landbosse.hub_height_meters') self.connect('costs.turbine_number', 'landbosse.num_turbines') self.connect('control.rated_power', 'landbosse.turbine_rating_MW') self.connect('env.shear_exp', 'landbosse.wind_shear_exponent') self.connect('assembly.rotor_diameter', 'landbosse.rotor_diameter_m') self.connect('configuration.n_blades', 'landbosse.number_of_blades') if modeling_options['Analysis_Flags']['ServoSE']: self.connect('sse.powercurve.rated_T', 'landbosse.rated_thrust_N') self.connect('towerse.tower_mass', 'landbosse.tower_mass') self.connect('drivese.nacelle_mass', 'landbosse.nacelle_mass') self.connect('elastic.precomp.blade_mass', 'landbosse.blade_mass') self.connect('hub.system_mass', 'landbosse.hub_mass') self.connect('foundation.height', 'landbosse.foundation_height') self.connect('bos.plant_turbine_spacing', 'landbosse.turbine_spacing_rotor_diameters') self.connect('bos.plant_row_spacing', 'landbosse.row_spacing_rotor_diameters') self.connect('bos.commissioning_pct', 'landbosse.commissioning_pct') self.connect('bos.decommissioning_pct', 'landbosse.decommissioning_pct') self.connect('bos.distance_to_substation', 'landbosse.trench_len_to_substation_km') self.connect('bos.distance_to_interconnection', 'landbosse.distance_to_interconnect_mi') self.connect('bos.interconnect_voltage', 'landbosse.interconnect_voltage_kV') # Inputs to plantfinancese from wt group if modeling_options['Analysis_Flags']['ServoSE']: self.connect('sse.AEP', 'financese.turbine_aep') self.connect('tcc.turbine_cost_kW', 'financese.tcc_per_kW') if modeling_options['flags']['bos']: if 'offshore' in modeling_options and modeling_options['offshore']: self.connect('orbit.total_capex_kW', 'financese.bos_per_kW') else: self.connect('landbosse.bos_capex_kW', 'financese.bos_per_kW') # Inputs to plantfinancese from input yaml if modeling_options['flags']['control']: self.connect('control.rated_power', 'financese.machine_rating') self.connect('costs.turbine_number', 'financese.turbine_number') self.connect('costs.opex_per_kW', 'financese.opex_per_kW') self.connect('costs.offset_tcc_per_kW', 'financese.offset_tcc_per_kW') self.connect('costs.wake_loss_factor', 'financese.wake_loss_factor') self.connect('costs.fixed_charge_rate', 'financese.fixed_charge_rate') # Connections to outputs to screen if modeling_options['Analysis_Flags']['ServoSE']: self.connect('sse.AEP', 'outputs_2_screen.aep') self.connect('financese.lcoe', 'outputs_2_screen.lcoe') self.connect('elastic.precomp.blade_mass', 'outputs_2_screen.blade_mass') self.connect('rlds.tip_pos.tip_deflection', 'outputs_2_screen.tip_deflection')