Skip to content

Commit 5c0bed1

Browse files
use workdps to correctly manage local context precision (previous commit modified global context as an unintended side effect)
1 parent 397530f commit 5c0bed1

File tree

1 file changed

+22
-35
lines changed

1 file changed

+22
-35
lines changed

src/geophires_x/MPFReservoir.py

Lines changed: 22 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import sys
22

3-
from mpmath import mp, MPContext, exp, sqrt, tanh
3+
from mpmath import mp, exp, invertlaplace, sqrt, tanh, workdps
44
import numpy as np
55

66
import geophires_x.Model as Model
@@ -108,18 +108,29 @@ def Calculate(self, model: Model):
108108
# calculate non-dimensional temperature array
109109
Twnd = []
110110
try:
111-
dps = mp.dps
112-
if self.gringarten_stehfest_precision.Provided:
113-
dps = self.gringarten_stehfest_precision.value
114-
115-
for t in range(1, len(model.reserv.timevector.value)):
116-
# Twnd = Twnd + [float(invertlaplace(fp, td[t], method='stehfest'))]
117-
Twnd = Twnd + [float(_thread_safe_invertlaplace_stehfest(fp, td[t], dps))]
111+
# Determine the required precision for this calculation.
112+
precision = (
113+
self.gringarten_stehfest_precision.value
114+
if self.gringarten_stehfest_precision.Provided
115+
else mp.dps
116+
)
117+
118+
# Use the workdps context manager for a robust, thread-safe solution.
119+
# It temporarily sets mp.dps for this block and restores it automatically.
120+
with workdps(precision):
121+
# A list comprehension is a more concise way to build the list.
122+
twnd_list = [
123+
float(invertlaplace(fp, td[t], method='stehfest'))
124+
for t in range(1, len(model.reserv.timevector.value))
125+
]
126+
Twnd = np.asarray(twnd_list)
118127

119128
except Exception as e_:
120-
msg = (f'Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1 '
121-
f'({self.gringarten_stehfest_precision.Name} = {dps}). '
122-
'Simulation will abort.')
129+
msg = (
130+
f'Error: GEOPHIRES could not execute numerical inverse laplace calculation for reservoir model 1 '
131+
f'({self.gringarten_stehfest_precision.Name} = {precision}). '
132+
'Simulation will abort.'
133+
)
123134
print(msg)
124135
raise RuntimeError(msg) from e_
125136

@@ -131,27 +142,3 @@ def Calculate(self, model: Model):
131142

132143
model.logger.info(f'Complete {str(__class__)}: {sys._getframe().f_code.co_name}')
133144

134-
135-
# noinspection SpellCheckingInspection
136-
def _thread_safe_invertlaplace_stehfest(fp, t, dps):
137-
"""
138-
Calculates the inverse Laplace transform at a specific precision
139-
without modifying the global mpmath context.
140-
141-
Args:
142-
fp: The Laplace-space function.
143-
t: The time at which to evaluate the inverse transform.
144-
dps: The desired decimal places of precision for this calculation.
145-
146-
Returns:
147-
The result of the inverse Laplace transform.
148-
"""
149-
# Create a local, temporary context object.
150-
local_ctx = MPContext()
151-
152-
# Set the desired precision *only* on this local context.
153-
local_ctx.dps = dps
154-
155-
# Call invertlaplace from the local_ctx object. It will use its own
156-
# precision when instantiating the stehfest method internally.
157-
return local_ctx.invertlaplace(fp, t, method='stehfest')

0 commit comments

Comments
 (0)