1
1
import sys
2
+
3
+ from mpmath import mp , exp , invertlaplace , sqrt , tanh , workdps
2
4
import numpy as np
3
- from mpmath import *
5
+
4
6
import geophires_x .Model as Model
7
+ from .Parameter import intParameter
5
8
from .Reservoir import Reservoir
9
+ from .Units import Units
6
10
7
11
8
12
class MPFReservoir (Reservoir ):
@@ -12,6 +16,7 @@ class MPFReservoir(Reservoir):
12
16
It also has its own methods and attributes that are unique to this class.
13
17
"""
14
18
19
+ # noinspection PyUnresolvedReferences,PyProtectedMember
15
20
def __init__ (self , model : Model ):
16
21
"""
17
22
The __init__ function is called automatically when a class is instantiated.
@@ -31,15 +36,33 @@ def __init__(self, model: Model):
31
36
:type model: :class:`~geophires_x.Model.Model`
32
37
:return: None
33
38
"""
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
+
35
41
super ().__init__ (model ) # initialize the parent parameters and variables
36
42
sclass = str (__class__ ).replace ("<class \' " , "" )
37
43
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 } ' )
39
61
40
62
def __str__ (self ):
41
63
return "MPFReservoir"
42
64
65
+ # noinspection PyUnresolvedReferences,PyProtectedMember
43
66
def read_parameters (self , model : Model ) -> None :
44
67
"""
45
68
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:
51
74
:type model: :class:`~geophires_x.Model.Model`
52
75
:return: None
53
76
"""
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 } ' )
55
78
# if we call super, we don't need to deal with setting the parameters here,
56
79
# just deal with the special cases for the variables in this class
57
80
# because the call to the super.readparameters will set all the variables,
58
81
# including the ones that are specific to this class
59
82
super ().read_parameters (model ) # read the parameters for the parent.
60
83
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 } ' )
62
85
86
+ # noinspection SpellCheckingInspection,PyUnresolvedReferences,PyProtectedMember
63
87
def Calculate (self , model : Model ):
64
88
"""
65
89
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):
87
111
# calculate non-dimensional temperature array
88
112
Twnd = []
89
113
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
+ )
95
137
print (msg )
96
- raise RuntimeError (msg )
138
+ raise RuntimeError (msg ) from e_
97
139
98
140
Twnd = np .asarray (Twnd )
99
141
@@ -102,3 +144,4 @@ def Calculate(self, model: Model):
102
144
model .reserv .Tresoutput .value = np .append ([model .reserv .Trock .value ], model .reserv .Tresoutput .value )
103
145
104
146
model .logger .info (f'Complete { str (__class__ )} : { sys ._getframe ().f_code .co_name } ' )
147
+
0 commit comments