fmu-pem 0.0.1__py3-none-any.whl → 0.0.3__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.
- fmu/pem/__main__.py +32 -16
- fmu/pem/forward_models/pem_model.py +19 -27
- fmu/pem/pem_functions/__init__.py +2 -2
- fmu/pem/pem_functions/density.py +32 -38
- fmu/pem/pem_functions/effective_pressure.py +153 -48
- fmu/pem/pem_functions/estimate_saturated_rock.py +244 -52
- fmu/pem/pem_functions/fluid_properties.py +453 -246
- fmu/pem/pem_functions/mineral_properties.py +77 -74
- fmu/pem/pem_functions/pressure_sensitivity.py +430 -0
- fmu/pem/pem_functions/regression_models.py +129 -97
- fmu/pem/pem_functions/run_friable_model.py +106 -37
- fmu/pem/pem_functions/run_patchy_cement_model.py +107 -45
- fmu/pem/pem_functions/{run_t_matrix_and_pressure.py → run_t_matrix_model.py} +48 -27
- fmu/pem/pem_utilities/__init__.py +31 -9
- fmu/pem/pem_utilities/cumsum_properties.py +29 -37
- fmu/pem/pem_utilities/delta_cumsum_time.py +8 -13
- fmu/pem/pem_utilities/enum_defs.py +77 -4
- fmu/pem/pem_utilities/export_routines.py +84 -72
- fmu/pem/pem_utilities/fipnum_pvtnum_utilities.py +217 -0
- fmu/pem/pem_utilities/import_config.py +64 -46
- fmu/pem/pem_utilities/import_routines.py +58 -69
- fmu/pem/pem_utilities/pem_class_definitions.py +81 -23
- fmu/pem/pem_utilities/pem_config_validation.py +374 -149
- fmu/pem/pem_utilities/rpm_models.py +481 -83
- fmu/pem/pem_utilities/update_grid.py +3 -2
- fmu/pem/pem_utilities/utils.py +90 -38
- fmu/pem/run_pem.py +70 -39
- fmu/pem/version.py +16 -3
- {fmu_pem-0.0.1.dist-info → fmu_pem-0.0.3.dist-info}/METADATA +33 -28
- fmu_pem-0.0.3.dist-info/RECORD +39 -0
- fmu_pem-0.0.1.dist-info/RECORD +0 -37
- {fmu_pem-0.0.1.dist-info → fmu_pem-0.0.3.dist-info}/WHEEL +0 -0
- {fmu_pem-0.0.1.dist-info → fmu_pem-0.0.3.dist-info}/entry_points.txt +0 -0
- {fmu_pem-0.0.1.dist-info → fmu_pem-0.0.3.dist-info}/licenses/LICENSE +0 -0
- {fmu_pem-0.0.1.dist-info → fmu_pem-0.0.3.dist-info}/top_level.txt +0 -0
fmu/pem/pem_utilities/utils.py
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import os
|
|
2
2
|
from contextlib import contextmanager
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Generator
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
import xtgeo
|
|
8
8
|
|
|
9
|
-
from .pem_class_definitions import
|
|
10
|
-
from .pem_config_validation import PemConfig
|
|
9
|
+
from .pem_class_definitions import EffectiveMineralProperties, PressureProperties
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
@contextmanager
|
|
14
|
-
def restore_dir(path: Path) ->
|
|
13
|
+
def restore_dir(path: Path) -> Generator: # type: ignore[return-value]
|
|
15
14
|
"""restore_dir run block of code from a given path, restore original path
|
|
16
15
|
|
|
17
16
|
Args:
|
|
@@ -29,7 +28,7 @@ def restore_dir(path: Path) -> None:
|
|
|
29
28
|
|
|
30
29
|
|
|
31
30
|
def to_masked_array(
|
|
32
|
-
value:
|
|
31
|
+
value: float | int, masked_array: np.ma.MaskedArray
|
|
33
32
|
) -> np.ma.MaskedArray:
|
|
34
33
|
"""Create a masked array with a constant value from an int or float and a template
|
|
35
34
|
masked array
|
|
@@ -44,12 +43,40 @@ def to_masked_array(
|
|
|
44
43
|
return np.ma.MaskedArray(value * np.ones_like(masked_array), mask=masked_array.mask)
|
|
45
44
|
|
|
46
45
|
|
|
46
|
+
def get_masked_array_mask(masked_array: np.ma.MaskedArray) -> np.ndarray:
|
|
47
|
+
"""Extract mask from MaskedArray or create default mask."""
|
|
48
|
+
return (
|
|
49
|
+
masked_array.mask
|
|
50
|
+
if hasattr(masked_array, "mask")
|
|
51
|
+
else np.zeros_like(masked_array.data, dtype=bool)
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def set_mask(
|
|
56
|
+
masked_template: np.ma.MaskedArray,
|
|
57
|
+
prop_array: np.ma.MaskedArray | None,
|
|
58
|
+
) -> np.ma.MaskedArray | None:
|
|
59
|
+
"""Check for existence of mask in masked_template, return prop_array
|
|
60
|
+
with masked values. In case prop_array is None, return None"""
|
|
61
|
+
if prop_array is None:
|
|
62
|
+
return None
|
|
63
|
+
return np.ma.masked_where(
|
|
64
|
+
masked_template.mask
|
|
65
|
+
if hasattr(masked_template, "mask")
|
|
66
|
+
else np.zeros_like(prop_array),
|
|
67
|
+
prop_array,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
47
71
|
def filter_and_one_dim(
|
|
48
72
|
*args: np.ma.MaskedArray, return_numpy_array: bool = False
|
|
49
|
-
) -> tuple[np.ma.MaskedArray, ...]:
|
|
73
|
+
) -> tuple[np.ma.MaskedArray | np.ndarray, ...]:
|
|
50
74
|
"""Filters multiple masked arrays by removing masked values and flattens them to 1D.
|
|
51
75
|
|
|
52
|
-
|
|
76
|
+
If no elements are masked (i.e., mask is scalar False), this function will still
|
|
77
|
+
flatten the arrays to 1D by treating all entries as valid. This ensures
|
|
78
|
+
downstream rock physics functions always receive 1D arrays, avoiding shape
|
|
79
|
+
issues (e.g. (1, nx, ny, nz)) when no masking occurs.
|
|
53
80
|
|
|
54
81
|
Args:
|
|
55
82
|
*args: One or more masked arrays of identical shape. Each array contains data
|
|
@@ -59,26 +86,34 @@ def filter_and_one_dim(
|
|
|
59
86
|
|
|
60
87
|
Returns:
|
|
61
88
|
tuple containing:
|
|
62
|
-
- mask: Boolean array of
|
|
63
|
-
|
|
64
|
-
- filtered arrays: One or more 1D arrays containing only the unmasked values
|
|
65
|
-
from each input array, in their original order
|
|
89
|
+
- mask: Boolean array of same shape where True indicates masked positions
|
|
90
|
+
- filtered arrays: 1D arrays containing the unmasked values from each arg
|
|
66
91
|
"""
|
|
67
92
|
if not np.all([isinstance(arg, np.ma.MaskedArray) for arg in args]):
|
|
68
93
|
raise ValueError(f"{__file__}: all inputs should be numpy masked arrays")
|
|
94
|
+
|
|
95
|
+
# Combine masks
|
|
69
96
|
mask = args[0].mask
|
|
70
97
|
for i in range(1, len(args)):
|
|
71
98
|
mask = np.logical_or(mask, args[i].mask)
|
|
99
|
+
|
|
100
|
+
# If mask is scalar (no masked elements), expand to full-shape False array
|
|
101
|
+
if np.isscalar(mask): # covers True/False scalar
|
|
102
|
+
# All values valid -> create explicit False mask array matching input shape
|
|
103
|
+
mask = np.zeros(args[0].shape, dtype=bool)
|
|
104
|
+
|
|
105
|
+
# Extract unmasked (valid) entries and flatten to 1D
|
|
72
106
|
if return_numpy_array:
|
|
73
|
-
out_args = [arg[~mask]
|
|
107
|
+
out_args = [arg.data[~mask] for arg in args]
|
|
74
108
|
else:
|
|
75
109
|
out_args = [arg[~mask] for arg in args]
|
|
76
|
-
|
|
110
|
+
|
|
111
|
+
return mask, *out_args # type: ignore[return-value]
|
|
77
112
|
|
|
78
113
|
|
|
79
114
|
def reverse_filter_and_restore(
|
|
80
115
|
mask: np.ndarray, *args: np.ndarray
|
|
81
|
-
) ->
|
|
116
|
+
) -> tuple[np.ma.MaskedArray, ...]:
|
|
82
117
|
"""Restores 1D filtered arrays back to their original shape with masking.
|
|
83
118
|
|
|
84
119
|
Typically called with results returned from the rock-physics library.
|
|
@@ -152,28 +187,11 @@ def _verify_export_inputs(props, grid, dates, file_format=None):
|
|
|
152
187
|
)
|
|
153
188
|
|
|
154
189
|
|
|
155
|
-
def ntg_to_shale_fraction(
|
|
156
|
-
ntg: np.ma.MaskedArray, por: np.ma.MaskedArray
|
|
157
|
-
) -> np.ma.MaskedArray:
|
|
158
|
-
"""Calculate sand and shale fraction from N/G property
|
|
159
|
-
|
|
160
|
-
Args:
|
|
161
|
-
ntg: net-to-gross property [fraction]
|
|
162
|
-
por: total porosity [fraction]
|
|
163
|
-
|
|
164
|
-
Returns:
|
|
165
|
-
shale fraction
|
|
166
|
-
"""
|
|
167
|
-
clip_ntg: np.ma.MaskedArray = np.ma.clip(np.ma.MaskedArray(ntg), 0.0, 1.0) # type: ignore[assignment]
|
|
168
|
-
vsh: np.ma.MaskedArray = np.ma.MaskedArray(1.0 - clip_ntg)
|
|
169
|
-
return (vsh / (1.0 - por)).clip(0.0, 1.0)
|
|
170
|
-
|
|
171
|
-
|
|
172
190
|
def get_shale_fraction(
|
|
173
|
-
vol_fractions:
|
|
191
|
+
vol_fractions: list[np.ma.MaskedArray],
|
|
174
192
|
fraction_names: list[str],
|
|
175
|
-
shale_fraction_names:
|
|
176
|
-
) ->
|
|
193
|
+
shale_fraction_names: str | list[str] | None = None,
|
|
194
|
+
) -> np.ma.MaskedArray | None:
|
|
177
195
|
"""
|
|
178
196
|
|
|
179
197
|
Args:
|
|
@@ -210,7 +228,7 @@ def estimate_cement(
|
|
|
210
228
|
shear_modulus: float | int,
|
|
211
229
|
density: float | int,
|
|
212
230
|
grid: np.ma.MaskedArray,
|
|
213
|
-
) ->
|
|
231
|
+
) -> EffectiveMineralProperties:
|
|
214
232
|
"""Creates masked arrays filled with constant cement properties, matching the shape
|
|
215
233
|
and mask of the input grid.
|
|
216
234
|
|
|
@@ -226,12 +244,12 @@ def estimate_cement(
|
|
|
226
244
|
cement_k = to_masked_array(bulk_modulus, grid)
|
|
227
245
|
cement_mu = to_masked_array(shear_modulus, grid)
|
|
228
246
|
cement_rho = to_masked_array(density, grid)
|
|
229
|
-
return
|
|
230
|
-
bulk_modulus=cement_k, shear_modulus=cement_mu,
|
|
247
|
+
return EffectiveMineralProperties(
|
|
248
|
+
bulk_modulus=cement_k, shear_modulus=cement_mu, density=cement_rho
|
|
231
249
|
)
|
|
232
250
|
|
|
233
251
|
|
|
234
|
-
def update_dict_list(base_list:
|
|
252
|
+
def update_dict_list(base_list: list[dict], add_list: list[dict]) -> list[dict]:
|
|
235
253
|
"""Update/add new key/value pairs to dicts in list
|
|
236
254
|
|
|
237
255
|
Args:
|
|
@@ -260,3 +278,37 @@ def _verify_update_inputs(base, add_list):
|
|
|
260
278
|
and all(isinstance(item, dict) for item in add_list)
|
|
261
279
|
):
|
|
262
280
|
raise TypeError(f"{__file__}: all items in input lists are not dict")
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def bar_to_pa(
|
|
284
|
+
pres_bar: float | np.ndarray | np.ma.MaskedArray,
|
|
285
|
+
) -> float | np.ndarray | np.ma.MaskedArray:
|
|
286
|
+
"""
|
|
287
|
+
Pressure unit conversion from bar to Pa
|
|
288
|
+
"""
|
|
289
|
+
return pres_bar * 1.0e5
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def pa_to_bar(
|
|
293
|
+
pres_pa: float | np.ndarray | np.ma.MaskedArray,
|
|
294
|
+
) -> float | np.ndarray | np.ma.MaskedArray:
|
|
295
|
+
"""
|
|
296
|
+
Pressure unit conversion from Pa to bar
|
|
297
|
+
"""
|
|
298
|
+
return pres_pa * 1.0e-5
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def convert_single_pressure_to_pa(
|
|
302
|
+
single_press_bar: PressureProperties,
|
|
303
|
+
) -> PressureProperties:
|
|
304
|
+
return PressureProperties(
|
|
305
|
+
effective_pressure=bar_to_pa(single_press_bar.effective_pressure),
|
|
306
|
+
formation_pressure=bar_to_pa(single_press_bar.formation_pressure),
|
|
307
|
+
overburden_pressure=bar_to_pa(single_press_bar.overburden_pressure),
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
def convert_pressures_list_to_pa(
|
|
312
|
+
press_bar: list[PressureProperties],
|
|
313
|
+
) -> list[PressureProperties]:
|
|
314
|
+
return [convert_single_pressure_to_pa(pres) for pres in press_bar]
|
fmu/pem/run_pem.py
CHANGED
|
@@ -6,9 +6,10 @@ from fmu.pem import pem_utilities as pem_utils
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def pem_fcn(
|
|
9
|
-
|
|
10
|
-
rel_path_pem: Path,
|
|
9
|
+
config_dir: Path,
|
|
11
10
|
pem_config_file_name: Path,
|
|
11
|
+
global_config_dir: Path,
|
|
12
|
+
global_config_file: Path,
|
|
12
13
|
run_from_rms=False,
|
|
13
14
|
proj=None,
|
|
14
15
|
) -> None:
|
|
@@ -18,81 +19,111 @@ def pem_fcn(
|
|
|
18
19
|
|
|
19
20
|
"""
|
|
20
21
|
# Read and validate all PEM parameters
|
|
21
|
-
config = pem_utils.read_pem_config(
|
|
22
|
-
start_dir.joinpath(rel_path_pem, pem_config_file_name)
|
|
23
|
-
)
|
|
22
|
+
config = pem_utils.read_pem_config(yaml_file=config_dir / pem_config_file_name)
|
|
24
23
|
|
|
25
24
|
# Read necessary part of global configurations and parameters
|
|
26
25
|
config.update_with_global(
|
|
27
26
|
pem_utils.get_global_params_and_dates(
|
|
28
|
-
|
|
27
|
+
global_config_dir=(config_dir / global_config_dir).resolve(),
|
|
28
|
+
global_conf_file=global_config_file,
|
|
29
29
|
)
|
|
30
30
|
)
|
|
31
31
|
|
|
32
32
|
# Import Eclipse simulation grid - INIT and RESTART
|
|
33
|
-
egrid_file = start_dir / config.paths.rel_path_simgrid / "ECLIPSE.EGRID"
|
|
34
|
-
init_property_file = start_dir / config.paths.rel_path_simgrid / "ECLIPSE.INIT"
|
|
35
|
-
restart_property_file = start_dir / config.paths.rel_path_simgrid / "ECLIPSE.UNRST"
|
|
36
|
-
|
|
37
33
|
sim_grid, constant_props, time_step_props = pem_utils.read_sim_grid_props(
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
config.
|
|
34
|
+
rel_dir_sim_files=config.eclipse_files.rel_path_simgrid,
|
|
35
|
+
egrid_file=config.eclipse_files.egrid_file,
|
|
36
|
+
init_property_file=config.eclipse_files.init_property_file,
|
|
37
|
+
restart_property_file=config.eclipse_files.restart_property_file,
|
|
38
|
+
seis_dates=config.global_params.seis_dates,
|
|
39
|
+
fipnum_name=config.alternative_fipnum_name,
|
|
42
40
|
)
|
|
43
41
|
|
|
44
42
|
# Calculate rock properties - fluids and minerals
|
|
45
|
-
# Fluid properties calculated for all time-steps
|
|
46
|
-
fluid_properties = pem_fcns.effective_fluid_properties(
|
|
47
|
-
time_step_props, config.fluids
|
|
48
|
-
)
|
|
49
|
-
|
|
50
43
|
# Effective mineral (matrix) properties - one set valid for all time-steps
|
|
51
44
|
vsh, matrix_properties = pem_fcns.effective_mineral_properties(
|
|
52
|
-
|
|
45
|
+
root_dir=config_dir,
|
|
46
|
+
matrix=config.rock_matrix,
|
|
47
|
+
sim_init=constant_props,
|
|
48
|
+
sim_grid=sim_grid,
|
|
53
49
|
)
|
|
54
50
|
# VSH is exported with other constant results, add it to the constant properties
|
|
55
|
-
constant_props.
|
|
51
|
+
constant_props.vsh_pem = vsh
|
|
52
|
+
|
|
53
|
+
# Fluid properties calculated for all time-steps
|
|
54
|
+
fluid_properties, below_bp_grids = pem_fcns.effective_fluid_properties_zoned(
|
|
55
|
+
restart_props=time_step_props,
|
|
56
|
+
fluids=config.fluids,
|
|
57
|
+
pvtnum=constant_props.pvtnum,
|
|
58
|
+
)
|
|
56
59
|
|
|
57
60
|
# Estimate effective pressure
|
|
58
61
|
eff_pres = pem_fcns.estimate_pressure(
|
|
59
|
-
config,
|
|
62
|
+
rock_matrix=config.rock_matrix,
|
|
63
|
+
overburden_pressure=config.pressure,
|
|
64
|
+
sim_init=constant_props,
|
|
65
|
+
sim_rst=time_step_props,
|
|
66
|
+
matrix_props=matrix_properties,
|
|
67
|
+
fluid_props=fluid_properties,
|
|
68
|
+
sim_dates=config.global_params.seis_dates,
|
|
69
|
+
fipnum=constant_props.fipnum,
|
|
60
70
|
)
|
|
61
71
|
|
|
62
72
|
# Estimate saturated rock properties
|
|
63
|
-
sat_rock_props = pem_fcns.estimate_saturated_rock(
|
|
64
|
-
config,
|
|
73
|
+
sat_rock_props, dry_rock = pem_fcns.estimate_saturated_rock(
|
|
74
|
+
rock_matrix=config.rock_matrix,
|
|
75
|
+
sim_init=constant_props,
|
|
76
|
+
press_props=eff_pres,
|
|
77
|
+
matrix_props=matrix_properties,
|
|
78
|
+
fluid_props=fluid_properties,
|
|
79
|
+
model_directory=config.paths.rel_path_pem,
|
|
80
|
+
fipnum_param=constant_props.fipnum,
|
|
65
81
|
)
|
|
66
82
|
|
|
67
83
|
# Delta and cumulative time estimates (only TWT properties are kept)
|
|
68
84
|
sum_delta_time = pem_utils.delta_cumsum_time.estimate_sum_delta_time(
|
|
69
|
-
constant_props,
|
|
85
|
+
constant_props=constant_props,
|
|
86
|
+
sat_rock_props=sat_rock_props,
|
|
70
87
|
)
|
|
71
88
|
|
|
72
89
|
# Calculate difference properties. Possible properties are all that vary with time
|
|
73
90
|
diff_props, diff_date_strs = pem_utils.calculate_diff_properties(
|
|
74
|
-
[time_step_props, eff_pres, sat_rock_props, sum_delta_time],
|
|
91
|
+
props=[time_step_props, eff_pres, sat_rock_props, sum_delta_time],
|
|
92
|
+
diff_dates=config.global_params.diff_dates,
|
|
93
|
+
seis_dates=config.global_params.seis_dates,
|
|
94
|
+
diff_calculation=config.diff_calculation,
|
|
75
95
|
)
|
|
76
96
|
|
|
77
97
|
# As a precaution, update the grid mask for inactive cells, based on the saturated
|
|
78
98
|
# rock properties
|
|
79
|
-
sim_grid = pem_utils.update_inactive_grid_cells(
|
|
99
|
+
sim_grid = pem_utils.update_inactive_grid_cells(
|
|
100
|
+
grid=sim_grid,
|
|
101
|
+
props=sat_rock_props,
|
|
102
|
+
)
|
|
80
103
|
|
|
81
104
|
# Save results to disk or RMS project according to settings in the PEM config
|
|
82
105
|
pem_utils.save_results(
|
|
83
|
-
|
|
84
|
-
run_from_rms,
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
106
|
+
config_dir=config_dir,
|
|
107
|
+
run_from_rms_flag=run_from_rms,
|
|
108
|
+
rms_project=proj,
|
|
109
|
+
sim_grid=sim_grid,
|
|
110
|
+
grid_name=config.global_params.grid_model,
|
|
111
|
+
seis_dates=config.global_params.seis_dates,
|
|
112
|
+
save_to_rms=config.results.save_results_to_rms,
|
|
113
|
+
save_to_disk=config.results.save_results_to_disk,
|
|
114
|
+
save_intermediate=config.results.save_intermediate_results,
|
|
115
|
+
mandatory_path=config.paths.rel_path_mandatory_output,
|
|
116
|
+
pem_output_path=config.paths.rel_path_output,
|
|
117
|
+
eff_pres_props=eff_pres,
|
|
118
|
+
sat_rock_props=sat_rock_props,
|
|
119
|
+
difference_props=diff_props,
|
|
120
|
+
difference_date_strs=diff_date_strs,
|
|
121
|
+
matrix_props=matrix_properties,
|
|
122
|
+
fluid_props=fluid_properties,
|
|
123
|
+
bubble_point_grids=below_bp_grids,
|
|
124
|
+
dry_rock_props=dry_rock,
|
|
94
125
|
)
|
|
95
126
|
|
|
96
127
|
# Restore original path
|
|
97
|
-
os.chdir(
|
|
128
|
+
os.chdir(config_dir)
|
|
98
129
|
return
|
fmu/pem/version.py
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '0.0.
|
|
21
|
-
__version_tuple__ = version_tuple = (0, 0,
|
|
31
|
+
__version__ = version = '0.0.3'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 0, 3)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmu-pem
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: pem
|
|
5
5
|
License: GNU GENERAL PUBLIC LICENSE
|
|
6
6
|
Version 3, 29 June 2007
|
|
@@ -686,12 +686,8 @@ Classifier: Topic :: Scientific/Engineering :: Physics
|
|
|
686
686
|
Classifier: Topic :: Software Development :: Libraries
|
|
687
687
|
Classifier: Topic :: Utilities
|
|
688
688
|
Classifier: Operating System :: POSIX :: Linux
|
|
689
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
690
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
691
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
692
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
693
689
|
Classifier: Natural Language :: English
|
|
694
|
-
Requires-Python: >=3.
|
|
690
|
+
Requires-Python: >=3.11
|
|
695
691
|
Description-Content-Type: text/markdown
|
|
696
692
|
License-File: LICENSE
|
|
697
693
|
Requires-Dist: numpy>=1.24.3
|
|
@@ -699,7 +695,7 @@ Requires-Dist: xtgeo>=4.7.1
|
|
|
699
695
|
Requires-Dist: fmu-tools
|
|
700
696
|
Requires-Dist: fmu-config
|
|
701
697
|
Requires-Dist: fmu-dataio
|
|
702
|
-
Requires-Dist: rock-physics-open>=0.
|
|
698
|
+
Requires-Dist: rock-physics-open>=0.3.3
|
|
703
699
|
Requires-Dist: PyYAML>=6.0.1
|
|
704
700
|
Requires-Dist: pydantic
|
|
705
701
|
Requires-Dist: ert>=14.1.10
|
|
@@ -719,50 +715,59 @@ Requires-Dist: sphinx-togglebutton; extra == "docs"
|
|
|
719
715
|
Requires-Dist: sphinx_rtd_theme; extra == "docs"
|
|
720
716
|
Dynamic: license-file
|
|
721
717
|
|
|
722
|
-
|
|
718
|
+
> [!WARNING]
|
|
719
|
+
> `fmu-pem` is not yet qualified technology, and as of today only applicable for
|
|
720
|
+
selected pilot test fields.
|
|
723
721
|
|
|
724
|
-
|
|
725
|
-
based on the [rock-physics-open](https://github.com/equinor/rock-physics-open)
|
|
726
|
-
library.
|
|
722
|
+
**[📚 User documentation](https://equinor.github.io/fmu-pem/)**
|
|
727
723
|
|
|
728
|
-
##
|
|
724
|
+
## What is fmu-pem?
|
|
725
|
+
|
|
726
|
+
Petro-elastic model (PEM) for use in e.g. [fmu-sim2seis](https://github.com/equinor/fmu-sim2seis)
|
|
727
|
+
based on the [rock-physics-open](https://github.com/equinor/rock-physics-open) library.
|
|
728
|
+
|
|
729
|
+
## How to use fmu-pem?
|
|
730
|
+
|
|
731
|
+
### Installation
|
|
729
732
|
|
|
730
733
|
To install `fmu-pem`, first activate a virtual environment, then type:
|
|
731
734
|
|
|
732
|
-
```
|
|
735
|
+
```shell
|
|
733
736
|
pip install fmu-pem
|
|
734
737
|
```
|
|
735
738
|
|
|
736
739
|
The PEM is controlled by parameter settings in a *yaml-file*, given as part of the
|
|
737
|
-
command line arguments, or by the workflow parameter if it is run as an ERT forward
|
|
740
|
+
command line arguments, or by the workflow parameter if it is run as an ERT forward
|
|
741
|
+
model.
|
|
738
742
|
|
|
739
|
-
|
|
743
|
+
### Calibration of rock physics models
|
|
740
744
|
|
|
741
745
|
Calibration of the rock physics models is normally carried out in
|
|
742
746
|
[RokDoc](https://www.ikonscience.com/rokdoc-geoprediction-software-platform/)
|
|
743
|
-
prior to running the PEM. Fluid and mineral properties can be found in the RokDoc
|
|
744
|
-
from LFP logs, if they are available.
|
|
747
|
+
prior to running the PEM. Fluid and mineral properties can be found in the RokDoc
|
|
748
|
+
project, or from LFP logs, if they are available.
|
|
745
749
|
|
|
746
|
-
> [!NOTE]
|
|
747
|
-
> The fluid models contained in this module may not cover all possible cases. Gas
|
|
748
|
-
> or reservoir pressure under hydrocarbon bubble point will
|
|
750
|
+
> [!NOTE]
|
|
751
|
+
> The fluid models contained in this module may not cover all possible cases. Gas
|
|
752
|
+
condensate, very heavy oil, > or reservoir pressure under hydrocarbon bubble point will
|
|
753
|
+
need additional proprietary code to run.
|
|
749
754
|
>
|
|
750
755
|
> Equinor users can install additional proprietary models using
|
|
756
|
+
|
|
751
757
|
> ```bash
|
|
752
758
|
> pip install "git+ssh://git@github.com/equinor/rock-physics"`
|
|
753
759
|
> ```
|
|
754
760
|
|
|
755
|
-
##
|
|
756
|
-
|
|
757
|
-
Users can visit https://equinor.github.io/fmu-pem/ in order to get help configuring the `fmu-pem` input data.
|
|
758
|
-
|
|
759
|
-
# How to develop fmu-pem
|
|
761
|
+
## How to develop fmu-pem?
|
|
760
762
|
|
|
761
763
|
Developing the user interface can be done by:
|
|
764
|
+
|
|
762
765
|
```bash
|
|
763
|
-
cd ./
|
|
766
|
+
cd ./documentation
|
|
764
767
|
npm ci # Install dependencies
|
|
765
768
|
npm run create-json-schema # Extract JSON schema from Python code
|
|
766
|
-
npm run dev # Start local development server
|
|
769
|
+
npm run docs:dev # Start local development server
|
|
767
770
|
```
|
|
768
|
-
|
|
771
|
+
|
|
772
|
+
The JSON schema itself (type, title, description etc.) comes from the corresponding
|
|
773
|
+
Pydantic models in the Python code.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
fmu/__init__.py,sha256=YWSE22UTDSocfqQHxEeXrRkdlA63t_aayQVdJkycwYs,83
|
|
2
|
+
fmu/pem/__init__.py,sha256=FhNaFibcFZEK1Rz7IBRXBgxMHGNlcgrHaD4FtU4pDjs,421
|
|
3
|
+
fmu/pem/__main__.py,sha256=hWYNOkn7gG6jUifHIXbG8ZJmUEDkv251v6OgiaR7rcY,1858
|
|
4
|
+
fmu/pem/run_pem.py,sha256=aMkOHDNg3wtdiZueDAGogrxyVI8Sk2RYHWeSe9AJVXk,4727
|
|
5
|
+
fmu/pem/version.py,sha256=pBZsQt6tlL02W-ri--X_4JCubpAK7jjCSnOmUp_isjc,704
|
|
6
|
+
fmu/pem/forward_models/__init__.py,sha256=WuN66rmgfqrekCy3Ss9NHqsy-lZ4WGY-4VZa3jYDV2s,117
|
|
7
|
+
fmu/pem/forward_models/pem_model.py,sha256=Hj7ueEu5bOKA84ldx1oKEqOntBKYySmY0Y6Z7ghZPeI,2025
|
|
8
|
+
fmu/pem/hook_implementations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
fmu/pem/hook_implementations/jobs.py,sha256=IQW5m7oeZ_MiemxXv-UGLCPeo4h3QT9oELPlWAzsN60,388
|
|
10
|
+
fmu/pem/pem_functions/__init__.py,sha256=aGFW0Gmr1rZsmzZhKdll9ofWcgpobzsHxfCNwr2Ypqc,551
|
|
11
|
+
fmu/pem/pem_functions/density.py,sha256=txcG0bp2Fq20A2E6O3-KQtiJm60BXOou-TcgZlnnluw,1605
|
|
12
|
+
fmu/pem/pem_functions/effective_pressure.py,sha256=Qd4selju2qGFWJdWuWFJu8Hyad3e_v3yS3nt5SjKXTQ,10706
|
|
13
|
+
fmu/pem/pem_functions/estimate_saturated_rock.py,sha256=S_uqsX5xDOhndSK7bvMYvdPj_VRwffkm17760T6tZNo,11577
|
|
14
|
+
fmu/pem/pem_functions/fluid_properties.py,sha256=i6iOHGCYC3DI4_Pe54DaMaBhJysdQNhAFQVko6PLnys,18325
|
|
15
|
+
fmu/pem/pem_functions/mineral_properties.py,sha256=1TLs8ZG8Js-k8QpgNNLesruUALQsfqgJawcLLfqZJRY,8068
|
|
16
|
+
fmu/pem/pem_functions/pressure_sensitivity.py,sha256=_IG7nMlalFuBlyrS9YpGZ2F-ClLENS75viDO1_OVaEA,13098
|
|
17
|
+
fmu/pem/pem_functions/regression_models.py,sha256=wUw5yIIeR5sGz7OqAp42K4lxLUOKr-B4_1XkM9k2WXA,10391
|
|
18
|
+
fmu/pem/pem_functions/run_friable_model.py,sha256=R3Nb0nQML6k5QrPwDoB7oMHaTkB-rJjCSPnJ_gsrIIQ,6885
|
|
19
|
+
fmu/pem/pem_functions/run_patchy_cement_model.py,sha256=M561C_4dfPW_Nxm0AgzCUdeQ9UVIrZGGhxBayII1IDQ,6667
|
|
20
|
+
fmu/pem/pem_functions/run_t_matrix_model.py,sha256=Ctl5Lw1HJvNYdqKDUnqrOWRisVV2m1J4gJ6S2u8j-Xw,7875
|
|
21
|
+
fmu/pem/pem_utilities/__init__.py,sha256=OjQz4PjT8Rj2WYnuIoRYSnUXgkSsQESLIT3rp14LP5c,2143
|
|
22
|
+
fmu/pem/pem_utilities/cumsum_properties.py,sha256=s3M0bMs6Dogg8cWzj5M6K5xifdRjhZse3dCWZL0_RCo,3431
|
|
23
|
+
fmu/pem/pem_utilities/delta_cumsum_time.py,sha256=vDc7Hvl50qzUXbK4oKq30zlQ2fqMel9EmBO0lmeoDbo,3035
|
|
24
|
+
fmu/pem/pem_utilities/enum_defs.py,sha256=R6Q0G6TQKe1MM4KTp1t_iCaFuCWEwLvIqV6tH3uxCms,2485
|
|
25
|
+
fmu/pem/pem_utilities/export_routines.py,sha256=hteGM4flK8B7Jy4BNk5bU33-_jcNndFrm9RcnzfTdy4,10108
|
|
26
|
+
fmu/pem/pem_utilities/fipnum_pvtnum_utilities.py,sha256=ypwTsyfqqBJ6d8WHY2HkKAdX9ZjHYLdQq_-3w2xEwVQ,7571
|
|
27
|
+
fmu/pem/pem_utilities/import_config.py,sha256=eKV1LsajELCcTijLsGMzQg16XcicedCKmhhZJce-SQ4,3554
|
|
28
|
+
fmu/pem/pem_utilities/import_routines.py,sha256=EVHCS-LaHXKwVgDiE5BDvybJgPi0PjFado2m1O9ezo4,5104
|
|
29
|
+
fmu/pem/pem_utilities/pem_class_definitions.py,sha256=Q_k5s_Zj8q_9TKdnxdJdOeN1UVGZbH997ngs8_5t0Es,5504
|
|
30
|
+
fmu/pem/pem_utilities/pem_config_validation.py,sha256=ps_mFuwh2SgpsoSC_5IwlLpMaLDzx9BRyEYvgSf3CQw,27441
|
|
31
|
+
fmu/pem/pem_utilities/rpm_models.py,sha256=S4BDv5aTaMHgk-nSYxBQ1I_SzkSGXVd6HNtoUViElwE,21212
|
|
32
|
+
fmu/pem/pem_utilities/update_grid.py,sha256=Ay0XPGXBl5CtdL5keTGzs0AKp44LgsuqxwBVwmHZV_s,1838
|
|
33
|
+
fmu/pem/pem_utilities/utils.py,sha256=dHfQLDfwG27eC86lHN12PrITuock8M5IH-gD7eWAtCE,10583
|
|
34
|
+
fmu_pem-0.0.3.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
35
|
+
fmu_pem-0.0.3.dist-info/METADATA,sha256=t2TFRKI9Cq718cFQxGYnmzfK1_8s9PSSGKpJ141K_Xo,43848
|
|
36
|
+
fmu_pem-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
37
|
+
fmu_pem-0.0.3.dist-info/entry_points.txt,sha256=NSoFnob1PAE6FzRyNJZn5idocnCB1ptNg6R8zYf7Gnc,98
|
|
38
|
+
fmu_pem-0.0.3.dist-info/top_level.txt,sha256=Z-FIY3pxn0UK2Wxi9IJ7fKoLSraaxuNGi1eokiE0ShM,4
|
|
39
|
+
fmu_pem-0.0.3.dist-info/RECORD,,
|
fmu_pem-0.0.1.dist-info/RECORD
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
fmu/__init__.py,sha256=YWSE22UTDSocfqQHxEeXrRkdlA63t_aayQVdJkycwYs,83
|
|
2
|
-
fmu/pem/__init__.py,sha256=FhNaFibcFZEK1Rz7IBRXBgxMHGNlcgrHaD4FtU4pDjs,421
|
|
3
|
-
fmu/pem/__main__.py,sha256=L8HW2P6_AQX70gcgmMdbW0BouCQdI0OVab-U4QkcPOk,1361
|
|
4
|
-
fmu/pem/run_pem.py,sha256=z6UAuEAJlSVcbTeC2q5q8_ToKe0HIgQPHZfjRWSg6PI,3218
|
|
5
|
-
fmu/pem/version.py,sha256=vgltXBYF55vNcC2regxjGN0_cbebmm8VgcDdQaDapWQ,511
|
|
6
|
-
fmu/pem/forward_models/__init__.py,sha256=WuN66rmgfqrekCy3Ss9NHqsy-lZ4WGY-4VZa3jYDV2s,117
|
|
7
|
-
fmu/pem/forward_models/pem_model.py,sha256=fKDD1-euwLBMr6rAjDYG0o-k7uKYRxG6De6bywF3AXI,2203
|
|
8
|
-
fmu/pem/hook_implementations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
-
fmu/pem/hook_implementations/jobs.py,sha256=IQW5m7oeZ_MiemxXv-UGLCPeo4h3QT9oELPlWAzsN60,388
|
|
10
|
-
fmu/pem/pem_functions/__init__.py,sha256=G2tu5E1PFvlw36fLdmr2A4Xr9ZqbKMf104OU5ydh_3A,539
|
|
11
|
-
fmu/pem/pem_functions/density.py,sha256=36A8yccsnVPXCpnIfuwNUf9FVvXDkCBpcn4UFuPngFE,1777
|
|
12
|
-
fmu/pem/pem_functions/effective_pressure.py,sha256=3p_bFwgS-PtCN0hAaJXYLwdzuv2J5PHDLWhzyBQNfgU,6118
|
|
13
|
-
fmu/pem/pem_functions/estimate_saturated_rock.py,sha256=azJjVwuUGCyiO-FIY-TYktR3PSBRoOB2ceY33PJyMsc,2756
|
|
14
|
-
fmu/pem/pem_functions/fluid_properties.py,sha256=HCRay1blnWiK19N0nncoV6ftB-DHPC8d029Xsg4jaFw,10458
|
|
15
|
-
fmu/pem/pem_functions/mineral_properties.py,sha256=ilf1TwE4DDev65TdHEuudxgLj41IRBWgSjXghNrCPak,8394
|
|
16
|
-
fmu/pem/pem_functions/regression_models.py,sha256=7YfEiAbjxnP1UP1ugW8ay202grbumG4_vFppEpBkEDE,9085
|
|
17
|
-
fmu/pem/pem_functions/run_friable_model.py,sha256=rT-LQ17gSrJS_l524LKiLnK5Q0Y5zx8lKRuO7GFd3fk,4258
|
|
18
|
-
fmu/pem/pem_functions/run_patchy_cement_model.py,sha256=B-j-Aza2yT6qbBXIsR3HZmtjcBkONLqnq7AYbrgp_uU,4201
|
|
19
|
-
fmu/pem/pem_functions/run_t_matrix_and_pressure.py,sha256=RmvFRm6QNvhpFp9Ar_ifWru6Yp0h-XnE9WS4lUR37Nk,6821
|
|
20
|
-
fmu/pem/pem_utilities/__init__.py,sha256=r9vSDgrY4B2NwBK5PL-4GMD5o1aT2IpR1vaeOCgJ-tI,1687
|
|
21
|
-
fmu/pem/pem_utilities/cumsum_properties.py,sha256=W2FtawYPZzdydGsVoOYCWIgOItNGKCRzhHzI5sUw05M,3769
|
|
22
|
-
fmu/pem/pem_utilities/delta_cumsum_time.py,sha256=J83PSpO2xjxHP5tpDpleVxynt0eytqHLgbGzj79wTQI,3267
|
|
23
|
-
fmu/pem/pem_utilities/enum_defs.py,sha256=nJWpvXBFRIE-f7A4AjsVwldM2fxSZGRXAYC0faEOckw,1067
|
|
24
|
-
fmu/pem/pem_utilities/export_routines.py,sha256=gZa3AscefV9h55JQXL7juQg5SpMvhnN5nbBHFU2VtCI,9879
|
|
25
|
-
fmu/pem/pem_utilities/import_config.py,sha256=H6nH_MVnVhuS4q-4KWhoOvQbGzV5Jnw1-KlD1BRccmY,3232
|
|
26
|
-
fmu/pem/pem_utilities/import_routines.py,sha256=PRnHn2wsHRewi2z3AlSNu9i3li9srfPNq_TS9qv89a4,5263
|
|
27
|
-
fmu/pem/pem_utilities/pem_class_definitions.py,sha256=IOwzHfMsoPoGWIs1-I-kI2wVbhgR5TjZHygXOMsECMk,3282
|
|
28
|
-
fmu/pem/pem_utilities/pem_config_validation.py,sha256=nxHCCLCOV0bODH7LfFjdbQRbe0zhLulKYcMgG1YnjjQ,17878
|
|
29
|
-
fmu/pem/pem_utilities/rpm_models.py,sha256=TxW8lmIMluU1JsgGUT6nlR899mlVk8GgQx2p5ODnr78,5726
|
|
30
|
-
fmu/pem/pem_utilities/update_grid.py,sha256=InGaWrgIH5G9xyGqazAxQmVHL0nve4B9dAttisBsIpU,1775
|
|
31
|
-
fmu/pem/pem_utilities/utils.py,sha256=Gm_onSB7KuHZ0iKzx5TjHCOBYkatewSyEXgC9J-UA70,8871
|
|
32
|
-
fmu_pem-0.0.1.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
33
|
-
fmu_pem-0.0.1.dist-info/METADATA,sha256=-3GgiilfNJq6zv7F6eD0fIZ5qYSIeFs6nlh2cL7VeBk,43944
|
|
34
|
-
fmu_pem-0.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
35
|
-
fmu_pem-0.0.1.dist-info/entry_points.txt,sha256=NSoFnob1PAE6FzRyNJZn5idocnCB1ptNg6R8zYf7Gnc,98
|
|
36
|
-
fmu_pem-0.0.1.dist-info/top_level.txt,sha256=Z-FIY3pxn0UK2Wxi9IJ7fKoLSraaxuNGi1eokiE0ShM,4
|
|
37
|
-
fmu_pem-0.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|