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,125 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from rock_physics_open.equinor_utilities import gen_utilities
|
|
4
|
+
from rock_physics_open.equinor_utilities.optimisation_utilities import (
|
|
5
|
+
gen_opt_routine,
|
|
6
|
+
save_opt_params,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from .curvefit_sandstone_models import curvefit_constant_cement
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def constant_cement_model_optimisation(
|
|
13
|
+
k_min: np.ndarray,
|
|
14
|
+
mu_min: np.ndarray,
|
|
15
|
+
rho_min: np.ndarray,
|
|
16
|
+
k_cem: np.ndarray,
|
|
17
|
+
mu_cem: np.ndarray,
|
|
18
|
+
rho_cem: np.ndarray,
|
|
19
|
+
k_fl: np.ndarray,
|
|
20
|
+
rho_fl: np.ndarray,
|
|
21
|
+
por: np.ndarray,
|
|
22
|
+
vp: np.ndarray,
|
|
23
|
+
vs: np.ndarray,
|
|
24
|
+
rhob: np.ndarray,
|
|
25
|
+
file_out_str: str = "constant_cement_optimal_params.pkl",
|
|
26
|
+
display_results: bool = False,
|
|
27
|
+
well_name: str = "Unknown well",
|
|
28
|
+
):
|
|
29
|
+
"""Patchy cement model with optimisation for a selection of parameters.
|
|
30
|
+
|
|
31
|
+
Parameters
|
|
32
|
+
----------
|
|
33
|
+
k_min :
|
|
34
|
+
Cement bulk modulus [Pa].
|
|
35
|
+
mu_min :
|
|
36
|
+
Cement shear modulus [Pa].
|
|
37
|
+
rho_min :
|
|
38
|
+
Cement density [kg/m^3].
|
|
39
|
+
k_cem :
|
|
40
|
+
Cement bulk modulus [Pa].
|
|
41
|
+
mu_cem :
|
|
42
|
+
Cement shear modulus [Pa].
|
|
43
|
+
rho_cem :
|
|
44
|
+
Cement density [kg/m^3].
|
|
45
|
+
k_fl :
|
|
46
|
+
Fluid bulk modulus [Pa].
|
|
47
|
+
rho_fl :
|
|
48
|
+
Fluid density [kg/m^3].
|
|
49
|
+
por :
|
|
50
|
+
Inclusion porosity [ratio].
|
|
51
|
+
vp :
|
|
52
|
+
Compressional velocity log [m/s].
|
|
53
|
+
vs :
|
|
54
|
+
Shear velocity log [m/s].
|
|
55
|
+
rhob :
|
|
56
|
+
Bulk density log [kg/m^3].
|
|
57
|
+
file_out_str :
|
|
58
|
+
Output file name (string) to store optimal parameters (pickle format).
|
|
59
|
+
display_results :
|
|
60
|
+
Display optimal parameters in a window after run.
|
|
61
|
+
well_name :
|
|
62
|
+
Name of well to be displayed in info box title.
|
|
63
|
+
|
|
64
|
+
Returns
|
|
65
|
+
-------
|
|
66
|
+
tuple
|
|
67
|
+
vp_mod, vs_mod - modelled logs, vp_res, vs_res - residual logs.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
# Skip hardcoded Vp/Vs ratio
|
|
71
|
+
def_vpvs = np.mean(vp / vs)
|
|
72
|
+
# Set weight to vs to give vp and vs similar influence on optimisation
|
|
73
|
+
y_data = np.stack([vp, vs * def_vpvs], axis=1)
|
|
74
|
+
# Optimisation function for selected parameters
|
|
75
|
+
opt_fun = curvefit_constant_cement
|
|
76
|
+
# expand single value parameters to match logs length
|
|
77
|
+
por, def_vpvs = gen_utilities.dim_check_vector((por, def_vpvs))
|
|
78
|
+
x_data = np.stack(
|
|
79
|
+
(k_min, mu_min, rho_min, k_cem, mu_cem, rho_cem, k_fl, rho_fl, por, def_vpvs),
|
|
80
|
+
axis=1,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Params: weight_k, weight_mu, shear_red, frac_cem
|
|
84
|
+
lower_bound = np.array(
|
|
85
|
+
[
|
|
86
|
+
0.35, # phi_c
|
|
87
|
+
0.0, # shear_red
|
|
88
|
+
0.01, # frac_cem
|
|
89
|
+
],
|
|
90
|
+
dtype=float,
|
|
91
|
+
)
|
|
92
|
+
upper_bound = np.array(
|
|
93
|
+
[
|
|
94
|
+
0.45, # phi_c
|
|
95
|
+
1.0, # shear_red
|
|
96
|
+
0.1, # frac_cem
|
|
97
|
+
],
|
|
98
|
+
dtype=float,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
x0 = (upper_bound + lower_bound) / 2.0
|
|
102
|
+
# Optimisation step without fluid substitution
|
|
103
|
+
vel_mod, vel_res, opt_params = gen_opt_routine(
|
|
104
|
+
opt_fun, x_data, y_data, x0, lower_bound, upper_bound
|
|
105
|
+
)
|
|
106
|
+
frac_cem = opt_params[2]
|
|
107
|
+
|
|
108
|
+
# Reshape outputs and remove weight from vs
|
|
109
|
+
vp_mod, vs_mod = [arr.flatten() for arr in np.split(vel_mod, 2, axis=1)]
|
|
110
|
+
vp_res, vs_res = [arr.flatten() for arr in np.split(vel_res, 2, axis=1)]
|
|
111
|
+
vs_mod = vs_mod / def_vpvs
|
|
112
|
+
vs_res = vs_res / def_vpvs
|
|
113
|
+
vpvs_mod = vp_mod / vs_mod
|
|
114
|
+
# Calculate the modelled density
|
|
115
|
+
rhob_mod = rho_min * (1.0 - por - frac_cem) + frac_cem * rho_cem + por * rho_fl
|
|
116
|
+
ai_mod = vp_mod * rhob_mod
|
|
117
|
+
rhob_res = rhob_mod - rhob
|
|
118
|
+
# Save the optimal parameters
|
|
119
|
+
save_opt_params("const_cem", opt_params, file_out_str, well_name=well_name)
|
|
120
|
+
if display_results:
|
|
121
|
+
from rock_physics_open.t_matrix_models import opt_param_to_ascii
|
|
122
|
+
|
|
123
|
+
opt_param_to_ascii(file_out_str, well_name=well_name)
|
|
124
|
+
|
|
125
|
+
return vp_mod, vs_mod, rhob_mod, ai_mod, vpvs_mod, vp_res, vs_res, rhob_res
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
from rock_physics_open.equinor_utilities import gen_utilities, std_functions
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def contact_cement_model(
|
|
5
|
+
k_min,
|
|
6
|
+
mu_min,
|
|
7
|
+
rho_min,
|
|
8
|
+
k_cem,
|
|
9
|
+
mu_cem,
|
|
10
|
+
rho_cem,
|
|
11
|
+
k_fl,
|
|
12
|
+
rho_fl,
|
|
13
|
+
phi,
|
|
14
|
+
frac_cem,
|
|
15
|
+
phi_c,
|
|
16
|
+
n,
|
|
17
|
+
shear_red,
|
|
18
|
+
):
|
|
19
|
+
"""
|
|
20
|
+
Contact cement model is a sandstone model where all variation in porosity is explained by variation in grain contact
|
|
21
|
+
cement. This is leads to the stiffest transition from critical porosity to the mineral point.
|
|
22
|
+
|
|
23
|
+
Mineral properties k_min, muMin, rho_min are effective properties. For mixtures of minerals, effective properties
|
|
24
|
+
are calculated by Hashin-Shtrikman or similar.
|
|
25
|
+
|
|
26
|
+
Cement properties kCem, muCem, rhoCem and cement fraction, the latter as a part of the whole volume.
|
|
27
|
+
|
|
28
|
+
Fluid properties k_fl, rho_fl are in situ properties calculated by fluid models using reservoir properties.
|
|
29
|
+
|
|
30
|
+
Critical porosity phiC is input to Dvorkin-Nur function. Coordination number n is normally set to a fixed value
|
|
31
|
+
(default 9) but it is possible to override this. Porosity phi is used in Hashin-Shtrikman mixing (together with
|
|
32
|
+
phiC) and Gassmann saturation.
|
|
33
|
+
|
|
34
|
+
Shear reduction parameter shearRed is used to account for tangential frictionless grain contacts.
|
|
35
|
+
|
|
36
|
+
All inputs are assumed to be vectors of the same length.
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
k_min : np.ndarray
|
|
42
|
+
Mineral bulk modulus [Pa].
|
|
43
|
+
mu_min : np.ndarray
|
|
44
|
+
Mineral shear modulus [Pa].
|
|
45
|
+
rho_min : np.ndarray
|
|
46
|
+
Mineral bulk density [kg/m^3].
|
|
47
|
+
k_cem : np.ndarray
|
|
48
|
+
Cement bulk modulus [Pa].
|
|
49
|
+
mu_cem : np.ndarray
|
|
50
|
+
Cement shear modulus [Pa].
|
|
51
|
+
rho_cem : np.ndarray
|
|
52
|
+
Cement bulk density [kg/m^3].
|
|
53
|
+
k_fl : np.ndarray
|
|
54
|
+
Fluid bulk modulus [Pa].
|
|
55
|
+
rho_fl : np.ndarray
|
|
56
|
+
Fluid bulk density [kg/m^3].
|
|
57
|
+
phi : np.ndarray
|
|
58
|
+
Porosity [fraction].
|
|
59
|
+
frac_cem : float
|
|
60
|
+
Cement fraction [fraction].
|
|
61
|
+
phi_c : float
|
|
62
|
+
Critical porosity [fraction].
|
|
63
|
+
n : float
|
|
64
|
+
Coordination number [unitless].
|
|
65
|
+
shear_red : float
|
|
66
|
+
Shear reduction factor [fraction].
|
|
67
|
+
|
|
68
|
+
Returns
|
|
69
|
+
-------
|
|
70
|
+
tuple
|
|
71
|
+
vp, vs, rho, ai, vpvs : (np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray)
|
|
72
|
+
vp [m/s] and vs [m/s], bulk density [kg/m^3], ai [m/s x kg/m^3], vpvs [ratio] of saturated rock.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
# Identify porosity values that are above (phi_c - frac_cem), for which the model is not defined
|
|
76
|
+
(
|
|
77
|
+
idx_phi,
|
|
78
|
+
(k_min, mu_min, rho_min, k_cem, mu_cem, rho_cem, k_fl, rho_fl, phi, _),
|
|
79
|
+
) = gen_utilities.filter_input_log(
|
|
80
|
+
(
|
|
81
|
+
k_min,
|
|
82
|
+
mu_min,
|
|
83
|
+
rho_min,
|
|
84
|
+
k_cem,
|
|
85
|
+
mu_cem,
|
|
86
|
+
rho_cem,
|
|
87
|
+
k_fl,
|
|
88
|
+
rho_fl,
|
|
89
|
+
phi,
|
|
90
|
+
phi_c - frac_cem - phi,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Expand input parameters to arrays
|
|
95
|
+
phi, frac_cem, phi_c, n, shear_red = gen_utilities.dim_check_vector(
|
|
96
|
+
(phi, frac_cem, phi_c, n, shear_red)
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
# At the zero-porosity point, all original porosity (critical porosity) is
|
|
100
|
+
# filled with cement. The cement surrounds the original grains, so they
|
|
101
|
+
# will be fraction 1 according to the geometrical interpretation of
|
|
102
|
+
# Hashin-Shtrikman
|
|
103
|
+
k_zero, mu_zero = std_functions.hashin_shtrikman_walpole(
|
|
104
|
+
k_cem, mu_cem, k_min, mu_min, phi_c, bound="lower"
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Dry rock properties of high-porosity end member calculated with
|
|
108
|
+
# Dvorkin-Nur equation. Cement is assumed to be evenly distributed on the
|
|
109
|
+
# grains (scheme 2 in Dvorkin and Nur's original paper)
|
|
110
|
+
|
|
111
|
+
k_cc, mu_cc = std_functions.dvorkin_contact_cement(
|
|
112
|
+
frac_cem, phi_c, mu_zero, k_zero, mu_cem, k_cem, shear_red, n
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
# Hashin-Shtrikman upper bound describes the dry rock property mixing from
|
|
116
|
+
# mineral properties to high-end porosity.
|
|
117
|
+
|
|
118
|
+
# Fraction of zero-porosity end member
|
|
119
|
+
f1 = 1 - phi / (phi_c - frac_cem)
|
|
120
|
+
|
|
121
|
+
k_dry, mu = std_functions.hashin_shtrikman_walpole(
|
|
122
|
+
k_zero, mu_zero, k_cc, mu_cc, f1, bound="upper"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Saturated rock incompressibility is calculated with Gassmann
|
|
126
|
+
k = std_functions.gassmann(k_dry, phi, k_fl, k_zero)
|
|
127
|
+
|
|
128
|
+
# Bulk density
|
|
129
|
+
rho = phi * rho_fl + (1 - phi_c) * rho_min + (phi_c - phi) * rho_cem
|
|
130
|
+
|
|
131
|
+
vp, vs, ai, vpvs = std_functions.velocity(k, mu, rho)
|
|
132
|
+
|
|
133
|
+
# Restore original array length
|
|
134
|
+
vp, vs, rho, ai, vpvs = gen_utilities.filter_output(
|
|
135
|
+
idx_phi, (vp, vs, rho, ai, vpvs)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
return vp, vs, rho, ai, vpvs
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from .constant_cement_models import constant_cement_model
|
|
4
|
+
from .friable_models import friable_model
|
|
5
|
+
from .patchy_cement_model import patchy_cement_model_weight
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def curvefit_patchy_cement(x_data, weight_k, weight_mu, shear_red, frac_cem):
|
|
9
|
+
"""Run patchy_cement_model_weight with parameter optimisation for closest possible fit to observations
|
|
10
|
+
|
|
11
|
+
Inputs: vp, vs, rho, por, k_fl, rho_fl, p_eff, k_min, mu_min, rho_min, k_cem, mu_cem, rho_cem, phi_c
|
|
12
|
+
Parameters to optimise for: frac_cem, shear_red, weight_k, weight_mu
|
|
13
|
+
Optimise for vp, vs
|
|
14
|
+
"""
|
|
15
|
+
# Unpack x inputs
|
|
16
|
+
# In calling function:
|
|
17
|
+
k_min = x_data[:, 0]
|
|
18
|
+
mu_min = x_data[:, 1]
|
|
19
|
+
rho_min = x_data[:, 2]
|
|
20
|
+
k_cem = x_data[:, 3]
|
|
21
|
+
mu_cem = x_data[:, 4]
|
|
22
|
+
rho_cem = x_data[:, 5]
|
|
23
|
+
k_fl = x_data[:, 6]
|
|
24
|
+
rho_fl = x_data[:, 7]
|
|
25
|
+
phi = x_data[:, 8]
|
|
26
|
+
p_eff = x_data[:, 9]
|
|
27
|
+
def_vp_vs_ratio = x_data[0, 10]
|
|
28
|
+
phi_c = x_data[0, 11]
|
|
29
|
+
|
|
30
|
+
# Catch phi values that are above phi_c - frac_cem, reduce silently to phi_c - frac_cem
|
|
31
|
+
phi = np.minimum(phi, phi_c - frac_cem)
|
|
32
|
+
|
|
33
|
+
try:
|
|
34
|
+
vp, vs = patchy_cement_model_weight(
|
|
35
|
+
k_min,
|
|
36
|
+
mu_min,
|
|
37
|
+
rho_min,
|
|
38
|
+
k_cem,
|
|
39
|
+
mu_cem,
|
|
40
|
+
rho_cem,
|
|
41
|
+
k_fl,
|
|
42
|
+
rho_fl,
|
|
43
|
+
phi,
|
|
44
|
+
p_eff,
|
|
45
|
+
frac_cem,
|
|
46
|
+
phi_c,
|
|
47
|
+
"por_based",
|
|
48
|
+
9.0,
|
|
49
|
+
shear_red,
|
|
50
|
+
weight_k,
|
|
51
|
+
weight_mu,
|
|
52
|
+
)[0:2]
|
|
53
|
+
except ValueError:
|
|
54
|
+
vp = np.zeros(k_min.shape)
|
|
55
|
+
vs = np.zeros(k_min.shape)
|
|
56
|
+
|
|
57
|
+
return np.stack((vp, def_vp_vs_ratio * vs), axis=1).flatten("F")
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def curvefit_friable(x_data, phi_c, shear_red):
|
|
61
|
+
"""Run friable sand model with parameter optimisation for closest possible fit to observations
|
|
62
|
+
|
|
63
|
+
Inputs: vp, vs, por, k_fl, rho_fl, p_eff, k_min, mu_min, rho_min
|
|
64
|
+
Parameters to optimise for: phi_c, shear_red
|
|
65
|
+
Optimise for vp, vs
|
|
66
|
+
"""
|
|
67
|
+
# Unpack x inputs
|
|
68
|
+
k_min = x_data[:, 0]
|
|
69
|
+
mu_min = x_data[:, 1]
|
|
70
|
+
rho_min = x_data[:, 2]
|
|
71
|
+
k_fl = x_data[:, 3]
|
|
72
|
+
rho_fl = x_data[:, 4]
|
|
73
|
+
phi = x_data[:, 5]
|
|
74
|
+
p_eff = x_data[:, 6]
|
|
75
|
+
def_vp_vs_ratio = x_data[0, 7]
|
|
76
|
+
|
|
77
|
+
# Catch phi values that are above phi_c, reduce silently to phi_c
|
|
78
|
+
phi = np.minimum(phi, phi_c)
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
vp, vs = friable_model(
|
|
82
|
+
k_min,
|
|
83
|
+
mu_min,
|
|
84
|
+
rho_min,
|
|
85
|
+
k_fl,
|
|
86
|
+
rho_fl,
|
|
87
|
+
phi,
|
|
88
|
+
p_eff,
|
|
89
|
+
phi_c,
|
|
90
|
+
"por_based",
|
|
91
|
+
1.0,
|
|
92
|
+
shear_red,
|
|
93
|
+
)[0:2]
|
|
94
|
+
except ValueError:
|
|
95
|
+
vp = np.zeros(k_min.shape)
|
|
96
|
+
vs = np.zeros(k_min.shape)
|
|
97
|
+
|
|
98
|
+
return np.stack((vp, def_vp_vs_ratio * vs), axis=1).flatten("F")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def curvefit_constant_cement(x_data, phi_c, shear_red, frac_cem):
|
|
102
|
+
"""Run constant_cement_model with parameter optimisation for closest possible fit to observations
|
|
103
|
+
|
|
104
|
+
Inputs: vp, vs, por, k_min, mu_min, rho_min, k_cem, mu_cem, rho_cem, k_fl, rho_fl
|
|
105
|
+
Parameters to optimise for: phi_c, shear_red, frac_cem
|
|
106
|
+
Optimise for vp, vs
|
|
107
|
+
"""
|
|
108
|
+
# Unpack x inputs
|
|
109
|
+
k_min = x_data[:, 0]
|
|
110
|
+
mu_min = x_data[:, 1]
|
|
111
|
+
rho_min = x_data[:, 2]
|
|
112
|
+
k_cem = x_data[:, 3]
|
|
113
|
+
mu_cem = x_data[:, 4]
|
|
114
|
+
rho_cem = x_data[:, 5]
|
|
115
|
+
k_fl = x_data[:, 6]
|
|
116
|
+
rho_fl = x_data[:, 7]
|
|
117
|
+
phi = x_data[:, 8]
|
|
118
|
+
def_vp_vs_ratio = x_data[0, 9]
|
|
119
|
+
|
|
120
|
+
# Catch phi values that are above phi_c - frac_cem, reduce silently to phi_c - frac_cem
|
|
121
|
+
phi = np.minimum(phi, phi_c - frac_cem)
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
vp, vs = constant_cement_model(
|
|
125
|
+
k_min,
|
|
126
|
+
mu_min,
|
|
127
|
+
rho_min,
|
|
128
|
+
k_cem,
|
|
129
|
+
mu_cem,
|
|
130
|
+
rho_cem,
|
|
131
|
+
k_fl,
|
|
132
|
+
rho_fl,
|
|
133
|
+
phi,
|
|
134
|
+
frac_cem,
|
|
135
|
+
phi_c,
|
|
136
|
+
9.0,
|
|
137
|
+
shear_red,
|
|
138
|
+
)[0:2]
|
|
139
|
+
except ValueError:
|
|
140
|
+
vp = np.zeros(k_min.shape)
|
|
141
|
+
vs = np.zeros(k_min.shape)
|
|
142
|
+
|
|
143
|
+
return np.stack((vp, def_vp_vs_ratio * vs), axis=1).flatten("F")
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
from rock_physics_open.equinor_utilities import gen_utilities, std_functions
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def friable_model(
|
|
5
|
+
k_min,
|
|
6
|
+
mu_min,
|
|
7
|
+
rho_min,
|
|
8
|
+
k_fl,
|
|
9
|
+
rho_fl,
|
|
10
|
+
phi,
|
|
11
|
+
p_eff,
|
|
12
|
+
phi_c,
|
|
13
|
+
coord_num_func,
|
|
14
|
+
n,
|
|
15
|
+
shear_red,
|
|
16
|
+
):
|
|
17
|
+
"""
|
|
18
|
+
Friable (non-cemented) sandstone model. All porosity variation is due to sorting, i.e. porosity filled with
|
|
19
|
+
smaller grains. This model is pressure sensitive, but without asymptotic behaviour, which could be expected.
|
|
20
|
+
|
|
21
|
+
The same model is also used for shale, with different set of parameters.
|
|
22
|
+
|
|
23
|
+
Mineral properties k_min, mu_min, rho_min are effective properties. For
|
|
24
|
+
mixtures of minerals, effective properties are calculated by
|
|
25
|
+
Hashin-Shtrikman or similar.
|
|
26
|
+
|
|
27
|
+
Fluid properties k_fl, rho_fl are in situ properties calculated by a fluid model using reservoir properties.
|
|
28
|
+
|
|
29
|
+
Effective pressure p_eff is normally calculated as differential
|
|
30
|
+
pressure, i.e. overburden pressure minus pore pressure.
|
|
31
|
+
|
|
32
|
+
Critical porosity phi_c is input to Hertz-Mindlin function. Coordination
|
|
33
|
+
number n is normally calculated from critical porosity, but it is
|
|
34
|
+
possible to override this through coord_num_func and parameter n.
|
|
35
|
+
Porosity phi is used in Hashin-Shtrikman mixing (together with phi_c)
|
|
36
|
+
and Gassmann saturation. Porosity values above the critical porosity are undefined and NaN is returned.
|
|
37
|
+
|
|
38
|
+
Shear reduction parameter shearRed is used to account for tangential
|
|
39
|
+
frictionless grain contacts.
|
|
40
|
+
|
|
41
|
+
All inputs are assumed to be vectors of the same length. Single parameters
|
|
42
|
+
are expanded to column vectors matching other inputs.
|
|
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_fl : np.ndarray
|
|
53
|
+
Fluid bulk modulus [Pa].
|
|
54
|
+
rho_fl : np.ndarray
|
|
55
|
+
Fluid bulk density [kg/m^3].
|
|
56
|
+
phi : np.ndarray
|
|
57
|
+
Porosity [fraction].
|
|
58
|
+
p_eff : np.ndarray
|
|
59
|
+
Effective pressure [Pa].
|
|
60
|
+
phi_c : float
|
|
61
|
+
Critical porosity [fraction].
|
|
62
|
+
coord_num_func : str
|
|
63
|
+
Indication if coordination number should be calculated from porosity or kept constant.
|
|
64
|
+
n : float
|
|
65
|
+
Coordination number [unitless].
|
|
66
|
+
shear_red : float
|
|
67
|
+
Shear reduction factor [fraction].
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
tuple
|
|
72
|
+
vp, vs, rho, ai, vpvs : (np.ndarray, np.ndarray, np.ndarray, np.ndarray, np.ndarray)
|
|
73
|
+
vp [m/s] and vs [m/s], bulk density [kg/m^3], ai [m/s x kg/m^3], vpvs [ratio] of saturated rock.
|
|
74
|
+
"""
|
|
75
|
+
k_dry, mu = friable_model_dry(
|
|
76
|
+
k_min, mu_min, phi, p_eff, phi_c, coord_num_func, n, shear_red
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Saturated rock incompressibility is calculated with Gassmann
|
|
80
|
+
k = std_functions.gassmann(k_dry, phi, k_fl, k_min)
|
|
81
|
+
|
|
82
|
+
# Bulk density
|
|
83
|
+
rhob = std_functions.rho_b(phi, rho_fl, rho_min)
|
|
84
|
+
|
|
85
|
+
vp, vs, ai, vpvs = std_functions.velocity(k, mu, rhob)
|
|
86
|
+
|
|
87
|
+
return vp, vs, rhob, ai, vpvs
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def friable_model_dry(k_min, mu_min, phi, p_eff, phi_c, coord_num_func, n, shear_red):
|
|
91
|
+
"""
|
|
92
|
+
Dry rock version of friable sandstone model.
|
|
93
|
+
|
|
94
|
+
Mineral properties k_min, mu_min, are effective properties. For
|
|
95
|
+
mixtures of minerals, effective properties are calculated by
|
|
96
|
+
Hashin-Shtrikman or similar.
|
|
97
|
+
|
|
98
|
+
Effective pressure p_eff is normally calculated as differential
|
|
99
|
+
pressure, i.e. overburden pressure minus pore pressure.
|
|
100
|
+
|
|
101
|
+
Critical porosity phi_c is input to Hertz-Mindlin function. Coordination
|
|
102
|
+
number n is normally calculated from critical porosity, but it is
|
|
103
|
+
possible to override this through coordNumFunc and parameter n.
|
|
104
|
+
Porosity phi is used in Hashin-Shtrikman mixing (together with phi_c).
|
|
105
|
+
Porosity values above the critical porosity are undefined and NaN is returned.
|
|
106
|
+
|
|
107
|
+
Shear reduction parameter shearRed is used to account for tangential
|
|
108
|
+
frictionless grain contacts.
|
|
109
|
+
|
|
110
|
+
All inputs are assumed to be vectors of the same length. Single parameters
|
|
111
|
+
are expanded to column vectors matching other inputs.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
k_min : np.ndarray
|
|
116
|
+
Mineral bulk modulus [Pa].
|
|
117
|
+
mu_min : np.ndarray
|
|
118
|
+
Mineral shear modulus [Pa].
|
|
119
|
+
phi : np.ndarray
|
|
120
|
+
Porosity [fraction].
|
|
121
|
+
p_eff : np.ndarray
|
|
122
|
+
Effective pressure [Pa].
|
|
123
|
+
phi_c : float
|
|
124
|
+
Critical porosity [fraction].
|
|
125
|
+
coord_num_func : str
|
|
126
|
+
Indication if coordination number should be calculated from porosity or kept constant.
|
|
127
|
+
n : float | None
|
|
128
|
+
Coordination number [unitless].
|
|
129
|
+
shear_red : float
|
|
130
|
+
Shear reduction factor [fraction].
|
|
131
|
+
|
|
132
|
+
Returns
|
|
133
|
+
-------
|
|
134
|
+
tuple
|
|
135
|
+
k, mu : (np.ndarray, np.ndarray).
|
|
136
|
+
Bulk modulus k [Pa], shear modulus mu [Pa] of dry rock.
|
|
137
|
+
"""
|
|
138
|
+
# Expand floats to arrays, check for equal length
|
|
139
|
+
phi, phi_c, shear_red, k_min, mu_min, p_eff = gen_utilities.dim_check_vector(
|
|
140
|
+
(phi, phi_c, shear_red, k_min, mu_min, p_eff)
|
|
141
|
+
)
|
|
142
|
+
# Valid porosity values are less or equal to the critical porosity
|
|
143
|
+
# Use filter_input_log to remove values that do not comply with this
|
|
144
|
+
(
|
|
145
|
+
idx_phi,
|
|
146
|
+
(phi, phi_c, shear_red, k_min, mu_min, p_eff, _),
|
|
147
|
+
) = gen_utilities.filter_input_log(
|
|
148
|
+
(phi, phi_c, shear_red, k_min, mu_min, p_eff, phi_c - phi)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Dry rock properties of high-porosity end member calculated with
|
|
152
|
+
# Hertz-Mindlin equation
|
|
153
|
+
|
|
154
|
+
# Override coordination number calculation based on porosity
|
|
155
|
+
if coord_num_func == "ConstVal":
|
|
156
|
+
k_hm, mu_hm = std_functions.hertz_mindlin(
|
|
157
|
+
k_min, mu_min, phi_c, p_eff, shear_red, n
|
|
158
|
+
)
|
|
159
|
+
else:
|
|
160
|
+
# Porosity based coordination number
|
|
161
|
+
k_hm, mu_hm = std_functions.hertz_mindlin(
|
|
162
|
+
k_min, mu_min, phi_c, p_eff, shear_red
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Hashin-Shtrikman lower bound describes the dry rock property mixing from
|
|
166
|
+
# mineral properties to high-end porosity.
|
|
167
|
+
|
|
168
|
+
# Fraction of solid
|
|
169
|
+
f1 = 1 - phi / phi_c
|
|
170
|
+
|
|
171
|
+
k_dry, mu = std_functions.hashin_shtrikman_walpole(
|
|
172
|
+
k_min, mu_min, k_hm, mu_hm, f1, bound="lower"
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
k_dry, mu = gen_utilities.filter_output(idx_phi, (k_dry, mu))
|
|
176
|
+
|
|
177
|
+
return k_dry, mu
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from rock_physics_open.equinor_utilities import gen_utilities
|
|
4
|
+
from rock_physics_open.equinor_utilities.optimisation_utilities import (
|
|
5
|
+
gen_opt_routine,
|
|
6
|
+
save_opt_params,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from .curvefit_sandstone_models import curvefit_friable
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def friable_model_optimisation(
|
|
13
|
+
k_min: np.ndarray,
|
|
14
|
+
mu_min: np.ndarray,
|
|
15
|
+
rho_min: np.ndarray,
|
|
16
|
+
k_fl: np.ndarray,
|
|
17
|
+
rho_fl: np.ndarray,
|
|
18
|
+
por: np.ndarray,
|
|
19
|
+
p_eff: np.ndarray,
|
|
20
|
+
vp: np.ndarray,
|
|
21
|
+
vs: np.ndarray,
|
|
22
|
+
rhob: np.ndarray,
|
|
23
|
+
file_out_str: str = "friable_model_optimal_params.pkl",
|
|
24
|
+
display_results: bool = False,
|
|
25
|
+
well_name: str = "Unknown well",
|
|
26
|
+
):
|
|
27
|
+
"""Patchy cement model with optimisation for a selection of parameters.
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
k_min :
|
|
32
|
+
Cement bulk modulus [Pa].
|
|
33
|
+
mu_min :
|
|
34
|
+
Cement shear modulus [Pa].
|
|
35
|
+
rho_min :
|
|
36
|
+
Cement density [kg/m^3].
|
|
37
|
+
k_fl :
|
|
38
|
+
Fluid bulk modulus [Pa].
|
|
39
|
+
rho_fl :
|
|
40
|
+
Fluid density [kg/m^3].
|
|
41
|
+
por :
|
|
42
|
+
Inclusion porosity [ratio].
|
|
43
|
+
vp :
|
|
44
|
+
Compressional velocity log [m/s].
|
|
45
|
+
vs :
|
|
46
|
+
Shear velocity log [m/s].
|
|
47
|
+
rhob :
|
|
48
|
+
Bulk density log [kg/m^3].
|
|
49
|
+
p_eff :
|
|
50
|
+
Effective pressure log [Pa].
|
|
51
|
+
file_out_str :
|
|
52
|
+
Output file name (string) to store optimal parameters (pickle format).
|
|
53
|
+
display_results :
|
|
54
|
+
D isplay optimal parameters in a window after run.
|
|
55
|
+
well_name :
|
|
56
|
+
Name of well to be displayed in info box title.
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
tuple
|
|
61
|
+
vp_mod, vs_mod, rho_mod, ai_mod, vpvs_mod - modelled logs, vp_res, vs_res, rho_res - residual logs.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
# Skip hardcoded Vp/Vs ratio
|
|
65
|
+
def_vpvs = np.mean(vp / vs)
|
|
66
|
+
# Set weight to vs to give vp and vs similar influence on optimisation
|
|
67
|
+
y_data = np.stack([vp, vs * def_vpvs], axis=1)
|
|
68
|
+
# Optimisation function for selected parameters
|
|
69
|
+
opt_fun = curvefit_friable
|
|
70
|
+
# expand single value parameters to match logs length
|
|
71
|
+
por, def_vpvs = gen_utilities.dim_check_vector((por, def_vpvs))
|
|
72
|
+
x_data = np.stack(
|
|
73
|
+
(k_min, mu_min, rho_min, k_fl, rho_fl, por, p_eff, def_vpvs), axis=1
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Params: weight_k, weight_mu, shear_red, frac_cem
|
|
77
|
+
lower_bound = np.array(
|
|
78
|
+
[
|
|
79
|
+
0.35, # phi_c
|
|
80
|
+
0.0, # shear_red
|
|
81
|
+
],
|
|
82
|
+
dtype=float,
|
|
83
|
+
)
|
|
84
|
+
upper_bound = np.array(
|
|
85
|
+
[
|
|
86
|
+
0.45, # phi_c
|
|
87
|
+
1.0, # shear_red
|
|
88
|
+
],
|
|
89
|
+
dtype=float,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
x0 = (upper_bound + lower_bound) / 2.0
|
|
93
|
+
# Optimisation step without fluid substitution
|
|
94
|
+
vel_mod, vel_res, opt_params = gen_opt_routine(
|
|
95
|
+
opt_fun, x_data, y_data, x0, lower_bound, upper_bound
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# Reshape outputs and remove weight from vs
|
|
99
|
+
vp_mod, vs_mod = [arr.flatten() for arr in np.split(vel_mod, 2, axis=1)]
|
|
100
|
+
vp_res, vs_res = [arr.flatten() for arr in np.split(vel_res, 2, axis=1)]
|
|
101
|
+
vs_mod = vs_mod / def_vpvs
|
|
102
|
+
vs_res = vs_res / def_vpvs
|
|
103
|
+
vpvs_mod = vp_mod / vs_mod
|
|
104
|
+
# Calculate the modelled density
|
|
105
|
+
rhob_mod = rho_min * (1.0 - por) + por * rho_fl
|
|
106
|
+
ai_mod = vp_mod * rhob_mod
|
|
107
|
+
rhob_res = rhob_mod - rhob
|
|
108
|
+
# Save the optimal parameters
|
|
109
|
+
save_opt_params("friable", opt_params, file_out_str, well_name=well_name)
|
|
110
|
+
if display_results:
|
|
111
|
+
from rock_physics_open.t_matrix_models import opt_param_to_ascii
|
|
112
|
+
|
|
113
|
+
opt_param_to_ascii(file_out_str, well_name=well_name)
|
|
114
|
+
|
|
115
|
+
return vp_mod, vs_mod, rhob_mod, ai_mod, vpvs_mod, vp_res, vs_res, rhob_res
|