|
2 | 2 |
|
3 | 3 | import json |
4 | 4 | import os |
| 5 | +from dataclasses import dataclass, field |
5 | 6 | from functools import lru_cache |
6 | 7 | from math import isnan |
7 | 8 | from pathlib import Path |
|
22 | 23 |
|
23 | 24 | # noinspection PyPackageRequirements |
24 | 25 | import PySAM.Utilityrate5 as UtilityRate |
| 26 | +from pint.facets.plain import PlainQuantity |
25 | 27 | from tabulate import tabulate |
26 | 28 |
|
27 | 29 | from geophires_x import Model as Model |
28 | 30 | from geophires_x.EconomicsSamCashFlow import _calculate_sam_economics_cash_flow |
29 | 31 | from geophires_x.EconomicsUtils import BuildPricingModel |
30 | 32 | from geophires_x.GeoPHIRESUtils import is_float, is_int |
31 | 33 | from geophires_x.OptionList import EconomicModel, EndUseOptions |
32 | | -from geophires_x.Parameter import Parameter |
33 | | -from geophires_x.Units import convertible_unit |
| 34 | +from geophires_x.Parameter import Parameter, HasQuantity, OutputParameter |
| 35 | +from geophires_x.Units import convertible_unit, EnergyCostUnit, CurrencyUnit, Units, PercentUnit |
34 | 36 |
|
35 | | -_SAM_CASH_FLOW_PROFILE_KEY = 'Cash Flow' |
| 37 | + |
| 38 | +@dataclass |
| 39 | +class SamEconomics: |
| 40 | + sam_cash_flow_profile: list[list[Any]] |
| 41 | + |
| 42 | + lcoe_nominal: OutputParameter = field( |
| 43 | + default_factory=lambda: OutputParameter( |
| 44 | + UnitType=Units.ENERGYCOST, |
| 45 | + CurrentUnits=EnergyCostUnit.CENTSSPERKWH, |
| 46 | + ) |
| 47 | + ) |
| 48 | + capex: OutputParameter = field( |
| 49 | + default_factory=lambda: OutputParameter( |
| 50 | + UnitType=Units.CURRENCY, |
| 51 | + CurrentUnits=CurrencyUnit.MDOLLARS, |
| 52 | + ) |
| 53 | + ) |
| 54 | + project_npv: OutputParameter = field( |
| 55 | + default_factory=lambda: OutputParameter( |
| 56 | + UnitType=Units.CURRENCY, |
| 57 | + CurrentUnits=CurrencyUnit.MDOLLARS, |
| 58 | + ) |
| 59 | + ) |
| 60 | + project_irr: OutputParameter = field( |
| 61 | + default_factory=lambda: OutputParameter( |
| 62 | + UnitType=Units.PERCENT, |
| 63 | + CurrentUnits=PercentUnit.PERCENT, |
| 64 | + ) |
| 65 | + ) |
36 | 66 |
|
37 | 67 |
|
38 | 68 | def validate_read_parameters(model: Model): |
@@ -63,8 +93,14 @@ def _inv_msg(param_name: str, invalid_value: Any, supported_description: str) -> |
63 | 93 | ) |
64 | 94 |
|
65 | 95 |
|
| 96 | +class _Quantity(HasQuantity): |
| 97 | + def __init__(self, value: Any, units: str) -> None: |
| 98 | + self.value = value |
| 99 | + self.units = units |
| 100 | + |
| 101 | + |
66 | 102 | @lru_cache(maxsize=12) |
67 | | -def calculate_sam_economics(model: Model) -> dict[str, dict[str, Any]]: |
| 103 | +def calculate_sam_economics(model: Model) -> SamEconomics: |
68 | 104 | custom_gen = CustomGeneration.new() |
69 | 105 | grid = Grid.from_existing(custom_gen) |
70 | 106 | utility_rate = UtilityRate.from_existing(custom_gen) |
@@ -97,25 +133,16 @@ def calculate_sam_economics(model: Model) -> dict[str, dict[str, Any]]: |
97 | 133 |
|
98 | 134 | cash_flow = _calculate_sam_economics_cash_flow(model, single_owner) |
99 | 135 |
|
100 | | - data = [ |
101 | | - ('LCOE (nominal)', single_owner.Outputs.lcoe_nom, 'cents/kWh'), |
102 | | - ('IRR', single_owner.Outputs.project_return_aftertax_irr, '%'), |
103 | | - ('NPV', single_owner.Outputs.project_return_aftertax_npv * 1e-6, 'MUSD'), |
104 | | - ('CAPEX', single_owner.Outputs.adjusted_installed_cost * 1e-6, 'MUSD'), |
105 | | - (_SAM_CASH_FLOW_PROFILE_KEY, cash_flow, None), |
106 | | - ] |
107 | | - |
108 | | - ret = {} |
109 | | - for e in data: |
110 | | - key = e[0] |
| 136 | + def sf(_v: float) -> float: |
| 137 | + return _sig_figs(_v, 5) |
111 | 138 |
|
112 | | - as_val = e[1] |
113 | | - if key != _SAM_CASH_FLOW_PROFILE_KEY: |
114 | | - as_val = {'value': _sig_figs(e[1], 5), 'unit': e[2]} |
| 139 | + sam_economics: SamEconomics = SamEconomics(sam_cash_flow_profile=cash_flow) |
| 140 | + sam_economics.lcoe_nominal.value = sf(single_owner.Outputs.lcoe_nom) |
| 141 | + sam_economics.project_irr.value = sf(single_owner.Outputs.project_return_aftertax_irr) |
| 142 | + sam_economics.project_npv.value = sf(single_owner.Outputs.project_return_aftertax_npv * 1e-6) |
| 143 | + sam_economics.capex.value = single_owner.Outputs.adjusted_installed_cost * 1e-6 |
115 | 144 |
|
116 | | - ret[key] = as_val |
117 | | - |
118 | | - return ret |
| 145 | + return sam_economics |
119 | 146 |
|
120 | 147 |
|
121 | 148 | def get_sam_cash_flow_profile_tabulated_output(model: Model, **tabulate_kw_args) -> str: |
@@ -143,7 +170,7 @@ def get_entry_display(entry: Any) -> str: |
143 | 170 | return entry_display |
144 | 171 | return entry |
145 | 172 |
|
146 | | - profile_display = model.economics.sam_economics.value[_SAM_CASH_FLOW_PROFILE_KEY].copy() |
| 173 | + profile_display = model.economics.sam_economics.sam_cash_flow_profile.copy() |
147 | 174 | for i in range(len(profile_display)): |
148 | 175 | for j in range(len(profile_display[i])): |
149 | 176 | profile_display[i][j] = get_entry_display(profile_display[i][j]) |
|
0 commit comments