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.
- rock_physics_open/__init__.py +0 -0
- rock_physics_open/equinor_utilities/__init__.py +0 -0
- rock_physics_open/equinor_utilities/anisotropy.py +211 -0
- rock_physics_open/equinor_utilities/classification_functions/__init__.py +17 -0
- rock_physics_open/equinor_utilities/classification_functions/class_stats.py +68 -0
- rock_physics_open/equinor_utilities/classification_functions/lin_class.py +53 -0
- rock_physics_open/equinor_utilities/classification_functions/mahal_class.py +63 -0
- rock_physics_open/equinor_utilities/classification_functions/norm_class.py +73 -0
- rock_physics_open/equinor_utilities/classification_functions/poly_class.py +45 -0
- rock_physics_open/equinor_utilities/classification_functions/post_prob.py +27 -0
- rock_physics_open/equinor_utilities/classification_functions/two_step_classification.py +60 -0
- rock_physics_open/equinor_utilities/conversions.py +10 -0
- rock_physics_open/equinor_utilities/gen_utilities/__init__.py +11 -0
- rock_physics_open/equinor_utilities/gen_utilities/dict_to_float.py +38 -0
- rock_physics_open/equinor_utilities/gen_utilities/dim_check_vector.py +113 -0
- rock_physics_open/equinor_utilities/gen_utilities/filter_input.py +131 -0
- rock_physics_open/equinor_utilities/gen_utilities/filter_output.py +88 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/__init__.py +15 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/base_pressure_model.py +170 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/dummy_vars.py +53 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/exponential_model.py +137 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/import_ml_models.py +77 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/polynomial_model.py +132 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/run_regression.py +209 -0
- rock_physics_open/equinor_utilities/machine_learning_utilities/sigmoidal_model.py +241 -0
- rock_physics_open/equinor_utilities/optimisation_utilities/__init__.py +19 -0
- rock_physics_open/equinor_utilities/optimisation_utilities/opt_subst_utilities.py +455 -0
- rock_physics_open/equinor_utilities/snapshot_test_utilities/__init__.py +10 -0
- rock_physics_open/equinor_utilities/snapshot_test_utilities/compare_snapshots.py +184 -0
- rock_physics_open/equinor_utilities/snapshot_test_utilities/snapshots.py +97 -0
- rock_physics_open/equinor_utilities/std_functions/__init__.py +43 -0
- rock_physics_open/equinor_utilities/std_functions/backus_ave.py +68 -0
- rock_physics_open/equinor_utilities/std_functions/dvorkin_nur.py +77 -0
- rock_physics_open/equinor_utilities/std_functions/gassmann.py +165 -0
- rock_physics_open/equinor_utilities/std_functions/hashin_shtrikman.py +224 -0
- rock_physics_open/equinor_utilities/std_functions/hertz_mindlin.py +51 -0
- rock_physics_open/equinor_utilities/std_functions/moduli_velocity.py +67 -0
- rock_physics_open/equinor_utilities/std_functions/reflection_eq.py +120 -0
- rock_physics_open/equinor_utilities/std_functions/rho.py +69 -0
- rock_physics_open/equinor_utilities/std_functions/voigt_reuss_hill.py +149 -0
- rock_physics_open/equinor_utilities/std_functions/walton.py +45 -0
- rock_physics_open/equinor_utilities/std_functions/wood_brie.py +94 -0
- rock_physics_open/equinor_utilities/various_utilities/Equinor_logo.gif +0 -0
- rock_physics_open/equinor_utilities/various_utilities/Equinor_logo.ico +0 -0
- rock_physics_open/equinor_utilities/various_utilities/__init__.py +24 -0
- rock_physics_open/equinor_utilities/various_utilities/display_result_statistics.py +90 -0
- rock_physics_open/equinor_utilities/various_utilities/gassmann_dry_mod.py +56 -0
- rock_physics_open/equinor_utilities/various_utilities/gassmann_mod.py +56 -0
- rock_physics_open/equinor_utilities/various_utilities/gassmann_sub_mod.py +64 -0
- rock_physics_open/equinor_utilities/various_utilities/hs_average.py +59 -0
- rock_physics_open/equinor_utilities/various_utilities/pressure.py +96 -0
- rock_physics_open/equinor_utilities/various_utilities/reflectivity.py +101 -0
- rock_physics_open/equinor_utilities/various_utilities/timeshift.py +104 -0
- rock_physics_open/equinor_utilities/various_utilities/vp_vs_rho_set_statistics.py +170 -0
- rock_physics_open/equinor_utilities/various_utilities/vrh_3_min.py +83 -0
- rock_physics_open/fluid_models/__init__.py +9 -0
- rock_physics_open/fluid_models/brine_model/__init__.py +5 -0
- rock_physics_open/fluid_models/brine_model/brine_properties.py +178 -0
- rock_physics_open/fluid_models/gas_model/__init__.py +5 -0
- rock_physics_open/fluid_models/gas_model/gas_properties.py +319 -0
- rock_physics_open/fluid_models/oil_model/__init__.py +5 -0
- rock_physics_open/fluid_models/oil_model/dead_oil_density.py +65 -0
- rock_physics_open/fluid_models/oil_model/dead_oil_velocity.py +30 -0
- rock_physics_open/fluid_models/oil_model/live_oil_density.py +82 -0
- rock_physics_open/fluid_models/oil_model/live_oil_velocity.py +24 -0
- rock_physics_open/fluid_models/oil_model/oil_bubble_point.py +69 -0
- rock_physics_open/fluid_models/oil_model/oil_properties.py +146 -0
- rock_physics_open/sandstone_models/__init__.py +59 -0
- rock_physics_open/sandstone_models/cemented_shalysand_sandyshale_models.py +304 -0
- rock_physics_open/sandstone_models/constant_cement_models.py +204 -0
- rock_physics_open/sandstone_models/constant_cement_optimisation.py +125 -0
- rock_physics_open/sandstone_models/contact_cement_model.py +138 -0
- rock_physics_open/sandstone_models/curvefit_sandstone_models.py +143 -0
- rock_physics_open/sandstone_models/friable_models.py +177 -0
- rock_physics_open/sandstone_models/friable_optimisation.py +115 -0
- rock_physics_open/sandstone_models/friable_shalysand_sandyshale_models.py +235 -0
- rock_physics_open/sandstone_models/patchy_cement_fluid_substitution_model.py +477 -0
- rock_physics_open/sandstone_models/patchy_cement_model.py +384 -0
- rock_physics_open/sandstone_models/patchy_cement_optimisation.py +254 -0
- rock_physics_open/sandstone_models/unresolved_cemented_sandshale_models.py +134 -0
- rock_physics_open/sandstone_models/unresolved_friable_sandshale_models.py +126 -0
- rock_physics_open/shale_models/__init__.py +19 -0
- rock_physics_open/shale_models/dem.py +174 -0
- rock_physics_open/shale_models/dem_dual_por.py +61 -0
- rock_physics_open/shale_models/kus_tok.py +59 -0
- rock_physics_open/shale_models/multi_sca.py +133 -0
- rock_physics_open/shale_models/pq.py +102 -0
- rock_physics_open/shale_models/sca.py +90 -0
- rock_physics_open/shale_models/shale4_mineral.py +147 -0
- rock_physics_open/shale_models/shale4_mineral_dem_overlay.py +92 -0
- rock_physics_open/span_wagner/__init__.py +5 -0
- rock_physics_open/span_wagner/co2_properties.py +444 -0
- rock_physics_open/span_wagner/coefficients.py +165 -0
- rock_physics_open/span_wagner/equations.py +104 -0
- rock_physics_open/span_wagner/tables/__init__.py +0 -0
- rock_physics_open/span_wagner/tables/carbon_dioxide_density.npz +0 -0
- rock_physics_open/span_wagner/tables/lookup_table.py +33 -0
- rock_physics_open/t_matrix_models/Equinor_logo.ico +0 -0
- rock_physics_open/t_matrix_models/__init__.py +35 -0
- rock_physics_open/t_matrix_models/carbonate_pressure_substitution.py +124 -0
- rock_physics_open/t_matrix_models/curvefit_t_matrix_exp.py +123 -0
- rock_physics_open/t_matrix_models/curvefit_t_matrix_min.py +86 -0
- rock_physics_open/t_matrix_models/parse_t_matrix_inputs.py +297 -0
- rock_physics_open/t_matrix_models/run_t_matrix.py +243 -0
- rock_physics_open/t_matrix_models/t_matrix_C.py +210 -0
- rock_physics_open/t_matrix_models/t_matrix_opt_fluid_sub_exp.py +137 -0
- rock_physics_open/t_matrix_models/t_matrix_opt_fluid_sub_petec.py +167 -0
- rock_physics_open/t_matrix_models/t_matrix_opt_forward_model_exp.py +76 -0
- rock_physics_open/t_matrix_models/t_matrix_opt_forward_model_min.py +89 -0
- rock_physics_open/t_matrix_models/t_matrix_parameter_optimisation_exp.py +176 -0
- rock_physics_open/t_matrix_models/t_matrix_parameter_optimisation_min.py +162 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/__init__.py +12 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/array_functions.py +75 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_c_eff.py +163 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_isolated.py +95 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd.py +40 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd_eff.py +116 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_kd_uuv.py +18 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_pressure.py +140 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_t.py +71 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_td.py +42 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_theta.py +43 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_x.py +33 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/calc_z.py +50 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/check_and_tile.py +43 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/g_tensor.py +140 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/iso_av.py +60 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/iso_ave_all.py +55 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/pressure_input.py +44 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/t_matrix_vec.py +278 -0
- rock_physics_open/t_matrix_models/t_matrix_vector/velocity_vti_angles.py +81 -0
- rock_physics_open/t_matrix_models/tmatrix_python.dll +0 -0
- rock_physics_open/t_matrix_models/tmatrix_python.so +0 -0
- rock_physics_open/ternary_plots/__init__.py +3 -0
- rock_physics_open/ternary_plots/gen_ternary_plot.py +73 -0
- rock_physics_open/ternary_plots/shale_prop_ternary.py +337 -0
- rock_physics_open/ternary_plots/ternary_patches.py +277 -0
- rock_physics_open/ternary_plots/ternary_plot_utilities.py +197 -0
- rock_physics_open/ternary_plots/unconventionals_ternary.py +75 -0
- rock_physics_open/version.py +34 -0
- rock_physics_open-0.3.2.dist-info/METADATA +90 -0
- rock_physics_open-0.3.2.dist-info/RECORD +145 -0
- rock_physics_open-0.3.2.dist-info/WHEEL +5 -0
- rock_physics_open-0.3.2.dist-info/licenses/LICENSE +165 -0
- rock_physics_open-0.3.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from collections.abc import Sequence
|
|
4
|
+
from typing import Any, Literal, cast
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import numpy.typing as npt
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def disp_result_stats(
|
|
11
|
+
title: str, arr: Sequence[Any], names_arr: list[str], **kwargs: Any
|
|
12
|
+
) -> None:
|
|
13
|
+
"""
|
|
14
|
+
Display results utilizing tkinter.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
title : Title.
|
|
19
|
+
arr : items to display
|
|
20
|
+
names_arr : array of names.
|
|
21
|
+
"""
|
|
22
|
+
from tkinter import END, Entry, PhotoImage, Tk
|
|
23
|
+
|
|
24
|
+
class Table:
|
|
25
|
+
def __init__(
|
|
26
|
+
self, tk_root: Tk, no_rows: int, no_cols: int, info: npt.NDArray[Any]
|
|
27
|
+
):
|
|
28
|
+
# code for creating table
|
|
29
|
+
str_len = np.vectorize(len)
|
|
30
|
+
text_justify: list[Literal["center", "left"]] = ["center", "left"]
|
|
31
|
+
text_weight: list[str] = ["bold", "normal"]
|
|
32
|
+
for i in range(no_rows):
|
|
33
|
+
weigh = text_weight[cast(int, np.sign(i))]
|
|
34
|
+
for j in range(no_cols):
|
|
35
|
+
just = text_justify[cast(int, np.sign(i))]
|
|
36
|
+
max_len = np.max(str_len(info[:, j]))
|
|
37
|
+
self.e: Entry = Entry(
|
|
38
|
+
tk_root,
|
|
39
|
+
width=max_len + 2,
|
|
40
|
+
fg="black",
|
|
41
|
+
font=("Consolas", 12, weigh),
|
|
42
|
+
justify=just,
|
|
43
|
+
)
|
|
44
|
+
self.e.grid(row=i, column=j)
|
|
45
|
+
self.e.insert(END, info[i][j])
|
|
46
|
+
|
|
47
|
+
values_only = kwargs.pop("values_only", False)
|
|
48
|
+
root = Tk(**kwargs)
|
|
49
|
+
root.title(title)
|
|
50
|
+
if values_only:
|
|
51
|
+
info_array = np.zeros((len(arr) + 1, 2)).astype(str)
|
|
52
|
+
info_array[0, :] = ["Property", "Value"]
|
|
53
|
+
for k in range(len(arr)):
|
|
54
|
+
info_array[k + 1, 0] = f"{names_arr[k]}"
|
|
55
|
+
info_array[k + 1, 1] = f"{arr[k]:.3g}"
|
|
56
|
+
else:
|
|
57
|
+
info_array = np.zeros((len(arr) + 1, 6)).astype(str)
|
|
58
|
+
info_array[0, :] = ["Var", "Min", "Mean", "Max", "No. NaN", "No. of Inf"]
|
|
59
|
+
for k in range(len(arr)):
|
|
60
|
+
info_array[k + 1, 0] = f"{names_arr[k]}"
|
|
61
|
+
info_array[k + 1, 1] = f"{np.nanmin(np.asarray(arr[k])):.3g}"
|
|
62
|
+
info_array[k + 1, 2] = f"{np.nanmean(np.asarray(arr[k])):.3g}"
|
|
63
|
+
info_array[k + 1, 3] = f"{np.nanmax(np.asarray(arr[k])):.3g}"
|
|
64
|
+
info_array[k + 1, 4] = f"{np.sum(np.isnan(np.asarray(arr[k])))}"
|
|
65
|
+
info_array[k + 1, 5] = f"{np.sum(np.isinf(np.asarray(arr[k])))}"
|
|
66
|
+
|
|
67
|
+
_ = Table(root, info_array.shape[0], info_array.shape[1], info_array)
|
|
68
|
+
|
|
69
|
+
root.update_idletasks()
|
|
70
|
+
window_height = root.winfo_height()
|
|
71
|
+
window_width = root.winfo_width()
|
|
72
|
+
screen_width = root.winfo_screenwidth()
|
|
73
|
+
screen_height = root.winfo_screenheight()
|
|
74
|
+
|
|
75
|
+
x_coordinate = int((screen_width / 2) - (window_width / 2))
|
|
76
|
+
y_coordinate = int((screen_height / 2) - (window_height / 2))
|
|
77
|
+
|
|
78
|
+
root.geometry(
|
|
79
|
+
"{}x{}+{}+{}".format(window_width, window_height, x_coordinate, y_coordinate)
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
if sys.platform.startswith("win"):
|
|
83
|
+
root.iconbitmap(os.path.join(os.path.dirname(__file__), "Equinor_logo.ico"))
|
|
84
|
+
else:
|
|
85
|
+
logo = PhotoImage(
|
|
86
|
+
file=os.path.join(os.path.dirname(__file__), "Equinor_logo.gif")
|
|
87
|
+
)
|
|
88
|
+
root.wm_iconphoto(True, logo)
|
|
89
|
+
|
|
90
|
+
root.mainloop()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
|
|
4
|
+
from rock_physics_open.equinor_utilities import std_functions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def gassmann_dry_model(
|
|
8
|
+
k_min: npt.NDArray[np.float64],
|
|
9
|
+
k_fl: npt.NDArray[np.float64],
|
|
10
|
+
rho_fl: npt.NDArray[np.float64],
|
|
11
|
+
k_sat: npt.NDArray[np.float64],
|
|
12
|
+
mu: npt.NDArray[np.float64],
|
|
13
|
+
rho_sat: npt.NDArray[np.float64],
|
|
14
|
+
por: npt.NDArray[np.float64],
|
|
15
|
+
) -> tuple[
|
|
16
|
+
npt.NDArray[np.float64],
|
|
17
|
+
npt.NDArray[np.float64],
|
|
18
|
+
npt.NDArray[np.float64],
|
|
19
|
+
npt.NDArray[np.float64],
|
|
20
|
+
npt.NDArray[np.float64],
|
|
21
|
+
npt.NDArray[np.float64],
|
|
22
|
+
npt.NDArray[np.float64],
|
|
23
|
+
]:
|
|
24
|
+
"""
|
|
25
|
+
Gassmann model to go from saturated rock to dry state.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
k_min : np.ndarray
|
|
30
|
+
Mineral bulk modulus [Pa].
|
|
31
|
+
k_fl : np.ndarray
|
|
32
|
+
Fluid bulk modulus [Pa].
|
|
33
|
+
rho_fl : np.ndarray
|
|
34
|
+
Fluid density [lg/m^3].
|
|
35
|
+
k_sat : np.ndarray
|
|
36
|
+
Saturated rock bulk modulus [Pa].
|
|
37
|
+
mu : np.ndarray
|
|
38
|
+
Saturated rock shear modulus [Pa].
|
|
39
|
+
rho_sat : np.ndarray
|
|
40
|
+
Saturated rock density [kg/m^3].
|
|
41
|
+
por : np.ndarray
|
|
42
|
+
Porosity [fraction].
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
tuple
|
|
47
|
+
vp_dry, vs_dry, rho_dry, ai_dry, vpvs_dry, k_dry, mu : np.ndarray
|
|
48
|
+
vp_dry, vs_dry: dry velocities [m/s], rho_dry: dry density [kg/m^3], ai_dry: dry acoustic impedance
|
|
49
|
+
[kg/m^3 x m/s], vpvs_dry: dry velocity ratio [unitless], k_dry, mu: dry bulk modulus and shear modulus (the
|
|
50
|
+
latter unchanged from saturated state) [Pa].
|
|
51
|
+
"""
|
|
52
|
+
rho_dry = rho_sat - por * rho_fl
|
|
53
|
+
k_dry = std_functions.gassmann_dry(k_sat, por, k_fl, k_min)
|
|
54
|
+
vp_dry, vs_dry, ai_dry, vpvs_dry = std_functions.velocity(k_dry, mu, rho_dry)
|
|
55
|
+
|
|
56
|
+
return vp_dry, vs_dry, rho_dry, ai_dry, vpvs_dry, k_dry, mu
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
|
|
4
|
+
from rock_physics_open.equinor_utilities import std_functions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def gassmann_model(
|
|
8
|
+
k_min: npt.NDArray[np.float64],
|
|
9
|
+
k_fl: npt.NDArray[np.float64],
|
|
10
|
+
rho_fl: npt.NDArray[np.float64],
|
|
11
|
+
k_dry: npt.NDArray[np.float64],
|
|
12
|
+
mu: npt.NDArray[np.float64],
|
|
13
|
+
rho_dry: npt.NDArray[np.float64],
|
|
14
|
+
por: npt.NDArray[np.float64],
|
|
15
|
+
) -> tuple[
|
|
16
|
+
npt.NDArray[np.float64],
|
|
17
|
+
npt.NDArray[np.float64],
|
|
18
|
+
npt.NDArray[np.float64],
|
|
19
|
+
npt.NDArray[np.float64],
|
|
20
|
+
npt.NDArray[np.float64],
|
|
21
|
+
npt.NDArray[np.float64],
|
|
22
|
+
npt.NDArray[np.float64],
|
|
23
|
+
]:
|
|
24
|
+
"""
|
|
25
|
+
Gassmann model to go from dry rock to saturated state.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
k_min : np.ndarray
|
|
30
|
+
Mineral bulk modulus [Pa].
|
|
31
|
+
k_fl : np.ndarray
|
|
32
|
+
Fluid bulk modulus [Pa].
|
|
33
|
+
rho_fl : np.ndarray
|
|
34
|
+
Fluid density [lg/m^3].
|
|
35
|
+
k_dry : np.ndarray
|
|
36
|
+
Dry rock bulk modulus [Pa].
|
|
37
|
+
mu : np.ndarray
|
|
38
|
+
Dry rock shear modulus [Pa].
|
|
39
|
+
rho_dry : np.ndarray
|
|
40
|
+
Dry rock density [kg/m^3].
|
|
41
|
+
por : np.ndarray
|
|
42
|
+
Porosity [fraction].
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
tuple
|
|
47
|
+
vp_sat, vs_sat, rho_sat, ai_sat, vpvs_sat, k_sat, mu : np.ndarray
|
|
48
|
+
vp_sat, vs_sat: saturated velocities [m/s], rho_sat: saturated density [kg/m^3], ai_sat: saturated acoustic
|
|
49
|
+
impedance [kg/m^3 x m/s], vpvs_sat: saturated velocity ratio [unitless], k_sat, mu: saturated bulk modulus and
|
|
50
|
+
shear modulus (the latter unchanged from dry state) [Pa].
|
|
51
|
+
"""
|
|
52
|
+
rho_sat = rho_dry + por * rho_fl
|
|
53
|
+
k_sat = std_functions.gassmann(k_dry, por, k_fl, k_min)
|
|
54
|
+
vp_sat, vs_sat, ai_sat, vpvs_sat = std_functions.velocity(k_sat, mu, rho_sat)
|
|
55
|
+
|
|
56
|
+
return vp_sat, vs_sat, rho_sat, ai_sat, vpvs_sat, k_sat, mu
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
|
|
4
|
+
from rock_physics_open.equinor_utilities import std_functions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def gassmann_sub_model(
|
|
8
|
+
k_min: npt.NDArray[np.float64],
|
|
9
|
+
k_fl_orig: npt.NDArray[np.float64],
|
|
10
|
+
rho_fl_orig: npt.NDArray[np.float64],
|
|
11
|
+
k_fl_sub: npt.NDArray[np.float64],
|
|
12
|
+
rho_fl_sub: npt.NDArray[np.float64],
|
|
13
|
+
k_sat_orig: npt.NDArray[np.float64],
|
|
14
|
+
mu: npt.NDArray[np.float64],
|
|
15
|
+
rho_sat_orig: npt.NDArray[np.float64],
|
|
16
|
+
por: npt.NDArray[np.float64],
|
|
17
|
+
) -> tuple[
|
|
18
|
+
npt.NDArray[np.float64],
|
|
19
|
+
npt.NDArray[np.float64],
|
|
20
|
+
npt.NDArray[np.float64],
|
|
21
|
+
npt.NDArray[np.float64],
|
|
22
|
+
npt.NDArray[np.float64],
|
|
23
|
+
npt.NDArray[np.float64],
|
|
24
|
+
npt.NDArray[np.float64],
|
|
25
|
+
]:
|
|
26
|
+
"""
|
|
27
|
+
Gassmann model to go from one saturated state to another.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
k_min : np.ndarray
|
|
32
|
+
Mineral bulk modulus [Pa].
|
|
33
|
+
k_fl_orig : np.ndarray
|
|
34
|
+
Original fluid bulk modulus [Pa].
|
|
35
|
+
rho_fl_orig : np.ndarray
|
|
36
|
+
Original fluid density [lg/m^3].
|
|
37
|
+
k_fl_sub : np.ndarray
|
|
38
|
+
Substituted fluid bulk modulus [Pa].
|
|
39
|
+
rho_fl_sub : np.ndarray
|
|
40
|
+
Substituted fluid density [lg/m^3].
|
|
41
|
+
k_sat_orig : np.ndarray
|
|
42
|
+
Saturated rock bulk modulus with original fluid [Pa].
|
|
43
|
+
mu : np.ndarray
|
|
44
|
+
Rock shear modulus [Pa].
|
|
45
|
+
rho_sat_orig : np.ndarray
|
|
46
|
+
Saturated rock density with original fluid [kg/m^3].
|
|
47
|
+
por : np.ndarray
|
|
48
|
+
Porosity [fraction].
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
tuple
|
|
53
|
+
vp_sat, vs_sat, rho_sat, ai_sat, vpvs_sat, k_sat, mu : np.ndarray
|
|
54
|
+
vp_sat, vs_sat: saturated velocities [m/s], rho_sat: saturated density [kg/m^3], ai_sat: saturated acoustic
|
|
55
|
+
impedance [kg/m^3 x m/s], vpvs_sat: saturated velocity ratio [unitless], k_sat, mu: saturated bulk modulus and
|
|
56
|
+
shear modulus (the latter unchanged from dry state) [Pa].
|
|
57
|
+
"""
|
|
58
|
+
rho_sat_sub = rho_sat_orig + por * (rho_fl_sub - rho_fl_orig)
|
|
59
|
+
k_sat_sub = std_functions.gassmann2(k_sat_orig, k_fl_orig, k_fl_sub, por, k_min)
|
|
60
|
+
vp_sat_sub, vs_sat_sub, ai_sat_sub, vpvs_sat_sub = std_functions.velocity(
|
|
61
|
+
k_sat_sub, mu, rho_sat_sub
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
return vp_sat_sub, vs_sat_sub, rho_sat_sub, ai_sat_sub, vpvs_sat_sub, k_sat_sub, mu
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
|
|
4
|
+
from rock_physics_open.equinor_utilities import std_functions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def hs_average(
|
|
8
|
+
k1: npt.NDArray[np.float64],
|
|
9
|
+
mu1: npt.NDArray[np.float64],
|
|
10
|
+
rhob1: npt.NDArray[np.float64],
|
|
11
|
+
k2: npt.NDArray[np.float64],
|
|
12
|
+
mu2: npt.NDArray[np.float64],
|
|
13
|
+
rhob2: npt.NDArray[np.float64],
|
|
14
|
+
f: npt.NDArray[np.float64],
|
|
15
|
+
) -> tuple[
|
|
16
|
+
npt.NDArray[np.float64],
|
|
17
|
+
npt.NDArray[np.float64],
|
|
18
|
+
npt.NDArray[np.float64],
|
|
19
|
+
npt.NDArray[np.float64],
|
|
20
|
+
npt.NDArray[np.float64],
|
|
21
|
+
npt.NDArray[np.float64],
|
|
22
|
+
npt.NDArray[np.float64],
|
|
23
|
+
]:
|
|
24
|
+
"""
|
|
25
|
+
BMix of two phases by Hashin-Shtrikman model. Derived properties are also returned.
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
k1 : np.ndarray
|
|
30
|
+
k1 array.
|
|
31
|
+
mu1 : np.ndarray
|
|
32
|
+
mu1 array.
|
|
33
|
+
rhob1 : np.ndarray
|
|
34
|
+
rhob1 array.
|
|
35
|
+
k2 : np.ndarray
|
|
36
|
+
k2 array.
|
|
37
|
+
mu2 : np.ndarray
|
|
38
|
+
mu2 array.
|
|
39
|
+
rhob2 : np.ndarray
|
|
40
|
+
rhob2 array.
|
|
41
|
+
f : float or np.ndarray
|
|
42
|
+
f value or array.
|
|
43
|
+
|
|
44
|
+
Returns
|
|
45
|
+
-------
|
|
46
|
+
tuple
|
|
47
|
+
vp, vs, rhob, ai, vp_vs, k, mu : np.ndarray
|
|
48
|
+
vp: compressional wave velocity [m/s], vs: shear wave velocity [m/s], ai: acoustic impedance [m/s x kg/m^3],
|
|
49
|
+
vp_vs: velocity ratio [ratio], k: bulk modulus [Pa], mu: shear modulus [Pa]
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
k, mu = std_functions.hashin_shtrikman_average(k1, mu1, k2, mu2, f)
|
|
54
|
+
|
|
55
|
+
rhob = rhob1 * f + rhob2 * (1 - f)
|
|
56
|
+
|
|
57
|
+
vp, vs, ai, vp_vs = std_functions.velocity(k, mu, rhob)
|
|
58
|
+
|
|
59
|
+
return vp, vs, rhob, ai, vp_vs, k, mu
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def pressure(
|
|
6
|
+
rho: npt.NDArray[np.float64],
|
|
7
|
+
tvd_msl: npt.NDArray[np.float64],
|
|
8
|
+
water_depth: float,
|
|
9
|
+
p_form: float,
|
|
10
|
+
tvd_p_form: float,
|
|
11
|
+
n: float,
|
|
12
|
+
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
|
|
13
|
+
"""
|
|
14
|
+
Function to estimate overburden pressure and vertical effective stress (lithostatic pressure)
|
|
15
|
+
based on density.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
rho : np.ndarray
|
|
20
|
+
Density log [kg/m3].
|
|
21
|
+
tvd_msl : np.ndarray
|
|
22
|
+
Vertical depth log [m].
|
|
23
|
+
water_depth : float
|
|
24
|
+
Down to this point the difference between formation pressure and overburden pressure shall be zero [m].
|
|
25
|
+
p_form : float
|
|
26
|
+
Formation pressure [Pa].
|
|
27
|
+
tvd_p_form : float
|
|
28
|
+
Depth of formation pressure point [m].
|
|
29
|
+
n: float
|
|
30
|
+
Biot coefficient [unitless].
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
tuple
|
|
35
|
+
p_eff, p_lith : np.ndarray.
|
|
36
|
+
p_eff [Pa] - effective pressure,
|
|
37
|
+
p_lith [Pa] - overburden pressure.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
# Standard brine density with salinity 40000 ppm, 2 MPa and 4 deg. C
|
|
41
|
+
rho_brine = 1.03e3
|
|
42
|
+
# Gravity constant
|
|
43
|
+
g = 9.80665
|
|
44
|
+
# Input log length
|
|
45
|
+
log_length = len(rho)
|
|
46
|
+
|
|
47
|
+
# Allocate output logs
|
|
48
|
+
p_eff = np.ones(log_length) * np.nan
|
|
49
|
+
p_lith = np.ones(log_length) * np.nan
|
|
50
|
+
|
|
51
|
+
# Does the depth log start at, above or below the sea bottom? We want it to
|
|
52
|
+
# start at sea bottom, so we get rid of values above this point.
|
|
53
|
+
# Also, as the tvd log normally is calculated by calling application, there can be
|
|
54
|
+
# undefined values, flagged as negative or NaN
|
|
55
|
+
idx = np.ones_like(rho, dtype=bool)
|
|
56
|
+
idx_inf_nan = np.any(
|
|
57
|
+
[np.isnan(rho), np.isinf(rho), np.isnan(tvd_msl), np.isinf(tvd_msl)], axis=0
|
|
58
|
+
)
|
|
59
|
+
idx[idx_inf_nan] = False
|
|
60
|
+
idx[~idx_inf_nan] = np.logical_and(
|
|
61
|
+
tvd_msl[~idx_inf_nan] >= water_depth, rho[~idx_inf_nan] > 0
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# We need a starting point for pressure at water bottom - use a standard
|
|
65
|
+
# density value
|
|
66
|
+
p_wb = g * rho_brine * water_depth
|
|
67
|
+
|
|
68
|
+
# p_form is a single value. No functionality is added at present to handle p_form in log version
|
|
69
|
+
# Find which depth in the log that matches the calibration point best
|
|
70
|
+
calib_point = np.argmin(abs(tvd_msl[idx] - tvd_p_form))
|
|
71
|
+
|
|
72
|
+
# Overburden pressure
|
|
73
|
+
dz = np.diff(tvd_msl[idx])
|
|
74
|
+
# Append one sample to match the density log length
|
|
75
|
+
dz = np.append(dz, dz[-1])
|
|
76
|
+
|
|
77
|
+
# Find a starting point for the litho pressure at the start of the depth log
|
|
78
|
+
# Density at water bottom is assumed to be for a sand with 40% porosity. Take the average
|
|
79
|
+
# of this and the first observation of density log
|
|
80
|
+
ave_dens = 0.5 * ((2650 * 0.6 + rho_brine * 0.4) + rho[0])
|
|
81
|
+
p_lith_start = ave_dens * g * (tvd_msl[0] - water_depth)
|
|
82
|
+
|
|
83
|
+
# Estimate the overburden pressure as the gravity of the cumulative bulk
|
|
84
|
+
# density plus the calculated starting point and the fluid pressure at sea bottom
|
|
85
|
+
p_lith[idx] = np.cumsum(g * dz * rho[idx]) + p_lith_start + p_wb
|
|
86
|
+
|
|
87
|
+
# Find the effective/differential pressure at the calibration point
|
|
88
|
+
p_eff_calib = p_lith[idx][calib_point] - n * p_form
|
|
89
|
+
# In the absence of any better alternative - make a linear interpolation
|
|
90
|
+
# from zero at water bottom to the calculated effective pressure at the
|
|
91
|
+
# calibration point
|
|
92
|
+
p_eff[idx] = np.interp(tvd_msl[idx], [water_depth, tvd_p_form], [0, p_eff_calib])
|
|
93
|
+
|
|
94
|
+
p_lith[idx] = np.interp(tvd_msl[idx], tvd_msl[idx], p_lith[idx])
|
|
95
|
+
|
|
96
|
+
return p_eff, p_lith
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
from typing import Literal, cast
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import numpy.typing as npt
|
|
5
|
+
|
|
6
|
+
from rock_physics_open.equinor_utilities import gen_utilities, std_functions
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def reflectivity(
|
|
10
|
+
vp_inp: npt.NDArray[np.float64],
|
|
11
|
+
vs_inp: npt.NDArray[np.float64],
|
|
12
|
+
rho_inp: npt.NDArray[np.float64],
|
|
13
|
+
theta: float = 0.0,
|
|
14
|
+
k: float = 2.0,
|
|
15
|
+
model: Literal["AkiRichards", "SmithGidlow"] = "AkiRichards",
|
|
16
|
+
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.bool_]]:
|
|
17
|
+
"""
|
|
18
|
+
Reflectivity model according to Aki and Richards or Smith and Gidlow for weak contrasts
|
|
19
|
+
and angles less than critical angle.
|
|
20
|
+
|
|
21
|
+
In this function it is not allowed to have any missing values in the input logs.
|
|
22
|
+
Instead of interpolating here without the user knowing, raise an input value
|
|
23
|
+
exception and leave it to the user to provide complete logs.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
vp_inp : np.ndarray
|
|
28
|
+
Compressional wave velocity [m/s].
|
|
29
|
+
vs_inp : np.ndarray
|
|
30
|
+
Shear wave velocity [m/s].
|
|
31
|
+
rho_inp : np.ndarray
|
|
32
|
+
Bulk density [kg/m^3].
|
|
33
|
+
theta : float
|
|
34
|
+
Incidence angle [radians] (default value 0).
|
|
35
|
+
k : float
|
|
36
|
+
Background Vp/Vs ratio [ratio] (default value 2.0).
|
|
37
|
+
model : str
|
|
38
|
+
One of 'AkiRichards' (default) or 'SmithGidlow'.
|
|
39
|
+
|
|
40
|
+
Returns
|
|
41
|
+
-------
|
|
42
|
+
tuple
|
|
43
|
+
refl_coef, idx_inp : np.ndarray.
|
|
44
|
+
refl_coef: reflection coefficient [ratio],
|
|
45
|
+
idx_inp: index to accepted part of the input arrays [bool].
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
vp, vs, rho, theta_, k_ = cast(
|
|
49
|
+
list[npt.NDArray[np.float64]],
|
|
50
|
+
gen_utilities.dim_check_vector((vp_inp, vs_inp, rho_inp, theta, k)),
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
idx_inp, (vp, vs, rho, theta_, k_) = cast(
|
|
54
|
+
tuple[npt.NDArray[np.bool_], list[npt.NDArray[np.float64]]],
|
|
55
|
+
gen_utilities.filter_input_log(
|
|
56
|
+
[vp, vs, rho, theta_, k_],
|
|
57
|
+
positive=True,
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if np.any(~idx_inp):
|
|
62
|
+
# Only NaNs at the start or end? Find the first and last valid sample and check
|
|
63
|
+
# if there are any invalid samples in between
|
|
64
|
+
first_samp = np.where(idx_inp)[0][0]
|
|
65
|
+
last_samp = np.where(idx_inp)[0][-1]
|
|
66
|
+
if np.any(~idx_inp[first_samp : last_samp + 1]):
|
|
67
|
+
# Find the culprit(s)
|
|
68
|
+
idx_vp = gen_utilities.filter_input_log(
|
|
69
|
+
[vp_inp[first_samp : last_samp + 1]], positive=True
|
|
70
|
+
)[0]
|
|
71
|
+
idx_vs = gen_utilities.filter_input_log(
|
|
72
|
+
[vs_inp[first_samp : last_samp + 1]], positive=True
|
|
73
|
+
)[0]
|
|
74
|
+
idx_rho = gen_utilities.filter_input_log(
|
|
75
|
+
[rho_inp[first_samp : last_samp + 1]], positive=True
|
|
76
|
+
)[0]
|
|
77
|
+
log_str = (
|
|
78
|
+
int(np.any(~idx_vp)) * "Vp, "
|
|
79
|
+
+ int(np.any(~idx_vs)) * "Vs, "
|
|
80
|
+
+ int(np.any(~idx_rho)) * "Rho, "
|
|
81
|
+
)
|
|
82
|
+
pl_str = (
|
|
83
|
+
(int(np.any(~idx_vp)) + int(np.any(~idx_vs)) + int(np.any(~idx_rho)))
|
|
84
|
+
> 1
|
|
85
|
+
) * "s"
|
|
86
|
+
raise ValueError(
|
|
87
|
+
"{0:} reflectivity: Missing or illegal values in input log{1:}: {2:}interpolation of input log{1:} is needed\n".format(
|
|
88
|
+
model, log_str, pl_str
|
|
89
|
+
)
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
if model == "AkiRichards":
|
|
93
|
+
refl_coef = std_functions.aki_richards(vp, vs, rho, theta_, k_)
|
|
94
|
+
elif model == "SmithGidlow":
|
|
95
|
+
refl_coef = std_functions.smith_gidlow(vp, vs, rho, theta_, k_)
|
|
96
|
+
else:
|
|
97
|
+
raise ValueError( # pyright: ignore[reportUnreachable] | Kept for backward compatibility
|
|
98
|
+
f'{__file__}: unknown model: {model}, should be one of "AkiRichards", "SmithGidlow"'
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return refl_coef, idx_inp
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import numpy.typing as npt
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def time_shift_pp(
|
|
6
|
+
tvd: npt.NDArray[np.float64],
|
|
7
|
+
vp_base: npt.NDArray[np.float64],
|
|
8
|
+
vp_mon: npt.NDArray[np.float64],
|
|
9
|
+
multiplier: int,
|
|
10
|
+
) -> tuple[npt.NDArray[np.float64], npt.NDArray[np.float64]]:
|
|
11
|
+
"""
|
|
12
|
+
Cumulative time shift calculation for 4D case. According to Equinor standard
|
|
13
|
+
the time shift is negative for an increase in velocity from base to monitor
|
|
14
|
+
survey.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
tvd : np.ndarray
|
|
19
|
+
True vertical depth along wellbore [m].
|
|
20
|
+
vp_base : np.ndarray
|
|
21
|
+
Initial Vp [m/s].
|
|
22
|
+
vp_mon : np.ndarray
|
|
23
|
+
vp at time of monitor survey [m/s].
|
|
24
|
+
multiplier : int
|
|
25
|
+
Time shift multiplier.
|
|
26
|
+
|
|
27
|
+
Returns
|
|
28
|
+
-------
|
|
29
|
+
tuple
|
|
30
|
+
owt_pp_shift, twt_pp_shift : np.ndarray.
|
|
31
|
+
owt_pp_shift: one way time shift [ms],
|
|
32
|
+
twt_pp_shift: two way time shift [ms].
|
|
33
|
+
|
|
34
|
+
Notes
|
|
35
|
+
-----
|
|
36
|
+
Original function by Sascha Bussat, Equinor
|
|
37
|
+
Ported to Python by Harald Flesche, Equinor 2016.
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
dx = np.diff(tvd)
|
|
41
|
+
dx = np.append(dx, dx[-1])
|
|
42
|
+
|
|
43
|
+
time_base = np.cumsum(dx / vp_base)
|
|
44
|
+
time_monitor = np.cumsum(dx / vp_mon)
|
|
45
|
+
|
|
46
|
+
owt_pp_shift = (time_monitor - time_base) * 1000 * multiplier
|
|
47
|
+
twt_pp_shift = 2 * owt_pp_shift
|
|
48
|
+
|
|
49
|
+
return owt_pp_shift, twt_pp_shift
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def time_shift_ps(
|
|
53
|
+
tvd: npt.NDArray[np.float64],
|
|
54
|
+
vp_base: npt.NDArray[np.float64],
|
|
55
|
+
vp_mon: npt.NDArray[np.float64],
|
|
56
|
+
vs_base: npt.NDArray[np.float64],
|
|
57
|
+
vs_mon: npt.NDArray[np.float64],
|
|
58
|
+
multiplier: int,
|
|
59
|
+
) -> npt.NDArray[np.float64]:
|
|
60
|
+
"""
|
|
61
|
+
Cumulative time shift calculation for 4D case. According to Equinor standard
|
|
62
|
+
the time shift is negative for an increase in velocity from base to monitor
|
|
63
|
+
survey.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
tvd : np.ndarray
|
|
68
|
+
True vertical depth along wellbore [m].
|
|
69
|
+
vp_base : np.ndarray
|
|
70
|
+
Initial vp [m/s].
|
|
71
|
+
vp_mon : np.ndarray
|
|
72
|
+
vs at time of monitor survey [m/s].
|
|
73
|
+
vs_base : np.ndarray
|
|
74
|
+
Initial vp [m/s].
|
|
75
|
+
vs_mon : np.ndarray
|
|
76
|
+
vs at time of monitor survey [m/s].
|
|
77
|
+
multiplier : int
|
|
78
|
+
Time shift multiplier.
|
|
79
|
+
|
|
80
|
+
Returns
|
|
81
|
+
-------
|
|
82
|
+
np.ndarray
|
|
83
|
+
twt_ps_shift: two way time shift [ms]
|
|
84
|
+
|
|
85
|
+
Notes
|
|
86
|
+
-----
|
|
87
|
+
Original function by Sascha Bussat, Equinor
|
|
88
|
+
Ported to Python by Harald Flesche, Equinor 2016.
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
dx = np.diff(tvd)
|
|
92
|
+
dx = np.append(dx, dx[-1])
|
|
93
|
+
|
|
94
|
+
time_base_vp = np.cumsum(dx / vp_base)
|
|
95
|
+
time_monitor_vp = np.cumsum(dx / vp_mon)
|
|
96
|
+
|
|
97
|
+
time_base_vs = np.cumsum(dx / vs_base)
|
|
98
|
+
time_monitor_vs = np.cumsum(dx / vs_mon)
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
((time_monitor_vp - time_base_vp) + (time_monitor_vs - time_base_vs))
|
|
102
|
+
* 1000
|
|
103
|
+
* multiplier
|
|
104
|
+
)
|