Skip to content

Commit 05a768b

Browse files
Include Nominal Discount Rate in output
1 parent 23c34ec commit 05a768b

File tree

7 files changed

+61
-18
lines changed

7 files changed

+61
-18
lines changed

src/geophires_x/Economics.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import geophires_x.Model as Model
66
from geophires_x import EconomicsSam
77
from geophires_x.EconomicsSam import calculate_sam_economics, SamEconomicsCalculations
8-
from geophires_x.EconomicsUtils import BuildPricingModel, wacc_output_parameter
8+
from geophires_x.EconomicsUtils import BuildPricingModel, wacc_output_parameter, nominal_discount_rate_parameter
99
from geophires_x.OptionList import Configuration, WellDrillingCostCorrelation, EconomicModel, EndUseOptions, PlantType, \
1010
_WellDrillingCostCorrelationCitation
1111
from geophires_x.Parameter import intParameter, floatParameter, OutputParameter, ReadParameter, boolParameter, \
@@ -1775,6 +1775,9 @@ def __init__(self, model: Model):
17751775
CurrentUnits=PercentUnit.PERCENT
17761776
)
17771777

1778+
self.nominal_discount_rate = self.OutputParameterDict[self.nominal_discount_rate.Name] = (
1779+
nominal_discount_rate_parameter())
1780+
17781781
self.wacc = self.OutputParameterDict[self.wacc.Name] = wacc_output_parameter()
17791782

17801783
# TODO this is displayed as "Project Net Revenue" in Revenue & Cashflow Profile which is probably not an
@@ -2758,6 +2761,8 @@ def Calculate(self, model: Model) -> None:
27582761
non_calculated_output_placeholder_val = -1
27592762
if self.econmodel.value == EconomicModel.SAM_SINGLE_OWNER_PPA:
27602763
self.sam_economics_calculations = calculate_sam_economics(model)
2764+
self.wacc.value = self.sam_economics_calculations.wacc.value
2765+
self.nominal_discount_rate.value = self.sam_economics_calculations.nominal_discount_rate.value
27612766
self.ProjectNPV.value = self.sam_economics_calculations.project_npv.quantity().to(
27622767
convertible_unit(self.ProjectNPV.CurrentUnits)).magnitude
27632768
self.ProjectIRR.value = self.sam_economics_calculations.project_irr.quantity().to(

src/geophires_x/EconomicsSam.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727

2828
from geophires_x import Model as Model
2929
from geophires_x.EconomicsSamCashFlow import _calculate_sam_economics_cash_flow
30-
from geophires_x.EconomicsUtils import BuildPricingModel, wacc_output_parameter
30+
from geophires_x.EconomicsUtils import BuildPricingModel, wacc_output_parameter, nominal_discount_rate_parameter
3131
from geophires_x.GeoPHIRESUtils import is_float, is_int
3232
from geophires_x.OptionList import EconomicModel, EndUseOptions
3333
from geophires_x.Parameter import Parameter, OutputParameter, floatParameter
@@ -63,6 +63,8 @@ class SamEconomicsCalculations:
6363
)
6464
)
6565

66+
nominal_discount_rate: OutputParameter = field(default_factory=nominal_discount_rate_parameter)
67+
6668
wacc: OutputParameter = field(default_factory=wacc_output_parameter)
6769

6870

@@ -159,27 +161,32 @@ def sf(_v: float) -> float:
159161
sam_economics.project_npv.value = sf(single_owner.Outputs.project_return_aftertax_npv * 1e-6)
160162
sam_economics.capex.value = single_owner.Outputs.adjusted_installed_cost * 1e-6
161163

162-
sam_economics.wacc.value = _calculate_wacc(model, single_owner)
164+
sam_economics.nominal_discount_rate.value, sam_economics.wacc.value = _calculate_nominal_discount_rate_and_wacc(
165+
model, single_owner
166+
)
163167

164168
return sam_economics
165169

166170

167-
def _calculate_wacc(model: Model, single_owner: Singleowner) -> float:
171+
def _calculate_nominal_discount_rate_and_wacc(model: Model, single_owner: Singleowner) -> tuple[float]:
168172
"""
169173
Calculation per SAM Help -> Financial Parameters -> Commercial -> Commercial Loan Parameters -> WACC
174+
175+
:return: tuple of Nominal Discount Rate (%), WACC (%)
170176
"""
171177

172178
econ = model.economics
173-
nominal_discount_rate = ((1 + econ.discountrate.value) * (1 + econ.RINFL.value) - 1) * 100
179+
nominal_discount_rate_pct = ((1 + econ.discountrate.value) * (1 + econ.RINFL.value) - 1) * 100
174180
fed_tax_rate = max(single_owner.Outputs.cf_federal_tax_frac)
175181
state_tax_rate = max(single_owner.Outputs.cf_state_tax_frac)
176182
effective_tax_rate = (fed_tax_rate * (1 - state_tax_rate) + state_tax_rate) * 100
177183
debt_fraction = single_owner.Outputs.debt_fraction / 100
178-
wacc = (
179-
nominal_discount_rate / 100 * (1 - debt_fraction)
184+
wacc_pct = (
185+
nominal_discount_rate_pct / 100 * (1 - debt_fraction)
180186
+ debt_fraction * econ.BIR.value * (1 - effective_tax_rate / 100)
181187
) * 100
182-
return wacc
188+
189+
return nominal_discount_rate_pct, wacc_pct
183190

184191

185192
def get_sam_cash_flow_profile_tabulated_output(model: Model, **tabulate_kw_args) -> str:

src/geophires_x/EconomicsUtils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,16 @@ def wacc_output_parameter() -> OutputParameter:
5252
CurrentUnits=PercentUnit.PERCENT,
5353
PreferredUnits=PercentUnit.PERCENT,
5454
)
55+
56+
57+
def nominal_discount_rate_parameter() -> OutputParameter:
58+
return OutputParameter(
59+
Name="Nominal Discount Rate",
60+
ToolTipText="Nominal Discount Rate is displayed for SAM Economic Models. "
61+
"It is calculated according to the following formula, defined in SAM Help documentation: "
62+
"Nominal Discount Rate = [ ( 1 + Real Discount Rate ÷ 100 ) "
63+
"× ( 1 + Inflation Rate ÷ 100 ) - 1 ] × 100.",
64+
UnitType=Units.PERCENT,
65+
CurrentUnits=PercentUnit.PERCENT,
66+
PreferredUnits=PercentUnit.PERCENT,
67+
)

src/geophires_x/Outputs.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -252,14 +252,25 @@ def PrintOutputs(self, model: Model):
252252
f.write(f' Economic Model = {model.economics.econmodel.value.value}\n')
253253

254254
if model.economics.econmodel.value == EconomicModel.SAM_SINGLE_OWNER_PPA:
255-
# TODO disambiguate interest rate for all economic models - see
256-
# https://github.com/softwareengineerprogrammer/GEOPHIRES/commit/535c02d4adbeeeca553b61e9b996fccf00016529
257-
ir_fl = Outputs._field_label(econ.interest_rate.Name, 49)
258-
f.write(f' {ir_fl}{econ.interest_rate.value:10.2f} {econ.interest_rate.CurrentUnits.value}\n')
259-
260-
wacc = econ.sam_economics_calculations.wacc
261-
wacc_fl = Outputs._field_label(wacc.Name, 49)
262-
f.write(f' {wacc_fl}{wacc.value:10.2f} {wacc.CurrentUnits.value}\n')
255+
fields : list[OutputParameter] = [
256+
# TODO disambiguate interest rate for all economic models - see
257+
# https://github.com/softwareengineerprogrammer/GEOPHIRES/commit/535c02d4adbeeeca553b61e9b996fccf00016529
258+
econ.interest_rate,
259+
260+
econ.nominal_discount_rate,
261+
econ.wacc,
262+
]
263+
264+
for field in fields:
265+
label = Outputs._field_label(field.Name, 49)
266+
f.write(f' {label}{field.value:10.2f} {field.CurrentUnits.value}\n')
267+
268+
# ir_fl = Outputs._field_label(econ.interest_rate.Name, 49)
269+
# f.write(f' {ir_fl}{econ.interest_rate.value:10.2f} {econ.interest_rate.CurrentUnits.value}\n')
270+
#
271+
# wacc = econ.sam_economics_calculations.wacc
272+
# wacc_fl = Outputs._field_label(wacc.Name, 49)
273+
# f.write(f' {wacc_fl}{wacc.value:10.2f} {wacc.CurrentUnits.value}\n')
263274

264275
# FIXME TODO unit is missing https://github.com/NREL/GEOPHIRES-X/issues/382
265276
f.write(f' Accrued financing during construction: {model.economics.inflrateconstruction.value*100:10.2f} {model.economics.inflrateconstruction.CurrentUnits.value}\n')

src/geophires_x_client/geophires_x_result.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class GeophiresXResult:
6868
_EqualSignDelimitedField('Economic Model'),
6969
'Interest Rate', # %
7070
'WACC',
71+
'Nominal Discount Rate',
7172
'Accrued financing during construction',
7273
'Project lifetime',
7374
'Capacity factor',

src/geophires_x_schema_generator/geophires-result.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@
7979
"description": "Weighted Average Cost of Capital displayed for SAM Economic Models. It is calculated according to the following formula, defined in SAM Help documentation: WACC = [ Nominal Discount Rate \u00f7 100 \u00d7 (1 - Debt Percent \u00f7 100) + Debt Percent \u00f7 100 \u00d7 Loan Rate \u00f7 100 \u00d7 (1 - Effective Tax Rate \u00f7 100 ) ] \u00d7 100; Effective Tax Rate = [ Federal Tax Rate \u00f7 100 \u00d7 ( 1 - State Tax Rate \u00f7 100 ) + State Tax Rate \u00f7 100 ] \u00d7 100; Nominal Discount Rate = [ ( 1 + Real Discount Rate \u00f7 100 ) \u00d7 ( 1 + Inflation Rate \u00f7 100 ) - 1 ] \u00d7 100. ",
8080
"units": "%"
8181
},
82+
"Nominal Discount Rate": {
83+
"type": "number",
84+
"description": "Nominal Discount Rate is displayed for SAM Economic Models. It is calculated according to the following formula, defined in SAM Help documentation: Nominal Discount Rate = [ ( 1 + Real Discount Rate \u00f7 100 ) \u00d7 ( 1 + Inflation Rate \u00f7 100 ) - 1 ] \u00d7 100.",
85+
"units": "%"
86+
},
8287
"Accrued financing during construction": {},
8388
"Project lifetime": {},
8489
"Capacity factor": {},

tests/examples/example_SAM-single-owner-PPA.out

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ Simulation Metadata
66
----------------------
77
GEOPHIRES Version: 3.9.6
88
Simulation Date: 2025-05-14
9-
Simulation Time: 10:30
10-
Calculation Time: 0.883 sec
9+
Simulation Time: 11:19
10+
Calculation Time: 0.880 sec
1111

1212
***SUMMARY OF RESULTS***
1313

@@ -26,6 +26,7 @@ Simulation Metadata
2626
Economic Model = SAM Single Owner PPA
2727
Interest Rate: 7.00 %
2828
WACC: 6.41 %
29+
Nominal Discount Rate: 9.14 %
2930
Accrued financing during construction: 5.00
3031
Project lifetime: 20 yr
3132
Capacity factor: 90.0 %

0 commit comments

Comments
 (0)