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())
Пример #2
0
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())
Пример #4
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')
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
Пример #6
0
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
Пример #7
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)
Пример #8
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')