Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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.8.4
current_version = 3.8.6
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.8.4
version: 3.8.6
version_manager: "bump2version"
website: "https://github.com/NREL"
year_from: "2023"
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ GEOPHIRES-X (2023-2025)
Revenue & Cashflow Profile period output aligned with NREL convention used to calculate NPV.
See https://github.com/NREL/GEOPHIRES-X/discussions/344

3.8.6: Baseline well drilling cost curves updated to NREL's 2025 cost curve update:
Akindipe, D. and Witter. E. 2025. "2025 Geothermal Drilling Cost Curves Update". https://pangea.stanford.edu/ERE/db/GeoConf/papers/SGW/2025/Akindipe.pdf?t=1740084555.

Intermediate and ideal correlations retain existing values from GeoVision:
DOE 2019. "GeoVision" p. 163. https://www.energy.gov/sites/prod/files/2019/06/f63/GeoVision-full-report-opt.pdf.

3.7
^^^

Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,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.8.4.svg
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.8.6.svg
:alt: Commits since latest release
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.8.4...main
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.8.6...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 = '2025'
author = 'NREL'
copyright = f'{year}, {author}'
version = release = '3.8.4'
version = release = '3.8.6'

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.8.4',
version='3.8.6',
license='MIT',
description='GEOPHIRES is a free and open-source geothermal techno-economic simulator.',
long_description='{}\n{}'.format(
Expand Down
20 changes: 17 additions & 3 deletions src/geophires_x/Economics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import numpy as np
import numpy_financial as npf
import geophires_x.Model as Model
from geophires_x.OptionList import Configuration, WellDrillingCostCorrelation, EconomicModel, EndUseOptions, PlantType
from geophires_x.OptionList import Configuration, WellDrillingCostCorrelation, EconomicModel, EndUseOptions, PlantType, \
_WellDrillingCostCorrelationCitation
from geophires_x.Parameter import intParameter, floatParameter, OutputParameter, ReadParameter, boolParameter, \
coerce_int_params_to_enum_values
from geophires_x.Units import *
Expand Down Expand Up @@ -1004,9 +1005,15 @@ def __init__(self, model: Model):
UnitType=Units.NONE,
ErrMessage="assume default well drilling cost correlation (10)",
ToolTipText="Select the built-in well drilling and completion cost correlation: " +
'; '.join([f'{it.int_value}: {it.value}' for it in WellDrillingCostCorrelation])
)
'; '.join([f'{it.int_value}: {it.value}'
for it in WellDrillingCostCorrelation]) +
f'. '
f'Baseline correlations (1-4) are from '
f'{_WellDrillingCostCorrelationCitation.NREL_COST_CURVE_2025.value}.'
f' Intermediate and ideal correlations (6-17) are from '
f'{_WellDrillingCostCorrelationCitation.GEOVISION.value}.'

)
self.DoAddOnCalculations = self.ParameterDict[self.DoAddOnCalculations.Name] = boolParameter(
"Do AddOn Calculations",
DefaultValue=False,
Expand Down Expand Up @@ -1778,18 +1785,25 @@ def __init__(self, model: Model):
PreferredUnits=PercentUnit.PERCENT,
CurrentUnits=PercentUnit.PERCENT
)

# TODO this is displayed as "Project Net Revenue" in Revenue & Cashflow Profile which is probably not an
# accurate synonym for annual revenue
self.TotalRevenue = self.OutputParameterDict[self.TotalRevenue.Name] = OutputParameter(
Name="Annual Revenue from Project",
UnitType=Units.CURRENCYFREQUENCY,
PreferredUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR,
CurrentUnits=CurrencyFrequencyUnit.MDOLLARSPERYEAR
)

# TODO this is displayed as "Project Net Cashflow" in Revenue & Cashflow Profile which is probably not an
# accurate synonym for cumulative revenue
self.TotalCummRevenue = self.OutputParameterDict[self.TotalCummRevenue.Name] = OutputParameter(
Name="Cumulative Revenue from Project",
UnitType=Units.CURRENCY,
PreferredUnits=CurrencyUnit.MDOLLARS,
CurrentUnits=CurrencyUnit.MDOLLARS
)
Comment on lines +1789 to 1805
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Economics naming TODOs unrelated to main changes


self.ProjectNPV = self.OutputParameterDict[self.ProjectNPV.Name] = OutputParameter(
"Project Net Present Value",
UnitType=Units.CURRENCY,
Expand Down
6 changes: 3 additions & 3 deletions src/geophires_x/GeoPHIRESUtils.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def density_water_kg_per_m3(Twater_degC: float, pressure: Optional[PlainQuantity

except (NotImplementedError, ValueError) as e:
raise ValueError(f'Input temperature & pressure ({Twater_degC}, {pressure}) '
f'are out of range or otherwise could not be used to calculate') from e
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes in utils to water property exception messages are unrelated to drilling cost curves update

f'are out of range or otherwise could not be used to calculate water density.') from e


def celsius_to_kelvin(celsius: float) -> float:
Expand Down Expand Up @@ -298,7 +298,7 @@ def viscosity_water_Pa_sec(

except (NotImplementedError, ValueError) as e:
raise ValueError(f'Input temperature & pressure ({Twater_degC}, {pressure}) '
f'are out of range or otherwise could not be used to calculate') from e
f'are out of range or otherwise could not be used to calculate water viscosity.') from e


@lru_cache
Expand Down Expand Up @@ -334,7 +334,7 @@ def heat_capacity_water_J_per_kg_per_K(

except (NotImplementedError, ValueError) as e:
raise ValueError(f'Input temperature & pressure ({Twater_degC}, {pressure}) '
f'are out of range or otherwise could not be used to calculate') from e
f'are out of range or otherwise could not be used to calculate heat capacity of water.') from e


@lru_cache
Expand Down
109 changes: 78 additions & 31 deletions src/geophires_x/OptionList.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class EndUseOptions(GeophiresInputEnum):
COGENERATION_PARALLEL_EXTRA_ELECTRICITY = 52, "Cogeneration Parallel Cycle, Electricity sales considered as extra income"

@staticmethod
def from_input_string(input_string:str):
def from_input_string(input_string: str):
"""
:rtype: EndUseOptions
"""
Expand Down Expand Up @@ -66,7 +66,7 @@ class PlantType(GeophiresInputEnum):
INDUSTRIAL = 9, "Industrial"

@staticmethod
def from_input_string(input_string:str):
def from_input_string(input_string: str):
"""
:rtype: PlantType
"""
Expand Down Expand Up @@ -97,7 +97,7 @@ def from_int(int_val):
return member

@staticmethod
def from_input_string(input_string:str):
def from_input_string(input_string: str):
for member in __class__:
if input_string == str(member.int_value):
return member
Expand All @@ -117,7 +117,7 @@ class ReservoirModel(GeophiresInputEnum):
SBT = 8, "SBT"

@staticmethod
def get_reservoir_model_from_input_string(input_string:str):
def get_reservoir_model_from_input_string(input_string: str):
"""
:rtype: ReservoirModel
"""
Expand Down Expand Up @@ -148,41 +148,89 @@ def from_int(int_val):
return member

@staticmethod
def from_input_string(input_string:str):
def from_input_string(input_string: str):
for member in __class__:
if input_string == str(member.int_value):
return member

raise ValueError(f'Unknown Reservoir Volume input value: {input_string}')


class _WellDrillingCostCorrelationCitation(str, Enum):
"""
Values are abbreviated citations used in tooltip text.
Commented full citations are present in CHANGELOG and could also be used in future documentation.
"""

NREL_COST_CURVE_2025 = 'NREL\'s 2025 cost curve update'
# ('Akindipe, D. and Witter. E. 2025. '
# '"2025 Geothermal Drilling Cost Curves Update". '
# 'https://pangea.stanford.edu/ERE/db/GeoConf/papers/SGW/2025/Akindipe.pdf?t=1740084555')

SIMPLE = 'Based on Fervo Project Cape cost per meter (~$1846/m)'

GEOVISION = 'GeoVision'
# ('DOE 2019. '
# '"GeoVision" p. 163. '
# 'https://www.energy.gov/sites/prod/files/2019/06/f63/GeoVision-full-report-opt.pdf')


class WellDrillingCostCorrelation(GeophiresInputEnum):
"""Note: order must be retained since input is read as an int; first int arg is duplicative of order"""

VERTICAL_SMALL = 1, "vertical small diameter, baseline", 0.30212, 584.91124, 751368.47270
DEVIATED_SMALL = 2, "deviated small diameter, baseline", 0.28977, 882.15067, 680562.50150
VERTICAL_LARGE = 3, "vertical large diameter, baseline", 0.28180, 1275.52130, 632315.12640
DEVIATED_LARGE = 4, "deviated large diameter, baseline", 0.25528, 1716.71568, 500866.89110

SIMPLE = 5, "Simple", 0, 1846*1E6, 0 # Based on Fervo Project Cape cost per meter (~$1846/m)

VERTICAL_SMALL_INT1 = 6, "vertical small diameter, intermediate1", 0.13710, 129.61033, 1205587.57100
VERTICAL_SMALL_INT2 = 7, "vertical small diameter, intermediate2", 0.00804, 455.60507, 921007.68680
DEVIATED_SMALL_INT1 = 8, "deviated small diameter, intermediate1", 0.15340, 120.31700, 1431801.54400
DEVIATED_SMALL_INT2 = 9, "deviated small diameter, intermediate2", 0.00854, 506.08357, 1057330.39000
VERTICAL_LARGE_INT1 = 10, "vertical large diameter, intermediate1", 0.18927, 293.45174, 1326526.31300
VERTICAL_LARGE_INT2 = 11, "vertical large diameter, intermediate2", 0.00315, 782.69676, 983620.25270
DEVIATED_LARGE_INT1 = 12, "deviated large diameter, intermediate1", 0.19950, 296.13011, 1697867.70900
DEVIATED_LARGE_INT2 = 13, "deviated large diameter, intermediate2", 0.00380, 838.90249, 1181947.04400
VERTICAL_SMALL_IDEAL = 14, "vertical open-hole, small diameter, ideal", 0.00252, 439.44503, 590611.90110
DEVIATED_SMALL_IDEAL = 15, "deviated liner, small diameter, ideal", 0.00719, 455.85233, 753377.73080
VERTICAL_LARGE_IDEAL = 16, "vertical open-hole, large diameter, ideal", -0.00240, 752.93946, 524337.65380
DEVIATED_LARGE_IDEAL = 17, "deviated liner, large diameter, ideal", 0.00376, 762.52696, 765103.07690

def __init__(self, int_value: int, _: str, c2: float, c1: float, c0: float):
"""
Akindipe, D. and Witter. E. 2025.
"2025 Geothermal Drilling Cost Curves Update".
https://pangea.stanford.edu/ERE/db/GeoConf/papers/SGW/2025/Akindipe.pdf?t=1740084555

Robins, J.C., Kesseli, D., Witter, E. and Rhodes, G. 2022.
"2022 GETEM Geothermal Drilling Cost Curve Update."
https://www.nrel.gov/docs/fy23osti/82771.pdf

Note: order should be retained since input is read as an int; first int arg is duplicative of order
"""

VERTICAL_SMALL = 1, "vertical small diameter, baseline", 0.258496, 357.967, 738531.58, \
_WellDrillingCostCorrelationCitation.NREL_COST_CURVE_2025
DEVIATED_SMALL = 2, "deviated small diameter, baseline", 0.240624, 646.1621, 503625.06, \
_WellDrillingCostCorrelationCitation.NREL_COST_CURVE_2025
VERTICAL_LARGE = 3, "vertical large diameter, baseline", 0.248458, 935.8985, 626586.68, \
_WellDrillingCostCorrelationCitation.NREL_COST_CURVE_2025
DEVIATED_LARGE = 4, "deviated large diameter, baseline", 0.217333, 1362.93, 301066.16, \
_WellDrillingCostCorrelationCitation.NREL_COST_CURVE_2025

SIMPLE = 5, "Simple (per-meter cost)", 0, 1846 * 1E6, 0, \
_WellDrillingCostCorrelationCitation.SIMPLE

VERTICAL_SMALL_INT1 = 6, "vertical small diameter, intermediate1", 0.13710, 129.61033, 1205587.57100, \
_WellDrillingCostCorrelationCitation.GEOVISION
VERTICAL_SMALL_INT2 = 7, "vertical small diameter, intermediate2", 0.00804, 455.60507, 921007.68680, \
_WellDrillingCostCorrelationCitation.GEOVISION
DEVIATED_SMALL_INT1 = 8, "deviated small diameter, intermediate1", 0.15340, 120.31700, 1431801.54400, \
_WellDrillingCostCorrelationCitation.GEOVISION
DEVIATED_SMALL_INT2 = 9, "deviated small diameter, intermediate2", 0.00854, 506.08357, 1057330.39000, \
_WellDrillingCostCorrelationCitation.GEOVISION
VERTICAL_LARGE_INT1 = 10, "vertical large diameter, intermediate1", 0.18927, 293.45174, 1326526.31300, \
_WellDrillingCostCorrelationCitation.GEOVISION
VERTICAL_LARGE_INT2 = 11, "vertical large diameter, intermediate2", 0.00315, 782.69676, 983620.25270, \
_WellDrillingCostCorrelationCitation.GEOVISION
DEVIATED_LARGE_INT1 = 12, "deviated large diameter, intermediate1", 0.19950, 296.13011, 1697867.70900, \
_WellDrillingCostCorrelationCitation.GEOVISION
DEVIATED_LARGE_INT2 = 13, "deviated large diameter, intermediate2", 0.00380, 838.90249, 1181947.04400, \
_WellDrillingCostCorrelationCitation.GEOVISION
VERTICAL_SMALL_IDEAL = 14, "vertical open-hole, small diameter, ideal", 0.00252, 439.44503, 590611.90110, \
_WellDrillingCostCorrelationCitation.GEOVISION
DEVIATED_SMALL_IDEAL = 15, "deviated liner, small diameter, ideal", 0.00719, 455.85233, 753377.73080, \
_WellDrillingCostCorrelationCitation.GEOVISION
VERTICAL_LARGE_IDEAL = 16, "vertical open-hole, large diameter, ideal", -0.00240, 752.93946, 524337.65380, \
_WellDrillingCostCorrelationCitation.GEOVISION
DEVIATED_LARGE_IDEAL = 17, "deviated liner, large diameter, ideal", 0.00376, 762.52696, 765103.07690, \
_WellDrillingCostCorrelationCitation.GEOVISION

def __init__(self, int_value: int, _: str, c2: float, c1: float, c0: float,
citation: _WellDrillingCostCorrelationCitation):
self._c2 = c2
self._c1 = c1
self._c0 = c0
self.citation: _WellDrillingCostCorrelationCitation = citation
super().__init__(int_value, _)

def calculate_cost_MUSD(self, meters) -> float:
Expand Down Expand Up @@ -216,7 +264,7 @@ def from_int(int_val):
return member

@staticmethod
def from_input_string(input_string:str):
def from_input_string(input_string: str):
for member in __class__:
if input_string == str(member.int_value):
return member
Expand All @@ -243,8 +291,6 @@ def from_input_string(input_string: str):
raise ValueError(f'Unknown Working Fluid input value: {input_string}')




class Configuration(GeophiresInputEnum):
ULOOP = 1, "utube"
COAXIAL = 2, "coaxial"
Expand Down Expand Up @@ -285,6 +331,7 @@ def from_input_string(input_string: str):

raise ValueError(f'Unknown Flow Rate Model input value: {input_string}')


class InjectionTemperatureModel(GeophiresInputEnum):
USER_SUPPLIED = 1, "user supplied"
FILE_SUPPLIED = 2, "file supplied"
Expand Down
2 changes: 1 addition & 1 deletion src/geophires_x/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '3.8.4'
__version__ = '3.8.6'
4 changes: 2 additions & 2 deletions src/geophires_x_schema_generator/geophires-request.json
Original file line number Diff line number Diff line change
Expand Up @@ -1671,7 +1671,7 @@
"maximum": 1.0
},
"Well Drilling Cost Correlation": {
"description": "Select the built-in well drilling and completion cost correlation: 1: vertical small diameter, baseline; 2: deviated small diameter, baseline; 3: vertical large diameter, baseline; 4: deviated large diameter, baseline; 5: Simple; 6: vertical small diameter, intermediate1; 7: vertical small diameter, intermediate2; 8: deviated small diameter, intermediate1; 9: deviated small diameter, intermediate2; 10: vertical large diameter, intermediate1; 11: vertical large diameter, intermediate2; 12: deviated large diameter, intermediate1; 13: deviated large diameter, intermediate2; 14: vertical open-hole, small diameter, ideal; 15: deviated liner, small diameter, ideal; 16: vertical open-hole, large diameter, ideal; 17: deviated liner, large diameter, ideal",
"description": "Select the built-in well drilling and completion cost correlation: 1: vertical small diameter, baseline; 2: deviated small diameter, baseline; 3: vertical large diameter, baseline; 4: deviated large diameter, baseline; 5: Simple (per-meter cost); 6: vertical small diameter, intermediate1; 7: vertical small diameter, intermediate2; 8: deviated small diameter, intermediate1; 9: deviated small diameter, intermediate2; 10: vertical large diameter, intermediate1; 11: vertical large diameter, intermediate2; 12: deviated large diameter, intermediate1; 13: deviated large diameter, intermediate2; 14: vertical open-hole, small diameter, ideal; 15: deviated liner, small diameter, ideal; 16: vertical open-hole, large diameter, ideal; 17: deviated liner, large diameter, ideal. Baseline correlations (1-4) are from NREL's 2025 cost curve update. Intermediate and ideal correlations (6-17) are from GeoVision.",
"type": "integer",
"units": null,
"category": "Economics",
Expand Down Expand Up @@ -1701,7 +1701,7 @@
},
{
"name": "SIMPLE",
"value": "Simple",
"value": "Simple (per-meter cost)",
"int_value": 5
},
{
Expand Down
Loading