rock-physics-open 0.3.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. rock_physics_open/__init__.py +0 -0
  2. rock_physics_open/equinor_utilities/__init__.py +0 -0
  3. rock_physics_open/equinor_utilities/anisotropy.py +211 -0
  4. rock_physics_open/equinor_utilities/classification_functions/__init__.py +17 -0
  5. rock_physics_open/equinor_utilities/classification_functions/class_stats.py +68 -0
  6. rock_physics_open/equinor_utilities/classification_functions/lin_class.py +53 -0
  7. rock_physics_open/equinor_utilities/classification_functions/mahal_class.py +63 -0
  8. rock_physics_open/equinor_utilities/classification_functions/norm_class.py +73 -0
  9. rock_physics_open/equinor_utilities/classification_functions/poly_class.py +45 -0
  10. rock_physics_open/equinor_utilities/classification_functions/post_prob.py +27 -0
  11. rock_physics_open/equinor_utilities/classification_functions/two_step_classification.py +60 -0
  12. rock_physics_open/equinor_utilities/conversions.py +10 -0
  13. rock_physics_open/equinor_utilities/gen_utilities/__init__.py +11 -0
  14. rock_physics_open/equinor_utilities/gen_utilities/dict_to_float.py +38 -0
  15. rock_physics_open/equinor_utilities/gen_utilities/dim_check_vector.py +113 -0
  16. rock_physics_open/equinor_utilities/gen_utilities/filter_input.py +131 -0
  17. rock_physics_open/equinor_utilities/gen_utilities/filter_output.py +88 -0
  18. rock_physics_open/equinor_utilities/machine_learning_utilities/__init__.py +15 -0
  19. rock_physics_open/equinor_utilities/machine_learning_utilities/base_pressure_model.py +170 -0
  20. rock_physics_open/equinor_utilities/machine_learning_utilities/dummy_vars.py +53 -0
  21. rock_physics_open/equinor_utilities/machine_learning_utilities/exponential_model.py +137 -0
  22. rock_physics_open/equinor_utilities/machine_learning_utilities/import_ml_models.py +77 -0
  23. rock_physics_open/equinor_utilities/machine_learning_utilities/polynomial_model.py +132 -0
  24. rock_physics_open/equinor_utilities/machine_learning_utilities/run_regression.py +209 -0
  25. rock_physics_open/equinor_utilities/machine_learning_utilities/sigmoidal_model.py +241 -0
  26. rock_physics_open/equinor_utilities/optimisation_utilities/__init__.py +19 -0
  27. rock_physics_open/equinor_utilities/optimisation_utilities/opt_subst_utilities.py +455 -0
  28. rock_physics_open/equinor_utilities/snapshot_test_utilities/__init__.py +10 -0
  29. rock_physics_open/equinor_utilities/snapshot_test_utilities/compare_snapshots.py +184 -0
  30. rock_physics_open/equinor_utilities/snapshot_test_utilities/snapshots.py +97 -0
  31. rock_physics_open/equinor_utilities/std_functions/__init__.py +43 -0
  32. rock_physics_open/equinor_utilities/std_functions/backus_ave.py +68 -0
  33. rock_physics_open/equinor_utilities/std_functions/dvorkin_nur.py +77 -0
  34. rock_physics_open/equinor_utilities/std_functions/gassmann.py +165 -0
  35. rock_physics_open/equinor_utilities/std_functions/hashin_shtrikman.py +224 -0
  36. rock_physics_open/equinor_utilities/std_functions/hertz_mindlin.py +51 -0
  37. rock_physics_open/equinor_utilities/std_functions/moduli_velocity.py +67 -0
  38. rock_physics_open/equinor_utilities/std_functions/reflection_eq.py +120 -0
  39. rock_physics_open/equinor_utilities/std_functions/rho.py +69 -0
  40. rock_physics_open/equinor_utilities/std_functions/voigt_reuss_hill.py +149 -0
  41. rock_physics_open/equinor_utilities/std_functions/walton.py +45 -0
  42. rock_physics_open/equinor_utilities/std_functions/wood_brie.py +94 -0
  43. rock_physics_open/equinor_utilities/various_utilities/Equinor_logo.gif +0 -0
  44. rock_physics_open/equinor_utilities/various_utilities/Equinor_logo.ico +0 -0
  45. rock_physics_open/equinor_utilities/various_utilities/__init__.py +24 -0
  46. rock_physics_open/equinor_utilities/various_utilities/display_result_statistics.py +90 -0
  47. rock_physics_open/equinor_utilities/various_utilities/gassmann_dry_mod.py +56 -0
  48. rock_physics_open/equinor_utilities/various_utilities/gassmann_mod.py +56 -0
  49. rock_physics_open/equinor_utilities/various_utilities/gassmann_sub_mod.py +64 -0
  50. rock_physics_open/equinor_utilities/various_utilities/hs_average.py +59 -0
  51. rock_physics_open/equinor_utilities/various_utilities/pressure.py +96 -0
  52. rock_physics_open/equinor_utilities/various_utilities/reflectivity.py +101 -0
  53. rock_physics_open/equinor_utilities/various_utilities/timeshift.py +104 -0
  54. rock_physics_open/equinor_utilities/various_utilities/vp_vs_rho_set_statistics.py +170 -0
  55. rock_physics_open/equinor_utilities/various_utilities/vrh_3_min.py +83 -0
  56. rock_physics_open/fluid_models/__init__.py +9 -0
  57. rock_physics_open/fluid_models/brine_model/__init__.py +5 -0
  58. rock_physics_open/fluid_models/brine_model/brine_properties.py +178 -0
  59. rock_physics_open/fluid_models/gas_model/__init__.py +5 -0
  60. rock_physics_open/fluid_models/gas_model/gas_properties.py +319 -0
  61. rock_physics_open/fluid_models/oil_model/__init__.py +5 -0
  62. rock_physics_open/fluid_models/oil_model/dead_oil_density.py +65 -0
  63. rock_physics_open/fluid_models/oil_model/dead_oil_velocity.py +30 -0
  64. rock_physics_open/fluid_models/oil_model/live_oil_density.py +82 -0
  65. rock_physics_open/fluid_models/oil_model/live_oil_velocity.py +24 -0
  66. rock_physics_open/fluid_models/oil_model/oil_bubble_point.py +69 -0
  67. rock_physics_open/fluid_models/oil_model/oil_properties.py +146 -0
  68. rock_physics_open/sandstone_models/__init__.py +59 -0
  69. rock_physics_open/sandstone_models/cemented_shalysand_sandyshale_models.py +304 -0
  70. rock_physics_open/sandstone_models/constant_cement_models.py +204 -0
  71. rock_physics_open/sandstone_models/constant_cement_optimisation.py +125 -0
  72. rock_physics_open/sandstone_models/contact_cement_model.py +138 -0
  73. rock_physics_open/sandstone_models/curvefit_sandstone_models.py +143 -0
  74. rock_physics_open/sandstone_models/friable_models.py +177 -0
  75. rock_physics_open/sandstone_models/friable_optimisation.py +115 -0
  76. rock_physics_open/sandstone_models/friable_shalysand_sandyshale_models.py +235 -0
  77. rock_physics_open/sandstone_models/patchy_cement_fluid_substitution_model.py +477 -0
  78. rock_physics_open/sandstone_models/patchy_cement_model.py +384 -0
  79. rock_physics_open/sandstone_models/patchy_cement_optimisation.py +254 -0
  80. rock_physics_open/sandstone_models/unresolved_cemented_sandshale_models.py +134 -0
  81. rock_physics_open/sandstone_models/unresolved_friable_sandshale_models.py +126 -0
  82. rock_physics_open/shale_models/__init__.py +19 -0
  83. rock_physics_open/shale_models/dem.py +174 -0
  84. rock_physics_open/shale_models/dem_dual_por.py +61 -0
  85. rock_physics_open/shale_models/kus_tok.py +59 -0
  86. rock_physics_open/shale_models/multi_sca.py +133 -0
  87. rock_physics_open/shale_models/pq.py +102 -0
  88. rock_physics_open/shale_models/sca.py +90 -0
  89. rock_physics_open/shale_models/shale4_mineral.py +147 -0
  90. rock_physics_open/shale_models/shale4_mineral_dem_overlay.py +92 -0
  91. rock_physics_open/span_wagner/__init__.py +5 -0
  92. rock_physics_open/span_wagner/co2_properties.py +444 -0
  93. rock_physics_open/span_wagner/coefficients.py +165 -0
  94. rock_physics_open/span_wagner/equations.py +104 -0
  95. rock_physics_open/span_wagner/tables/__init__.py +0 -0
  96. rock_physics_open/span_wagner/tables/carbon_dioxide_density.npz +0 -0
  97. rock_physics_open/span_wagner/tables/lookup_table.py +33 -0
  98. rock_physics_open/t_matrix_models/Equinor_logo.ico +0 -0
  99. rock_physics_open/t_matrix_models/__init__.py +35 -0
  100. rock_physics_open/t_matrix_models/carbonate_pressure_substitution.py +124 -0
  101. rock_physics_open/t_matrix_models/curvefit_t_matrix_exp.py +123 -0
  102. rock_physics_open/t_matrix_models/curvefit_t_matrix_min.py +86 -0
  103. rock_physics_open/t_matrix_models/parse_t_matrix_inputs.py +297 -0
  104. rock_physics_open/t_matrix_models/run_t_matrix.py +243 -0
  105. rock_physics_open/t_matrix_models/t_matrix_C.py +210 -0
  106. rock_physics_open/t_matrix_models/t_matrix_opt_fluid_sub_exp.py +137 -0
  107. rock_physics_open/t_matrix_models/t_matrix_opt_fluid_sub_petec.py +167 -0
  108. rock_physics_open/t_matrix_models/t_matrix_opt_forward_model_exp.py +76 -0
  109. rock_physics_open/t_matrix_models/t_matrix_opt_forward_model_min.py +89 -0
  110. rock_physics_open/t_matrix_models/t_matrix_parameter_optimisation_exp.py +176 -0
  111. rock_physics_open/t_matrix_models/t_matrix_parameter_optimisation_min.py +162 -0
  112. rock_physics_open/t_matrix_models/t_matrix_vector/__init__.py +12 -0
  113. rock_physics_open/t_matrix_models/t_matrix_vector/array_functions.py +75 -0
  114. rock_physics_open/t_matrix_models/t_matrix_vector/calc_c_eff.py +163 -0
  115. rock_physics_open/t_matrix_models/t_matrix_vector/calc_isolated.py +95 -0
  116. rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd.py +40 -0
  117. rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd_eff.py +116 -0
  118. rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd_uuv.py +18 -0
  119. rock_physics_open/t_matrix_models/t_matrix_vector/calc_pressure.py +140 -0
  120. rock_physics_open/t_matrix_models/t_matrix_vector/calc_t.py +71 -0
  121. rock_physics_open/t_matrix_models/t_matrix_vector/calc_td.py +42 -0
  122. rock_physics_open/t_matrix_models/t_matrix_vector/calc_theta.py +43 -0
  123. rock_physics_open/t_matrix_models/t_matrix_vector/calc_x.py +33 -0
  124. rock_physics_open/t_matrix_models/t_matrix_vector/calc_z.py +50 -0
  125. rock_physics_open/t_matrix_models/t_matrix_vector/check_and_tile.py +43 -0
  126. rock_physics_open/t_matrix_models/t_matrix_vector/g_tensor.py +140 -0
  127. rock_physics_open/t_matrix_models/t_matrix_vector/iso_av.py +60 -0
  128. rock_physics_open/t_matrix_models/t_matrix_vector/iso_ave_all.py +55 -0
  129. rock_physics_open/t_matrix_models/t_matrix_vector/pressure_input.py +44 -0
  130. rock_physics_open/t_matrix_models/t_matrix_vector/t_matrix_vec.py +278 -0
  131. rock_physics_open/t_matrix_models/t_matrix_vector/velocity_vti_angles.py +81 -0
  132. rock_physics_open/t_matrix_models/tmatrix_python.dll +0 -0
  133. rock_physics_open/t_matrix_models/tmatrix_python.so +0 -0
  134. rock_physics_open/ternary_plots/__init__.py +3 -0
  135. rock_physics_open/ternary_plots/gen_ternary_plot.py +73 -0
  136. rock_physics_open/ternary_plots/shale_prop_ternary.py +337 -0
  137. rock_physics_open/ternary_plots/ternary_patches.py +277 -0
  138. rock_physics_open/ternary_plots/ternary_plot_utilities.py +197 -0
  139. rock_physics_open/ternary_plots/unconventionals_ternary.py +75 -0
  140. rock_physics_open/version.py +34 -0
  141. rock_physics_open-0.3.2.dist-info/METADATA +90 -0
  142. rock_physics_open-0.3.2.dist-info/RECORD +145 -0
  143. rock_physics_open-0.3.2.dist-info/WHEEL +5 -0
  144. rock_physics_open-0.3.2.dist-info/licenses/LICENSE +165 -0
  145. rock_physics_open-0.3.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,297 @@
1
+ import sys
2
+
3
+ import numpy as np
4
+
5
+ from rock_physics_open import t_matrix_models
6
+ from rock_physics_open.equinor_utilities import gen_utilities
7
+
8
+
9
+ def parse_t_matrix_inputs(
10
+ k_min,
11
+ mu_min,
12
+ rho_min,
13
+ k_fl,
14
+ rho_fl,
15
+ phi,
16
+ perm,
17
+ visco,
18
+ alpha,
19
+ v,
20
+ tau,
21
+ frequency,
22
+ angle,
23
+ frac_inc_con,
24
+ frac_inc_ani,
25
+ pressure,
26
+ scenario,
27
+ fcn,
28
+ ):
29
+ """Function to do all necessary checking of input type, dimension, reshaping etc. that clutter up the start of T-Matrix
30
+ NB: Setting scenario will override the settings for alpha, v and tau.
31
+
32
+ Parameters
33
+ ----------
34
+ k_min : np.ndarray
35
+ N length numpy array, mineral bulk modulus [Pa].
36
+ mu_min : np.ndarray
37
+ N length numpy array, mineral shear modulus [Pa].
38
+ rho_min : np.ndarray
39
+ N length numpy array, mineral density [kg/m^3].
40
+ k_fl : np.ndarray
41
+ N length numpy array, fluid bulk modulus [Pa].
42
+ rho_fl : np.ndarray
43
+ N length numpy array, mineral density [kg/m^3].
44
+ phi : np.ndarray or float
45
+ N length numpy array, total porosity [ratio].
46
+ perm : np.ndarray or float
47
+ float or N length numpy array, permeability [mD].
48
+ visco : np.ndarray or float
49
+ float or N length numpy array, fluid viscosity [cP].
50
+ alpha : np.ndarray
51
+ M or NxM length numpy array, inclusion aspect ratio [ratio].
52
+ v : np.ndarray
53
+ M or NxM length numpy array, inclusion concentration [ratio].
54
+ tau : np.ndarray
55
+ M length numpy array, relaxation time [s].
56
+ frequency : float
57
+ single float, signal frequency [Hz].
58
+ angle : float
59
+ single float, angle of symmetry plane [degree].
60
+ frac_inc_con : np.ndarray or float
61
+ single float or N length numpy array, fraction of connected inclusions [ratio].
62
+ frac_inc_ani : np.ndarray or float
63
+ single float or N length numpy array, fraction of anisotropic inclusions [ratio].
64
+ pressure : list or np.ndarray
65
+ > 1 value list or numpy array in ascending order, effective pressure [Pa].
66
+ scenario : int
67
+ pre-set scenarios for alpha, v and tau
68
+ fcn : callable
69
+ function with which to run the T-Matrix model.
70
+
71
+ Returns
72
+ -------
73
+ tuple
74
+ All inputs in correct dimension and data type plus ctrl_connected, ctrl_anisotropy - control parameters.
75
+ """
76
+
77
+ def _assert_type(arg, exp_dtype, err_str="check inputs, wrong type encountered"):
78
+ """Assert type.
79
+
80
+ Parameters
81
+ ----------
82
+ arg : any
83
+ To be asserted.
84
+ exp_dtype : type
85
+ Expected data type.
86
+ err_str : str, optional
87
+ Error string, by default 'check inputs, wrong type encountered'.
88
+
89
+ Raises
90
+ ------
91
+ ValueError
92
+ Content of err_str.
93
+ """
94
+ if not isinstance(arg, exp_dtype):
95
+ raise ValueError("t-matrix inputs: " + err_str)
96
+
97
+ # 1: Check all single float values, silently cast int to float
98
+ # Permeability and viscosity: Check that they are floats and convert them to to SI units
99
+ _assert_type(
100
+ perm, (float, int), "expect permeability given as single float in units mD"
101
+ )
102
+ perm = perm * 0.986923e-15
103
+
104
+ _assert_type(
105
+ visco, (float, int), "expect viscosity given as single float in units cP"
106
+ )
107
+ visco = visco * 1.0e-2
108
+
109
+ _assert_type(
110
+ frequency, (float, int), "expect frequency given as single float value in Hz"
111
+ )
112
+ frequency = float(frequency)
113
+
114
+ _assert_type(
115
+ angle, (float, int), "expect angle given as single float value in degrees"
116
+ )
117
+ angle = float(angle)
118
+
119
+ # 2: Determine the T-Matrix function, use the C++ implementation as default in case of None
120
+ # If it given as a string, it must belong to the t_matrix_models module
121
+ if not fcn: # None
122
+ t_matrix_fcn = t_matrix_models.t_matrix_porosity_c_alpha_v
123
+ elif not callable(fcn):
124
+ fcn_err_str = (
125
+ "T-Matrix function should be given as the callable function or a string "
126
+ "to the function name within t_matrix_models "
127
+ )
128
+ _assert_type(fcn, str, fcn_err_str)
129
+ if not hasattr(t_matrix_models, fcn):
130
+ raise ValueError(fcn_err_str)
131
+ t_matrix_fcn = getattr(t_matrix_models, fcn)
132
+
133
+ else: # Function must be recognised
134
+ if not fcn: # check that the function exists
135
+ raise ValueError(
136
+ "t-matrix inputs: function for T-Matrix model is not known"
137
+ )
138
+ t_matrix_fcn = fcn
139
+
140
+ # 3: Check all inputs that should be one value per sample, expand perm and visco to match this.
141
+ # frac_inc_ani and frac_inc_con can be single floats or vectors of the same length as the other vector inputs
142
+
143
+ log_length = len(phi)
144
+
145
+ # Check that the inputs that should have the same length actually do
146
+ # dim_check_vector may throw an error message, modify it to show origin
147
+ try:
148
+ (
149
+ k_min,
150
+ mu_min,
151
+ rho_min,
152
+ k_fl,
153
+ rho_fl,
154
+ phi,
155
+ perm,
156
+ visco,
157
+ frac_inc_con,
158
+ frac_inc_ani,
159
+ ) = gen_utilities.dim_check_vector(
160
+ (
161
+ k_min,
162
+ mu_min,
163
+ rho_min,
164
+ k_fl,
165
+ rho_fl,
166
+ phi,
167
+ perm,
168
+ visco,
169
+ frac_inc_con,
170
+ frac_inc_ani,
171
+ ),
172
+ force_type=np.dtype(float),
173
+ )
174
+ except ValueError:
175
+ raise ValueError("t-matrix inputs: {}".format(str(sys.exc_info())))
176
+
177
+ # 4: Scenario will override settings for alpha, v and tau
178
+ if scenario:
179
+ scenario = int(scenario)
180
+ if scenario == 1: # Mostly rounded pores
181
+ alpha = np.array([0.9, 0.1])
182
+ v = np.array([0.9, 0.1])
183
+ elif scenario == 2: # Dual porosity with little rounded pores
184
+ alpha = np.array([0.58, 0.027])
185
+ v = np.array([0.85, 0.15])
186
+ elif scenario == 3: # Mixed pores
187
+ alpha = np.array([0.9, 0.1, 0.01])
188
+ v = np.array([0.8, 0.19, 0.01])
189
+ elif scenario == 4: # Flat pores and cracks
190
+ alpha = np.array([0.9, 0.1, 0.01, 0.001])
191
+ v = np.array([0.689, 0.3, 0.01, 0.001])
192
+ tau = np.ones_like(alpha) * 1.0e-7
193
+
194
+ # 4a: Check alpha, v, tau
195
+ # alpha and v is either 1D vector with inclusion aspect ratios and proportions applying to all samples or 2D arrays
196
+ # where the first dimension must coincide with the log_length
197
+ # tau should be a 1D vector with length equal to the number of inclusions per sample
198
+ _assert_type(
199
+ alpha,
200
+ np.ndarray,
201
+ "alpha should be a 1D or 2D numpy array of matching size with v",
202
+ )
203
+ _assert_type(
204
+ v, np.ndarray, "v should be a 1D or 2D numpy array og matching size with alpha"
205
+ )
206
+ _assert_type(
207
+ tau,
208
+ (float, np.ndarray),
209
+ "tau should be a single float or 1D numpy array with length matching "
210
+ "the number of inclusions",
211
+ )
212
+
213
+ alpha_shape = alpha.shape
214
+ # First make sure that alpha and v have the same number of elements
215
+ try:
216
+ alpha, v = gen_utilities.dim_check_vector(
217
+ (alpha, v), force_type=np.dtype(float)
218
+ )
219
+ except ValueError:
220
+ raise ValueError("t-matrix inputs: {}".format(str(sys.exc_info())))
221
+ alpha = alpha.reshape(alpha_shape)
222
+ v = v.reshape(alpha_shape)
223
+ # If they are 2D arrays, the first dimension should match log_length
224
+ if alpha.ndim == 2:
225
+ if not (alpha_shape[0] == log_length or alpha_shape[0] == 1):
226
+ raise ValueError(
227
+ "t-matrix inputs: number of samples in alpha is not matching length of inputs"
228
+ )
229
+ if alpha_shape[0] == 1:
230
+ alpha = np.tile(alpha, (log_length, 1))
231
+ v = np.tile(v, (log_length, 1))
232
+
233
+ elif alpha.ndim == 1:
234
+ alpha = np.tile(alpha.reshape(1, alpha_shape[0]), (log_length, 1))
235
+ v = np.tile(v.reshape(1, alpha_shape[0]), (log_length, 1))
236
+ # Check that the number of elements in tau matches dim 1 of alpha
237
+ if isinstance(tau, float):
238
+ tau = np.ones(alpha_shape) * tau
239
+ else:
240
+ if not tau.ndim == 1 and tau.shape[0] == alpha.shape[1]:
241
+ raise ValueError(
242
+ "t-matrix inputs: number of elements in tau is not matching number of inclusions"
243
+ )
244
+
245
+ # 5: Check pressure
246
+ # Check that pressure either consists of at least two elements in ascending order or is None
247
+ # in the case there is no pressure modelling
248
+ if pressure is not None:
249
+ _assert_type(
250
+ pressure,
251
+ (list, np.ndarray),
252
+ "pressure should be a list or numpy array of at least two "
253
+ "elements in ascending order",
254
+ )
255
+ pressure = np.sort(np.array(pressure).flatten())
256
+ if not pressure.shape[0] > 1:
257
+ raise ValueError(
258
+ "t-matrix inputs: if pressure is given, it should contain two or more values"
259
+ )
260
+
261
+ # 6: Determine case for connected/isolated and isotropic/anisotropic inclusions
262
+ # Assume the most general case: mix of isotropic and anisotropic inclusions and connected and isolated inclusions
263
+ ctrl_anisotropy = 1
264
+ if np.all(frac_inc_ani == 0):
265
+ ctrl_anisotropy = 0 # All isotropic
266
+ angle = 0
267
+ elif np.all(frac_inc_ani == 1):
268
+ ctrl_anisotropy = 2 # All anisotropic
269
+
270
+ ctrl_connected = 1
271
+ # Create case based on amount of connected inclusions
272
+ if np.all(frac_inc_con == 0):
273
+ ctrl_connected = 0 # All isolated
274
+ elif np.all(frac_inc_con == 1):
275
+ ctrl_connected = 2 # All connected
276
+
277
+ return (
278
+ k_min,
279
+ mu_min,
280
+ rho_min,
281
+ k_fl,
282
+ rho_fl,
283
+ phi,
284
+ perm,
285
+ visco,
286
+ alpha,
287
+ v,
288
+ tau,
289
+ frequency,
290
+ angle,
291
+ frac_inc_con,
292
+ frac_inc_ani,
293
+ pressure,
294
+ t_matrix_fcn,
295
+ ctrl_connected,
296
+ ctrl_anisotropy,
297
+ )
@@ -0,0 +1,243 @@
1
+ import numpy as np
2
+
3
+ from .parse_t_matrix_inputs import parse_t_matrix_inputs
4
+ from .t_matrix_vector import calc_pressure_vec, pressure_input_utility
5
+
6
+
7
+ def run_t_matrix(
8
+ k_min,
9
+ mu_min,
10
+ rho_min,
11
+ k_fl,
12
+ rho_fl,
13
+ phi,
14
+ perm,
15
+ visco,
16
+ alpha,
17
+ v,
18
+ tau,
19
+ frequency,
20
+ angle,
21
+ frac_inc_con,
22
+ frac_inc_ani,
23
+ pressure=None,
24
+ scenario=None,
25
+ fcn=None,
26
+ ):
27
+ """Function to run T-Matrix in different flavours, with or without pressure steps included.
28
+ A frontend to running T-Matrix model, including testing of all input parameters in the parse_t_matrix_inputs.
29
+
30
+ Parameters
31
+ ----------
32
+ k_min : np.ndarray
33
+ N length numpy array, mineral bulk modulus [Pa].
34
+ mu_min : np.ndarray
35
+ N length numpy array, mineral shear modulus [Pa].
36
+ rho_min : np.ndarray
37
+ N length numpy array, mineral density [kg/m^3].
38
+ k_fl : np.ndarray
39
+ N length numpy array, fluid bulk modulus [Pa].
40
+ rho_fl : np.ndarray
41
+ N length numpy array, mineral density [kg/m^3].
42
+ phi : np.ndarray or float
43
+ N length numpy array, total porosity [ratio].
44
+ perm : np.ndarray or float
45
+ Float or N length numpy array, permeability [mD].
46
+ visco : np.ndarray or float
47
+ Float or N length numpy array, fluid viscosity [cP].
48
+ alpha : np.ndarray
49
+ M or NxM length numpy array, inclusion aspect ratio [ratio].
50
+ v : np.ndarray
51
+ M or NxM length numpy array, inclusion concentration [ratio].
52
+ tau : np.ndarray
53
+ M length numpy array, relaxation time [s].
54
+ frequency : float
55
+ Single float, signal frequency [Hz].
56
+ angle : float
57
+ Single float, angle of symmetry plane [degree].
58
+ frac_inc_con : np.ndarray or float
59
+ Single float or N length numpy array, fraction of connected inclusions [ratio].
60
+ frac_inc_ani : np.ndarray or float
61
+ Single float or N length numpy array, fraction of anisotropic inclusions [ratio].
62
+ pressure : [type], optional
63
+ > 1 value list or numpy array in ascending order, effective pressure [Pa], by default None.
64
+ scenario : int, optional
65
+ Pre-set scenarios for alpha, v and tau, by default None.
66
+ fcn : callable, optional
67
+ Function with which to run the T-Matrix model, by default None.
68
+
69
+ Returns
70
+ -------
71
+ tuple
72
+ vp, vsv, vsh, rho: (np.ndarray, np.ndarray, np.ndarray, np.ndarray).
73
+ """
74
+ # Check all input parameters and make sure that they are on expected format and shape
75
+ (
76
+ k_min,
77
+ mu_min,
78
+ rho_min,
79
+ k_fl,
80
+ rho_fl,
81
+ phi,
82
+ perm,
83
+ visco,
84
+ alpha,
85
+ v,
86
+ tau,
87
+ frequency,
88
+ angle,
89
+ frac_inc_con,
90
+ frac_inc_ani,
91
+ pressure,
92
+ fcn,
93
+ ctrl_connected,
94
+ ctrl_anisotropy,
95
+ ) = parse_t_matrix_inputs(
96
+ k_min,
97
+ mu_min,
98
+ rho_min,
99
+ k_fl,
100
+ rho_fl,
101
+ phi,
102
+ perm,
103
+ visco,
104
+ alpha,
105
+ v,
106
+ tau,
107
+ frequency,
108
+ angle,
109
+ frac_inc_con,
110
+ frac_inc_ani,
111
+ pressure,
112
+ scenario,
113
+ fcn,
114
+ )
115
+
116
+ # If there are no pressure steps to consider the whole task can be assigned to the T-Matrix function
117
+ if pressure is None:
118
+ vp, vsv, vsh, rho = fcn(
119
+ k_min,
120
+ mu_min,
121
+ rho_min,
122
+ k_fl,
123
+ rho_fl,
124
+ phi,
125
+ perm,
126
+ visco,
127
+ alpha,
128
+ v,
129
+ tau,
130
+ frequency,
131
+ angle,
132
+ frac_inc_con,
133
+ frac_inc_ani,
134
+ )
135
+ return vp, vsv, vsh, rho
136
+
137
+ # Pressure steps is mimicking depletion, and inclusion shape parameters can be changed
138
+ # In Remy's implementation it is generally possible to have different alpha's and v's for connected and
139
+ # isolated part, but this is not included directly in Calculo's implementation in C++. For the time being,
140
+ # this possibility is not included here
141
+
142
+ log_length = phi.shape[0]
143
+ pressure_steps = pressure.shape[0]
144
+ # It is the change from initial pressure (first value in the pressure vector) that is input to the function
145
+ # that estimates matrix pressure sensitivity
146
+ delta_pres = np.diff(pressure)
147
+
148
+ # Predefine output vectors
149
+ vp = np.zeros((log_length, pressure_steps))
150
+ vs_v = np.zeros((log_length, pressure_steps))
151
+ vs_h = np.zeros((log_length, pressure_steps))
152
+ rho_b_est = np.zeros((log_length, pressure_steps))
153
+
154
+ # Matrix properties needed as input to calc_pressure_vec
155
+ c0, s0, gd = pressure_input_utility(k_min, mu_min, log_length)
156
+
157
+ for i in range(pressure_steps):
158
+ vp[:, i], vs_v[:, i], vs_h[:, i], rho_b_est[:, i] = fcn(
159
+ k_min,
160
+ mu_min,
161
+ rho_min,
162
+ k_fl,
163
+ rho_fl,
164
+ phi,
165
+ perm,
166
+ visco,
167
+ alpha,
168
+ v,
169
+ tau,
170
+ frequency,
171
+ angle,
172
+ frac_inc_con,
173
+ frac_inc_ani,
174
+ )
175
+
176
+ if i != pressure_steps - 1:
177
+ # Need to check for extreme cases with all connected or all isolated
178
+ if ctrl_connected != 0:
179
+ v_con = v * (phi * frac_inc_con).reshape(log_length, 1)
180
+ else:
181
+ v_con = np.zeros(v.shape)
182
+ if ctrl_connected != 2:
183
+ v_iso = v * (phi * (1 - frac_inc_con)).reshape(log_length, 1)
184
+ else:
185
+ v_iso = np.zeros(v.shape)
186
+ alpha_con, v_con, alpha_iso, v_iso, tau, gamma = calc_pressure_vec(
187
+ alpha,
188
+ alpha,
189
+ v_con,
190
+ v_iso,
191
+ c0,
192
+ s0,
193
+ gd,
194
+ delta_pres[i],
195
+ tau,
196
+ np.zeros_like(tau),
197
+ k_fl,
198
+ ctrl_connected,
199
+ frac_inc_ani,
200
+ )
201
+
202
+ # Post-process outputs from calc_pressure_vec to match required inputs to the T-Matrix function
203
+ # frac_inc_con, v and alpha are inputs that need to be updated
204
+ # As mentioned: assume that there is no distinction between alpha_con and alpha_iso, that could only
205
+ # happen if they differed from the start
206
+
207
+ # v_con, alpha_con or v_iso, alpha_iso can be returned as None from calc_pressure_vec
208
+ if ctrl_connected == 0:
209
+ v_con = np.zeros_like(v_iso)
210
+ alpha = alpha_iso
211
+ elif ctrl_connected == 2:
212
+ alpha = alpha_con
213
+ v_iso = np.zeros_like(v_con)
214
+ else:
215
+ alpha = alpha_con
216
+ # Don't divide by zero
217
+ idx_zero = phi == 0
218
+ if np.any(idx_zero):
219
+ v = v_con + v_iso
220
+ no_zero = np.sum(idx_zero)
221
+ v[~idx_zero, :] = v[~idx_zero, :] / phi[~idx_zero].reshape(
222
+ log_length - no_zero, 1
223
+ )
224
+ else:
225
+ v = (v_con + v_iso) / phi.reshape(log_length, 1)
226
+
227
+ # frac_inc_con is close to a single value, only numerical difference in the range 10^-16, can safely
228
+ # take the average over the alphas to make it match expected input shape
229
+ frac_inc_con = np.mean(v_con / (v_con + v_iso), axis=1)
230
+
231
+ # Return variables for each pressure step
232
+ vp_out = []
233
+ vs_v_out = []
234
+ vs_h_out = []
235
+
236
+ # Only one rho is needed - no change
237
+ rho_out = rho_b_est[:, 0]
238
+
239
+ for i in range(pressure_steps):
240
+ vp_out.append(vp[:, i])
241
+ vs_v_out.append(vs_v[:, i])
242
+ vs_h_out.append(vs_h[:, i])
243
+ return vp_out + vs_v_out + vs_h_out + [rho_out]