rock-physics-open 0.0__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.

Potentially problematic release.


This version of rock-physics-open might be problematic. Click here for more details.

Files changed (142) 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 +162 -0
  4. rock_physics_open/equinor_utilities/classification_functions/__init__.py +17 -0
  5. rock_physics_open/equinor_utilities/classification_functions/class_stats.py +58 -0
  6. rock_physics_open/equinor_utilities/classification_functions/lin_class.py +47 -0
  7. rock_physics_open/equinor_utilities/classification_functions/mahal_class.py +56 -0
  8. rock_physics_open/equinor_utilities/classification_functions/norm_class.py +65 -0
  9. rock_physics_open/equinor_utilities/classification_functions/poly_class.py +40 -0
  10. rock_physics_open/equinor_utilities/classification_functions/post_prob.py +26 -0
  11. rock_physics_open/equinor_utilities/classification_functions/two_step_classification.py +46 -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 +33 -0
  15. rock_physics_open/equinor_utilities/gen_utilities/dim_check_vector.py +83 -0
  16. rock_physics_open/equinor_utilities/gen_utilities/filter_input.py +126 -0
  17. rock_physics_open/equinor_utilities/gen_utilities/filter_output.py +78 -0
  18. rock_physics_open/equinor_utilities/machine_learning_utilities/__init__.py +14 -0
  19. rock_physics_open/equinor_utilities/machine_learning_utilities/dummy_vars.py +42 -0
  20. rock_physics_open/equinor_utilities/machine_learning_utilities/exponential_model.py +119 -0
  21. rock_physics_open/equinor_utilities/machine_learning_utilities/import_ml_models.py +61 -0
  22. rock_physics_open/equinor_utilities/machine_learning_utilities/run_regression.py +151 -0
  23. rock_physics_open/equinor_utilities/machine_learning_utilities/sigmoidal_model.py +188 -0
  24. rock_physics_open/equinor_utilities/snapshot_test_utilities/__init__.py +10 -0
  25. rock_physics_open/equinor_utilities/snapshot_test_utilities/compare_snapshots.py +145 -0
  26. rock_physics_open/equinor_utilities/snapshot_test_utilities/snapshots.py +54 -0
  27. rock_physics_open/equinor_utilities/std_functions/__init__.py +43 -0
  28. rock_physics_open/equinor_utilities/std_functions/backus_ave.py +53 -0
  29. rock_physics_open/equinor_utilities/std_functions/dvorkin_nur.py +69 -0
  30. rock_physics_open/equinor_utilities/std_functions/gassmann.py +140 -0
  31. rock_physics_open/equinor_utilities/std_functions/hashin_shtrikman.py +195 -0
  32. rock_physics_open/equinor_utilities/std_functions/hertz_mindlin.py +43 -0
  33. rock_physics_open/equinor_utilities/std_functions/moduli_velocity.py +51 -0
  34. rock_physics_open/equinor_utilities/std_functions/reflection_eq.py +98 -0
  35. rock_physics_open/equinor_utilities/std_functions/rho.py +59 -0
  36. rock_physics_open/equinor_utilities/std_functions/voigt_reuss_hill.py +128 -0
  37. rock_physics_open/equinor_utilities/std_functions/walton.py +38 -0
  38. rock_physics_open/equinor_utilities/std_functions/wood_brie.py +77 -0
  39. rock_physics_open/equinor_utilities/various_utilities/Equinor_logo.gif +0 -0
  40. rock_physics_open/equinor_utilities/various_utilities/Equinor_logo.ico +0 -0
  41. rock_physics_open/equinor_utilities/various_utilities/__init__.py +24 -0
  42. rock_physics_open/equinor_utilities/various_utilities/display_result_statistics.py +83 -0
  43. rock_physics_open/equinor_utilities/various_utilities/gassmann_dry_mod.py +37 -0
  44. rock_physics_open/equinor_utilities/various_utilities/gassmann_mod.py +37 -0
  45. rock_physics_open/equinor_utilities/various_utilities/gassmann_sub_mod.py +53 -0
  46. rock_physics_open/equinor_utilities/various_utilities/hs_average.py +40 -0
  47. rock_physics_open/equinor_utilities/various_utilities/pressure.py +88 -0
  48. rock_physics_open/equinor_utilities/various_utilities/reflectivity.py +85 -0
  49. rock_physics_open/equinor_utilities/various_utilities/timeshift.py +91 -0
  50. rock_physics_open/equinor_utilities/various_utilities/vp_vs_rho_set_statistics.py +154 -0
  51. rock_physics_open/equinor_utilities/various_utilities/vrh_3_min.py +61 -0
  52. rock_physics_open/fluid_models/__init__.py +9 -0
  53. rock_physics_open/fluid_models/brine_model/__init__.py +5 -0
  54. rock_physics_open/fluid_models/brine_model/brine_properties.py +143 -0
  55. rock_physics_open/fluid_models/gas_model/__init__.py +5 -0
  56. rock_physics_open/fluid_models/gas_model/gas_properties.py +277 -0
  57. rock_physics_open/fluid_models/oil_model/__init__.py +5 -0
  58. rock_physics_open/fluid_models/oil_model/dead_oil_density.py +60 -0
  59. rock_physics_open/fluid_models/oil_model/dead_oil_velocity.py +28 -0
  60. rock_physics_open/fluid_models/oil_model/live_oil_density.py +79 -0
  61. rock_physics_open/fluid_models/oil_model/live_oil_velocity.py +24 -0
  62. rock_physics_open/fluid_models/oil_model/oil_bubble_point.py +69 -0
  63. rock_physics_open/fluid_models/oil_model/oil_properties.py +114 -0
  64. rock_physics_open/sandstone_models/__init__.py +57 -0
  65. rock_physics_open/sandstone_models/cemented_shalysand_sandyshale_models.py +304 -0
  66. rock_physics_open/sandstone_models/constant_cement_models.py +204 -0
  67. rock_physics_open/sandstone_models/constant_cement_optimisation.py +122 -0
  68. rock_physics_open/sandstone_models/contact_cement_model.py +138 -0
  69. rock_physics_open/sandstone_models/curvefit_sandstone_models.py +143 -0
  70. rock_physics_open/sandstone_models/friable_models.py +178 -0
  71. rock_physics_open/sandstone_models/friable_optimisation.py +112 -0
  72. rock_physics_open/sandstone_models/friable_shalysand_sandyshale_models.py +235 -0
  73. rock_physics_open/sandstone_models/patchy_cement_fluid_substitution_model.py +477 -0
  74. rock_physics_open/sandstone_models/patchy_cement_model.py +286 -0
  75. rock_physics_open/sandstone_models/patchy_cement_optimisation.py +251 -0
  76. rock_physics_open/sandstone_models/unresolved_cemented_sandshale_models.py +134 -0
  77. rock_physics_open/sandstone_models/unresolved_friable_sandshale_models.py +126 -0
  78. rock_physics_open/shale_models/__init__.py +19 -0
  79. rock_physics_open/shale_models/dem.py +174 -0
  80. rock_physics_open/shale_models/dem_dual_por.py +61 -0
  81. rock_physics_open/shale_models/kus_tok.py +59 -0
  82. rock_physics_open/shale_models/multi_sca.py +133 -0
  83. rock_physics_open/shale_models/pq.py +102 -0
  84. rock_physics_open/shale_models/sca.py +90 -0
  85. rock_physics_open/shale_models/shale4_mineral.py +147 -0
  86. rock_physics_open/shale_models/shale4_mineral_dem_overlay.py +92 -0
  87. rock_physics_open/span_wagner/__init__.py +5 -0
  88. rock_physics_open/span_wagner/co2_properties.py +438 -0
  89. rock_physics_open/span_wagner/coefficients.py +165 -0
  90. rock_physics_open/span_wagner/equations.py +104 -0
  91. rock_physics_open/span_wagner/tables/__init__.py +0 -0
  92. rock_physics_open/span_wagner/tables/carbon_dioxide_density.npz +0 -0
  93. rock_physics_open/span_wagner/tables/lookup_table.py +33 -0
  94. rock_physics_open/t_matrix_models/Equinor_logo.ico +0 -0
  95. rock_physics_open/t_matrix_models/__init__.py +45 -0
  96. rock_physics_open/t_matrix_models/carbonate_pressure_substitution.py +124 -0
  97. rock_physics_open/t_matrix_models/curvefit_t_matrix_exp.py +124 -0
  98. rock_physics_open/t_matrix_models/curvefit_t_matrix_min.py +86 -0
  99. rock_physics_open/t_matrix_models/opt_subst_utilities.py +415 -0
  100. rock_physics_open/t_matrix_models/parse_t_matrix_inputs.py +297 -0
  101. rock_physics_open/t_matrix_models/run_t_matrix.py +243 -0
  102. rock_physics_open/t_matrix_models/t_matrix_C.py +210 -0
  103. rock_physics_open/t_matrix_models/t_matrix_opt_fluid_sub_exp.py +137 -0
  104. rock_physics_open/t_matrix_models/t_matrix_opt_fluid_sub_petec.py +163 -0
  105. rock_physics_open/t_matrix_models/t_matrix_opt_forward_model_exp.py +72 -0
  106. rock_physics_open/t_matrix_models/t_matrix_opt_forward_model_min.py +86 -0
  107. rock_physics_open/t_matrix_models/t_matrix_parameter_optimisation_exp.py +172 -0
  108. rock_physics_open/t_matrix_models/t_matrix_parameter_optimisation_min.py +159 -0
  109. rock_physics_open/t_matrix_models/t_matrix_vector/__init__.py +12 -0
  110. rock_physics_open/t_matrix_models/t_matrix_vector/array_functions.py +75 -0
  111. rock_physics_open/t_matrix_models/t_matrix_vector/calc_c_eff.py +163 -0
  112. rock_physics_open/t_matrix_models/t_matrix_vector/calc_isolated.py +95 -0
  113. rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd.py +40 -0
  114. rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd_eff.py +116 -0
  115. rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd_uuv.py +18 -0
  116. rock_physics_open/t_matrix_models/t_matrix_vector/calc_pressure.py +140 -0
  117. rock_physics_open/t_matrix_models/t_matrix_vector/calc_t.py +71 -0
  118. rock_physics_open/t_matrix_models/t_matrix_vector/calc_td.py +42 -0
  119. rock_physics_open/t_matrix_models/t_matrix_vector/calc_theta.py +43 -0
  120. rock_physics_open/t_matrix_models/t_matrix_vector/calc_x.py +33 -0
  121. rock_physics_open/t_matrix_models/t_matrix_vector/calc_z.py +50 -0
  122. rock_physics_open/t_matrix_models/t_matrix_vector/check_and_tile.py +43 -0
  123. rock_physics_open/t_matrix_models/t_matrix_vector/g_tensor.py +140 -0
  124. rock_physics_open/t_matrix_models/t_matrix_vector/iso_av.py +60 -0
  125. rock_physics_open/t_matrix_models/t_matrix_vector/iso_ave_all.py +55 -0
  126. rock_physics_open/t_matrix_models/t_matrix_vector/pressure_input.py +44 -0
  127. rock_physics_open/t_matrix_models/t_matrix_vector/t_matrix_vec.py +278 -0
  128. rock_physics_open/t_matrix_models/t_matrix_vector/velocity_vti_angles.py +81 -0
  129. rock_physics_open/t_matrix_models/tmatrix_python.dll +0 -0
  130. rock_physics_open/t_matrix_models/tmatrix_python.so +0 -0
  131. rock_physics_open/ternary_plots/__init__.py +3 -0
  132. rock_physics_open/ternary_plots/gen_ternary_plot.py +73 -0
  133. rock_physics_open/ternary_plots/shale_prop_ternary.py +337 -0
  134. rock_physics_open/ternary_plots/ternary_patches.py +277 -0
  135. rock_physics_open/ternary_plots/ternary_plot_utilities.py +197 -0
  136. rock_physics_open/ternary_plots/unconventionals_ternary.py +75 -0
  137. rock_physics_open/version.py +21 -0
  138. rock_physics_open-0.0.dist-info/METADATA +92 -0
  139. rock_physics_open-0.0.dist-info/RECORD +142 -0
  140. rock_physics_open-0.0.dist-info/WHEEL +5 -0
  141. rock_physics_open-0.0.dist-info/licenses/LICENSE +165 -0
  142. rock_physics_open-0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,195 @@
1
+ import numpy as np
2
+
3
+ from rock_physics_open.equinor_utilities.gen_utilities import dim_check_vector
4
+
5
+
6
+ def hashin_shtrikman(k1, mu1, k2, mu2, f):
7
+ """
8
+ Hashin-Sktrikman upper or lower according to ordering of phases.
9
+
10
+ Parameters
11
+ ----------
12
+ k1 : np.ndarray
13
+ Bulk modulus of phase 1 [Pa].
14
+ mu1 : np.ndarray
15
+ Shear modulus of phase 1 [Pa].
16
+ k2 : np.ndarray
17
+ Bulk modulus of phase 2 [Pa].
18
+ mu2 : np.ndarray
19
+ Shear modulus of phase 2 [Pa].
20
+ f : np.ndarray
21
+ Fraction of phase 1 [fraction].
22
+
23
+ Returns
24
+ -------
25
+ tuple
26
+ k, mu : np.ndarray.
27
+ k: effective bulk modulus [Pa], mu: effective shear modulus [Pa].
28
+ """
29
+ k = k1 + (1 - f) * (k2 - k1) / (1 + (k2 - k1) * f * (k1 + 4 / 3 * mu1) ** -1)
30
+ mu = mu1 + (1 - f) * (mu2 - mu1) / (
31
+ 1 + 2 * (mu2 - mu1) * f * (k1 + 2 * mu1) / (5 * mu1 * (k1 + 4 / 3 * mu1))
32
+ )
33
+
34
+ return k, mu
35
+
36
+
37
+ def hashin_shtrikman_average(k1, mu1, k2, mu2, f):
38
+ """
39
+ Average of Hashin-Shtrikman upper and lower bound.
40
+
41
+ Parameters
42
+ ----------
43
+ k1 : np.ndarray
44
+ Bulk modulus of phase 1 [Pa].
45
+ mu1 : np.ndarray
46
+ Shear modulus of phase 1 [Pa].
47
+ k2 : np.ndarray
48
+ Bulk modulus of phase 2 [Pa].
49
+ mu2 : np.ndarray
50
+ Shear modulus of phase 2 [Pa].
51
+ f : np.ndarray
52
+ Fraction of phase 1 [fraction].
53
+
54
+ Returns
55
+ -------
56
+ tuple
57
+ k_av, mu_av : np.ndarray.
58
+ k_av: effective bulk modulus [Pa], mu_av: effective shear modulus [Pa]
59
+ """
60
+ k_hs1, mu_hs1 = hashin_shtrikman(k1, mu1, k2, mu2, f)
61
+ k_hs2, mu_hs2 = hashin_shtrikman(k2, mu2, k1, mu1, 1 - f)
62
+
63
+ k_av = (k_hs1 + k_hs2) / 2
64
+ mu_av = (mu_hs1 + mu_hs2) / 2
65
+
66
+ return k_av, mu_av
67
+
68
+
69
+ def hashin_shtrikman_walpole(k1, mu1, k2, mu2, f1, bound="lower"):
70
+ """
71
+ Hashin-Shtrikman upper bound is obtained when the stiffest material is
72
+ termed 1 and vice versa for lower bound. Tricky in cases like Quartz -
73
+ Calcite where the K and Mu have opposed values. HS - Walpole is
74
+ generalised to regard highest and lowest values in each case. The default
75
+ is to generate lower bound.
76
+
77
+ Parameters
78
+ ----------
79
+ k1 : np.ndarray
80
+ Bulk modulus of phase 1 [Pa].
81
+ mu1 : np.ndarray
82
+ Shear modulus of phase 1 [Pa].
83
+ k2 : np.ndarray
84
+ Bulk modulus of phase 2 [Pa].
85
+ mu2 : np.ndarray
86
+ Shear modulus of phase 2 [Pa].
87
+ f1 : np.ndarray or float
88
+ Fraction of phase 1 [fraction].
89
+ bound: str
90
+ 'upper' or 'lower' selection of upper of lower bound of effective medium.
91
+ Returns
92
+ -------
93
+ tuple
94
+ k, mu : np.ndarray.
95
+ k: effective bulk modulus [Pa], mu: effective shear modulus [Pa].
96
+ """
97
+ k1, mu1, k2, mu2, f1 = dim_check_vector((k1, mu1, k2, mu2, f1))
98
+ if bound.lower() not in ["lower", "upper"]:
99
+ raise ValueError(f'{__file__}: bound must be one of "lower" or "upper"')
100
+
101
+ idx_k = k1 == k2
102
+ idx_mu = mu1 == mu2
103
+ f2 = 1 - f1
104
+
105
+ if bound.lower() == "lower":
106
+ k_m = np.minimum(k1, k2)
107
+ mu_m = np.minimum(mu1, mu2)
108
+ else:
109
+ k_m = np.maximum(k1, k2)
110
+ mu_m = np.maximum(mu1, mu2)
111
+
112
+ k = np.zeros(k1.shape)
113
+ mu = np.zeros(k1.shape)
114
+
115
+ if np.any(idx_k):
116
+ k[idx_k] = k1[idx_k]
117
+ if np.any(~idx_k):
118
+ k[~idx_k] = k1[~idx_k] + f2[~idx_k] / (
119
+ (k2[~idx_k] - k1[~idx_k]) ** -1
120
+ + f1[~idx_k] * (k1[~idx_k] + 4 / 3 * mu_m[~idx_k]) ** -1
121
+ )
122
+ if np.any(idx_mu):
123
+ mu[idx_mu] = mu1[idx_mu]
124
+ if np.any(~idx_mu):
125
+ mu[~idx_mu] = mu1[~idx_mu] + f2[~idx_mu] / (
126
+ (mu2[~idx_mu] - mu1[~idx_mu]) ** -1
127
+ + f1[~idx_mu]
128
+ * (
129
+ mu1[~idx_mu]
130
+ + mu_m[~idx_mu]
131
+ / 6
132
+ * (9 * k_m[~idx_mu] + 8 * mu_m[~idx_mu])
133
+ / (k_m[~idx_mu] + 2 * mu_m[~idx_mu])
134
+ )
135
+ ** -1
136
+ )
137
+
138
+ return k, mu
139
+
140
+
141
+ def multi_hashin_shtrikman(*coeffs, mode="average"):
142
+ """
143
+ Hashin-Shtrikman effective medium calculation for multi-mineral case.
144
+
145
+ Parameters
146
+ ----------
147
+ coeffs : np.ndarray
148
+ Triplets of vectors with k (bulk modulus [Pa]), mu (shear modulus [Pa]) and fraction for each mineral.
149
+ mode : str
150
+ 'average', 'upper' or 'lower'.
151
+
152
+ Returns
153
+ -------
154
+ tuple
155
+ k_hs, mu_hs : np.ndarray.
156
+ k_hs, mu_hs - bulk modulus and shear modulus for effective medium [Pa].
157
+ """
158
+ if not len(coeffs) % 3 == 0:
159
+ raise ValueError(
160
+ "multi_hashin_shtrikman: inputs not vectors of k, mu and fraction for each mineral"
161
+ )
162
+
163
+ k_arr = np.array(coeffs[::3])
164
+ mu_arr = np.array(coeffs[1::3])
165
+ f = np.array(coeffs[2::3])
166
+
167
+ if not np.all(np.around(np.sum(f, axis=0), decimals=6) == 1.0):
168
+ raise ValueError("multi_hashin_shtrikman: all fractions do not add up to 1.0")
169
+
170
+ if mode.lower() not in ["average", "upper", "lower"]:
171
+ raise ValueError(
172
+ 'multi_hashin_shtrikman: mode is not one of "average", "upper" or "lower"'
173
+ )
174
+
175
+ k_min = np.min(k_arr, axis=0)
176
+ k_max = np.max(k_arr, axis=0)
177
+ mu_min = np.min(mu_arr, axis=0)
178
+ mu_max = np.max(mu_arr, axis=0)
179
+
180
+ k_hs_upper = np.sum(f / (k_arr + 4 / 3 * mu_max), axis=0) ** -1 - 4 / 3 * mu_max
181
+ k_hs_lower = np.sum(f / (k_arr + 4 / 3 * mu_min), axis=0) ** -1 - 4 / 3 * mu_min
182
+
183
+ zeta_max = mu_max / 6 * (9 * k_max + 8 * mu_max) / (k_max + 2 * mu_max)
184
+ zeta_min = mu_min / 6 * (9 * k_min + 8 * mu_min) / (k_min + 2 * mu_min)
185
+
186
+ mu_hs_upper = np.sum(f / (mu_arr + zeta_max), axis=0) ** -1 - zeta_max
187
+ mu_hs_lower = np.sum(f / (mu_arr + zeta_min), axis=0) ** -1 - zeta_min
188
+
189
+ if mode == "lower":
190
+ return k_hs_lower, mu_hs_lower
191
+ if mode == "upper":
192
+ return k_hs_upper, mu_hs_upper
193
+ k_hs = 0.5 * (k_hs_upper + k_hs_lower)
194
+ mu_hs = 0.5 * (mu_hs_upper + mu_hs_lower)
195
+ return k_hs, mu_hs
@@ -0,0 +1,43 @@
1
+ import numpy as np
2
+
3
+
4
+ def hertz_mindlin(k, mu, phi_c, p, shear_red, coord=None):
5
+ """
6
+ Hertz-Mindlin Pressure-induced moduli increase at critical porosity.
7
+
8
+ Parameters
9
+ ----------
10
+ k : np.ndarray
11
+ Bulk modulus of grain mineral [Pa].
12
+ mu : np.ndarray
13
+ Shear modulus of grain mineral [Pa].
14
+ phi_c : np.ndarray
15
+ Critical porosity [fraction].
16
+ p : np.ndarray
17
+ Effective pressure = lithostatic pressure - hydrostatic pressure [Pa].
18
+ shear_red : float or np.ndarray
19
+ Reduced shear factor, if set to 1.0, calculation reduces to standard Hertz-Mindlin equation.
20
+ coord
21
+ coordination number, i.e. the number of grain contacts per grain. If not provided a porosity based
22
+ estimate is used.
23
+
24
+ Returns
25
+ -------
26
+ tuple
27
+ k_dry, mu_dry : np.ndarray.
28
+ k_dry: Bulk modulus [Pa] at effective pressure p,
29
+ mu_dry: Shear modulus [Pa] at effective pressure p.
30
+ """
31
+ n = 25.98805 * phi_c**2 - 43.7622 * phi_c + 21.6719 if coord is None else coord
32
+
33
+ poiss = (3 * k - 2 * mu) / (2 * (3 * k + mu))
34
+
35
+ a = ((3 * np.pi * (1 - poiss) * p) / (2 * n * (1 - phi_c) * mu)) ** (1 / 3)
36
+
37
+ s_n = (4 * a * mu) / (1 - poiss)
38
+ s_t = (8 * a * mu) / (2 - poiss)
39
+
40
+ k_dry = (n * (1 - phi_c) / (12 * np.pi)) * s_n
41
+ mu_dry = (n * (1 - phi_c) / (20 * np.pi)) * (s_n + 1.5 * s_t * shear_red)
42
+
43
+ return k_dry, mu_dry
@@ -0,0 +1,51 @@
1
+ def moduli(vp, vs, rhob):
2
+ """
3
+ Calculate isotropic moduli from velocity and density.
4
+
5
+ Parameters
6
+ ----------
7
+ vp : np.ndarray or float
8
+ Pressure wave velocity [m/s].
9
+ vs : np.ndarray or float
10
+ Shear wave velocity [m/s].
11
+ rhob : np.ndarray or float
12
+ Bulk density [kg/m^3].
13
+
14
+ Returns
15
+ -------
16
+ tuple
17
+ k, mu : (np.ndarray, np.ndarray) or (float, float).
18
+ k: bulk modulus [Pa], mu: shear modulus [Pa].
19
+ """
20
+ mu = vs**2 * rhob
21
+ k = vp**2 * rhob - 4 / 3 * mu
22
+
23
+ return k, mu
24
+
25
+
26
+ def velocity(k, mu, rhob):
27
+ """
28
+ Calculate velocity, acoustic impedance and vp/vs ratio from elastic moduli and density.
29
+
30
+ Parameters
31
+ ----------
32
+ k : np.ndarray, float
33
+ Bulk modulus [Pa].
34
+ mu : np.ndarray, float
35
+ Shear modulus [Pa].
36
+ rhob : np.ndarray, float
37
+ Bulk density [kg/m^3].
38
+
39
+ Returns
40
+ -------
41
+ tuple
42
+ vp, vs, ai, vp_vs : np.ndarray.
43
+ vp: pressure wave velocity [m/s], vs: shear wave velocity [m/s], ai: acoustic impedance [m/s x kg/m^3],
44
+ vp_vs: velocity ratio [fraction].
45
+ """
46
+ vs = (mu / rhob) ** 0.5
47
+ vp = ((k + 4 / 3 * mu) / rhob) ** 0.5
48
+ ai = vp * rhob
49
+ vp_vs = vp / vs
50
+
51
+ return vp, vs, ai, vp_vs
@@ -0,0 +1,98 @@
1
+ import numpy as np
2
+
3
+
4
+ def _refl_models(vp, vs, rho, theta, k=2.0, mod="aki_richards"):
5
+ """Calculate reflect coeff.
6
+
7
+ Parameters
8
+ ----------
9
+ vp : np.ndarray
10
+ vp array.
11
+ vs : np.ndarray
12
+ vs array.
13
+ rho : np.ndarray
14
+ rho array.
15
+ theta : float, np.ndarray
16
+ Theta value.
17
+ k : float, optional
18
+ By default 2.0.
19
+ mod : str, optional
20
+ By default 'aki_richards'.
21
+
22
+ Returns
23
+ -------
24
+ np.ndarray
25
+ Reflect coeff.
26
+ """
27
+ theta = theta / 180 * np.pi
28
+ r_vp = (vp[1:] - vp[0:-1]) / (vp[0:-1] + vp[1:])
29
+ r_vs = (vs[1:] - vs[0:-1]) / (vs[0:-1] + vs[1:])
30
+ r_rho = (rho[1:] - rho[0:-1]) / (rho[0:-1] + rho[1:])
31
+ # Need to append one sample to make returned array of the same size - repeat the last value
32
+ r_vp = np.append(r_vp, r_vp[-1])
33
+ r_vs = np.append(r_vs, r_vs[-1])
34
+ r_rho = np.append(r_rho, r_rho[-1])
35
+
36
+ if mod == "aki_richards":
37
+ reflect_coeff = (
38
+ 0.5 * (r_vp + r_rho)
39
+ + (0.5 * r_vp - 2 * k**-2 * (2 * r_vs + r_rho)) * np.sin(theta) ** 2
40
+ + 0.5 * r_vp * (np.tan(theta) ** 2 - np.sin(theta) ** 2)
41
+ )
42
+ else:
43
+ reflect_coeff = (
44
+ 5 / 8 - 0.5 * k**-2 * np.sin(theta) ** 2 + 0.5 * np.tan(theta) ** 2
45
+ ) * r_vp - 4 * k**-2 * np.sin(theta) ** 2 * r_vs
46
+
47
+ return reflect_coeff
48
+
49
+
50
+ def aki_richards(vp, vs, rho, theta, k=2.0):
51
+ """
52
+ Linearised Zoeppritz equation according to Aki and Richards.
53
+
54
+ Parameters
55
+ ----------
56
+ vp : np.ndarray
57
+ Pressure wave velocity [m/s].
58
+ vs : np.ndarray
59
+ Shear wave velocity [m/s].
60
+ rho : np.ndarray
61
+ Density [kg/m^3].
62
+ theta : np.ndarray
63
+ Angle of incident ray [radians].
64
+ k : float
65
+ Background vp/vs [unitless].
66
+
67
+ Returns
68
+ -------
69
+ refl_coeff : np.ndarray
70
+ Reflection coefficient [unitless].
71
+ """
72
+ return _refl_models(vp, vs, rho, theta, k, mod="aki_richards")
73
+
74
+
75
+ def smith_gidlow(vp, vs, rho, theta, k=2.0):
76
+ """
77
+ Linearised Zoeppritz equation according to Smith and Gidlow.
78
+
79
+ Parameters
80
+ ----------
81
+ vp : np.ndarray
82
+ Pressure wave velocity [m/s].
83
+ vs : np.ndarray
84
+ Shear wave velocity [m/s].
85
+ rho : np.ndarray
86
+ Density [kg/m^3].
87
+ theta : np.ndarray
88
+ Angle of incident ray [radians].
89
+ k : float
90
+ Background vp/vs [unitless].
91
+
92
+ Returns
93
+ -------
94
+ refl_coeff : np.ndarray
95
+ Reflection coefficient [unitless].
96
+ """
97
+
98
+ return _refl_models(vp, vs, rho, theta, k, mod="smith_gidlow")
@@ -0,0 +1,59 @@
1
+ from warnings import warn
2
+
3
+ import numpy as np
4
+
5
+
6
+ def rho_b(phi, rho_f, rho_mat):
7
+ """
8
+ Calculate bulk density from porosity, fluid density and matrix density.
9
+
10
+ Parameters
11
+ ----------
12
+ phi: np.ndarray
13
+ Porosity [fraction].
14
+ rho_f: np.ndarray
15
+ Fluid bulk density [kg/m^3].
16
+ rho_mat: np.ndarray
17
+ Matrix bulk density [kg/m^3].
18
+
19
+ Returns
20
+ -------
21
+ np.ndarray
22
+ rhob: bulk density [kg/m^3].
23
+ """
24
+ return phi * rho_f + (1 - phi) * rho_mat
25
+
26
+
27
+ def rho_m(frac_cem, phi, rho_cem, rho_min):
28
+ """
29
+ Calculates matrix density as a combination of cement fraction and minerals
30
+ fracCem is defined as cement fraction relative to total volume.
31
+
32
+ Parameters
33
+ ----------
34
+ frac_cem : np.ndarray
35
+ Cement fraction [fraction].
36
+ phi : np.ndarray
37
+ Porosity [fraction].
38
+ rho_cem : np.ndarray
39
+ Cement density [kg/m^3].
40
+ rho_min : np.ndarray
41
+ Mineral density [kg/m^3].
42
+
43
+ Returns
44
+ -------
45
+ np.ndarray
46
+ rho_mat: matrix density [kg/m^3]
47
+ """
48
+ idx = np.logical_and(phi >= 0.0, phi < 1.0)
49
+ if np.sum(idx) != len(phi):
50
+ warn(
51
+ f"{__file__}: phi out of range in {len(phi) - np.sum(idx)} sample",
52
+ )
53
+
54
+ rho_mat = np.ones_like(phi) * np.nan
55
+ f_cem = frac_cem[idx] / (1 - phi[idx])
56
+
57
+ rho_mat[idx] = f_cem * rho_cem[idx] + (1 - f_cem) * rho_min[idx]
58
+
59
+ return rho_mat
@@ -0,0 +1,128 @@
1
+ import numpy as np
2
+
3
+
4
+ def voigt(k1, mu1, k2, mu2, f1):
5
+ """
6
+ Effective media calculation of a mixture of two phases using the Voigt bound.
7
+
8
+ Parameters
9
+ ----------
10
+ k1 : np.ndarray
11
+ Bulk modulus of phase 1 [Pa].
12
+ mu1 : np.ndarray
13
+ Shear modulus of phase 1 [Pa].
14
+ k2 : np.ndarray
15
+ Bulk modulus of phase 2 [Pa].
16
+ mu2 : np.ndarray
17
+ Shear modulus of phase 2 [Pa].
18
+ f1 : np.ndarray
19
+ Fraction of phase 1 [fraction].
20
+
21
+ Returns
22
+ -------
23
+ tuple
24
+ k, mu : np.ndarray.
25
+ k: effective bulk modulus [Pa], mu: effective shear modulus [Pa]
26
+ """
27
+ f2 = 1 - f1
28
+ k_v = f1 * k1 + f2 * k2
29
+ mu_v = f1 * mu1 + f2 * mu2
30
+
31
+ return k_v, mu_v
32
+
33
+
34
+ def voigt_reuss_hill(k1, mu1, k2, mu2, f1):
35
+ """
36
+ Effective media calculation of a mixture of two phases using the Voigt-Reuss-Hill average.
37
+
38
+ Parameters
39
+ ----------
40
+ k1 : np.ndarray
41
+ Bulk modulus of phase 1 [Pa].
42
+ mu1 : np.ndarray
43
+ Shear modulus of phase 1 [Pa].
44
+ k2 : np.ndarray
45
+ Bulk modulus of phase 2 [Pa].
46
+ mu2 : np.ndarray
47
+ Shear modulus of phase 2 [Pa].
48
+ f1 : np.ndarray
49
+ Fraction of phase 1 [fraction].
50
+
51
+ Returns
52
+ -------
53
+ tuple
54
+ k, mu : np.ndarray
55
+ k: effective bulk modulus [Pa], mu: effective shear modulus [Pa]
56
+ """
57
+ k_v, mu_v = voigt(k1, mu1, k2, mu2, f1)
58
+ k_r, mu_r = reuss(k1, mu1, k2, mu2, f1)
59
+
60
+ k_vrh = (k_r + k_v) / 2
61
+ mu_vrh = (mu_r + mu_v) / 2
62
+
63
+ return k_vrh, mu_vrh
64
+
65
+
66
+ def multi_voigt_reuss_hill(*varargin):
67
+ """
68
+ Voigt-Reuss-Hill with multiple mineral input.
69
+
70
+ Call function with [k, mu] = multi_voigt_reuss_hill(k1, mu1, f2, ....kn,
71
+ mun, fn). Fractions must add up to 1.0. All inputs are assumed to be
72
+ vectors with the same length.
73
+
74
+ Parameters
75
+ ----------
76
+ varargin : np.ndarray
77
+
78
+ Returns
79
+ -------
80
+ tuple
81
+ k, mu : np.ndarray
82
+ k: effective bulk modulus [Pa], mu: effective shear modulus [Pa].
83
+ """
84
+ k_min = np.array(varargin[::3])
85
+ mu_min = np.array(varargin[1::3])
86
+ f = np.array(varargin[2::3])
87
+
88
+ k_voigt = np.sum(k_min * f, axis=0)
89
+ mu_voigt = np.sum(mu_min * f, axis=0)
90
+
91
+ k_reuss = 1 / np.sum(f / k_min, axis=0)
92
+ mu_reuss = 1 / np.sum(f / mu_min, axis=0)
93
+
94
+ k = (k_voigt + k_reuss) / 2
95
+ mu = (mu_voigt + mu_reuss) / 2
96
+
97
+ return k, mu
98
+
99
+
100
+ def reuss(k1, mu1, k2, mu2, f1):
101
+ """
102
+ Effective media calculation of a mixture of two phases using the Reuss bound.
103
+
104
+ Parameters
105
+ ----------
106
+ k1 : np.ndarray
107
+ Bulk modulus of phase 1 [Pa].
108
+ mu1 : np.ndarray
109
+ Shear modulus of phase 1 [Pa].
110
+ k2 : np.ndarray
111
+ Bulk modulus of phase 2 [Pa].
112
+ mu2 : np.ndarray
113
+ Shear modulus of phase 2 [Pa].
114
+ f1 : np.ndarray
115
+ Fraction of phase 1 [fraction].
116
+
117
+ Returns
118
+ -------
119
+ tuple
120
+ k, mu : np.ndarray.
121
+ k: effective bulk modulus [Pa], mu: effective shear modulus [Pa].
122
+ """
123
+ f2 = 1 - f1
124
+
125
+ k_r = 1 / (f1 / k1 + f2 / k2)
126
+ mu_r = 1 / (f1 / mu1 + f2 / mu2)
127
+
128
+ return k_r, mu_r
@@ -0,0 +1,38 @@
1
+ import numpy as np
2
+
3
+
4
+ def walton_smooth(k, mu, phi, p_eff, coord=None):
5
+ """
6
+ Walton Smooth Pressure-induced moduli increase at critical porosity.
7
+
8
+ Parameters
9
+ ----------
10
+ k : np.ndarray
11
+ Bulk modulus of grain mineral [Pa].
12
+ mu : np.ndarray
13
+ Shear modulus of grain mineral [Pa].
14
+ phi : np.ndarray
15
+ Critical porosity [fraction].
16
+ p_eff : np.ndarray
17
+ Effective Pressure = (Lithostatic - Hydrostatic) pressure [Pa].
18
+ coord : float or np.ndarray
19
+ Coordination number, i.e. number of grain contract per grain. If not provided a porosity based estimate is
20
+ used [unitless].
21
+
22
+ Returns
23
+ -------
24
+ tuple
25
+ k_dry , mu_dry : np.ndarray.
26
+ k_dry Bulk modulus at effective pressure p,
27
+ mu_dry Shear modulus at effective pressure p.
28
+ """
29
+
30
+ n = 25.98805 * phi**2 - 43.7622 * phi + 21.6719 if coord is None else coord
31
+
32
+ pr_min = (3 * k - 2 * mu) / (2 * (3 * k + mu))
33
+ k_dry_num = n**2 * (1 - phi) ** 2 * mu**2 * p_eff # Numerator in walton expression
34
+ k_dry_denom = 18 * np.pi**2 * (1 - pr_min) ** 2 # Denominator in Walton expression
35
+ k_dry = (k_dry_num / k_dry_denom) ** (1 / 3) # Bulk modulus
36
+ mu_dry = 3 / 5 * k_dry
37
+
38
+ return k_dry, mu_dry
@@ -0,0 +1,77 @@
1
+ import numpy as np
2
+
3
+
4
+ def brie(s_gas, k_gas, s_brine, k_brine, s_oil, k_oil, e):
5
+ """
6
+ Brie function for effective bulk modulus of a mix of fluids.
7
+
8
+ Parameters
9
+ ----------
10
+ s_gas : np.ndarray
11
+ Gas saturation [ratio].
12
+ k_gas : np.ndarray
13
+ Gas bulk modulus [Pa].
14
+ s_brine : np.ndarray
15
+ Brine saturation [ratio].
16
+ k_brine : np.ndarray
17
+ Brine bulk modulus [Pa].
18
+ s_oil : np.ndarray
19
+ Oil saturation [ratio].
20
+ k_oil : np.ndarray
21
+ Oil bulk modulus [Pa].
22
+ e : float or np.ndarray
23
+ Exponent in Brie function [unitless].
24
+
25
+ Returns
26
+ -------
27
+ np.ndarray
28
+ k: effective bulk modulus [Pa].
29
+ """
30
+
31
+ # Reuss average for fluids, catch zero fluid saturations
32
+ idx = s_brine + s_oil > 0
33
+ k_liquid = np.zeros(k_brine.shape)
34
+ k_liquid[idx] = (s_brine[idx] / k_brine[idx] + s_oil[idx] / k_oil[idx]) ** -1
35
+
36
+ return (k_liquid - k_gas) * (1 - s_gas) ** e + k_gas
37
+
38
+
39
+ def wood(s1, k1, rho1, k2, rho2):
40
+ """
41
+ Wood effective fluid properties for a mix of two fluids.
42
+
43
+ Parameters
44
+ ----------
45
+ s1 : np.ndarray
46
+ Saturation of phase 1 [ratio].
47
+ k1 : np.ndarray
48
+ Bulk modulus of phase 1 [Pa].
49
+ rho1 : np.ndarray
50
+ Density of phase 1 [kg/m^3].
51
+ k2 : np.ndarray
52
+ Bulk modulus of phase 2 [Pa].
53
+ rho2 : np.ndarray
54
+ Density of phase 2 [kg/m^3].
55
+
56
+ Returns
57
+ -------
58
+ tuple
59
+ k, rho : np.ndarray.
60
+ k: effective fluid bulk modulus [Pa], rho: effective fluid density [kg/m^3].
61
+ """
62
+ s2 = 1 - s1
63
+
64
+ k = 1 / (s1 / k1 + s2 / k2)
65
+ rho = s1 * rho1 + s2 * rho2
66
+
67
+ return k, rho
68
+
69
+
70
+ def multi_wood(fractions, bulk_moduli):
71
+ assert len(fractions) == len(bulk_moduli)
72
+ sum_fractions = sum(fractions)
73
+ ratio_sum = sum(
74
+ saturation / bulk_modulus
75
+ for (saturation, bulk_modulus) in zip(fractions, bulk_moduli)
76
+ )
77
+ return sum_fractions / ratio_sum