class ExtendedFinancialAnalysis_Example(Assembly): """ Extended financial analysis assembly for coupling models to get a full wind plant cost of energy estimate as well as provides a detailed cost breakdown for the plant. """ # Inputs turbine_number = Int(iotype='in', desc='number of turbines at plant') #Outputs turbine_cost = Float(iotype='out', desc='A Wind Turbine Capital _cost') bos_costs = Float(iotype='out', desc='A Wind Plant Balance of Station _cost Model') avg_annual_opex = Float(iotype='out', desc='A Wind Plant Operations Expenditures Model') net_aep = Float(iotype='out', desc='A Wind Plant Annual Energy Production Model', units='kW*h') coe = Float(iotype='out', desc='Levelized cost of energy for the wind plant') opex_breakdown = VarTree(OPEXVarTree(), iotype='out') bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown') def configure(self): configure_extended_financial_analysis(self) self.replace('tcc_a', BaseTurbineCostModel_Example()) self.replace('aep_a', BaseAEPModel_Example()) self.replace('fin_a', BaseFinancialModel_Example()) self.replace('bos_a', ExtendedBOSCostModel_Example()) self.replace('opex_a', ExtendedOPEXModel_Example())
class bos_csm_assembly(Assembly): # Variables machine_rating = Float(iotype='in', units='kW', desc='turbine machine rating') rotor_diameter = Float(iotype='in', units='m', desc='rotor diameter') hub_height = Float(iotype='in', units='m', desc='hub height') RNA_mass = Float(iotype='in', units='kg', desc='Rotor Nacelle Assembly mass') turbine_cost = Float(iotype='in', units='USD', desc='Single Turbine Capital _costs') # Parameters turbine_number = Int(iotype='in', desc='number of turbines in project') sea_depth = Float(20.0, units='m', iotype='in', desc='sea depth for offshore wind plant') year = Int(2009, iotype='in', desc='year for project start') month = Int(12, iotype='in', desc='month for project start') multiplier = Float(1.0, iotype='in') # Outputs bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown') bos_costs = Float( iotype='out', desc= 'Overall wind plant balance of station/system costs up to point of comissioning' ) def configure(self): super(bos_csm_assembly, self).configure() configure_extended_bos(self) self.replace('bos', bos_csm_component()) self.connect('machine_rating', 'bos.machine_rating') self.connect('rotor_diameter', 'bos.rotor_diameter') self.connect('hub_height', 'bos.hub_height') self.connect('RNA_mass', 'bos.RNA_mass') self.connect('turbine_cost', 'bos.turbine_cost') self.connect('turbine_number', 'bos.turbine_number') self.connect('sea_depth', 'bos.sea_depth') self.connect('year', 'bos.year') self.connect('month', 'bos.month') self.connect('multiplier', 'bos.multiplier')
class ExtendedBOSCostModel_Example(Assembly): """ Extended balance of station cost assembly for coupling models to get a full wind plant balance of station cost estimate as well as a detailed cost breakdown. """ # Outputs bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown') bos_costs = Float( iotype='out', desc= 'Overall wind plant balance of station/system costs up to point of comissioning' ) def configure(self): configure_extended_bos(self) self.replace('bos', ExtendedBOSCostAggregator_Example())
class ExtendedFinancialAnalysis(Assembly): """ Extended financial analysis assembly for coupling models to get a full wind plant cost of energy estimate as well as provides a detailed cost breakdown for the plant. """ # Inputs turbine_number = Int(iotype='in', desc='number of turbines at plant') #Outputs turbine_cost = Float(iotype='out', desc='A Wind Turbine Capital _cost') bos_costs = Float(iotype='out', desc='A Wind Plant Balance of Station _cost Model') avg_annual_opex = Float(iotype='out', desc='A Wind Plant Operations Expenditures Model') net_aep = Float(iotype='out', desc='A Wind Plant Annual Energy Production Model', units='kW*h') coe = Float(iotype='out', desc='Levelized cost of energy for the wind plant') opex_breakdown = VarTree(OPEXVarTree(), iotype='out') bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown')
class ExtendedBOSCostAggregator_Example(Component): """ Extended balance of station cost aggregator for doing some auxiliary cost calculations needed to get a full wind plant balance of station cost estimate as well as a detailed cost breakdown. """ # Outputs bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown') bos_costs = Float( iotype='out', desc= 'Overall wind plant balance of station/system costs up to point of comissioning' ) def execute(self): self.bos_costs = 1800000000.0 self.bos_breakdown.development_costs = self.bos_costs * 0.05 self.bos_breakdown.preparation_and_staging_costs = self.bos_costs * 0.10 self.bos_breakdown.transportation_costs = self.bos_costs * 0.20 self.bos_breakdown.foundation_and_substructure_costs = self.bos_costs * 0.20 self.bos_breakdown.electrical_costs = self.bos_costs * 0.15 self.bos_breakdown.assembly_and_installation_costs = self.bos_costs * 0.15 self.bos_breakdown.soft_costs = self.bos_costs * 0.10 self.bos_breakdown.other_costs = self.bos_costs * 0.05
class bos_csm_component(Component): # Variables machine_rating = Float(iotype='in', units='kW', desc='turbine machine rating') rotor_diameter = Float(iotype='in', units='m', desc='rotor diameter') hub_height = Float(iotype='in', units='m', desc='hub height') RNA_mass = Float(iotype='in', units='kg', desc='Rotor Nacelle Assembly mass') turbine_cost = Float(iotype='in', units='USD', desc='Single Turbine Capital _costs') # Parameters turbine_number = Int(iotype='in', desc='number of turbines in project') sea_depth = Float(20.0, units='m', iotype='in', desc='sea depth for offshore wind plant') year = Int(2009, iotype='in', desc='year for project start') month = Int(12, iotype='in', desc='month for project start') multiplier = Float(1.0, iotype='in') # Outputs bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown') bos_costs = Float( iotype='out', desc= 'Overall wind plant balance of station/system costs up to point of comissioning' ) def __init__(self): """ OpenMDAO component to wrap BOS model of the NREL _cost and Scaling Model (csmBOS.py) """ #super(bos_csm_component, self).__init__() #update for FUSED - not recognizing bos_csm_component super due to decorator Component.__init__(self) #controls what happens if derivatives are missing self.missing_deriv_policy = 'assume_zero' def execute(self): """ Executes BOS model of the NREL _cost and Scaling Model to estimate wind plant BOS costs. """ # print "In {0}.execute()...".format(self.__class__) lPrmtsCostCoeff1 = 9.94E-04 lPrmtsCostCoeff2 = 20.31 oPrmtsCostFactor = 37.0 # $/kW (2003) scourCostFactor = 55.0 # $/kW (2003) ptstgCostFactor = 20.0 # $/kW (2003) ossElCostFactor = 260.0 # $/kW (2003) shallow ostElCostFactor = 290.0 # $/kW (2003) transitional ostSTransFactor = 25.0 # $/kW (2003) ostTTransFactor = 77.0 # $/kW (2003) osInstallFactor = 100.0 # $/kW (2003) shallow & trans suppInstallFactor = 330.0 # $/kW (2003) trans additional paiCost = 60000.0 # per turbine suretyBRate = 0.03 # 3% of ICC suretyBond = 0.0 #set variables if self.sea_depth == 0: # type of plant # 1: Land, 2: < 30m, 3: < 60m, 4: >= 60m iDepth = 1 elif self.sea_depth < 30: iDepth = 2 elif self.sea_depth < 60: iDepth = 3 else: iDepth = 4 # initialize self.ppi index calculator if iDepth == 1: ref_yr = 2002 ref_mon = 9 else: ref_yr = 2003 ref_mon = 9 ppi.ref_yr = ref_yr ppi.ref_mon = ref_mon ppi.curr_yr = self.year ppi.curr_mon = self.month self.d_foundation_d_diameter = 0.0 self.d_foundation_d_hheight = 0.0 self.d_foundation_d_rating = 0.0 # foundation costs if (iDepth == 1): # land fcCoeff = 303.23 fcExp = 0.4037 SweptArea = (self.rotor_diameter * 0.5)**2.0 * np.pi foundation_cost = fcCoeff * (self.hub_height * SweptArea)**fcExp fndnCostEscalator = ppi.compute('IPPI_FND') self.d_foundation_d_diameter = fndnCostEscalator * fcCoeff * fcExp * ( (self.hub_height * (2.0 * 0.5 * (self.rotor_diameter * 0.5) * np.pi)) **(fcExp - 1)) * self.hub_height self.d_foundation_d_hheight = fndnCostEscalator * fcCoeff * fcExp * ( (self.hub_height * SweptArea)**(fcExp - 1)) * SweptArea elif (iDepth == 2): sscf = 300.0 # $/kW foundation_cost = sscf * self.machine_rating fndnCostEscalator = ppi.compute('IPPI_MPF') self.d_foundation_d_rating = fndnCostEscalator * sscf elif (iDepth == 3): sscf = 450.0 # $/kW foundation_cost = sscf * self.machine_rating fndnCostEscalator = ppi.compute('IPPI_OAI') self.d_foundation_d_rating = fndnCostEscalator * sscf elif (iDepth == 4): foundation_cost = 0.0 fndnCostEscalator = 1.0 foundation_cost *= fndnCostEscalator # cost calculations tpC1 = 0.00001581 tpC2 = -0.0375 tpInt = 54.7 tFact = tpC1 * self.machine_rating * self.machine_rating + tpC2 * self.machine_rating + tpInt roadsCivil_costs = 0.0 portStaging_costs = 0.0 pai_costs = 0.0 scour_costs = 0.0 self.d_assembly_d_diameter = 0.0 self.d_assembly_d_hheight = 0.0 self.d_development_d_rating = 0.0 self.d_preparation_d_rating = 0.0 self.d_transport_d_rating = 0.0 self.d_electrical_d_rating = 0.0 self.d_assembly_d_rating = 0.0 self.d_other_d_rating = 0.0 if (iDepth == 1): engPermits_costs = (lPrmtsCostCoeff1 * self.machine_rating * self.machine_rating) + \ (lPrmtsCostCoeff2 * self.machine_rating) ppi.ref_mon = 3 engPermits_costs *= ppi.compute('IPPI_LPM') self.d_development_d_rating = ppi.compute('IPPI_LPM') * ( 2.0 * lPrmtsCostCoeff1 * self.machine_rating + lPrmtsCostCoeff2) ppi.ref_mon = 9 elC1 = 3.49E-06 elC2 = -0.0221 elInt = 109.7 eFact = elC1 * self.machine_rating * self.machine_rating + elC2 * self.machine_rating + elInt electrical_costs = self.machine_rating * eFact * ppi.compute( 'IPPI_LEL') self.d_electrical_d_rating = ppi.compute('IPPI_LEL') * (3. * elC1*self.machine_rating**2. + \ 2. * elC2*self.machine_rating + elInt) rcC1 = 2.17E-06 rcC2 = -0.0145 rcInt = 69.54 rFact = rcC1 * self.machine_rating * self.machine_rating + rcC2 * self.machine_rating + rcInt roadsCivil_costs = self.machine_rating * rFact * ppi.compute( 'IPPI_RDC') self.d_preparation_d_rating = ppi.compute('IPPI_RDC') * (3. * rcC1 * self.machine_rating**2. + \ 2. * rcC2 * self.machine_rating + rcInt) iCoeff = 1.965 iExp = 1.1736 installation_costs = iCoeff * ( (self.hub_height * self.rotor_diameter)** iExp) * ppi.compute('IPPI_LAI') self.d_assembly_d_diameter = iCoeff * ( (self.hub_height * self.rotor_diameter) **(iExp - 1)) * self.hub_height * ppi.compute('IPPI_LAI') self.d_assembly_d_hheight = iCoeff * ( (self.hub_height * self.rotor_diameter) **(iExp - 1)) * self.rotor_diameter * ppi.compute('IPPI_LAI') transportation_costs = self.machine_rating * tFact * ppi.compute( 'IPPI_TPT') self.d_transport_d_rating = ppi.compute('IPPI_TPT') * (tpC1* 3. * self.machine_rating**2. + \ tpC2* 2. * self.machine_rating + tpInt ) elif (iDepth == 2): # offshore shallow ppi.ref_yr = 2003 pai_costs = paiCost * ppi.compute('IPPI_PAE') portStaging_costs = ptstgCostFactor * self.machine_rating * ppi.compute( 'IPPI_STP') # 1.415538133 self.d_preparation_d_rating = ptstgCostFactor * ppi.compute( 'IPPI_STP') engPermits_costs = oPrmtsCostFactor * self.machine_rating * ppi.compute( 'IPPI_OPM') self.d_development_d_rating = oPrmtsCostFactor * ppi.compute( 'IPPI_OPM') scour_costs = scourCostFactor * self.machine_rating * ppi.compute( 'IPPI_STP') # 1.415538133# self.d_other_d_rating = scourCostFactor * ppi.compute('IPPI_STP') installation_costs = osInstallFactor * self.machine_rating * ppi.compute( 'IPPI_OAI') self.d_assembly_d_rating = osInstallFactor * ppi.compute( 'IPPI_OAI') electrical_costs = ossElCostFactor * self.machine_rating * ppi.compute( 'IPPI_OEL') self.d_electrical_d_rating = ossElCostFactor * ppi.compute( 'IPPI_OEL') ppi.ref_yr = 2002 transportation_costs = self.machine_rating * tFact * ppi.compute( 'IPPI_TPT') self.d_transport_d_rating = ppi.compute('IPPI_TPT') * (tpC1* 3. * self.machine_rating**2. + \ tpC2* 2. * self.machine_rating + tpInt ) ppi.ref_yr = 2003 elif (iDepth == 3): # offshore transitional depth ppi.ref_yr = 2003 turbInstall = osInstallFactor * self.machine_rating * ppi.compute( 'IPPI_OAI') supportInstall = suppInstallFactor * self.machine_rating * ppi.compute( 'IPPI_OAI') installation_costs = turbInstall + supportInstall self.d_assembly_d_rating = ( osInstallFactor + suppInstallFactor) * ppi.compute('IPPI_OAI') pai_costs = paiCost * ppi.compute('IPPI_PAE') electrical_costs = ostElCostFactor * self.machine_rating * ppi.compute( 'IPPI_OEL') self.d_electrical_d_rating = ossElCostFactor * ppi.compute( 'IPPI_OEL') portStaging_costs = ptstgCostFactor * self.machine_rating * ppi.compute( 'IPPI_STP') self.d_preparation_d_rating = ptstgCostFactor * ppi.compute( 'IPPI_STP') engPermits_costs = oPrmtsCostFactor * self.machine_rating * ppi.compute( 'IPPI_OPM') self.d_development_d_rating = oPrmtsCostFactor * ppi.compute( 'IPPI_OPM') scour_costs = scourCostFactor * self.machine_rating * ppi.compute( 'IPPI_STP') self.d_other_d_rating = scourCostFactor * ppi.compute('IPPI_STP') ppi.ref_yr = 2002 turbTrans = ostTTransFactor * self.machine_rating * ppi.compute( 'IPPI_TPT') self.d_transport_d_rating = ostTTransFactor * ppi.compute( 'IPPI_TPT') ppi.ref_yr = 2003 supportTrans = ostSTransFactor * self.machine_rating * ppi.compute( 'IPPI_OAI') transportation_costs = self.turbTrans + self.supportTrans self.d_transport_d_rating += ostSTransFactor * ppi.compute( 'IPPI_OAI') elif (iDepth == 4): # offshore deep print "\ncsmBOS: Add costCat 4 code\n\n" bos_costs = foundation_cost + \ transportation_costs + \ roadsCivil_costs + \ portStaging_costs + \ installation_costs + \ electrical_costs + \ engPermits_costs + \ pai_costs + \ scour_costs self.d_other_d_tcc = 0.0 if (self.sea_depth > 0.0): suretyBond = suretyBRate * (self.turbine_cost + bos_costs) self.d_other_d_tcc = suretyBRate d_surety_d_rating = suretyBRate * (self.d_development_d_rating + self.d_preparation_d_rating + self.d_transport_d_rating + \ self.d_foundation_d_rating + self.d_electrical_d_rating + self.d_assembly_d_rating + self.d_other_d_rating) self.d_other_d_rating += d_surety_d_rating else: suretyBond = 0.0 self.bos_costs = self.turbine_number * (bos_costs + suretyBond) self.bos_costs *= self.multiplier # TODO: add to gradients self.bos_breakdown.development_costs = engPermits_costs * self.turbine_number self.bos_breakdown.preparation_and_staging_costs = ( roadsCivil_costs + portStaging_costs) * self.turbine_number self.bos_breakdown.transportation_costs = (transportation_costs * self.turbine_number) self.bos_breakdown.foundation_and_substructure_costs = foundation_cost * self.turbine_number self.bos_breakdown.electrical_costs = electrical_costs * self.turbine_number self.bos_breakdown.assembly_and_installation_costs = installation_costs * self.turbine_number self.bos_breakdown.soft_costs = 0.0 self.bos_breakdown.other_costs = (pai_costs + scour_costs + suretyBond) * self.turbine_number # derivatives self.d_development_d_rating *= self.turbine_number self.d_preparation_d_rating *= self.turbine_number self.d_transport_d_rating *= self.turbine_number self.d_foundation_d_rating *= self.turbine_number self.d_electrical_d_rating *= self.turbine_number self.d_assembly_d_rating *= self.turbine_number self.d_soft_d_rating = 0.0 self.d_other_d_rating *= self.turbine_number self.d_cost_d_rating = self.d_development_d_rating + self.d_preparation_d_rating + self.d_transport_d_rating + \ self.d_foundation_d_rating + self.d_electrical_d_rating + self.d_assembly_d_rating + \ self.d_soft_d_rating + self.d_other_d_rating self.d_development_d_diameter = 0.0 self.d_preparation_d_diameter = 0.0 self.d_transport_d_diameter = 0.0 #self.d_foundation_d_diameter self.d_electrical_d_diameter = 0.0 #self.d_assembly_d_diameter self.d_soft_d_diameter = 0.0 self.d_other_d_diameter = 0.0 self.d_cost_d_diameter = self.d_development_d_diameter + self.d_preparation_d_diameter + self.d_transport_d_diameter + \ self.d_foundation_d_diameter + self.d_electrical_d_diameter + self.d_assembly_d_diameter + \ self.d_soft_d_diameter + self.d_other_d_diameter self.d_development_d_tcc = 0.0 self.d_preparation_d_tcc = 0.0 self.d_transport_d_tcc = 0.0 self.d_foundation_d_tcc = 0.0 self.d_electrical_d_tcc = 0.0 self.d_assembly_d_tcc = 0.0 self.d_soft_d_tcc = 0.0 self.d_other_d_tcc *= self.turbine_number self.d_cost_d_tcc = self.d_development_d_tcc + self.d_preparation_d_tcc + self.d_transport_d_tcc + \ self.d_foundation_d_tcc + self.d_electrical_d_tcc + self.d_assembly_d_tcc + \ self.d_soft_d_tcc + self.d_other_d_tcc self.d_development_d_hheight = 0.0 self.d_preparation_d_hheight = 0.0 self.d_transport_d_hheight = 0.0 #self.d_foundation_d_hheight self.d_electrical_d_hheight = 0.0 #self.d_assembly_d_hheight self.d_soft_d_hheight = 0.0 self.d_other_d_hheight = 0.0 self.d_cost_d_hheight = self.d_development_d_hheight + self.d_preparation_d_hheight + self.d_transport_d_hheight + \ self.d_foundation_d_hheight + self.d_electrical_d_hheight + self.d_assembly_d_hheight + \ self.d_soft_d_hheight + self.d_other_d_hheight self.d_development_d_rna = 0.0 self.d_preparation_d_rna = 0.0 self.d_transport_d_rna = 0.0 self.d_foundation_d_rna = 0.0 self.d_electrical_d_rna = 0.0 self.d_assembly_d_rna = 0.0 self.d_soft_d_rna = 0.0 self.d_other_d_rna = 0.0 self.d_cost_d_rna = self.d_development_d_rna + self.d_preparation_d_rna + self.d_transport_d_rna + \ self.d_foundation_d_rna + self.d_electrical_d_rna + self.d_assembly_d_rna + \ self.d_soft_d_rna + self.d_other_d_rna def list_deriv_vars(self): inputs = [ 'machine_rating', 'rotor_diameter', 'turbine_cost', 'hub_height', 'RNA_mass' ] outputs = ['bos_breakdown.development_costs', 'bos_breakdown.preparation_and_staging_costs',\ 'bos_breakdown.transportation_costs', 'bos_breakdown.foundation_and_substructure_costs',\ 'bos_breakdown.electrical_costs', 'bos_breakdown.assembly_and_installation_costs',\ 'bos_breakdown.soft_costs', 'bos_breakdown.other_costs', 'bos_costs'] return inputs, outputs def provideJ(self): self.J = np.array([[self.d_development_d_rating, self.d_development_d_diameter, self.d_development_d_tcc, self.d_development_d_hheight, self.d_development_d_rna],\ [self.d_preparation_d_rating, self.d_preparation_d_diameter, self.d_preparation_d_tcc, self.d_preparation_d_hheight, self.d_preparation_d_rna],\ [self.d_transport_d_rating, self.d_transport_d_diameter, self.d_transport_d_tcc, self.d_transport_d_hheight, self.d_transport_d_rna],\ [self.d_foundation_d_rating, self.d_foundation_d_diameter, self.d_foundation_d_tcc, self.d_foundation_d_hheight, self.d_foundation_d_rna],\ [self.d_electrical_d_rating, self.d_electrical_d_diameter, self.d_electrical_d_tcc, self.d_electrical_d_hheight, self.d_electrical_d_rna],\ [self.d_assembly_d_rating, self.d_assembly_d_diameter, self.d_assembly_d_tcc, self.d_assembly_d_hheight, self.d_assembly_d_rna],\ [self.d_soft_d_rating, self.d_soft_d_diameter, self.d_soft_d_tcc, self.d_soft_d_hheight, self.d_soft_d_rna],\ [self.d_other_d_rating, self.d_other_d_diameter, self.d_other_d_tcc, self.d_other_d_hheight, self.d_other_d_rna],\ [self.d_cost_d_rating, self.d_cost_d_diameter, self.d_cost_d_tcc, self.d_cost_d_hheight, self.d_cost_d_rna]]) return self.J
class lcoe_se_assembly(Assembly): # Base I/O # Inputs turbine_number = Int(iotype='in', desc='number of turbines at plant') #Outputs turbine_cost = Float(iotype='out', desc='A Wind Turbine Capital _cost') bos_costs = Float(iotype='out', desc='A Wind Plant Balance of Station _cost Model') avg_annual_opex = Float(iotype='out', desc='A Wind Plant Operations Expenditures Model') net_aep = Float(iotype='out', desc='A Wind Plant Annual Energy Production Model', units='kW*h') coe = Float(iotype='out', desc='Levelized cost of energy for the wind plant') opex_breakdown = VarTree(OPEXVarTree(), iotype='out') bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown') # Configuration options with_new_nacelle = Bool( False, iotype='in', desc='configure with DriveWPACT if false, else configure with DriveSE') with_landbose = Bool( False, iotype='in', desc= 'configure with CSM BOS if false, else configure with new LandBOS model' ) flexible_blade = Bool(False, iotype='in', desc='configure rotor with flexible blade if True') with_3pt_drive = Bool( False, iotype='in', desc= 'only used if configuring DriveSE - selects 3 pt or 4 pt design option' ) # TODO: change nacelle selection to enumerated rather than nested boolean with_ecn_opex = Bool( False, iotype='in', desc= 'configure with CSM OPEX if flase, else configure with ECN OPEX model') ecn_file = Str(iotype='in', desc='location of ecn excel file if used') # Other I/O needed at lcoe system level sea_depth = Float(0.0, units='m', iotype='in', desc='sea depth for offshore wind project') year = Int(2009, iotype='in', desc='year of project start') month = Int(12, iotype='in', desc='month of project start') project_lifetime = Float(20.0, iotype='in', desc='project lifetime for wind plant') def __init__(self, with_new_nacelle=False, with_landbos=False, flexible_blade=False, with_3pt_drive=False, with_ecn_opex=False, ecn_file=None): self.with_new_nacelle = with_new_nacelle self.with_landbos = with_landbos self.flexible_blade = flexible_blade self.with_3pt_drive = with_3pt_drive self.with_ecn_opex = with_ecn_opex if ecn_file == None: self.ecn_file = '' else: self.ecn_file = ecn_file super(lcoe_se_assembly, self).__init__() def configure(self): """ tcc_a inputs: advanced_blade = Bool offshore = Bool assemblyCostMultiplier = Float overheadCostMultiplier = Float profitMultiplier = Float transportMultiplier = Float aep inputs: array_losses = Float other_losses = Float fin inputs: fixed_charge_rate = Float construction_finance_rate = Float tax_rate = Float discount_rate = Float construction_time = Float bos inputs: bos_multiplier = Float inputs: sea_depth year month project lifetime if csm opex additional inputs: availability = Float() if openwind opex additional inputs: power_curve rpm ct if with_landbos additional inputs: voltage distInter terrain layout soil """ # configure base assembly configure_extended_financial_analysis(self) # putting replace statements here for now; TODO - openmdao bug # replace BOS with either CSM or landbos if self.with_landbos: self.replace('bos_a', NREL_Land_BOSSE()) else: self.replace('bos_a', bos_csm_assembly()) self.replace('tcc_a', Turbine_CostsSE()) if self.with_ecn_opex: self.replace('opex_a', opex_ecn_assembly(ecn_file)) else: self.replace('opex_a', opex_csm_assembly()) self.replace('aep_a', aep_weibull_assembly()) self.replace('fin_a', fin_csm_assembly()) # add TurbineSE assembly configure_turbine(self, self.with_new_nacelle, self.flexible_blade, self.with_3pt_drive) # replace TCC with turbine_costs configure_lcoe_with_turb_costs(self) # replace BOS with either CSM or landbos if self.with_landbos: configure_lcoe_with_landbos(self) else: configure_lcoe_with_csm_bos(self) # replace AEP with weibull AEP (TODO: option for basic aep) configure_lcoe_with_weibull_aep(self) # replace OPEX with CSM or ECN opex and add AEP if self.with_ecn_opex: configure_lcoe_with_ecn_opex(self, ecn_file) self.connect( 'opex_a.availability', 'aep_a.availability' ) # connecting here due to aep / opex reversal depending on model else: configure_lcoe_with_csm_opex(self) self.add( 'availability', Float( 0.94, iotype='in', desc='average annual availbility of wind turbines at plant' )) self.connect( 'availability', 'aep_a.availability' ) # connecting here due to aep / opex reversal depending on model # replace Finance with CSM Finance configure_lcoe_with_csm_fin(self)
class lcoe_csm_assembly(Assembly): # Variables machine_rating = Float(units = 'kW', iotype='in', desc= 'rated machine power in kW') rotor_diameter = Float(units = 'm', iotype='in', desc= 'rotor diameter of the machine') max_tip_speed = Float(units = 'm/s', iotype='in', desc= 'maximum allowable tip speed for the rotor') hub_height = Float(units = 'm', iotype='in', desc='hub height of wind turbine above ground / sea level') sea_depth = Float(units = 'm', iotype='in', desc = 'sea depth for offshore wind project') # Parameters drivetrain_design = Enum('geared', ('geared', 'single_stage', 'multi_drive', 'pm_direct_drive'), iotype='in') altitude = Float(0.0, units = 'm', iotype='in', desc= 'altitude of wind plant') turbine_number = Int(100, iotype='in', desc = 'total number of wind turbines at the plant') year = Int(2009, iotype='in', desc = 'year of project start') month = Int(12, iotype='in', desc = 'month of project start') # Extra AEP parameters max_power_coefficient = Float(0.488, iotype='in', desc= 'maximum power coefficient of rotor for operation in region 2') opt_tsr = Float(7.525, iotype='in', desc= 'optimum tip speed ratio for operation in region 2') cut_in_wind_speed = Float(3.0, units = 'm/s', iotype='in', desc= 'cut in wind speed for the wind turbine') cut_out_wind_speed = Float(25.0, units = 'm/s', iotype='in', desc= 'cut out wind speed for the wind turbine') altitude = Float(0.0, units = 'm', iotype='in', desc= 'altitude of wind plant') shear_exponent = Float(0.1, iotype='in', desc= 'shear exponent for wind plant') wind_speed_50m = Float(8.35, units = 'm/s', iotype='in', desc='mean annual wind speed at 50 m height') weibull_k= Float(2.1, iotype='in', desc = 'weibull shape factor for annual wind speed distribution') soiling_losses = Float(0.0, iotype='in', desc = 'energy losses due to blade soiling for the wind plant - average across turbines') array_losses = Float(0.06, iotype='in', desc = 'energy losses due to turbine interactions - across entire plant') availability = Float(0.94287630736, iotype='in', desc = 'average annual availbility of wind turbines at plant') thrust_coefficient = Float(0.50, iotype='in', desc='thrust coefficient at rated power') # Extra TCC parameters blade_number = Int(3, iotype='in', desc = 'number of rotor blades') offshore = Bool(True, iotype='in', desc = 'boolean for offshore') advanced_blade = Bool(False, iotype='in', desc = 'boolean for use of advanced blade curve') crane = Bool(True, iotype='in', desc = 'boolean for presence of a service crane up tower') advanced_bedplate = Int(0, iotype='in', desc= 'indicator for drivetrain bedplate design 0 - conventional') advanced_tower = Bool(False, iotype='in', desc = 'advanced tower configuration') # Extra Finance parameters fixed_charge_rate = Float(0.12, iotype = 'in', desc = 'fixed charge rate for coe calculation') construction_finance_rate = Float(0.00, iotype='in', desc = 'construction financing rate applied to overnight capital costs') tax_rate = Float(0.4, iotype = 'in', desc = 'tax rate applied to operations') discount_rate = Float(0.07, iotype = 'in', desc = 'applicable project discount rate') construction_time = Float(1.0, iotype = 'in', desc = 'number of years to complete project construction') project_lifetime = Float(20.0, iotype = 'in', desc = 'project lifetime for LCOE calculation') #Outputs turbine_cost = Float(iotype='out', desc = 'A Wind Turbine Capital _cost') bos_costs = Float(iotype='out', desc='A Wind Plant Balance of Station _cost Model') avg_annual_opex = Float(iotype='out', desc='A Wind Plant Operations Expenditures Model') net_aep = Float(iotype='out', desc='A Wind Plant Annual Energy Production Model', units='kW*h') coe = Float(iotype='out', desc='Levelized cost of energy for the wind plant') opex_breakdown = VarTree(OPEXVarTree(),iotype='out') bos_breakdown = VarTree(BOSVarTree(), iotype='out', desc='BOS cost breakdown') #AEP outputs rated_wind_speed = Float(11.506, units = 'm / s', iotype='out', desc='wind speed for rated power') rated_rotor_speed = Float(12.126, units = 'rpm', iotype='out', desc = 'rotor speed at rated power') rotor_thrust = Float(iotype='out', units='N', desc='maximum thrust from rotor') rotor_torque = Float(iotype='out', units='N * m', desc = 'torque from rotor at rated power') power_curve = Array(np.array([[4.0,80.0],[25.0, 5000.0]]), iotype='out', desc = 'power curve for a particular rotor') max_efficiency = Float(0.902, iotype='out', desc = 'maximum efficiency of rotor and drivetrain - at rated power') gross_aep = Float(0.0, iotype='out', desc='Gross Annual Energy Production before availability and loss impacts', unit='kWh') #TCC outputs turbine_mass = Float(0.0, units='kg', iotype='out', desc='turbine mass') #Finance outputs lcoe = Float(iotype='out', desc='_cost of energy - unlevelized') def configure(self): configure_extended_financial_analysis(self) self.replace('tcc_a', tcc_csm_assembly()) self.replace('bos_a', bos_csm_assembly()) self.replace('opex_a', opex_csm_assembly()) self.replace('aep_a', aep_csm_assembly()) self.replace('fin_a', fin_csm_assembly()) # connect i/o to component and assembly inputs # turbine configuration # rotor self.connect('rotor_diameter', ['aep_a.rotor_diameter', 'tcc_a.rotor_diameter', 'bos_a.rotor_diameter']) self.connect('max_tip_speed', ['aep_a.max_tip_speed']) self.connect('opt_tsr','aep_a.opt_tsr') self.connect('cut_in_wind_speed','aep_a.cut_in_wind_speed') self.connect('cut_out_wind_speed','aep_a.cut_out_wind_speed') self.connect('altitude','aep_a.altitude') self.connect('shear_exponent','aep_a.shear_exponent') self.connect('wind_speed_50m','aep_a.wind_speed_50m') self.connect('weibull_k','aep_a.weibull_k') self.connect('soiling_losses','aep_a.soiling_losses') self.connect('array_losses','aep_a.array_losses') self.connect('availability','aep_a.availability') self.connect('thrust_coefficient','aep_a.thrust_coefficient') self.connect('blade_number','tcc_a.blade_number') self.connect('advanced_blade','tcc_a.advanced_blade') # drivetrain self.connect('machine_rating', ['aep_a.machine_rating', 'tcc_a.machine_rating', 'bos_a.machine_rating', 'opex_a.machine_rating']) self.connect('drivetrain_design', ['aep_a.drivetrain_design', 'tcc_a.drivetrain_design']) self.connect('crane','tcc_a.crane') self.connect('advanced_bedplate','tcc_a.advanced_bedplate') # tower self.connect('hub_height', ['aep_a.hub_height', 'tcc_a.hub_height', 'bos_a.hub_height']) self.connect('advanced_tower','tcc_a.advanced_tower') # plant configuration # climate self.connect('sea_depth', ['bos_a.sea_depth', 'opex_a.sea_depth', 'fin_a.sea_depth']) self.connect('offshore','tcc_a.offshore') # plant operation self.connect('turbine_number', ['aep_a.turbine_number', 'bos_a.turbine_number', 'opex_a.turbine_number']) # financial self.connect('year', ['tcc_a.year', 'bos_a.year', 'opex_a.year']) self.connect('month', ['tcc_a.month', 'bos_a.month', 'opex_a.month']) self.connect('fixed_charge_rate','fin_a.fixed_charge_rate') self.connect('construction_finance_rate','fin_a.construction_finance_rate') self.connect('tax_rate','fin_a.tax_rate') self.connect('discount_rate','fin_a.discount_rate') self.connect('construction_time','fin_a.construction_time') self.connect('project_lifetime','fin_a.project_lifetime') # connections self.connect('aep_a.rotor_thrust','tcc_a.rotor_thrust') self.connect('aep_a.rotor_torque','tcc_a.rotor_torque') self.connect('aep_a.net_aep', ['opex_a.net_aep']) self.connect('tcc_a.turbine_cost','bos_a.turbine_cost') # create passthroughs for key output variables of interest # aep_a self.connect('aep_a.rated_rotor_speed','rated_rotor_speed') self.connect('aep_a.rated_wind_speed','rated_wind_speed') self.connect('aep_a.rotor_thrust','rotor_thrust') self.connect('aep_a.rotor_torque','rotor_torque') self.connect('aep_a.power_curve','power_curve') self.connect('aep_a.max_efficiency','max_efficiency') self.connect('aep_a.gross_aep','gross_aep') # tcc_a self.connect('tcc_a.turbine_mass','turbine_mass') # fin_a self.connect('fin_a.lcoe','lcoe')