Skip to content

Commit 59103ba

Browse files
Limit construction years = 1
1 parent 80299df commit 59103ba

File tree

4 files changed

+58
-13
lines changed

4 files changed

+58
-13
lines changed

docs/SAM-Economic-Models.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## SAM Single-Owner PPA
44

5+
### Parameters
6+
57
| GEOPHIRES Parameter(s) | SAM Category | SAM Input(s) | SAM Module(s) | SAM Parameter Name(s) | Comment |
68
|------------------------------------------------------|--------------------------------------------------------|----------------------------------------------------------------------------------|-----------------------------------|--------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
79
| `Max Net Electricity Production` | Generation Profile | `Nameplate capacity` | `Singleowner` | `system_capacity` | |
@@ -21,3 +23,8 @@
2123
| `Other Incentives` + `One-time Grants Etc` | Incentives → Investment Based Incentive (IBI) | `Other``Amount ($)` | `Singleowner` | `ibi_oth_amount` | |
2224

2325
[Implementation in source code](https://github.com/softwareengineerprogrammer/GEOPHIRES/blob/274786e6799d32dad3f42a2a04297818b811f24c/src/geophires_x/EconomicsSam.py#L135-L195)
26+
27+
### Limitations
28+
29+
1. Only Electricity end-use is supported
30+
2. Only 1 construction year is supported

src/geophires_x/Economics.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import numpy as np
55
import numpy_financial as npf
66
import geophires_x.Model as Model
7-
from geophires_x.EconomicsSam import calculate_sam_economics, _SAM_CASH_FLOW_PROFILE_KEY
7+
from geophires_x import EconomicsSam
8+
from geophires_x.EconomicsSam import calculate_sam_economics
89
from geophires_x.OptionList import Configuration, WellDrillingCostCorrelation, EconomicModel, EndUseOptions, PlantType, \
910
_WellDrillingCostCorrelationCitation
1011
from geophires_x.Parameter import intParameter, floatParameter, OutputParameter, ReadParameter, boolParameter, \
@@ -1947,13 +1948,8 @@ def _warn(_msg: str) -> None:
19471948
if ParameterToModify.Name == "Economic Model":
19481949
em: EconomicModel = EconomicModel.from_input_string(ParameterReadIn.sValue)
19491950

1950-
if (em == EconomicModel.SAM_SINGLE_OWNER_PPA
1951-
and model.surfaceplant.enduse_option.value != EndUseOptions.ELECTRICITY):
1952-
raise RuntimeError(f'Invalid End-Use Option '
1953-
f'({model.surfaceplant.enduse_option.value.value}) for '
1954-
f'{EconomicModel.SAM_SINGLE_OWNER_PPA.name} economic model. '
1955-
f'{EconomicModel.SAM_SINGLE_OWNER_PPA.name} only supports '
1956-
f'{EndUseOptions.ELECTRICITY.name} End-Use Option.')
1951+
if em == EconomicModel.SAM_SINGLE_OWNER_PPA:
1952+
EconomicsSam.validate_read_parameters(model)
19571953

19581954
self.econmodel.value = em
19591955

src/geophires_x/EconomicsSam.py

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,42 @@
2727
from geophires_x import Model as Model
2828
from geophires_x.EconomicsSamCashFlow import _calculate_sam_economics_cash_flow
2929
from geophires_x.GeoPHIRESUtils import is_float, is_int
30+
from geophires_x.OptionList import EconomicModel, EndUseOptions
3031
from geophires_x.Parameter import Parameter
3132
from geophires_x.Units import convertible_unit
3233

3334
_SAM_CASH_FLOW_PROFILE_KEY = 'Cash Flow'
3435
_GEOPHIRES_TO_SAM_PRICING_MODEL_RATE_CONVERSION_CONSTANT = 0.745
3536

3637

38+
def validate_read_parameters(model: Model):
39+
def _inv_msg(param_name: str, invalid_value: Any, supported_description: str) -> str:
40+
return (
41+
f'Invalid {param_name} ({invalid_value}) for '
42+
f'{EconomicModel.SAM_SINGLE_OWNER_PPA.name} economic model. '
43+
f'{EconomicModel.SAM_SINGLE_OWNER_PPA.name} only supports '
44+
f'{supported_description}.'
45+
)
46+
47+
if model.surfaceplant.enduse_option.value != EndUseOptions.ELECTRICITY:
48+
raise ValueError(
49+
_inv_msg(
50+
model.surfaceplant.enduse_option.Name,
51+
model.surfaceplant.enduse_option.value.value,
52+
f'{EndUseOptions.ELECTRICITY.name} End-Use Option',
53+
)
54+
)
55+
56+
if model.surfaceplant.construction_years.value != 1:
57+
raise ValueError(
58+
_inv_msg(
59+
model.surfaceplant.construction_years.Name,
60+
model.surfaceplant.construction_years.value,
61+
f'{model.surfaceplant.construction_years.Name} = 1',
62+
)
63+
)
64+
65+
3766
@lru_cache(maxsize=12)
3867
def calculate_sam_economics(model: Model) -> dict[str, dict[str, Any]]:
3968
custom_gen = CustomGeneration.new()
@@ -126,7 +155,12 @@ def get_entry_display(entry: Any) -> str:
126155

127156

128157
def _get_custom_gen_parameters(model: Model) -> dict[str, Any]:
129-
ret: dict[str, Any] = {'analysis_period': model.surfaceplant.plant_lifetime.value}
158+
# fmt:off
159+
ret: dict[str, Any] = {
160+
# Project lifetime
161+
'analysis_period': model.surfaceplant.plant_lifetime.value
162+
}
163+
# fmt:on
130164

131165
return ret
132166

@@ -164,10 +198,10 @@ def pct(econ_value: Parameter) -> float:
164198
# GEOPHIRES assumes O&M fixed costs are not affected by inflation
165199
ret['om_fixed_escal'] = -1.0 * pct(econ.RINFL)
166200

167-
# TODO project lifetime
168-
169201
# TODO construction years
170202

203+
# TODO 'Inflation Rate During Construction'
204+
171205
# Note generation profile is generated relative to the max in _get_utility_rate_parameters
172206
ret['system_capacity'] = _get_max_net_generation_MW(model) * 1e3
173207

@@ -205,6 +239,7 @@ def pct(econ_value: Parameter) -> float:
205239
# Interest rate
206240
ret['real_discount_rate'] = pct(econ.discountrate)
207241

242+
# Project lifetime
208243
ret['term_tenor'] = model.surfaceplant.plant_lifetime.value
209244
ret['term_int_rate'] = pct(econ.BIR)
210245

tests/geophires_x_tests/test_economics_sam.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,17 @@ def _get_cash_flow_row(cash_flow, name):
150150
)[1:]
151151

152152
def test_only_electricity_end_use_supported(self):
153-
with self.assertRaises(RuntimeError) as re:
153+
with self.assertRaises(RuntimeError) as e:
154154
self._get_result({'End-Use Option': 2})
155155

156-
self.assertIn('Invalid End-Use Option (Direct-Use Heat)', str(re.exception))
156+
self.assertIn('Invalid End-Use Option (Direct-Use Heat)', str(e.exception))
157+
158+
def test_only_1_construction_year_supported(self):
159+
with self.assertRaises(RuntimeError) as e:
160+
self._get_result({'Construction Years': 2})
161+
162+
self.assertIn('Invalid Construction Years (2)', str(e.exception))
163+
self.assertIn('SAM_SINGLE_OWNER_PPA only supports Construction Years = 1.', str(e.exception))
157164

158165
def test_property_tax_rate(self):
159166
pt_rate = 0.01

0 commit comments

Comments
 (0)