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,146 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from .dead_oil_density import dead_oil_density
|
|
6
|
+
from .dead_oil_velocity import dead_oil_velocity
|
|
7
|
+
from .live_oil_density import live_oil_density
|
|
8
|
+
from .live_oil_velocity import live_oil_velocity
|
|
9
|
+
from .oil_bubble_point import bp_standing
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def oil_properties(
|
|
13
|
+
temperature: np.ndarray | float,
|
|
14
|
+
pressure: np.ndarray | float,
|
|
15
|
+
rho0: np.ndarray | float,
|
|
16
|
+
gas_oil_ratio: np.ndarray | float,
|
|
17
|
+
gas_gravity: np.ndarray | float,
|
|
18
|
+
) -> np.ndarray | float:
|
|
19
|
+
"""
|
|
20
|
+
:param temperature: Temperature [°C] of oil.
|
|
21
|
+
:param pressure: Pressure [Pa] of oil
|
|
22
|
+
:param rho0: Density of the oil without dissolved gas at 15.6 degrees Celsius and
|
|
23
|
+
atmospheric pressure. [kg/m^3]
|
|
24
|
+
:param gas_oil_ratio: The volume ratio of gas to oil [l/l]
|
|
25
|
+
:param gas_gravity: Gas Gravity, molar mass of gas relative to air molar mas.
|
|
26
|
+
:return: vel_oil [m/s], den_oil [kg/m^3], k_oil [Pa]
|
|
27
|
+
"""
|
|
28
|
+
# Since live_oil with gas_oil_ratio=0.0 is not equal to dead oil
|
|
29
|
+
# we use an apodization function to interpolate between the two
|
|
30
|
+
|
|
31
|
+
def triangular_window(x, length=2):
|
|
32
|
+
"""
|
|
33
|
+
A triangular window function around the origin, 1.0 at x=0.0, linear
|
|
34
|
+
and 0.0 outside the window.
|
|
35
|
+
:param length: total length of the window, ie., function is nonzero in
|
|
36
|
+
[-length/2, length/2].
|
|
37
|
+
:param x: numpy array containing x'es to evaluate the window at
|
|
38
|
+
:return: value of window function at x.
|
|
39
|
+
"""
|
|
40
|
+
x = np.asarray(x) # Ensure x is a numpy array
|
|
41
|
+
window = np.clip((np.abs(x) - length / 2) / (length / 2), 0, 1)
|
|
42
|
+
return 1 - window
|
|
43
|
+
|
|
44
|
+
(
|
|
45
|
+
loil_vel,
|
|
46
|
+
loil_den,
|
|
47
|
+
) = live_oil(temperature, pressure, rho0, gas_oil_ratio, gas_gravity)
|
|
48
|
+
doil_vel, doil_den = dead_oil(temperature, pressure, rho0)
|
|
49
|
+
window = triangular_window(gas_oil_ratio)
|
|
50
|
+
den_oil = doil_den * window + (1 - window) * loil_den
|
|
51
|
+
vel_oil = doil_vel * window + (1 - window) * loil_vel
|
|
52
|
+
k_oil = vel_oil**2 * den_oil
|
|
53
|
+
return vel_oil, den_oil, k_oil
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def dead_oil(
|
|
57
|
+
temperature: np.ndarray | float,
|
|
58
|
+
pressure: np.ndarray | float,
|
|
59
|
+
reference_density: np.ndarray | float,
|
|
60
|
+
) -> tuple[np.ndarray | float, np.ndarray | float]:
|
|
61
|
+
"""
|
|
62
|
+
:param reference_density: Density of the oil without dissolved gas
|
|
63
|
+
at 15.6 degrees Celsius and atmospheric pressure. [kg/m^3]
|
|
64
|
+
:param gas_oil_ratio: The volume ratio of gas to oil [l/l]
|
|
65
|
+
:param gas_gravity: molar mass of gas relative to air molar mas.
|
|
66
|
+
:param pressure: Pressure [Pa] of oil
|
|
67
|
+
:param temperature: Temperature [°C] of oil.
|
|
68
|
+
:return: dead_oil_density [kg/m^3], dead_oil_velocity [m/s]
|
|
69
|
+
"""
|
|
70
|
+
dead_oil_den = dead_oil_density(temperature, pressure, reference_density)
|
|
71
|
+
dead_oil_vel = dead_oil_velocity(temperature, pressure, reference_density)
|
|
72
|
+
return dead_oil_vel, dead_oil_den
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def live_oil(
|
|
76
|
+
temperature: np.ndarray | float,
|
|
77
|
+
pressure: np.ndarray | float,
|
|
78
|
+
reference_density: np.ndarray | float,
|
|
79
|
+
gas_oil_ratio: np.ndarray | float,
|
|
80
|
+
gas_gravity: np.ndarray | float,
|
|
81
|
+
) -> tuple[np.ndarray | float, np.ndarray | float]:
|
|
82
|
+
"""
|
|
83
|
+
:param reference_density: Density of the oil without dissolved gas
|
|
84
|
+
at 15.6 degrees Celsius and atmospheric pressure. [kg/m^3]
|
|
85
|
+
:param gas_oil_ratio: The volume ratio of gas to oil [l/l]
|
|
86
|
+
:param gas_gravity: molar mass of gas relative to air molar mas.
|
|
87
|
+
:param pressure: Pressure [Pa] of oil
|
|
88
|
+
:param temperature: Temperature [°C] of oil.
|
|
89
|
+
:return: live_oil_density , live_oil_velocity
|
|
90
|
+
"""
|
|
91
|
+
if np.any(
|
|
92
|
+
pressure
|
|
93
|
+
< bp_standing(reference_density, gas_oil_ratio, gas_gravity, temperature)
|
|
94
|
+
):
|
|
95
|
+
warnings.warn(
|
|
96
|
+
"Pressure is below bubble point of oil, estimated elastic properties can be inaccurate",
|
|
97
|
+
stacklevel=1,
|
|
98
|
+
)
|
|
99
|
+
live_oil_den = live_oil_density(
|
|
100
|
+
temperature,
|
|
101
|
+
pressure,
|
|
102
|
+
reference_density,
|
|
103
|
+
gas_oil_ratio,
|
|
104
|
+
gas_gravity,
|
|
105
|
+
)
|
|
106
|
+
live_oil_vel = live_oil_velocity(
|
|
107
|
+
temperature,
|
|
108
|
+
pressure,
|
|
109
|
+
reference_density,
|
|
110
|
+
gas_oil_ratio,
|
|
111
|
+
gas_gravity,
|
|
112
|
+
)
|
|
113
|
+
return (
|
|
114
|
+
live_oil_vel,
|
|
115
|
+
live_oil_den,
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def oil_viscosity(
|
|
120
|
+
temperature: np.ndarray | float,
|
|
121
|
+
pressure: np.ndarray | float,
|
|
122
|
+
reference_density: np.ndarray | float,
|
|
123
|
+
) -> np.ndarray | float:
|
|
124
|
+
"""
|
|
125
|
+
Calculate dead oil viscosity. If dissolved gas is present in the oil, the reference density
|
|
126
|
+
should be substituted by live oil density.
|
|
127
|
+
|
|
128
|
+
Equations 25a, 25b, 26a & 26b in Batzle and Wang 1992
|
|
129
|
+
|
|
130
|
+
Based on Beggs and Robinson 1975
|
|
131
|
+
|
|
132
|
+
:param temperature: Temperature [°C] of oil
|
|
133
|
+
:param pressure: Pressure [Pa] of oil
|
|
134
|
+
:param reference_density: Density of the oil without dissolved gas
|
|
135
|
+
"""
|
|
136
|
+
# Change unit in pressure to MPa
|
|
137
|
+
pressure_mpa = pressure / 1.0e6
|
|
138
|
+
# Change unit in density to g/cc
|
|
139
|
+
density_gcc = reference_density / 1000.0
|
|
140
|
+
|
|
141
|
+
y_factor = 10 ** (5.693 - 2.863 / density_gcc)
|
|
142
|
+
eta_t = -1.0 + 10 ** (0.505 * y_factor * (17.8 + temperature) ** -1.163)
|
|
143
|
+
i_factor = 10 ** (
|
|
144
|
+
18.6 * (0.1 * np.log10(eta_t) + (np.log10(eta_t) + 2) ** -0.1 - 0.985)
|
|
145
|
+
)
|
|
146
|
+
return eta_t + 0.145 * pressure_mpa * i_factor
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
from .cemented_shalysand_sandyshale_models import cemented_shaly_sand_sandy_shale_model
|
|
2
|
+
from .constant_cement_models import (
|
|
3
|
+
constant_cement_model,
|
|
4
|
+
constant_cement_model_dry,
|
|
5
|
+
)
|
|
6
|
+
from .constant_cement_optimisation import constant_cement_model_optimisation
|
|
7
|
+
from .contact_cement_model import contact_cement_model
|
|
8
|
+
from .curvefit_sandstone_models import (
|
|
9
|
+
curvefit_constant_cement,
|
|
10
|
+
curvefit_friable,
|
|
11
|
+
curvefit_patchy_cement,
|
|
12
|
+
)
|
|
13
|
+
from .friable_models import (
|
|
14
|
+
friable_model,
|
|
15
|
+
friable_model_dry,
|
|
16
|
+
)
|
|
17
|
+
from .friable_optimisation import friable_model_optimisation
|
|
18
|
+
from .friable_shalysand_sandyshale_models import friable_shaly_sand_sandy_shale_model
|
|
19
|
+
from .patchy_cement_fluid_substitution_model import (
|
|
20
|
+
patchy_cement_pressure_fluid_substitution,
|
|
21
|
+
)
|
|
22
|
+
from .patchy_cement_model import (
|
|
23
|
+
constant_cement_model_pcm,
|
|
24
|
+
patchy_cement_model_cem_frac,
|
|
25
|
+
patchy_cement_model_dry,
|
|
26
|
+
patchy_cement_model_weight,
|
|
27
|
+
)
|
|
28
|
+
from .patchy_cement_optimisation import (
|
|
29
|
+
patchy_cement_model_optimisation,
|
|
30
|
+
patchy_cement_model_optimisation_multiwell,
|
|
31
|
+
)
|
|
32
|
+
from .unresolved_cemented_sandshale_models import (
|
|
33
|
+
unresolved_constant_cement_sand_shale_model,
|
|
34
|
+
)
|
|
35
|
+
from .unresolved_friable_sandshale_models import unresolved_friable_sand_shale_model
|
|
36
|
+
|
|
37
|
+
__all__ = [
|
|
38
|
+
"cemented_shaly_sand_sandy_shale_model",
|
|
39
|
+
"constant_cement_model",
|
|
40
|
+
"constant_cement_model_dry",
|
|
41
|
+
"constant_cement_model_optimisation",
|
|
42
|
+
"contact_cement_model",
|
|
43
|
+
"curvefit_constant_cement",
|
|
44
|
+
"curvefit_friable",
|
|
45
|
+
"curvefit_patchy_cement",
|
|
46
|
+
"friable_model",
|
|
47
|
+
"friable_model_dry",
|
|
48
|
+
"friable_model_optimisation",
|
|
49
|
+
"friable_shaly_sand_sandy_shale_model",
|
|
50
|
+
"patchy_cement_pressure_fluid_substitution",
|
|
51
|
+
"constant_cement_model_pcm",
|
|
52
|
+
"patchy_cement_model_dry",
|
|
53
|
+
"patchy_cement_model_cem_frac",
|
|
54
|
+
"patchy_cement_model_weight",
|
|
55
|
+
"patchy_cement_model_optimisation",
|
|
56
|
+
"patchy_cement_model_optimisation_multiwell",
|
|
57
|
+
"unresolved_constant_cement_sand_shale_model",
|
|
58
|
+
"unresolved_friable_sand_shale_model",
|
|
59
|
+
]
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from rock_physics_open import sandstone_models
|
|
4
|
+
from rock_physics_open.equinor_utilities import gen_utilities, std_functions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def cemented_shaly_sand_sandy_shale_model(
|
|
8
|
+
k_sst,
|
|
9
|
+
mu_sst,
|
|
10
|
+
rho_sst,
|
|
11
|
+
k_cem,
|
|
12
|
+
mu_cem,
|
|
13
|
+
rho_cem,
|
|
14
|
+
k_mud,
|
|
15
|
+
mu_mud,
|
|
16
|
+
rho_mud,
|
|
17
|
+
k_fl_sst,
|
|
18
|
+
rho_fl_sst,
|
|
19
|
+
k_fl_mud,
|
|
20
|
+
rho_fl_mud,
|
|
21
|
+
phi,
|
|
22
|
+
p_eff_mud,
|
|
23
|
+
shale_frac,
|
|
24
|
+
frac_cem,
|
|
25
|
+
phi_c_sst,
|
|
26
|
+
n_sst,
|
|
27
|
+
shear_red_sst,
|
|
28
|
+
phi_c_mud,
|
|
29
|
+
phi_intr_mud,
|
|
30
|
+
coord_num_func_mud,
|
|
31
|
+
n_mud,
|
|
32
|
+
shear_red_mud,
|
|
33
|
+
):
|
|
34
|
+
"""
|
|
35
|
+
Model for mixing of cemented sand and friable shale.
|
|
36
|
+
|
|
37
|
+
It is no point to use this model to calculate the shale response only,
|
|
38
|
+
in that case Friable Model with shale parameters does the job
|
|
39
|
+
|
|
40
|
+
The shale fluid should be brine.
|
|
41
|
+
|
|
42
|
+
Shale fraction shaleFrac is in the range 0 to 1. For shaleFrac = 0 we
|
|
43
|
+
have a pure sand end member with phi =< phi_c for sand. For shaleFrac = 1
|
|
44
|
+
we have pure shale with phi = intrinsic porosity. For shaleFrac < phi_c
|
|
45
|
+
the model is on the shaly sand trend, for shaleFrac > phi_c it is on the
|
|
46
|
+
sandy shale trend.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
k_sst : np.ndarray
|
|
51
|
+
Sandstone matrix bulk modulus [Pa].
|
|
52
|
+
mu_sst : np.ndarray
|
|
53
|
+
Sandstone matrix shear modulus [Pa].
|
|
54
|
+
rho_sst : np.ndarray
|
|
55
|
+
Sandstone matrix bulk density [kg/m^3].
|
|
56
|
+
k_cem : np.ndarray
|
|
57
|
+
Sandstone cement bulk modulus [Pa].
|
|
58
|
+
mu_cem : np.ndarray
|
|
59
|
+
Sandstone cement shear modulus [Pa].
|
|
60
|
+
rho_cem : np.ndarray
|
|
61
|
+
Sandstone cement bulk density [kg/m^3].
|
|
62
|
+
k_mud : np.ndarray
|
|
63
|
+
Shale bulk modulus [Pa].
|
|
64
|
+
mu_mud : np.ndarray
|
|
65
|
+
Shale shear modulus [Pa].
|
|
66
|
+
rho_mud : np.ndarray
|
|
67
|
+
Shale bulk density [kg/m^3].
|
|
68
|
+
k_fl_sst : np.ndarray
|
|
69
|
+
Fluid bulk modulus for sandstone fluid [Pa].
|
|
70
|
+
rho_fl_sst : np.ndarray
|
|
71
|
+
Fluid bulk density for sandstone fluid [kg/m^3].
|
|
72
|
+
k_fl_mud : np.ndarray
|
|
73
|
+
Fluid bulk modulus for shale fluid [Pa].
|
|
74
|
+
rho_fl_mud : np.ndarray
|
|
75
|
+
Fluid bulk density for shale fluid[kg/m^3].
|
|
76
|
+
phi : np.ndarray
|
|
77
|
+
Total porosity [fraction].
|
|
78
|
+
p_eff_mud : np.ndarray
|
|
79
|
+
Effective pressure in mud [Pa].
|
|
80
|
+
shale_frac : np.ndarray
|
|
81
|
+
Shale fraction [fraction].
|
|
82
|
+
frac_cem : np.ndarray
|
|
83
|
+
Cement volume fraction [fraction].
|
|
84
|
+
phi_c_sst : float
|
|
85
|
+
Critical porosity for sandstone[fraction].
|
|
86
|
+
phi_c_mud : float
|
|
87
|
+
Critical porosity for mud [fraction].
|
|
88
|
+
phi_intr_mud : float
|
|
89
|
+
Intrinsic porosity for mud [fraction].
|
|
90
|
+
n_sst : float
|
|
91
|
+
Coordination number for sandstone [unitless].
|
|
92
|
+
n_mud : float
|
|
93
|
+
Coordination number for shale [unitless].
|
|
94
|
+
coord_num_func_mud : str
|
|
95
|
+
Indication if coordination number should be calculated from porosity or kept constant for shale.
|
|
96
|
+
shear_red_sst : float
|
|
97
|
+
Shear reduction factor for sandstone [fraction].
|
|
98
|
+
shear_red_mud : float
|
|
99
|
+
Shear reduction factor for mud [fraction].
|
|
100
|
+
|
|
101
|
+
Returns
|
|
102
|
+
-------
|
|
103
|
+
tuple
|
|
104
|
+
vp, vs, rho, ai, vpvs : (np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray)
|
|
105
|
+
vp [m/s] and vs [m/s], bulk density [kg/m^3], ai [m/s x kg/m^3], vpvs [ratio] of saturated rock.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
# Valid porosity values must not exceed (phi_c - frac_cem)
|
|
109
|
+
# Assume that this only needs to be considered for the sandstone fraction
|
|
110
|
+
(
|
|
111
|
+
k_sst,
|
|
112
|
+
mu_sst,
|
|
113
|
+
rho_sst,
|
|
114
|
+
k_cem,
|
|
115
|
+
mu_cem,
|
|
116
|
+
rho_cem,
|
|
117
|
+
k_mud,
|
|
118
|
+
mu_mud,
|
|
119
|
+
rho_mud,
|
|
120
|
+
k_fl_sst,
|
|
121
|
+
rho_fl_sst,
|
|
122
|
+
k_fl_mud,
|
|
123
|
+
rho_fl_mud,
|
|
124
|
+
phi,
|
|
125
|
+
p_eff_mud,
|
|
126
|
+
shale_frac,
|
|
127
|
+
frac_cem,
|
|
128
|
+
) = gen_utilities.dim_check_vector(
|
|
129
|
+
(
|
|
130
|
+
k_sst,
|
|
131
|
+
mu_sst,
|
|
132
|
+
rho_sst,
|
|
133
|
+
k_cem,
|
|
134
|
+
mu_cem,
|
|
135
|
+
rho_cem,
|
|
136
|
+
k_mud,
|
|
137
|
+
mu_mud,
|
|
138
|
+
rho_mud,
|
|
139
|
+
k_fl_sst,
|
|
140
|
+
rho_fl_sst,
|
|
141
|
+
k_fl_mud,
|
|
142
|
+
rho_fl_mud,
|
|
143
|
+
phi,
|
|
144
|
+
p_eff_mud,
|
|
145
|
+
shale_frac,
|
|
146
|
+
frac_cem,
|
|
147
|
+
)
|
|
148
|
+
)
|
|
149
|
+
(
|
|
150
|
+
idx_phi,
|
|
151
|
+
(
|
|
152
|
+
k_sst,
|
|
153
|
+
mu_sst,
|
|
154
|
+
rho_sst,
|
|
155
|
+
k_cem,
|
|
156
|
+
mu_cem,
|
|
157
|
+
rho_cem,
|
|
158
|
+
k_mud,
|
|
159
|
+
mu_mud,
|
|
160
|
+
rho_mud,
|
|
161
|
+
k_fl_sst,
|
|
162
|
+
rho_fl_sst,
|
|
163
|
+
k_fl_mud,
|
|
164
|
+
rho_fl_mud,
|
|
165
|
+
phi,
|
|
166
|
+
p_eff_mud,
|
|
167
|
+
shale_frac,
|
|
168
|
+
frac_cem,
|
|
169
|
+
_,
|
|
170
|
+
_,
|
|
171
|
+
),
|
|
172
|
+
) = gen_utilities.filter_input_log(
|
|
173
|
+
(
|
|
174
|
+
k_sst,
|
|
175
|
+
mu_sst,
|
|
176
|
+
rho_sst,
|
|
177
|
+
k_cem,
|
|
178
|
+
mu_cem,
|
|
179
|
+
rho_cem,
|
|
180
|
+
k_mud,
|
|
181
|
+
mu_mud,
|
|
182
|
+
rho_mud,
|
|
183
|
+
k_fl_sst,
|
|
184
|
+
rho_fl_sst,
|
|
185
|
+
k_fl_mud,
|
|
186
|
+
rho_fl_mud,
|
|
187
|
+
phi,
|
|
188
|
+
p_eff_mud,
|
|
189
|
+
shale_frac,
|
|
190
|
+
frac_cem,
|
|
191
|
+
phi_c_sst - frac_cem - phi,
|
|
192
|
+
phi - phi_intr_mud,
|
|
193
|
+
),
|
|
194
|
+
no_zero=False,
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Reduce range of porosity by frac_cem
|
|
198
|
+
phi_c = phi_c_sst - frac_cem
|
|
199
|
+
|
|
200
|
+
sandy_shale_idx = shale_frac > phi
|
|
201
|
+
shaly_sand_idx = ~sandy_shale_idx
|
|
202
|
+
|
|
203
|
+
# Fraction of silt in silt - shale trend
|
|
204
|
+
frac_silt = (1 - shale_frac) / (1 - phi)
|
|
205
|
+
# Fraction of sand in sand - silt trend
|
|
206
|
+
frac_sand = 1 - shale_frac / phi
|
|
207
|
+
|
|
208
|
+
# Shale properties for intrinsic porosity point NB! The phi_intr_mud is
|
|
209
|
+
# normally a parameter, but the assumption in Friable model is that it is a
|
|
210
|
+
# log. Make sure that it is of the same length as the other
|
|
211
|
+
|
|
212
|
+
# Expand the needed variables from float to numpy array
|
|
213
|
+
phi, phi_intr_mud = gen_utilities.dim_check_vector((phi, phi_intr_mud))
|
|
214
|
+
|
|
215
|
+
vp_sat_mud, vs_sat_mud, rho_b_mud = sandstone_models.friable_model(
|
|
216
|
+
k_mud,
|
|
217
|
+
mu_mud,
|
|
218
|
+
rho_mud,
|
|
219
|
+
k_fl_mud,
|
|
220
|
+
rho_fl_mud,
|
|
221
|
+
phi_intr_mud,
|
|
222
|
+
p_eff_mud,
|
|
223
|
+
phi_c_mud,
|
|
224
|
+
coord_num_func_mud,
|
|
225
|
+
n_mud,
|
|
226
|
+
shear_red_mud,
|
|
227
|
+
)[0:3]
|
|
228
|
+
k_sat_mud, mu_sat_mud = std_functions.moduli(vp_sat_mud, vs_sat_mud, rho_b_mud)
|
|
229
|
+
|
|
230
|
+
# Calculate cemented zero-porosity sand
|
|
231
|
+
k_zero, mu_zero = std_functions.hashin_shtrikman_walpole(
|
|
232
|
+
k_cem, mu_cem, k_sst, mu_sst, frac_cem, bound="lower"
|
|
233
|
+
)
|
|
234
|
+
rho_zero = rho_cem * frac_cem + (1 - frac_cem) * rho_sst
|
|
235
|
+
|
|
236
|
+
# Silt end member
|
|
237
|
+
k_silt, mu_silt = std_functions.hashin_shtrikman_walpole(
|
|
238
|
+
k_sat_mud, mu_sat_mud, k_zero, mu_zero, phi_c
|
|
239
|
+
)
|
|
240
|
+
rho_silt = rho_b_mud * phi + rho_zero * (1 - phi)
|
|
241
|
+
|
|
242
|
+
# Estimate the sand end member through the constant cement model with phi =
|
|
243
|
+
# phiCSst <= maybe dubious to expand parameter to vector with assumption
|
|
244
|
+
# that kSst has the correct size
|
|
245
|
+
|
|
246
|
+
vp_sat_sst, vs_sat_sst, rho_sat_sst = sandstone_models.constant_cement_model(
|
|
247
|
+
k_sst,
|
|
248
|
+
mu_sst,
|
|
249
|
+
rho_sst,
|
|
250
|
+
k_cem,
|
|
251
|
+
mu_cem,
|
|
252
|
+
rho_cem,
|
|
253
|
+
k_fl_sst,
|
|
254
|
+
rho_fl_sst,
|
|
255
|
+
phi,
|
|
256
|
+
frac_cem,
|
|
257
|
+
phi_c_sst,
|
|
258
|
+
n_sst,
|
|
259
|
+
shear_red_sst,
|
|
260
|
+
)[0:3]
|
|
261
|
+
k_sat_sst, mu_sat_sst = std_functions.moduli(vp_sat_sst, vs_sat_sst, rho_sat_sst)
|
|
262
|
+
|
|
263
|
+
k = np.ones(shale_frac.shape) * np.nan
|
|
264
|
+
mu = np.ones(shale_frac.shape) * np.nan
|
|
265
|
+
rhob = np.ones(shale_frac.shape) * np.nan
|
|
266
|
+
|
|
267
|
+
# Points on sandy shale trend
|
|
268
|
+
k[sandy_shale_idx], mu[sandy_shale_idx] = std_functions.hashin_shtrikman_walpole(
|
|
269
|
+
k_silt[sandy_shale_idx],
|
|
270
|
+
mu_silt[sandy_shale_idx],
|
|
271
|
+
k_sat_mud[sandy_shale_idx],
|
|
272
|
+
mu_sat_mud[sandy_shale_idx],
|
|
273
|
+
frac_silt[sandy_shale_idx],
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
rhob[sandy_shale_idx] = (
|
|
277
|
+
rho_b_mud[sandy_shale_idx] * (1 - frac_silt[sandy_shale_idx])
|
|
278
|
+
+ rho_silt[sandy_shale_idx] * frac_silt[sandy_shale_idx]
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Points on shaly sand trend
|
|
282
|
+
k[shaly_sand_idx], mu[shaly_sand_idx] = std_functions.hashin_shtrikman_walpole(
|
|
283
|
+
k_sat_sst[shaly_sand_idx],
|
|
284
|
+
mu_sat_sst[shaly_sand_idx],
|
|
285
|
+
k_silt[shaly_sand_idx],
|
|
286
|
+
mu_silt[shaly_sand_idx],
|
|
287
|
+
frac_sand[shaly_sand_idx],
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
rhob[shaly_sand_idx] = (
|
|
291
|
+
(1 - phi[shaly_sand_idx]) * rho_zero[shaly_sand_idx]
|
|
292
|
+
+ phi[shaly_sand_idx] * rho_fl_sst[shaly_sand_idx]
|
|
293
|
+
) * frac_sand[shaly_sand_idx] + (1 - frac_sand[shaly_sand_idx]) * rho_silt[
|
|
294
|
+
shaly_sand_idx
|
|
295
|
+
]
|
|
296
|
+
|
|
297
|
+
vp, vs, ai, vpvs = std_functions.velocity(k, mu, rhob)
|
|
298
|
+
|
|
299
|
+
# Restore original length
|
|
300
|
+
vp, vs, rhob, ai, vpvs = gen_utilities.filter_output(
|
|
301
|
+
idx_phi, (vp, vs, rhob, ai, vpvs)
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
return vp, vs, rhob, ai, vpvs
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from scipy.interpolate import interp1d
|
|
3
|
+
|
|
4
|
+
from rock_physics_open.equinor_utilities import gen_utilities, std_functions
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def constant_cement_model(
|
|
8
|
+
k_min,
|
|
9
|
+
mu_min,
|
|
10
|
+
rho_min,
|
|
11
|
+
k_cem,
|
|
12
|
+
mu_cem,
|
|
13
|
+
rho_cem,
|
|
14
|
+
k_fl,
|
|
15
|
+
rho_fl,
|
|
16
|
+
phi,
|
|
17
|
+
frac_cem,
|
|
18
|
+
phi_c,
|
|
19
|
+
n,
|
|
20
|
+
shear_red,
|
|
21
|
+
extrapolate_to_max_phi=False,
|
|
22
|
+
):
|
|
23
|
+
"""
|
|
24
|
+
Constant cement model is a sandstone model that combined a cemented and a friable sand, so that a constant
|
|
25
|
+
proportion of the rock volume is made up of grain-bonding cement. Variation in porosity is due to grain sorting,
|
|
26
|
+
i.e. a well-sorted sand will have high porosity, and a poorly sorted one will have low porosity. In the extreme
|
|
27
|
+
end all porosity is removed and the effective mineral properties is returned.
|
|
28
|
+
|
|
29
|
+
Mineral properties k_min, mu_min, rho_min are effective properties. For mixtures of minerals, effective
|
|
30
|
+
properties are calculated by Hashin-Shtrikman or similar.
|
|
31
|
+
|
|
32
|
+
Cement properties k_cem, mu_cem, rho_cem and cement fraction, the latter as a part of the whole volume.
|
|
33
|
+
|
|
34
|
+
Fluid properties k_fl, rho_fl are in situ properties calculated by fluid models using reservoir properties.
|
|
35
|
+
|
|
36
|
+
Critical porosity phi_c is input to Dvorkin-Nur function. Coordination number n is normally set to a fixed
|
|
37
|
+
value (default 9) but it is possible to override this. Porosity phi is used in Hashin-Shtrikman mixing
|
|
38
|
+
(together with phi_c) and Gassmann saturation.
|
|
39
|
+
|
|
40
|
+
Shear reduction parameter shear_red is used to account for tangential frictionless grain contacts
|
|
41
|
+
|
|
42
|
+
All inputs are assumed to be vectors of the same length
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
k_min : np.ndarray
|
|
47
|
+
Mineral bulk modulus [Pa].
|
|
48
|
+
mu_min : np.ndarray
|
|
49
|
+
Mineral shear modulus [Pa].
|
|
50
|
+
rho_min : np.ndarray
|
|
51
|
+
Mineral bulk density [kg/m^3].
|
|
52
|
+
k_cem : np.ndarray
|
|
53
|
+
Cement bulk modulus [Pa].
|
|
54
|
+
mu_cem : np.ndarray
|
|
55
|
+
Cement shear modulus [Pa].
|
|
56
|
+
rho_cem : np.ndarray
|
|
57
|
+
Cement bulk density [kg/m^3].
|
|
58
|
+
k_fl : np.ndarray
|
|
59
|
+
Fluid bulk modulus [Pa].
|
|
60
|
+
rho_fl : np.ndarray
|
|
61
|
+
Fluid bulk density [kg/m^3].
|
|
62
|
+
phi : np.ndarray
|
|
63
|
+
Porosity [fraction].
|
|
64
|
+
frac_cem : np.ndarray or float
|
|
65
|
+
Cement fraction [fraction].
|
|
66
|
+
phi_c : float
|
|
67
|
+
Critical porosity [fraction].
|
|
68
|
+
n : float
|
|
69
|
+
Coordination number [unitless].
|
|
70
|
+
shear_red : float
|
|
71
|
+
Shear reduction factor [fraction].
|
|
72
|
+
extrapolate_to_max_phi : bool
|
|
73
|
+
If True, the model will extrapolate to the maximum porosity value (phi_c - frac_cem) if the input porosity
|
|
74
|
+
exceeds this value. If False, the model will return NaN for porosity values exceeding this limit.
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
tuple
|
|
79
|
+
vp, vs, rho, ai, vpvs : (np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray)
|
|
80
|
+
vp [m/s] and vs [m/s], bulk density [kg/m^3], ai [m/s x kg/m^3], vpvs [ratio] of saturated rock.
|
|
81
|
+
"""
|
|
82
|
+
k_zero, k_dry, mu = constant_cement_model_dry(
|
|
83
|
+
k_min,
|
|
84
|
+
mu_min,
|
|
85
|
+
k_cem,
|
|
86
|
+
mu_cem,
|
|
87
|
+
phi,
|
|
88
|
+
frac_cem,
|
|
89
|
+
phi_c,
|
|
90
|
+
n,
|
|
91
|
+
shear_red,
|
|
92
|
+
extrapolate_to_max_phi=extrapolate_to_max_phi,
|
|
93
|
+
return_k_zero=True,
|
|
94
|
+
)
|
|
95
|
+
# Saturated rock incompressibility is calculated with Gassmann
|
|
96
|
+
k = std_functions.gassmann(k_dry, phi, k_fl, k_zero)
|
|
97
|
+
|
|
98
|
+
# Bulk density
|
|
99
|
+
rho = phi * rho_fl + (1 - phi - frac_cem) * rho_min + frac_cem * rho_cem
|
|
100
|
+
# Velocity
|
|
101
|
+
vp, vs, ai, vpvs = std_functions.velocity(k, mu, rho)
|
|
102
|
+
|
|
103
|
+
return vp, vs, rho, ai, vpvs
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def constant_cement_model_dry(
|
|
107
|
+
k_min,
|
|
108
|
+
mu_min,
|
|
109
|
+
k_cem,
|
|
110
|
+
mu_cem,
|
|
111
|
+
phi,
|
|
112
|
+
frac_cem,
|
|
113
|
+
phi_c,
|
|
114
|
+
n,
|
|
115
|
+
shear_red,
|
|
116
|
+
extrapolate_to_max_phi=False,
|
|
117
|
+
return_k_zero=False,
|
|
118
|
+
):
|
|
119
|
+
"""
|
|
120
|
+
Dry rock version of the constant cement model. The method is identical to the constant cement model function,
|
|
121
|
+
except that a saturation step is not performed at the end.
|
|
122
|
+
|
|
123
|
+
Parameters
|
|
124
|
+
----------
|
|
125
|
+
k_min : np.ndarray
|
|
126
|
+
Mineral bulk modulus [Pa].
|
|
127
|
+
mu_min : np.ndarray
|
|
128
|
+
Mineral shear modulus [Pa].
|
|
129
|
+
k_cem : np.ndarray
|
|
130
|
+
Cement bulk modulus [Pa].
|
|
131
|
+
mu_cem : np.ndarray
|
|
132
|
+
Cement shear modulus [Pa].
|
|
133
|
+
phi : np.ndarray
|
|
134
|
+
Porosity [fraction].
|
|
135
|
+
frac_cem : float or np.ndarray
|
|
136
|
+
Cement fraction [fraction].
|
|
137
|
+
phi_c : float
|
|
138
|
+
Critical porosity [fraction].
|
|
139
|
+
n : float
|
|
140
|
+
Coordination number [unitless].
|
|
141
|
+
shear_red : float
|
|
142
|
+
Shear reduction factor [fraction].
|
|
143
|
+
extrapolate_to_max_phi : bool
|
|
144
|
+
If True, the model will extrapolate to the maximum porosity value (phi_c - frac_cem) if the input porosity
|
|
145
|
+
exceeds this value. If False, the model will return NaN for porosity values exceeding this limit.
|
|
146
|
+
return_k_zero : bool
|
|
147
|
+
If True, the model will return the zero-porosity end member bulk modulus k_zero in addition to the dry rock
|
|
148
|
+
bulk modulus k_dry and shear modulus mu.
|
|
149
|
+
|
|
150
|
+
Returns
|
|
151
|
+
-------
|
|
152
|
+
tuple
|
|
153
|
+
k_dry, mu : (np.ndarray, np.ndarray).
|
|
154
|
+
Bulk modulus k [Pa] and shear modulus mu [Pa] of dry rock.
|
|
155
|
+
"""
|
|
156
|
+
# First check if there are input values that are unphysical, i.e. negative values, separate between dry and
|
|
157
|
+
# saturated rock properties. Use the filter_input_log function to identify these values
|
|
158
|
+
idx, (k_min, mu_min, k_cem, mu_cem, phi) = gen_utilities.filter_input_log(
|
|
159
|
+
(k_min, mu_min, k_cem, mu_cem, phi)
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# Identify porosity values that exceed (phi_c - frac_cem). This is regardless of setting for extrapolate_to_max_phi
|
|
163
|
+
idx_phi = np.where(phi > phi_c - frac_cem)[0]
|
|
164
|
+
|
|
165
|
+
# At the zero-porosity point, all original porosity (critical porosity -
|
|
166
|
+
# cement fraction) is filled with grains. The cement fraction surrounds the
|
|
167
|
+
# original grains, so they will be fraction 1 according to the geometrical
|
|
168
|
+
# interpretation of Hashin-Shtrikman
|
|
169
|
+
k_zero, mu_zero = std_functions.hashin_shtrikman_walpole(
|
|
170
|
+
k_cem, mu_cem, k_min, mu_min, frac_cem, bound="lower"
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
# Dry rock properties of high-porosity end member calculated with
|
|
174
|
+
# Dvorkin-Nur equation. Cement is assumed to be evenly distributed on the
|
|
175
|
+
# grains (scheme 2 in Dvorkin and Nur's original paper)
|
|
176
|
+
|
|
177
|
+
k_cc, mu_cc = std_functions.dvorkin_contact_cement(
|
|
178
|
+
frac_cem, phi_c, mu_min, k_min, mu_cem, k_cem, shear_red, n
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# Hashin-Shtrikman lower bound describes the dry rock property mixing from
|
|
182
|
+
# mineral properties to high-end porosity.
|
|
183
|
+
|
|
184
|
+
# Fraction of zero-porosity end member
|
|
185
|
+
f1 = 1 - phi / (phi_c - frac_cem)
|
|
186
|
+
|
|
187
|
+
k_dry, mu = std_functions.hashin_shtrikman_walpole(
|
|
188
|
+
k_zero, mu_zero, k_cc, mu_cc, f1, bound="lower"
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# If extrapolate_to_max_phi is True, create extrapolation functions for k_dry and mu using scipy's interp1d
|
|
192
|
+
if extrapolate_to_max_phi:
|
|
193
|
+
k_dry_func = interp1d(phi, k_dry, fill_value="extrapolate")
|
|
194
|
+
mu_func = interp1d(phi, mu, fill_value="extrapolate")
|
|
195
|
+
k_dry[idx_phi] = k_dry_func(phi[idx_phi])
|
|
196
|
+
mu[idx_phi] = mu_func(phi[idx_phi])
|
|
197
|
+
else:
|
|
198
|
+
k_dry[idx_phi] = np.nan
|
|
199
|
+
mu[idx_phi] = np.nan
|
|
200
|
+
|
|
201
|
+
k_dry, mu = gen_utilities.filter_output(idx, (k_dry, mu))
|
|
202
|
+
if return_k_zero:
|
|
203
|
+
return k_zero, k_dry, mu
|
|
204
|
+
return k_dry, mu
|