Skip to content

Commit 05a8996

Browse files
Merge pull request #103 from softwareengineerprogrammer/gringarten-stehfest-precision-3
Gringarten-Stehfest Precision [v3.9.52]
2 parents 84faafb + e36ba38 commit 05a8996

17 files changed

+197
-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.52
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.52
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

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.52.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.52...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.52'
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.52',
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.52'

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

src/geophires_x_schema_generator/geophires-request.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,15 @@
412412
"minimum": 0,
413413
"maximum": 0.2
414414
},
415+
"Gringarten-Stehfest Precision": {
416+
"description": "Sets the numerical precision (decimal places) for the inverse Laplace transform (Stehfest algorithm) used in the Gringarten calculation for the Multiple Parallel Fractures Reservoir Model. The default value provides maximum result stability; lower values calculate faster but may reduce consistency.",
417+
"type": "integer",
418+
"units": null,
419+
"category": "Reservoir",
420+
"default": 15,
421+
"minimum": 8,
422+
"maximum": 15
423+
},
415424
"Cylindrical Reservoir Input Depth": {
416425
"description": "Depth of the inflow end of a cylindrical reservoir",
417426
"type": "number",

0 commit comments

Comments
 (0)