Skip to content

Commit

Permalink
Merge pull request NREL#231 from softwareengineerprogrammer/main
Browse files Browse the repository at this point in the history
Consolidate well drilling cost correlations into single definition; GEOPHIRES Version metadata; heating price output fix [3.4.34]
  • Loading branch information
softwareengineerprogrammer authored Jun 18, 2024
2 parents becec79 + 232e7c7 commit 90ff58b
Show file tree
Hide file tree
Showing 25 changed files with 1,309 additions and 676 deletions.
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.4.30
current_version = 3.4.34
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.4.30
version: 3.4.34
version_manager: "bump2version"
website: "https://github.com/NREL"
year_from: "2023"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pip-log.txt
coverage.xml
htmlcov
nosetests.xml
--cov-report=term-missing

# Translations
*.mo
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,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.4.30.svg
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.4.34.svg
:alt: Commits since latest release
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.4.30...main
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.4.34...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 = '2023'
author = 'NREL'
copyright = f'{year}, {author}'
version = release = '3.4.30'
version = release = '3.4.34'

pygments_style = 'trac'
templates_path = ['./templates']
Expand Down
7 changes: 4 additions & 3 deletions 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.4.30',
version='3.4.34',
license='MIT',
description='GEOPHIRES is a free and open-source geothermal techno-economic simulator.',
long_description='{}\n{}'.format(
Expand Down Expand Up @@ -59,9 +59,10 @@ def read(*names, **kwargs):
'Documentation': 'https://nrel.github.io/python-geophires-x-nrel/',
},
keywords=['geothermal'],
python_requires='>=3.7',
python_requires='>=3.8',
install_requires=[
'numpy',
'numpy==1.24; python_version == "3.8"', # Last version compatible with Python 3.8
'numpy==1.26; python_version > "3.8"',
'numpy-financial',
'pint',
'forex_python',
Expand Down
92 changes: 9 additions & 83 deletions src/geophires_x/Economics.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,43 +95,13 @@ def calculate_cost_of_one_vertical_well(model: Model, depth_m: float, well_corre
)

if well_correlation is WellDrillingCostCorrelation.SIMPLE:
cost_of_one_well = vertical_drilling_cost_per_m * depth_m * 1E-6

elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL:
cost_of_one_well = (0.30212 * depth_m ** 2 + 584.91124 * depth_m + 751368.47270) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE:
cost_of_one_well = (0.28180 * depth_m ** 2 + 1275.52130 * depth_m + 632315.12640) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL:
cost_of_one_well = (0.28977 * depth_m ** 2 + 882.15067 * depth_m + 680562.50150) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE:
cost_of_one_well = (0.25528 * depth_m ** 2 + 1716.71568 * depth_m + 500866.89110) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL_INT1:
cost_of_one_well = (0.13710 * depth_m ** 2 + 129.61033 * depth_m + 1205587.57100) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE_INT1:
cost_of_one_well = (0.18927 * depth_m ** 2 + 293.45174 * depth_m + 1326526.31300) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL_INT1:
cost_of_one_well = (0.15340 * depth_m ** 2 + 120.31700 * depth_m + 1431801.54400) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE_INT1:
cost_of_one_well = (0.19950 * depth_m ** 2 + 296.13011 * depth_m + 1697867.70900) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL_INT2:
cost_of_one_well = (0.00804 * depth_m ** 2 + 455.60507 * depth_m + 921007.68680) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE_INT2:
cost_of_one_well = (0.00315 * depth_m ** 2 + 782.69676 * depth_m + 983620.25270) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL_INT2:
cost_of_one_well = (0.00854 * depth_m ** 2 + 506.08357 * depth_m + 1057330.39000) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE_INT2:
cost_of_one_well = (0.00380 * depth_m ** 2 + 838.90249 * depth_m + 1181947.04400) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL_IDEAL:
cost_of_one_well = (0.00252 * depth_m ** 2 + 439.44503 * depth_m + 590611.90110) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE_IDEAL:
cost_of_one_well = (-0.00240 * depth_m ** 2 + 752.93946 * depth_m + 524337.65380) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL_IDEAL:
cost_of_one_well = (0.00719 * depth_m ** 2 + 455.85233 * depth_m + 753377.73080) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE_IDEAL:
cost_of_one_well = (0.00376 * depth_m ** 2 + 762.52696 * depth_m + 765103.07690) * 1E-6
cost_of_one_well = vertical_drilling_cost_per_m * depth_m * 1E-6
else:
cost_of_one_well = well_correlation.calculate_cost_MUSD(depth_m)

# account for adjustment factor
cost_of_one_well = well_cost_adjustment_factor * cost_of_one_well

return cost_of_one_well


Expand Down Expand Up @@ -195,60 +165,16 @@ def calculate_cost_of_non_vertical_section(model: Model, length_m: float, well_c
if not NonverticalsCased:
# assume that casing & cementing costs 50% of drilling costs
casing_factor = 0.5

if model.economics.Nonvertical_drilling_cost_per_m.Provided or well_correlation is WellDrillingCostCorrelation.SIMPLE:
cost_of_non_vertical_section = casing_factor * ((num_nonvertical_sections * nonvertical_drilling_cost_per_m * length_per_section_m)) * 1E-6
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL:
cost_per_section = (0.30212 * length_per_section_m ** 2 + 584.91124 * length_per_section_m + 751368.47270) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE:
cost_per_section = (0.28180 * length_per_section_m ** 2 + 1275.52130 * length_per_section_m + 632315.12640) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL:
cost_per_section = (0.28977 * length_per_section_m ** 2 + 882.15067 * length_per_section_m + 680562.50150) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE:
cost_per_section = (0.25528 * length_per_section_m ** 2 + 1716.71568 * length_per_section_m + 500866.89110) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL_INT1:
cost_per_section = (0.13710 * length_per_section_m ** 2 + 129.61033 * length_per_section_m + 1205587.57100) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE_INT1:
cost_per_section = (0.18927 * length_per_section_m ** 2 + 293.45174 * length_per_section_m + 1326526.31300) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL_INT1:
cost_per_section = (0.15340 * length_per_section_m ** 2 + 120.31700 * length_per_section_m + 1431801.54400) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE_INT1:
cost_per_section = (0.19950 * length_per_section_m ** 2 + 296.13011 * length_per_section_m + 1697867.70900) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL_INT2:
cost_per_section = (0.00804 * length_per_section_m ** 2 + 455.60507 * length_per_section_m + 921007.68680) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE_INT2:
cost_per_section = (0.00315 * length_per_section_m ** 2 + 782.69676 * length_per_section_m + 983620.25270) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL_INT2:
cost_per_section = (0.00854 * length_per_section_m ** 2 + 506.08357 * length_per_section_m + 1057330.39000) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE_INT2:
cost_per_section = (0.00380 * length_per_section_m ** 2 + 838.90249 * length_per_section_m + 1181947.04400) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_SMALL_IDEAL:
cost_per_section = (0.00252 * length_per_section_m ** 2 + 439.44503 * length_per_section_m + 590611.90110) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.VERTICAL_LARGE_IDEAL:
cost_per_section = (-0.00240 * length_per_section_m ** 2 + 752.93946 * length_per_section_m + 524337.65380) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_SMALL_IDEAL:
cost_per_section = (0.00719 * length_per_section_m ** 2 + 455.85233 * length_per_section_m + 753377.73080) * 1E-6
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section
elif well_correlation is WellDrillingCostCorrelation.DEVIATED_LARGE_IDEAL:
cost_per_section = (0.00376 * length_per_section_m ** 2 + 762.52696 * length_per_section_m + 765103.07690) * 1E-6
else:
cost_per_section = well_correlation.calculate_cost_MUSD(length_per_section_m)
cost_of_non_vertical_section = casing_factor * num_nonvertical_sections * cost_per_section

# account for adjustment factor

cost_of_non_vertical_section = well_cost_adjustment_factor * cost_of_non_vertical_section

return cost_of_non_vertical_section


Expand Down Expand Up @@ -1613,7 +1539,7 @@ def __init__(self, model: Model):
CurrentUnits=EnergyCostUnit.DOLLARSPERKWH,
)
self.CoolingPrice = self.OutputParameterDict[self.CoolingPrice.Name] = OutputParameter(
"Heat Sale Price Model",
"Cooling Sale Price Model",
UnitType=Units.ENERGYCOST,
PreferredUnits=EnergyCostUnit.CENTSSPERKWH,
CurrentUnits=EnergyCostUnit.DOLLARSPERKWH,
Expand Down
56 changes: 35 additions & 21 deletions src/geophires_x/OptionList.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,27 +51,41 @@ class ReservoirVolume(str, Enum):


class WellDrillingCostCorrelation(str, Enum):
"""Note: order must be retained since input is read as an int"""

VERTICAL_SMALL = "vertical small diameter, baseline"
DEVIATED_SMALL = "deviated small diameter, baseline"
VERTICAL_LARGE = "vertical large diameter, baseline"
DEVIATED_LARGE = "deviated large diameter, baseline"

SIMPLE = "Simple"

VERTICAL_SMALL_INT1 = "vertical small diameter, intermediate1"
VERTICAL_SMALL_INT2 = "vertical small diameter, intermediate2"
DEVIATED_SMALL_INT1 = "deviated small diameter, intermediate1"
DEVIATED_SMALL_INT2 = "deviated small diameter, intermediate2"
VERTICAL_LARGE_INT1 = "vertical large diameter, intermediate1"
VERTICAL_LARGE_INT2 = "vertical large diameter, intermediate2"
DEVIATED_LARGE_INT1 = "deviated large diameter, intermediate1"
DEVIATED_LARGE_INT2 = "deviated large diameter, intermediate2"
VERTICAL_SMALL_IDEAL = "vertical open-hole, small diameter, ideal"
DEVIATED_SMALL_IDEAL = "deviated liner, small diameter, ideal"
VERTICAL_LARGE_IDEAL = "vertical open-hole, large diameter, ideal"
DEVIATED_LARGE_IDEAL = "deviated liner, large diameter, ideal"
"""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 __new__(cls, *args, **kwds):
obj = str.__new__(cls)
obj._value_ = args[1]
return obj

def __init__(self, idx: int, _: str, c2:float, c1:float, c0:float):
self._c2 = c2
self._c1 = c1
self._c0 = c0

def calculate_cost_MUSD(self, meters) -> float:
return (self._c2 * meters ** 2 + self._c1 * meters + self._c0) * 1E-6



Expand Down
2 changes: 1 addition & 1 deletion src/geophires_x/Outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2043,7 +2043,7 @@ def o(output_param: OutputParameter):
if output_param.Name in econ.OutputParameterDict:
return econ.OutputParameterDict[output_param.Name]
else:
return o
return output_param

f.write('Start ('
+ o(econ.ElecPrice).CurrentUnits.value +
Expand Down
Loading

0 comments on commit 90ff58b

Please sign in to comment.