Skip to content

Commit e93abe3

Browse files
Merge pull request NREL#417 from softwareengineerprogrammer/main
Gringarten-Stehfest Precision [v3.9.53]
2 parents aa8e7a2 + 8cbeeb7 commit e93abe3

18 files changed

+199
-51
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 3.9.50
2+
current_version = 3.9.53
33
commit = True
44
tag = True
55

.cookiecutterrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ default_context:
5454
sphinx_doctest: "no"
5555
sphinx_theme: "sphinx-py3doc-enhanced-theme"
5656
test_matrix_separate_coverage: "no"
57-
version: 3.9.50
57+
version: 3.9.53
5858
version_manager: "bump2version"
5959
website: "https://github.com/NREL"
6060
year_from: "2023"

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ _site/
104104
/Useful sites for Sphinx docstrings.txt
105105
/.github/workflows/workflows.7z
106106

107+
# TODO unignore once favicon is correctly configured
108+
docs/_images/geophires-favicon.png
109+
107110
# Mypy Cache
108111
.mypy_cache/
109112

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ GEOPHIRES v3 (2023-2025)
77

88
3.9
99
^^^
10+
3.9.53: `Gringarten-Stehfest Precision <https://github.com/NREL/GEOPHIRES-X/pull/417>`__ | `release <https://github.com/NREL/GEOPHIRES-X/releases/tag/v3.9.53>`__
11+
1012
3.9.50: `HIP-RA-X Print Output to Console parameter <https://github.com/NREL/GEOPHIRES-X/pull/416>`__ | `release <https://github.com/NREL/GEOPHIRES-X/releases/tag/v3.9.50>`__
1113

1214
3.9.49: `Fervo_Project_Cape-4 Stimulation Costs Update <https://github.com/NREL/GEOPHIRES-X/pull/414>`__ | `release <https://github.com/NREL/GEOPHIRES-X/releases/tag/v3.9.49>`__

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ Free software: `MIT license <LICENSE>`__
5858
:alt: Supported implementations
5959
:target: https://pypi.org/project/geophires-x
6060

61-
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.9.50.svg
61+
.. |commits-since| image:: https://img.shields.io/github/commits-since/softwareengineerprogrammer/GEOPHIRES-X/v3.9.53.svg
6262
:alt: Commits since latest release
63-
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.9.50...main
63+
:target: https://github.com/softwareengineerprogrammer/GEOPHIRES-X/compare/v3.9.53...main
6464

6565
.. |docs| image:: https://readthedocs.org/projects/GEOPHIRES-X/badge/?style=flat
6666
:target: https://nrel.github.io/GEOPHIRES-X

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
year = '2025'
1919
author = 'NREL'
2020
copyright = f'{year}, {author}'
21-
version = release = '3.9.50'
21+
version = release = '3.9.53'
2222

2323
pygments_style = 'trac'
2424
templates_path = ['./templates']

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ def read(*names, **kwargs):
1313

1414
setup(
1515
name='geophires-x',
16-
version='3.9.50',
16+
version='3.9.53',
1717
license='MIT',
1818
description='GEOPHIRES is a free and open-source geothermal techno-economic simulator.',
1919
long_description='{}\n{}'.format(

src/geophires_x/MPFReservoir.py

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import sys
2+
3+
from mpmath import mp, exp, invertlaplace, sqrt, tanh, workdps
24
import numpy as np
3-
from mpmath import *
5+
46
import geophires_x.Model as Model
7+
from .Parameter import intParameter
58
from .Reservoir import Reservoir
9+
from .Units import Units
610

711

812
class MPFReservoir(Reservoir):
@@ -12,6 +16,7 @@ class MPFReservoir(Reservoir):
1216
It also has its own methods and attributes that are unique to this class.
1317
"""
1418

19+
# noinspection PyUnresolvedReferences,PyProtectedMember
1520
def __init__(self, model: Model):
1621
"""
1722
The __init__ function is called automatically when a class is instantiated.
@@ -31,15 +36,33 @@ def __init__(self, model: Model):
3136
:type model: :class:`~geophires_x.Model.Model`
3237
:return: None
3338
"""
34-
model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name)
39+
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')
40+
3541
super().__init__(model) # initialize the parent parameters and variables
3642
sclass = str(__class__).replace("<class \'", "")
3743
self.MyClass = sclass.replace("\'>", "")
38-
model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name)
44+
45+
max_allowed_precision = 15
46+
self.gringarten_stehfest_precision = self.ParameterDict[self.gringarten_stehfest_precision.Name] = intParameter(
47+
'Gringarten-Stehfest Precision',
48+
DefaultValue=15,
49+
AllowableRange=list(range(8, max_allowed_precision + 1)),
50+
UnitType=Units.NONE,
51+
Required=False,
52+
ToolTipText='Sets the numerical precision (decimal places) for the inverse Laplace transform '
53+
'(Stehfest algorithm) used in the Gringarten calculation for the Multiple Parallel Fractures '
54+
'Reservoir Model. '
55+
'The default value provides maximum result stability; '
56+
'lower values calculate faster but may reduce consistency.'
57+
)
58+
59+
60+
model.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}')
3961

4062
def __str__(self):
4163
return "MPFReservoir"
4264

65+
# noinspection PyUnresolvedReferences,PyProtectedMember
4366
def read_parameters(self, model: Model) -> None:
4467
"""
4568
The read_parameters function reads in the parameters from a dictionary created by reading the user-provided file
@@ -51,15 +74,16 @@ def read_parameters(self, model: Model) -> None:
5174
:type model: :class:`~geophires_x.Model.Model`
5275
:return: None
5376
"""
54-
model.logger.info("Init " + str(__class__) + ": " + sys._getframe().f_code.co_name)
77+
model.logger.info(f'Init {str(__class__)}: {sys._getframe().f_code.co_name}')
5578
# if we call super, we don't need to deal with setting the parameters here,
5679
# just deal with the special cases for the variables in this class
5780
# because the call to the super.readparameters will set all the variables,
5881
# including the ones that are specific to this class
5982
super().read_parameters(model) # read the parameters for the parent.
6083

61-
model.logger.info("Complete " + str(__class__) + ": " + sys._getframe().f_code.co_name)
84+
model.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}')
6285

86+
# noinspection SpellCheckingInspection,PyUnresolvedReferences,PyProtectedMember
6387
def Calculate(self, model: Model):
6488
"""
6589
The Calculate function calculates the values of all the parameters that are calculated by this object.
@@ -87,13 +111,31 @@ def Calculate(self, model: Model):
87111
# calculate non-dimensional temperature array
88112
Twnd = []
89113
try:
90-
for t in range(1, len(model.reserv.timevector.value)):
91-
Twnd = Twnd + [float(invertlaplace(fp, td[t], method='stehfest'))]
92-
except:
93-
msg = ('Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1. '
94-
'Simulation will abort.')
114+
# Determine the required precision for this calculation.
115+
precision = (
116+
self.gringarten_stehfest_precision.value
117+
if self.gringarten_stehfest_precision.Provided
118+
else mp.dps
119+
)
120+
121+
# Use the workdps context manager for a robust, thread-safe solution.
122+
# It temporarily sets mp.dps for this block and restores it automatically.
123+
with workdps(precision):
124+
twnd_list = [
125+
float(invertlaplace(fp, td[t], method='stehfest'))
126+
for t in range(1, len(model.reserv.timevector.value))
127+
]
128+
129+
Twnd = np.asarray(twnd_list)
130+
131+
except Exception as e_:
132+
msg = (
133+
f'Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1 '
134+
f'({self.gringarten_stehfest_precision.Name} = {precision}). '
135+
'Simulation will abort.'
136+
)
95137
print(msg)
96-
raise RuntimeError(msg)
138+
raise RuntimeError(msg) from e_
97139

98140
Twnd = np.asarray(Twnd)
99141

@@ -102,3 +144,4 @@ def Calculate(self, model: Model):
102144
model.reserv.Tresoutput.value = np.append([model.reserv.Trock.value], model.reserv.Tresoutput.value)
103145

104146
model.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}')
147+

src/geophires_x/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '3.9.50'
1+
__version__ = '3.9.53'

src/geophires_x_client/geophires_x_result.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,10 @@ class GeophiresXResult:
346346
'Average Annual Total Heating Production',
347347
'Average Annual Electricity Use for Pumping',
348348
],
349-
'Simulation Metadata': [_StringValueField('GEOPHIRES Version')],
349+
'Simulation Metadata': [
350+
_StringValueField('GEOPHIRES Version'),
351+
'Calculation Time',
352+
],
350353
}
351354
)
352355

0 commit comments

Comments
 (0)