Skip to content

Commit

Permalink
Finalize bespoke meta outputs
Browse files Browse the repository at this point in the history
  • Loading branch information
ppinchuk committed Jun 12, 2024
1 parent 24a0e17 commit a3cd110
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 50 deletions.
61 changes: 31 additions & 30 deletions reV/bespoke/bespoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -1071,11 +1071,9 @@ def recalc_lcoe(self):
cc = lcoe_kwargs['capital_cost']
foc = lcoe_kwargs['fixed_operating_cost']
voc = lcoe_kwargs['variable_operating_cost']
bos = lcoe_kwargs['balance_of_system_cost']
aep = self.outputs['annual_energy-means']
cap_cost = cc + bos

my_mean_lcoe = lcoe_fcr(fcr, cap_cost, foc, aep, voc)
my_mean_lcoe = lcoe_fcr(fcr, cc, foc, aep, voc)

self._outputs["lcoe_fcr-means"] = my_mean_lcoe
self._meta[SupplyCurveField.MEAN_LCOE] = my_mean_lcoe
Expand Down Expand Up @@ -1117,9 +1115,6 @@ def get_lcoe_kwargs(self):
value = float(self.meta[kwarg].values[0])
lcoe_kwargs[kwarg] = value

for k, v in lcoe_kwargs.items():
self._meta[k] = v

missing = [k for k in kwargs_list if k not in lcoe_kwargs]
if any(missing):
msg = (
Expand All @@ -1131,6 +1126,8 @@ def get_lcoe_kwargs(self):
logger.error(msg)
raise KeyError(msg)

bos = lcoe_kwargs.pop("balance_of_system_cost")
lcoe_kwargs["capital_cost"] = lcoe_kwargs["capital_cost"] + bos
return lcoe_kwargs

@staticmethod
Expand Down Expand Up @@ -1299,9 +1296,12 @@ def run_plant_optimization(self):
logger.exception(msg)
raise RuntimeError(msg) from e

# TODO need to add:
# total cell area
# cell capacity density
self._outputs["full_polygons"] = self.plant_optimizer.full_polygons
self._outputs["packing_polygons"] = (
self.plant_optimizer.packing_polygons
)
system_capacity_kw = self.plant_optimizer.capacity
self._outputs["system_capacity"] = system_capacity_kw

txc = [int(np.round(c)) for c in self.plant_optimizer.turbine_x]
tyc = [int(np.round(c)) for c in self.plant_optimizer.turbine_y]
Expand All @@ -1315,31 +1315,31 @@ def run_plant_optimization(self):

self._meta[SupplyCurveField.TURBINE_X_COORDS] = txc
self._meta[SupplyCurveField.TURBINE_Y_COORDS] = tyc
self._meta["possible_x_coords"] = pxc
self._meta["possible_y_coords"] = pyc

self._outputs["full_polygons"] = self.plant_optimizer.full_polygons
self._outputs["packing_polygons"] = (
self.plant_optimizer.packing_polygons
)
self._outputs["system_capacity"] = self.plant_optimizer.capacity
self._meta[SupplyCurveField.POSSIBLE_X_COORDS] = pxc
self._meta[SupplyCurveField.POSSIBLE_Y_COORDS] = pyc

self._meta["n_turbines"] = self.plant_optimizer.nturbs
self._meta["avg_sl_dist_to_center_m"] = \
self._meta[SupplyCurveField.N_TURBINES] = self.plant_optimizer.nturbs
self._meta["avg_sl_dist_to_center_m"] = (
self.plant_optimizer.avg_sl_dist_to_center_m
self._meta["avg_sl_dist_to_medoid_m"] = \
)
self._meta["avg_sl_dist_to_medoid_m"] = (
self.plant_optimizer.avg_sl_dist_to_medoid_m
)
self._meta["nn_conn_dist_m"] = self.plant_optimizer.nn_conn_dist_m
self._meta["bespoke_aep"] = self.plant_optimizer.aep
self._meta["bespoke_objective"] = self.plant_optimizer.objective
self._meta["bespoke_capital_cost"] = self.plant_optimizer.capital_cost
self._meta["bespoke_fixed_operating_cost"] = (
self._meta[SupplyCurveField.BESPOKE_AEP] = self.plant_optimizer.aep
self._meta[SupplyCurveField.BESPOKE_OBJECTIVE] = (
self.plant_optimizer.objective
)
self._meta[SupplyCurveField.BESPOKE_CAPITAL_COST] = (
self.plant_optimizer.capital_cost
)
self._meta[SupplyCurveField.BESPOKE_FIXED_OPERATING_COST] = (
self.plant_optimizer.fixed_operating_cost
)
self._meta["bespoke_variable_operating_cost"] = (
self._meta[SupplyCurveField.BESPOKE_VARIABLE_OPERATING_COST] = (
self.plant_optimizer.variable_operating_cost
)
self._meta["bespoke_balance_of_system_cost"] = (
self._meta[SupplyCurveField.BESPOKE_BALANCE_OF_SYSTEM_COST] = (
self.plant_optimizer.balance_of_system_cost
)
self._meta[SupplyCurveField.INCLUDED_AREA] = self.plant_optimizer.area
Expand All @@ -1356,11 +1356,9 @@ def run_plant_optimization(self):
self.plant_optimizer.full_cell_capacity_density
)

logger.debug("Plant layout optimization complete!")

# copy dataset outputs to meta data for supply curve table summary
# convert SAM system capacity in kW to reV supply curve cap in MW
capacity_ac_mw = self.outputs["system_capacity"] / 1e3
capacity_ac_mw = system_capacity_kw / 1e3
self._meta[SupplyCurveField.CAPACITY_AC_MW] = capacity_ac_mw
self._meta[SupplyCurveField.CAPACITY_DC_MW] = None

Expand All @@ -1380,7 +1378,9 @@ def run_plant_optimization(self):
self.plant_optimizer.capital_cost
+ self.plant_optimizer.balance_of_system_cost
)
self._meta[SupplyCurveField.COST_SITE_OCC_USD_PER_AC_MW] = cap_cost
self._meta[SupplyCurveField.COST_SITE_OCC_USD_PER_AC_MW] = (
cap_cost / capacity_ac_mw
)
self._meta[SupplyCurveField.COST_BASE_OCC_USD_PER_AC_MW] = (
cap_cost / eos_mult / reg_mult / capacity_ac_mw
)
Expand All @@ -1400,6 +1400,7 @@ def run_plant_optimization(self):
self.plant_optimizer.fixed_charge_rate
)

logger.debug("Plant layout optimization complete!")
return self.outputs

def agg_data_layers(self):
Expand Down
9 changes: 9 additions & 0 deletions reV/utilities/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ class SupplyCurveField(FieldEnum):
MEAN_LCOE_FRICTION = "mean_lcoe_friction"
TOTAL_LCOE_FRICTION = "total_lcoe_friction"
RAW_LCOE = "raw_lcoe"
POSSIBLE_X_COORDS = "possible_x_coords"
POSSIBLE_Y_COORDS = "possible_y_coords"
TURBINE_X_COORDS = "turbine_x_coords"
TURBINE_Y_COORDS = "turbine_y_coords"
N_TURBINES = "n_turbines"
EOS_MULT = "eos_mult"
REG_MULT = "reg_mult"
INCLUDED_AREA = "included_area"
Expand All @@ -164,6 +167,12 @@ class SupplyCurveField(FieldEnum):
COST_BASE_VOC_USD_PER_AC_MW = "cost_base_voc_usd_per_ac_mw"
COST_SITE_VOC_USD_PER_AC_MW = "cost_site_voc_usd_per_ac_mw"
FIXED_CHARGE_RATE = "fixed_charge_rate"
BESPOKE_AEP = "bespoke_aep"
BESPOKE_OBJECTIVE = "bespoke_objective"
BESPOKE_CAPITAL_COST = "bespoke_capital_cost"
BESPOKE_FIXED_OPERATING_COST = "bespoke_fixed_operating_cost"
BESPOKE_VARIABLE_OPERATING_COST = "bespoke_variable_operating_cost"
BESPOKE_BALANCE_OF_SYSTEM_COST = "bespoke_balance_of_system_cost"

@classmethod
def map_from_legacy(cls):
Expand Down
45 changes: 25 additions & 20 deletions tests/test_bespoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@
EXPECTED_META_COLUMNS = [SupplyCurveField.SC_POINT_GID,
SupplyCurveField.TURBINE_X_COORDS,
SupplyCurveField.TURBINE_Y_COORDS,
SupplyCurveField.POSSIBLE_X_COORDS,
SupplyCurveField.POSSIBLE_Y_COORDS,
SupplyCurveField.N_TURBINES,
SupplyCurveField.RES_GIDS,
SupplyCurveField.CAPACITY_AC_MW,
SupplyCurveField.CAPACITY_DC_MW,
Expand All @@ -107,7 +110,13 @@
SupplyCurveField.INCLUDED_AREA_CAPACITY_DENSITY,
SupplyCurveField.CONVEX_HULL_AREA,
SupplyCurveField.CONVEX_HULL_CAPACITY_DENSITY,
SupplyCurveField.FULL_CELL_CAPACITY_DENSITY]
SupplyCurveField.FULL_CELL_CAPACITY_DENSITY,
SupplyCurveField.BESPOKE_AEP,
SupplyCurveField.BESPOKE_OBJECTIVE,
SupplyCurveField.BESPOKE_CAPITAL_COST,
SupplyCurveField.BESPOKE_FIXED_OPERATING_COST,
SupplyCurveField.BESPOKE_VARIABLE_OPERATING_COST,
SupplyCurveField.BESPOKE_BALANCE_OF_SYSTEM_COST]


def test_turbine_placement(gid=33):
Expand Down Expand Up @@ -393,7 +402,7 @@ def test_single(gid=33):
assert "annual_energy-means" in out

assert (
TURB_RATING * bsp.meta["n_turbines"].values[0]
TURB_RATING * bsp.meta[SupplyCurveField.N_TURBINES].values[0]
== out["system_capacity"]
)
x_coords = json.loads(
Expand All @@ -402,8 +411,8 @@ def test_single(gid=33):
y_coords = json.loads(
bsp.meta[SupplyCurveField.TURBINE_Y_COORDS].values[0]
)
assert bsp.meta["n_turbines"].values[0] == len(x_coords)
assert bsp.meta["n_turbines"].values[0] == len(y_coords)
assert bsp.meta[SupplyCurveField.N_TURBINES].values[0] == len(x_coords)
assert bsp.meta[SupplyCurveField.N_TURBINES].values[0] == len(y_coords)

for y in (2012, 2013):
cf = out[f"cf_profile-{y}"]
Expand Down Expand Up @@ -556,7 +565,7 @@ def test_extra_outputs(gid=33):
bsp.close()


def test_bespoke():
def test_bespok_kjbndkjnbdfkjne():
"""Test bespoke optimization with multiple plants, parallel processing, and
file output."""
output_request = (
Expand Down Expand Up @@ -595,6 +604,8 @@ def test_bespoke():
)

TechMapping.run(excl_fp, RES.format(2012), dset=TM_DSET, max_workers=1)
sam_configs = copy.deepcopy(SAM_CONFIGS)
sam_configs["default"]["fixed_charge_rate"] = 0.0975

# test no outputs
with pytest.warns(UserWarning) as record:
Expand All @@ -603,7 +614,7 @@ def test_bespoke():
OBJECTIVE_FUNCTION, CAP_COST_FUN,
FOC_FUN, VOC_FUN, BOS_FUN,
fully_excluded_points,
SAM_CONFIGS, ga_kwargs={'max_time': 5},
sam_configs, ga_kwargs={'max_time': 5},
excl_dict=EXCL_DICT,
output_request=output_request)
test_fpath = bsp.run(max_workers=2, out_fpath=out_fpath_request)
Expand All @@ -613,7 +624,7 @@ def test_bespoke():
assert not os.path.exists(out_fpath_truth)
bsp = BespokeWindPlants(excl_fp, res_fp, TM_DSET, OBJECTIVE_FUNCTION,
CAP_COST_FUN, FOC_FUN, VOC_FUN, BOS_FUN,
points, SAM_CONFIGS, ga_kwargs={'max_time': 5},
points, sam_configs, ga_kwargs={'max_time': 5},
excl_dict=EXCL_DICT,
output_request=output_request)
test_fpath = bsp.run(max_workers=2, out_fpath=out_fpath_request)
Expand All @@ -625,9 +636,6 @@ def test_bespoke():
for col in EXPECTED_META_COLUMNS:
assert col in meta

assert "possible_x_coords" in meta
assert "possible_y_coords" in meta

dsets_1d = (
"system_capacity",
"cf_mean-2012",
Expand Down Expand Up @@ -670,9 +678,7 @@ def test_bespoke():
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])
lcoe_site = lcoe_fcr(fcr, cap_cost, foc, aep, voc)

cap_cost = (meta[SupplyCurveField.COST_BASE_OCC_USD_PER_AC_MW]
* meta[SupplyCurveField.CAPACITY_AC_MW]
Expand All @@ -682,9 +688,9 @@ def test_bespoke():
* meta[SupplyCurveField.CAPACITY_AC_MW])
voc = (meta[SupplyCurveField.COST_BASE_VOC_USD_PER_AC_MW]
* meta[SupplyCurveField.CAPACITY_AC_MW])
lcoe_base = lcoe_fcr(fcr, cap_cost, foc, aep, voc)

lcoe = lcoe_fcr(fcr, cap_cost, foc, aep, voc)
assert np.allclose(lcoe, meta[SupplyCurveField.MEAN_LCOE])
assert np.allclose(lcoe_site, lcoe_base)

out_fpath_pre = os.path.join(td, 'bespoke_out_pre.h5')
bsp = BespokeWindPlants(excl_fp, res_fp, TM_DSET, OBJECTIVE_FUNCTION,
Expand Down Expand Up @@ -784,11 +790,10 @@ def test_consistent_eval_namespace(gid=33):
)
_ = bsp.run_plant_optimization()

assert bsp.meta["bespoke_aep"].values[0] == bsp.plant_optimizer.aep
assert (
bsp.meta["bespoke_objective"].values[0]
== bsp.plant_optimizer.objective
)
assert (bsp.meta[SupplyCurveField.BESPOKE_AEP].values[0]
== bsp.plant_optimizer.aep)
assert (bsp.meta[SupplyCurveField.BESPOKE_OBJECTIVE].values[0]
== bsp.plant_optimizer.objective)

bsp.close()

Expand Down

0 comments on commit a3cd110

Please sign in to comment.