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 ExtendedOPEXModel_Example(Assembly):
    """ Extended operational expenditures assembly for coupling models to get a full wind plant operational expenditures estimate as well as a detailed cost breakdown.    """

    # Outputs
    avg_annual_opex = Float(
        iotype='out',
        desc=
        'Average annual Operating Expenditures for a wind plant over its lifetime'
    )
    opex_breakdown = VarTree(OPEXVarTree(), iotype='out')

    def configure(self):

        configure_extended_opex(self)

        self.replace('opex', ExtendedOPEXAggregator_Example())
Ejemplo n.º 3
0
class opex_ecn_assembly(Assembly):

    # variables
    turbine_cost = Float(units='USD',
                         iotype='in',
                         desc='turbine system capital costs')
    machine_rating = Float(units='kW',
                           iotype='in',
                           desc='wind turbine rated power')

    # parameters
    turbine_number = Int(100,
                         iotype='in',
                         desc='total number of wind turbines at the plant')
    project_lifetime = Float(20.0,
                             iotype='in',
                             desc='project lifetime for wind plant')

    # Outputs
    avg_annual_opex = Float(
        iotype='out',
        desc=
        'Average annual Operating Expenditures for a wind plant over its lifetime'
    )
    opex_breakdown = VarTree(OPEXVarTree(), iotype='out')
    availability = Float(0.0, iotype='out', desc='Availability')

    def __init__(self, ssfile=None):

        self.ssfile = ssfile

        Assembly.__init__(self)

    def configure(self):

        configure_extended_opex(self)

        self.replace('opex', opex_ecn_offshore_component(self.ssfile))

        self.connect('turbine_cost', 'opex.turbine_cost')
        self.connect('machine_rating', 'opex.machine_rating')
        self.connect('turbine_number', 'opex.turbine_number')
        self.connect('project_lifetime', 'opex.project_lifetime')

        self.connect('opex.availability', 'availability')
class ExtendedOPEXAggregator_Example(Component):
    """ Extended operational expenditures aggregator for doing some auxiliary cost calculations needed to get a full wind plant operational expenditures estimate as well as a detailed cost breakdown.    """

    # Outputs
    avg_annual_opex = Float(
        iotype='out',
        desc=
        'Average annual Operating Expenditures for a wind plant over its lifetime'
    )
    opex_breakdown = VarTree(OPEXVarTree(), iotype='out')

    def execute(self):

        self.avg_annual_opex = 50000000.00
        self.opex_breakdown.preventative_opex = self.avg_annual_opex * 0.25
        self.opex_breakdown.corrective_opex = self.avg_annual_opex * 0.50
        self.opex_breakdown.lease_opex = self.avg_annual_opex * 0.25
        self.opex_breakdown.other_opex = 0.0
Ejemplo n.º 5
0
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')
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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')
Ejemplo n.º 8
0
class opex_ecn_offshore_component(Component):
    """ Evaluates the ECN O&M spreadsheet """

    # variables
    turbine_cost = Float(units='USD',
                         iotype='in',
                         desc='turbine system capital costs')
    machine_rating = Float(units='kW',
                           iotype='in',
                           desc='wind turbine rated power')

    # parameters
    turbine_number = Int(100,
                         iotype='in',
                         desc='total number of wind turbines at the plant')
    project_lifetime = Float(20.0,
                             iotype='in',
                             desc='project lifetime for wind plant')

    # Outputs
    avg_annual_opex = Float(
        iotype='out',
        desc=
        'Average annual Operating Expenditures for a wind plant over its lifetime'
    )
    opex_breakdown = VarTree(OPEXVarTree(), iotype='out')
    availability = Float(0.0, iotype='out', desc='Availability')

    def __init__(self, ssfile=None):
        """
        OpenMDAO component to wrap ECN Offshore O&M Excel Model (ecnomXLS.py).
        Call __init__ with a file name to override default ECN spreadsheet file
        """

        Component.__init__(self)

        #open excel account
        self.ecnxls = ecnomXLS(debug=False)
        self.ecnxls.ssopen(ssfile)

    def execute(self):
        """
        Executes the ECN O&M Offshore model using excel spreadsheet and finds total and detailed O&M costs for the plant as well as availability.
        """
        # print "In {0}.execute()...".format(self.__class__)

        # Inputs - copy to spreadsheet

        # set basic plant inputs
        self.ecnxls.setCell(6, 3, self.turbine_number)
        self.ecnxls.setCell(5, 8, self.machine_rating)
        self.ecnxls.setCell(7, 3, self.project_lifetime)

        # set basic turbine inputs
        self.invCosts = self.turbine_cost / self.machine_rating  # investment costs per kW
        self.ecnxls.setCell(6, 8, self.invCosts)

        # Outputs - read from spreadsheet

        self.availability = self.ecnxls.getCell(20, 9)
        self.avg_annual_opex = self.ecnxls.getCell(56, 9) * 1000
        self.opex_breakdown.lease_opex = 21.0 * self.turbine_number * self.machine_rating  # hack to include land lease costs not in ECN model, cost from COE Review 2011
        self.avg_annual_opex += self.opex_breakdown.lease_opex

        self.opex_breakdown.corrective_opex = self.ecnxls.getCell(
            51, 9) * 1000 + self.ecnxls.getCell(52, 9) * 1000
        self.opex_breakdown.preventative_opex = self.ecnxls.getCell(53,
                                                                    9) * 1000
        self.opex_breakdown.other_opex = self.ecnxls.getCell(54, 9) * 1000

    def close(self):
        """
        Close the spreadsheet inputs and clean up
        """
        self.ecnxls.ssclose()