Skip to content

Commit

Permalink
Merge pull request #456 from NREL/pp/minor_updates
Browse files Browse the repository at this point in the history
Minor updates
  • Loading branch information
ppinchuk authored Jun 18, 2024
2 parents ef9aa04 + 4d27801 commit e92af3a
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 39 deletions.
3 changes: 3 additions & 0 deletions reV/SAM/SAM.py
Original file line number Diff line number Diff line change
Expand Up @@ -950,4 +950,7 @@ def _add_sys_capacity(sam_inputs):
if cap is not None:
cap = max(cap)

if cap is None:
cap = sam_inputs.get("nameplate")

sam_inputs["system_capacity"] = cap
38 changes: 31 additions & 7 deletions reV/SAM/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1786,6 +1786,10 @@ def _set_nameplate_to_match_resource_potential(self, resource):
"{}".format(self.sam_sys_inputs["nameplate"])
)
logger.info(msg)
# required for downstream LCOE calcs
self.sam_sys_inputs["system_capacity"] = (
self.sam_sys_inputs["nameplate"]
)
return

val = set(resource["potential_MW"].unique())
Expand All @@ -1801,6 +1805,8 @@ def _set_nameplate_to_match_resource_potential(self, resource):

logger.debug("Setting the nameplate to {}".format(val))
self.sam_sys_inputs["nameplate"] = val
# required for downstream LCOE calcs
self.sam_sys_inputs["system_capacity"] = val

def _set_resource_potential_to_match_gross_output(self):
"""Set the resource potential input to match the gross generation.
Expand Down Expand Up @@ -1861,7 +1867,9 @@ def _set_costs(self):
logger.debug(
"Setting the capital_cost to ${:,.2f}".format(capital_cost)
)
self.sam_sys_inputs["capital_cost"] = capital_cost
reg_mult = self.sam_sys_inputs.get("capital_cost_multiplier", 1)
self.sam_sys_inputs["base_capital_cost"] = capital_cost
self.sam_sys_inputs["capital_cost"] = capital_cost * reg_mult

dc_per_well = self.sam_sys_inputs.pop("drill_cost_per_well", None)
num_wells = self.sam_sys_inputs.pop(
Expand All @@ -1884,19 +1892,35 @@ def _set_costs(self):
drill_cost, num_wells, dc_per_well
)
)
self.sam_sys_inputs["capital_cost"] = capital_cost + drill_cost
reg_mult = self.sam_sys_inputs.get(
"capital_cost_multiplier", 1
)
base_cc = capital_cost / reg_mult
new_base_cc = base_cc + drill_cost
self.sam_sys_inputs["base_capital_cost"] = new_base_cc
self.sam_sys_inputs["capital_cost"] = new_base_cc * reg_mult

foc_per_kw = self.sam_sys_inputs.pop(
"fixed_operating_cost_per_kw", None
)
if foc_per_kw is not None:
fixed_operating_cost = foc_per_kw * plant_size_kw
foc = foc_per_kw * plant_size_kw
logger.debug(
"Setting the fixed_operating_cost to ${:,.2f}".format(
capital_cost
)
"Setting the fixed_operating_cost to ${:,.2f}".format(foc)
)
self.sam_sys_inputs["base_fixed_operating_cost"] = foc
self.sam_sys_inputs["fixed_operating_cost"] = foc

voc_per_kw = self.sam_sys_inputs.pop(
"variable_operating_cost_per_kw", None
)
if voc_per_kw is not None:
voc = voc_per_kw * plant_size_kw
logger.debug(
"Setting the variable_operating_cost to ${:,.2f}".format(voc)
)
self.sam_sys_inputs["fixed_operating_cost"] = fixed_operating_cost
self.sam_sys_inputs["base_variable_operating_cost"] = voc
self.sam_sys_inputs["variable_operating_cost"] = voc

def _create_pysam_wfile(self, resource, meta):
"""Create PySAM weather input file.
Expand Down
14 changes: 7 additions & 7 deletions reV/bespoke/bespoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -1263,10 +1263,10 @@ def run_wind_plant_ts(self):
self._outputs.update(means)

self._meta[SupplyCurveField.MEAN_RES] = self.res_df["windspeed"].mean()
self._meta[SupplyCurveField.MEAN_CF_DC] = None
self._meta[SupplyCurveField.MEAN_CF_AC] = None
self._meta[SupplyCurveField.MEAN_LCOE] = None
self._meta[SupplyCurveField.SC_POINT_ANNUAL_ENERGY_MW] = None
self._meta[SupplyCurveField.MEAN_CF_DC] = np.nan
self._meta[SupplyCurveField.MEAN_CF_AC] = np.nan
self._meta[SupplyCurveField.MEAN_LCOE] = np.nan
self._meta[SupplyCurveField.SC_POINT_ANNUAL_ENERGY_MW] = np.nan
# copy dataset outputs to meta data for supply curve table summary
if "cf_mean-means" in self.outputs:
self._meta.loc[:, SupplyCurveField.MEAN_CF_AC] = self.outputs[
Expand Down Expand Up @@ -1373,7 +1373,7 @@ def run_plant_optimization(self):
# convert SAM system capacity in kW to reV supply curve cap in MW
capacity_ac_mw = system_capacity_kw / 1e3
self._meta[SupplyCurveField.CAPACITY_AC_MW] = capacity_ac_mw
self._meta[SupplyCurveField.CAPACITY_DC_MW] = None
self._meta[SupplyCurveField.CAPACITY_DC_MW] = np.nan

# add required ReEDS multipliers to meta
baseline_cost = self.plant_optimizer.capital_cost_per_kw(
Expand Down Expand Up @@ -1618,7 +1618,7 @@ def __init__(self, excl_fpath, res_fpath, tm_dset, objective_function,
multiple sites can be specified to evaluate ``reV`` at
multiple specific locations. A string pointing to a project
points CSV file may also be specified. Typically, the CSV
contains two columns:
contains the following columns:
- ``gid``: Integer specifying the supply curve GID of
each site.
Expand All @@ -1635,7 +1635,7 @@ def __init__(self, excl_fpath, res_fpath, tm_dset, objective_function,
site-specific capital cost value for each location). Columns
that do not correspond to a config key may also be included,
but they will be ignored. The CSV file input can also have
these extra columns:
these extra, optional columns:
- ``capital_cost_multiplier``
- ``fixed_operating_cost_multiplier``
Expand Down
33 changes: 22 additions & 11 deletions reV/econ/econ.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,36 @@ def __init__(self, project_points, sam_files, cf_file, site_data=None,
(or slice) representing the GIDs of multiple sites can be
specified to evaluate reV at multiple specific locations.
A string pointing to a project points CSV file may also be
specified. Typically, the CSV contains two columns:
specified. Typically, the CSV contains the following
columns:
- ``gid``: Integer specifying the GID of each site.
- ``gid``: Integer specifying the generation GID of each
site.
- ``config``: Key in the `sam_files` input dictionary
(see below) corresponding to the SAM configuration to
use for each particular site. This value can also be
``None`` (or left out completely) if you specify only
a single SAM configuration file as the `sam_files`
input.
The CSV file may also contain site-specific inputs by
- ``capital_cost_multiplier``: This is an *optional*
multiplier input that, if included, will be used to
regionally scale the ``capital_cost`` input in the SAM
config. If you include this column in your CSV, you
*do not* need to specify ``capital_cost``, unless you
would like that value to vary regionally and
independently of the multiplier (i.e. the multiplier
will still be applied on top of the ``capital_cost``
input).
The CSV file may also contain other site-specific inputs by
including a column named after a config keyword (e.g. a
column called ``capital_cost`` may be included to specify a
site-specific capital cost value for each location). Columns
that do not correspond to a config key may also be included,
but they will be ignored. A DataFrame following the same
guidelines as the CSV input (or a dictionary that can be
used to initialize such a DataFrame) may be used for this
input as well.
column called ``wind_turbine_rotor_diameter`` may be
included to specify a site-specific turbine diameter for
each location). Columns that do not correspond to a config
key may also be included, but they will be ignored. A
DataFrame following the same guidelines as the CSV input
(or a dictionary that can be used to initialize such a
DataFrame) may be used for this input as well.
sam_files : dict | str
A dictionary mapping SAM input configuration ID(s) to SAM
configuration(s). Keys are the SAM config ID(s) which
Expand Down
29 changes: 19 additions & 10 deletions reV/generation/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def __init__(
multiple sites can be specified to evaluate reV at multiple
specific locations. A string pointing to a project points
CSV file may also be specified. Typically, the CSV contains
two columns:
the following columns:
- ``gid``: Integer specifying the generation GID of each
site.
Expand All @@ -181,16 +181,25 @@ def __init__(
``None`` (or left out completely) if you specify only
a single SAM configuration file as the `sam_files`
input.
The CSV file may also contain site-specific inputs by
- ``capital_cost_multiplier``: This is an *optional*
multiplier input that, if included, will be used to
regionally scale the ``capital_cost`` input in the SAM
config. If you include this column in your CSV, you
*do not* need to specify ``capital_cost``, unless you
would like that value to vary regionally and
independently of the multiplier (i.e. the multiplier
will still be applied on top of the ``capital_cost``
input).
The CSV file may also contain other site-specific inputs by
including a column named after a config keyword (e.g. a
column called ``capital_cost`` may be included to specify a
site-specific capital cost value for each location). Columns
that do not correspond to a config key may also be included,
but they will be ignored. A DataFrame following the same
guidelines as the CSV input (or a dictionary that can be
used to initialize such a DataFrame) may be used for this
input as well.
column called ``wind_turbine_rotor_diameter`` may be
included to specify a site-specific turbine diameter for
each location). Columns that do not correspond to a config
key may also be included, but they will be ignored. A
DataFrame following the same guidelines as the CSV input
(or a dictionary that can be used to initialize such a
DataFrame) may be used for this input as well.
.. Note:: By default, the generation GID of each site is
assumed to match the resource GID to be evaluated for that
Expand Down
4 changes: 4 additions & 0 deletions reV/supply_curve/points.py
Original file line number Diff line number Diff line change
Expand Up @@ -2537,6 +2537,10 @@ def summarize(
if cap_cost_scale is not None:
summary = point.economies_of_scale(cap_cost_scale, summary)

for arg, val in summary.items():
if val is None:
summary[arg] = np.nan

return summary


Expand Down
5 changes: 2 additions & 3 deletions reV/supply_curve/supply_curve.py
Original file line number Diff line number Diff line change
Expand Up @@ -1116,8 +1116,7 @@ def add_sum_cols(table, sum_cols):

return table

# pylint: disable=C901
def _full_sort(
def _full_sort( # noqa: C901
self,
trans_table,
trans_costs=None,
Expand Down Expand Up @@ -1289,7 +1288,7 @@ def _adjust_output_columns(self, columns, consider_friction):

for col in _REQUIRED_OUTPUT_COLS:
if col not in self._trans_table:
self._trans_table[col] = None
self._trans_table[col] = np.nan
if col not in columns:
columns.append(col)

Expand Down
2 changes: 1 addition & 1 deletion reV/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
reV Version number
"""

__version__ = "0.9.0"
__version__ = "0.9.1"
35 changes: 35 additions & 0 deletions tests/test_gen_geothermal.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ def test_gen_geothermal(depth, sample_resource_data):
"lcoe_fcr": 12.52,
"nameplate": 200_000,
"resource_temp": 150,
"capital_cost": 172485199.53989035,
"fixed_operating_cost": 4885201.7298879623,
"variable_operating_cost": 0,
"fixed_charge_rate": 0.098000000000000004,
"base_capital_cost": 172485199.53989035,
"base_fixed_operating_cost": 4885201.7298879623,
"base_variable_operating_cost": 0,
"system_capacity": 200_000,
}
for dset in output_request:
truth = truth_vals[dset]
Expand Down Expand Up @@ -156,6 +164,14 @@ def test_gen_geothermal_temp_too_low(sample_resource_data):
"lcoe_fcr": 0,
"nameplate": 0,
"resource_temp": 60,
"capital_cost": 0,
"fixed_operating_cost": 0,
"variable_operating_cost": 0,
"fixed_charge_rate": 0,
"base_capital_cost": 0,
"base_fixed_operating_cost": 0,
"base_variable_operating_cost": 0,
"system_capacity": 0,
}
for dset in output_request:
truth = truth_vals[dset]
Expand Down Expand Up @@ -207,7 +223,13 @@ def test_per_kw_cost_inputs(sample_resource_data):
truth_vals = {
"capital_cost": 383_086_656,
"fixed_operating_cost": 25539104,
"variable_operating_cost": 0,
"lcoe_fcr": 72.5092,
"fixed_charge_rate": 0.098000000000000004,
"base_capital_cost": 383_086_656,
"base_fixed_operating_cost": 25539104,
"base_variable_operating_cost": 0,
"system_capacity": 383_086_656 / 3_000,
}
for dset in output_request:
truth = truth_vals[dset]
Expand Down Expand Up @@ -257,7 +279,12 @@ def test_drill_cost_inputs(sample_resource_data):
truth_vals = {
"capital_cost": 466_134_733,
"fixed_operating_cost": 25539104,
"variable_operating_cost": 0,
"lcoe_fcr": 81.8643,
"fixed_charge_rate": 0.098000000000000004,
"base_capital_cost": 466_134_733,
"base_fixed_operating_cost": 25539104,
"base_variable_operating_cost": 0,
}
for dset in output_request:
truth = truth_vals[dset]
Expand Down Expand Up @@ -315,6 +342,14 @@ def test_gen_with_nameplate_input(sample_resource_data):
"lcoe_fcr": 62.613,
"nameplate": 40_000,
"resource_temp": 150,
"capital_cost": 172485199.53989035,
"fixed_operating_cost": 4885201.7298879623,
"variable_operating_cost": 0,
"fixed_charge_rate": 0.098000000000000004,
"base_capital_cost": 172485199.53989035,
"base_fixed_operating_cost": 4885201.7298879623,
"base_variable_operating_cost": 0,
"system_capacity": 40_000,
}
for dset in output_request:
truth = truth_vals[dset]
Expand Down

0 comments on commit e92af3a

Please sign in to comment.