Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set fixed internal rate default value to same as discount rate #302

Merged
merged 19 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
14bc59d
Set discount rate = fixed internal rate = 6.25%, per https://github.c…
softwareengineerprogrammer Oct 10, 2024
c549c39
Convert units in all Outputs classes
softwareengineerprogrammer Oct 10, 2024
6bbea76
Update repo references in setup.py
softwareengineerprogrammer Oct 11, 2024
9047c65
Add OSX classifier in setup.py
softwareengineerprogrammer Oct 11, 2024
7c008fa
Temporarily disable fail-fast to debug Actions failures
softwareengineerprogrammer Oct 11, 2024
ffcb990
Unit registry preprocessor to attempt to fix percent unit issue in py…
softwareengineerprogrammer Oct 11, 2024
7f1fc0a
workaround pint's apparent inability to handle '%' as a unit in pytho…
softwareengineerprogrammer Oct 11, 2024
97c65d5
Try alternative preprocessor workaround for python3.8
softwareengineerprogrammer Oct 11, 2024
707ef39
use convertible_unit in conversions
softwareengineerprogrammer Oct 11, 2024
1aeb71d
PercentUnit.PERCENT convertible unit
softwareengineerprogrammer Oct 11, 2024
7fb804d
convertible_unit docstring. remove registry preprocessor since it app…
softwareengineerprogrammer Oct 11, 2024
f6e2645
Remove redundant comment
softwareengineerprogrammer Oct 11, 2024
04f9feb
Revert "Temporarily disable fail-fast to debug Actions failures"
softwareengineerprogrammer Oct 11, 2024
381f796
Merge pull request #37 from softwareengineerprogrammer/combine-discou…
softwareengineerprogrammer Oct 15, 2024
e49a1f5
Set default DR/FIR to 7% per sync discussion re: https://github.com/N…
softwareengineerprogrammer Oct 15, 2024
214cbe5
Regenerate schema with 7% FIR
softwareengineerprogrammer Oct 15, 2024
d4b7fc6
Sync csv test with updates
softwareengineerprogrammer Oct 15, 2024
48d0914
Bump version: 3.6.0 → 3.6.1
softwareengineerprogrammer Oct 15, 2024
0338348
Document 3.6.1 https://github.com/NREL/GEOPHIRES-X/issues/301 in CHAN…
softwareengineerprogrammer Oct 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.6.0
current_version = 3.6.1
commit = True
tag = True

Expand Down
2 changes: 1 addition & 1 deletion .cookiecutterrc
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ default_context:
sphinx_doctest: "no"
sphinx_theme: "sphinx-py3doc-enhanced-theme"
test_matrix_separate_coverage: "no"
version: 3.6.0
version: 3.6.1
version_manager: "bump2version"
website: "https://github.com/NREL"
year_from: "2023"
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ This affects:
Affected users who do not want the new behavior can specify absolute output paths instead of relative ones e.g. ``python ./geophires-x/GEOPHIRESv3.py my-input.txt /home/user/my-geophires-project/geophires-x/HDR.out``
(Most users are expected to be unaffected.)

3.6.1: Fixed Internal Rate default value changed to 7% from 6.25% per https://github.com/NREL/GEOPHIRES-X/issues/301

3.5
^^^

Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ Free software: `MIT license <LICENSE>`__
:alt: Supported implementations
:target: https://pypi.org/project/geophires-x

.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.6.0.svg
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.6.1.svg
:alt: Commits since latest release
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.6.0...main
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.6.1...main

.. |docs| image:: https://readthedocs.org/projects/GEOPHIRES-X/badge/?style=flat
:target: https://nrel.github.io/GEOPHIRES-X
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
year = '2024'
author = 'NREL'
copyright = f'{year}, {author}'
version = release = '3.6.0'
version = release = '3.6.1'

pygments_style = 'trac'
templates_path = ['./templates']
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def read(*names, **kwargs):

setup(
name='geophires-x',
version='3.6.0',
version='3.6.1',
license='MIT',
description='GEOPHIRES is a free and open-source geothermal techno-economic simulator.',
long_description='{}\n{}'.format(
Expand Down
4 changes: 2 additions & 2 deletions src/geophires_x/AGSEconomics.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ def read_parameters(self, model: Model) -> None:
# including the ones that are specific to this class

# inputs we already have - needs to be set at ReadParameter time so values set at the latest possible time
self.Discount_rate = model.economics.discountrate.value # same units are GEOPHIRES
self.Electricity_rate = model.surfaceplant.electricity_cost_to_buy.value # same units are GEOPHIRES
self.Discount_rate = model.economics.discountrate.value # same units as GEOPHIRES
self.Electricity_rate = model.surfaceplant.electricity_cost_to_buy.value # same units as GEOPHIRES

model.logger.info(f'complete {__class__!s}: {sys._getframe().f_code.co_name}')

Expand Down
30 changes: 6 additions & 24 deletions src/geophires_x/AGSOutputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@

import geophires_x

from .Parameter import ConvertUnitsBack, ConvertOutputUnits
from .OptionList import EndUseOptions, EconomicModel
from .Units import *
from geophires_x.OptionList import EndUseOptions, EconomicModel

import geophires_x.Model as Model
import geophires_x.Outputs as Outputs
import numpy as np

from geophires_x.Units import TemperatureUnit

NL = "\n"


Expand All @@ -28,27 +29,8 @@ def PrintOutputs(self, model: Model):
:return: None
"""
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')
# Deal with converting Units back to PreferredUnits, if required.
# before we write the outputs, we go thru all the parameters for all of the objects and set the values
# back to the units that the user entered the data in
# We do this because the value may be displayed in the output, and we want the user to recognize their value,
# not some converted value
for obj in [model.reserv, model.wellbores, model.surfaceplant, model.economics]:
for key in obj.ParameterDict:
param = obj.ParameterDict[key]
if not param.UnitsMatch:
ConvertUnitsBack(param, model)

# now we need to loop thru all the output parameters to update their units to whatever units the user has specified.
# i.e., they may have specified that all LENGTH results must be in feet, so we need to convert
# those from whatever LENGTH unit they are to feet.
# same for all the other classes of units (TEMPERATURE, DENSITY, etc).

for obj in [model.reserv, model.wellbores, model.surfaceplant, model.economics]:
for key in obj.OutputParameterDict:
if key in self.ParameterDict:
if self.ParameterDict[key] != obj.OutputParameterDict[key].CurrentUnits:
ConvertOutputUnits(obj.OutputParameterDict[key], self.ParameterDict[key], model)

self._convert_units(model)

# ---------------------------------------
# write results to output file and screen
Expand Down
17 changes: 11 additions & 6 deletions src/geophires_x/Economics.py
Original file line number Diff line number Diff line change
Expand Up @@ -837,15 +837,17 @@ def __init__(self, model: Model):
ErrMessage="assume default fixed charge rate (0.1)",
ToolTipText="Fixed charge rate (FCR) used in the Fixed Charge Rate Model"
)

discount_rate_default_val = 0.07
self.discountrate = self.ParameterDict[self.discountrate.Name] = floatParameter(
"Discount Rate",
DefaultValue=0.07,
DefaultValue=discount_rate_default_val,
Min=0.0,
Max=1.0,
UnitType=Units.PERCENT,
PreferredUnits=PercentUnit.TENTH,
PreferredUnits=PercentUnit.PERCENT,
CurrentUnits=PercentUnit.TENTH,
ErrMessage="assume default discount rate (0.07)",
ErrMessage=f'assume default discount rate ({discount_rate_default_val})',
ToolTipText="Discount rate used in the Standard Levelized Cost Model"
)
self.FIB = self.ParameterDict[self.FIB.Name] = floatParameter(
Expand Down Expand Up @@ -1379,15 +1381,18 @@ def __init__(self, model: Model):
PreferredUnits=CurrencyUnit.MDOLLARS,
CurrentUnits=CurrencyUnit.MDOLLARS
)

fir_default_unit = PercentUnit.PERCENT
fir_default_val = self.discountrate.quantity().to(convertible_unit(fir_default_unit)).magnitude
self.FixedInternalRate = self.ParameterDict[self.FixedInternalRate.Name] = floatParameter(
"Fixed Internal Rate",
DefaultValue=6.25,
DefaultValue=fir_default_val,
Min=0.0,
Max=100.0,
UnitType=Units.PERCENT,
PreferredUnits=PercentUnit.PERCENT,
CurrentUnits=PercentUnit.PERCENT,
ErrMessage="assume default for fixed internal rate (6.25%)",
CurrentUnits=fir_default_unit,
ErrMessage=f'assume default for fixed internal rate ({fir_default_val}%)',
ToolTipText="Fixed Internal Rate (used in NPV calculation)"
)
self.CAPEX_heat_electricity_plant_ratio = self.ParameterDict[self.CAPEX_heat_electricity_plant_ratio.Name] = floatParameter(
Expand Down
2 changes: 2 additions & 0 deletions src/geophires_x/GEOPHIRES3_newunits.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
USD = [currency]
cents = USD / 100
KUSD = USD * 1000
MMBTU = BTU * 1_000_000
4 changes: 2 additions & 2 deletions src/geophires_x/GeoPHIRESUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import CoolProp.CoolProp as CP

from geophires_x.Parameter import ParameterEntry, Parameter
from geophires_x.Units import get_unit_registry
from geophires_x.Units import get_unit_registry, convertible_unit

_logger = logging.getLogger('root') # TODO use __name__ instead of root

Expand Down Expand Up @@ -224,7 +224,7 @@ def quantity(value: float, unit: str) -> PlainQuantity:
:rtype: pint.registry.Quantity - note type annotation uses PlainQuantity due to issues with python 3.8 failing
to import the Quantity TypeAlias
"""
return _ureg.Quantity(value, unit)
return _ureg.Quantity(value, convertible_unit(unit))


@lru_cache
Expand Down
27 changes: 17 additions & 10 deletions src/geophires_x/Outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,15 +744,7 @@ def read_parameters(self, model: Model, default_output_path: Path = None) -> Non

model.logger.info(f'Complete {__class__!s}: {__name__}')

def PrintOutputs(self, model: Model):
"""
PrintOutputs writes the standard outputs to the output file.
:param model: The container class of the application, giving access to everything else, including the logger
:type model: :class:`~geophires_x.Model.Model`
:return: None
"""
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')

def _convert_units(self, model: Model):
# Deal with converting Units back to PreferredUnits, if required.
# before we write the outputs, we go thru all the parameters for all of the objects and set the values back
# to the units that the user entered the data in
Expand All @@ -779,6 +771,17 @@ def PrintOutputs(self, model: Model):
elif not output_param.UnitsMatch:
obj.OutputParameterDict[key] = output_param.with_preferred_units()

def PrintOutputs(self, model: Model):
"""
PrintOutputs writes the standard outputs to the output file.
:param model: The container class of the application, giving access to everything else, including the logger
:type model: :class:`~geophires_x.Model.Model`
:return: None
"""
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')

self._convert_units(model)

#data structures and assignments for HTML and Improved Text Output formats
simulation_metadata = []
summary = []
Expand Down Expand Up @@ -1634,7 +1637,11 @@ def PrintOutputs(self, model: Model):
f.write(f' Fixed Charge Rate (FCR): {model.economics.FCR.value*100.0:10.2f} ' + model.economics.FCR.CurrentUnits.value + NL)
elif model.economics.econmodel.value == EconomicModel.STANDARDIZED_LEVELIZED_COST:
f.write(' Economic Model = ' + model.economics.econmodel.value.value + NL)
f.write(f' Interest Rate: {model.economics.discountrate.value*100.0:10.2f} ' + model.economics.discountrate.CurrentUnits.value + NL)

# FIXME discountrate should not be multiplied by 100 here -
# it appears to be incorrectly claiming its units are percent when the actual value is in tenths.
f.write(f' Interest Rate: {model.economics.discountrate.value*100.0:10.2f} {model.economics.discountrate.CurrentUnits.value}\n')

elif model.economics.econmodel.value == EconomicModel.BICYCLE:
f.write(' Economic Model = ' + model.economics.econmodel.value.value + NL)
f.write(f' Accrued financing during construction: {model.economics.inflrateconstruction.value*100:10.2f} ' + model.economics.inflrateconstruction.CurrentUnits.value + NL)
Expand Down
2 changes: 2 additions & 0 deletions src/geophires_x/OutputsAddOns.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def PrintOutputs(self, model) -> tuple:
"""
model.logger.info(f'Init {str(__class__)}: {__name__}')

self._convert_units(model)

# now do AddOn output, which will append to the original output
# write results to output file and screen
try:
Expand Down
4 changes: 3 additions & 1 deletion src/geophires_x/OutputsCCUS.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ def PrintOutputs(self, model):
:type model: :class:`~geophires_x.Model.Model`
:return: Nothing
"""
model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name)
model.logger.info(f'Init {__class__!s}: sys._getframe().f_code.co_name')

self._convert_units(model)

if np.sum(model.ccuseconomics.CCUSRevenue.value) == 0:
return # don't bother if we have nothing to report.
Expand Down
2 changes: 2 additions & 0 deletions src/geophires_x/OutputsS_DAC_GT.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ def PrintOutputs(self, model) -> tuple:
"""
model.logger.info(f'Init {str(__class__)}: {__name__}')

self._convert_units(model)

# now do S_DAC_GT output, which will append to the original output
# write results to output file and screen
try:
Expand Down
6 changes: 3 additions & 3 deletions src/geophires_x/Parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def UnitsMatch(self) -> str:

def with_preferred_units(self) -> Any: # Any is a proxy for Self
ret: OutputParameter = dataclasses.replace(self)
ret.value = ret.quantity().to(ret.PreferredUnits).magnitude
ret.value = ret.quantity().to(convertible_unit(ret.PreferredUnits)).magnitude
ret.CurrentUnits = ret.PreferredUnits
return ret

Expand Down Expand Up @@ -609,7 +609,7 @@ def ConvertUnitsBack(ParamToModify: Parameter, model):
model.logger.info(f'Init {str(__name__)}: {sys._getframe().f_code.co_name} for {ParamToModify.Name}')

try:
ParamToModify.value = _ureg.Quantity(ParamToModify.value, ParamToModify.CurrentUnits.value).to(ParamToModify.PreferredUnits.value).magnitude
ParamToModify.value = _ureg.Quantity(ParamToModify.value, convertible_unit(ParamToModify.CurrentUnits)).to(convertible_unit(ParamToModify.PreferredUnits)).magnitude
ParamToModify.CurrentUnits = ParamToModify.PreferredUnits
except AttributeError as ae:
# TODO refactor to check for/convert currency instead of relying on try/except once currency conversion is
Expand Down Expand Up @@ -848,7 +848,7 @@ def ConvertOutputUnits(oparam: OutputParameter, newUnit: Units, model):
"""

try:
oparam.value = _ureg.Quantity(oparam.value, oparam.CurrentUnits.value).to(newUnit.value).magnitude
oparam.value = _ureg.Quantity(oparam.value, oparam.CurrentUnits.value).to(convertible_unit(newUnit.value)).magnitude
oparam.CurrentUnits = newUnit
return
except AttributeError as ae:
Expand Down
13 changes: 0 additions & 13 deletions src/geophires_x/SUTRAEconomics.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,19 +111,6 @@ def __init__(self, model: Model):
ToolTipText="Multiplier for built-in surface plant capital cost correlation",
)

self.discountrate = self.ParameterDict[self.discountrate.Name] = floatParameter(
"Discount Rate",
value=0.07,
DefaultValue=0.07,
Min=0.0,
Max=1.0,
UnitType=Units.PERCENT,
PreferredUnits=PercentUnit.PERCENT,
CurrentUnits=PercentUnit.TENTH,
ErrMessage="assume default discount rate (0.07)",
ToolTipText="Discount rate used in the Standard Levelized Cost Model",
)

self.inflrateconstruction = self.ParameterDict[self.inflrateconstruction.Name] = floatParameter(
"Inflation Rate During Construction",
value=0.0,
Expand Down
12 changes: 9 additions & 3 deletions src/geophires_x/SUTRAOutputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
import sys

import geophires_x
import numpy as np
import geophires_x.Model as Model
from geophires_x.Outputs import Outputs
from .OptionList import EconomicModel
from geophires_x.OptionList import EconomicModel

import numpy as np

NL="\n"

Expand Down Expand Up @@ -47,6 +48,7 @@ def PrintOutputs(self, model: Model):
"""
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')

self._convert_units(model)

# write results to output file and screen
try:
Expand Down Expand Up @@ -83,7 +85,11 @@ def PrintOutputs(self, model: Model):
f.write(f" Fixed Charge Rate (FCR): {model.economics.FCR.value*100.0:10.2f} " + model.economics.FCR.CurrentUnits.value + NL)
elif model.economics.econmodel.value == EconomicModel.STANDARDIZED_LEVELIZED_COST:
f.write(" Economic Model = " + model.economics.econmodel.value.value + NL)
f.write(f" Interest Rate: {model.economics.discountrate.value*100.0:10.2f} " + model.economics.discountrate.PreferredUnits.value + NL)

# FIXME discountrate should not be multiplied by 100 here -
# it appears to be incorrectly claiming its units are percent when the actual value is in tenths.
f.write(f" Interest Rate: {model.economics.discountrate.value*100.0:10.2f} {model.economics.discountrate.CurrentUnits.value}\n")

elif model.economics.econmodel.value == EconomicModel.BICYCLE:
f.write(" Economic Model = " + model.economics.econmodel.value.value + NL)
f.write(f" Accrued financing during construction: {model.economics.inflrateconstruction.value*100:10.2f} " + model.economics.inflrateconstruction.PreferredUnits.value + NL)
Expand Down
Loading