diff --git a/reV/bespoke/bespoke.py b/reV/bespoke/bespoke.py index 628155578..d39a309eb 100644 --- a/reV/bespoke/bespoke.py +++ b/reV/bespoke/bespoke.py @@ -1360,22 +1360,44 @@ def run_plant_optimization(self): # copy dataset outputs to meta data for supply curve table summary # convert SAM system capacity in kW to reV supply curve cap in MW - self._meta[SupplyCurveField.CAPACITY_AC_MW] = ( - self.outputs["system_capacity"] / 1e3 - ) + capacity_ac_mw = self.outputs["system_capacity"] / 1e3 + self._meta[SupplyCurveField.CAPACITY_AC_MW] = capacity_ac_mw self._meta[SupplyCurveField.CAPACITY_DC_MW] = None # add required ReEDS multipliers to meta baseline_cost = self.plant_optimizer.capital_cost_per_kw( capacity_mw=self._baseline_cap_mw ) - self._meta[SupplyCurveField.EOS_MULT] = ( + eos_mult = (self.plant_optimizer.capital_cost + / self.plant_optimizer.capacity + / baseline_cost) + reg_mult = self.sam_sys_inputs.get("capital_cost_multiplier", 1) + + self._meta[SupplyCurveField.EOS_MULT] = eos_mult + self._meta[SupplyCurveField.REG_MULT] = reg_mult + + cap_cost = ( self.plant_optimizer.capital_cost - / self.plant_optimizer.capacity - / baseline_cost + + self.plant_optimizer.balance_of_system_cost + ) + self._meta[SupplyCurveField.COST_SITE_OCC_USD_PER_AC_MW] = cap_cost + self._meta[SupplyCurveField.COST_BASE_OCC_USD_PER_AC_MW] = ( + cap_cost / eos_mult / reg_mult / capacity_ac_mw + ) + self._meta[SupplyCurveField.COST_SITE_FOC_USD_PER_AC_MW] = ( + self.plant_optimizer.fixed_operating_cost / capacity_ac_mw + ) + self._meta[SupplyCurveField.COST_BASE_FOC_USD_PER_AC_MW] = ( + self.plant_optimizer.fixed_operating_cost / capacity_ac_mw + ) + self._meta[SupplyCurveField.COST_SITE_VOC_USD_PER_AC_MW] = ( + self.plant_optimizer.variable_operating_cost / capacity_ac_mw + ) + self._meta[SupplyCurveField.COST_BASE_VOC_USD_PER_AC_MW] = ( + self.plant_optimizer.variable_operating_cost / capacity_ac_mw ) - self._meta[SupplyCurveField.REG_MULT] = self.sam_sys_inputs.get( - "capital_cost_multiplier", 1 + self._meta[SupplyCurveField.FIXED_CHARGE_RATE] = ( + self.plant_optimizer.fixed_charge_rate ) return self.outputs diff --git a/tests/test_bespoke.py b/tests/test_bespoke.py index 82dcd7b1e..cd65d5083 100644 --- a/tests/test_bespoke.py +++ b/tests/test_bespoke.py @@ -17,6 +17,7 @@ from rex import Resource from reV import TESTDATADIR +from reV.econ.utilities import lcoe_fcr from reV.bespoke.bespoke import BespokeSinglePlant, BespokeWindPlants from reV.bespoke.place_turbines import PlaceTurbines, _compute_nn_conn_dist from reV.cli import main @@ -88,9 +89,25 @@ SupplyCurveField.TURBINE_X_COORDS, SupplyCurveField.TURBINE_Y_COORDS, SupplyCurveField.RES_GIDS, + SupplyCurveField.CAPACITY_AC_MW, SupplyCurveField.CAPACITY_DC_MW, + SupplyCurveField.MEAN_CF_AC, SupplyCurveField.MEAN_CF_DC, - SupplyCurveField.SC_POINT_ANNUAL_ENERGY_MW] + SupplyCurveField.SC_POINT_ANNUAL_ENERGY_MW, + SupplyCurveField.EOS_MULT, + SupplyCurveField.REG_MULT, + SupplyCurveField.COST_BASE_OCC_USD_PER_AC_MW, + SupplyCurveField.COST_SITE_OCC_USD_PER_AC_MW, + SupplyCurveField.COST_BASE_FOC_USD_PER_AC_MW, + SupplyCurveField.COST_SITE_FOC_USD_PER_AC_MW, + SupplyCurveField.COST_BASE_VOC_USD_PER_AC_MW, + SupplyCurveField.COST_SITE_VOC_USD_PER_AC_MW, + SupplyCurveField.FIXED_CHARGE_RATE, + SupplyCurveField.INCLUDED_AREA, + SupplyCurveField.INCLUDED_AREA_CAPACITY_DENSITY, + SupplyCurveField.CONVEX_HULL_AREA, + SupplyCurveField.CONVEX_HULL_CAPACITY_DENSITY, + SupplyCurveField.FULL_CELL_CAPACITY_DENSITY] def test_turbine_placement(gid=33): @@ -645,6 +662,30 @@ def test_bespoke(): assert f[dset].shape[1] == len(meta) assert f[dset].any() # not all zeros + fcr = meta[SupplyCurveField.FIXED_CHARGE_RATE] + cap_cost = (meta[SupplyCurveField.COST_SITE_OCC_USD_PER_AC_MW] + * meta[SupplyCurveField.CAPACITY_AC_MW]) + foc = (meta[SupplyCurveField.COST_SITE_FOC_USD_PER_AC_MW] + * meta[SupplyCurveField.CAPACITY_AC_MW]) + voc = (meta[SupplyCurveField.COST_SITE_VOC_USD_PER_AC_MW] + * meta[SupplyCurveField.CAPACITY_AC_MW]) + aep = meta[SupplyCurveField.SC_POINT_ANNUAL_ENERGY_MW] + + lcoe = lcoe_fcr(fcr, cap_cost, foc, aep, voc) + assert np.allclose(lcoe, meta[SupplyCurveField.MEAN_LCOE]) + + cap_cost = (meta[SupplyCurveField.COST_BASE_OCC_USD_PER_AC_MW] + * meta[SupplyCurveField.CAPACITY_AC_MW] + * meta[SupplyCurveField.REG_MULT] + * meta[SupplyCurveField.EOS_MULT]) + foc = (meta[SupplyCurveField.COST_BASE_FOC_USD_PER_AC_MW] + * meta[SupplyCurveField.CAPACITY_AC_MW]) + voc = (meta[SupplyCurveField.COST_BASE_VOC_USD_PER_AC_MW] + * meta[SupplyCurveField.CAPACITY_AC_MW]) + + lcoe = lcoe_fcr(fcr, cap_cost, foc, aep, voc) + assert np.allclose(lcoe, meta[SupplyCurveField.MEAN_LCOE]) + out_fpath_pre = os.path.join(td, 'bespoke_out_pre.h5') bsp = BespokeWindPlants(excl_fp, res_fp, TM_DSET, OBJECTIVE_FUNCTION, CAP_COST_FUN, FOC_FUN, VOC_FUN, BOS_FUN,