pyopmnearwell.ml.upscale module
Functionality to upscale data from an ensemble run on a radial grid to a cartesian grid.
Note: pylint: no-member is disabled, because it complains about the BaseUpscaler
missing instance attributes, which are taken care of by the Upscaler
protocol.
pylint: pointless-string-statement is disabled, as it complains an attribute docstring
in the Upscaler
protocol.
- class pyopmnearwell.ml.upscale.BaseUpscaler
Bases:
ABC
Extract and upscale data from an array of ensemble data.
This base class provides several methods to extract features from fine-scale radial simulations and upscale to coarse cartesian cells. Depending on the type of data, this is done by averaging/summing/etc. values along all cells that correspond to a coarse cell.
Additionally, the sparsity of the dataset can be increased by taking only some timesteps/horizontal cells.
The upscaled data is usually provided in form of two
np.ndarrays
, one for features and one for targets.Subclasses need to implement
__init__
and (if needed)create_ds
methods.The feature array will have shape
(num_ensemble_runs, num_timesteps/step_size_t, num_layers, num_xcells/step_size_x, num_features)
. The target array will have shape(num_ensemble_runs, num_timesteps/step_size_t, num_layers, num_xcells/step_size_x, 1)
- Note: All methods assume that all cells have the same height. if this is not the
case, the methods must be overridden.
Methods
get_analytical_PI
(permeabilities, ...)_summary_
get_analytical_WI
(pressures, saturations, ...)_summary_
get_data_WI
(features, pressure_index, ...[, ...])Calculate data-driven WI from pressure and flow rate.
get_homogeneous_values
(features, feature_index)Get a feature that is homogeneous inside a layer.
get_horizontically_integrated_values
(...[, ...])Integrate feature horizontically along layers and divide by equivalent cartesian block area.
get_radii
(radii_file)Get full list of cell radii.
get_timesteps
(simulation_length)_summary_
get_vertically_averaged_values
(features, ...)Average features vertically inside each layer.
reduce_data_size
(feature[, step_size_x, ...])Reduce the size of the input feature array by selecting elements with a fixed step size.
create_ds
- _abc_impl = <_abc._abc_data object>
- abstract create_ds()
- get_analytical_PI(permeabilities: ndarray, cell_heights: ndarray, radii: ndarray, well_radius: float) ndarray
_summary_
_extended_summary_
- Args:
permeabilities (np.ndarray): Unit has to be [m^2]! cell_heights (np.ndarray): Unit [m]. radii (np.ndarray): _description_ well_radius (float): _description_
- Returns:
np.ndarray: _description_
- get_analytical_WI(pressures: ndarray, saturations: ndarray, permeabilities: ndarray, temperature: float, surface_density: float, radii: ndarray, well_radius: float, OPM: Path) ndarray
_summary_
_extended_summary_
- Args:
pressures (np.ndarray): _description_ saturations (np.ndarray): _description_ permeabilities (np.ndarray): Unit has to be [mD]! temperature (float): _description_ surface_density (float): _description_ radii (np.ndarray): _description_ well_radius (float): _description_ OPM (pathlib.Path): _description_
- Returns:
np.ndarray: _description_
- get_data_WI(features: ndarray, pressure_index: int, inj_rate_index: int, angle: float = 1.0471975511965976) ndarray
Calculate data-driven WI from pressure and flow rate.
Similar functionality to
ensemble.calculate_WI
, but can additionally treat multiple vertical cells in a layer correctly.- Note:
Pressures get averaged over each layer, injection rates get summed over each layer.
The method automatically scales the near-well injection rate from the cake grid with angle
angle
to a 360° well. Furthermore, the rate is scaled from rate-per-day (which the results are in) to rate-per-second, which OPM Flow uses internally for the WI.
- Args:
features (np.ndarray): _description_ pressure_index (int): _description_ inj_rate_index (int): _description_
- Returns:
np.ndarray: _description_
- get_homogeneous_values(features, feature_index, disregard_first_xcell: bool = True)
Get a feature that is homogeneous inside a layer.
Note: Since the feature is equal inside a layer, this method takes the first value for each layer.
- Args:
features (np.ndarray): _description_ feature_index (int): _description_. disregard_first_xcell (bool): __description__. Default is True.
- Returns:
- np.ndarray (``shape = (num_ensemble_runs, num_timesteps, num_layers,
num_xcells)``):
- get_horizontically_integrated_values(features: ndarray, cell_center_radii: ndarray, cell_boundary_radii: ndarray, feature_index: int, disregard_first_xcell: bool = True)
Integrate feature horizontically along layers and divide by equivalent cartesian block area.
- Note:
Before integrating, the feature is averaged vertically inside each layer.
As the feature is averaged and not summed, the integration takes place in 2D with vertically averaged values. Hence it suffices to divide by area and not by volume.
- Args:
features (np.ndarray): _description_ cell_center_radii (np.ndarray): cell_boundary_radii (np.ndarray): feature_index (int): _description_. Default is 1. disregard_first_xcell (bool): __description__. Default is True.
- Returns:
- np.ndarray (``shape = (num_ensemble_runs, num_timesteps, num_layers,
num_xcells)``): Features values average for each cell.
- get_radii(radii_file: Path) tuple[ndarray, ndarray]
Get full list of cell radii.
- get_timesteps(simulation_length: float) ndarray
_summary_
- get_vertically_averaged_values(features: ndarray, feature_index, disregard_first_xcell: bool = True) ndarray
Average features vertically inside each layer.
- Args:
features (np.ndarray): _description_ feature_index (int): _description_. disregard_first_xcell (bool): __description__. Default is True.
- Returns:
- np.ndarray (``shape = (num_ensemble_runs, num_timesteps, num_layers,
num_xcells)``):
- reduce_data_size(feature: ndarray, step_size_x: int = 1, step_size_t: int = 1, random: bool = False) ndarray
Reduce the size of the input feature array by selecting elements with a fixed step size.
- Args:
feature (np.ndarray): The input feature array. step_size_x (int, optional): The step size for the x-axis. Defaults to 1. step_size_t (int, optional): The step size for the t-axis. Defaults to 1. random (bool, optional): If True, select elements randomly instead of using
a fixed step size. Defaults to False. Not implemented yet.
- Returns:
np.ndarray: The reduced feature array.
- class pyopmnearwell.ml.upscale.Upscaler(*args, **kwargs)
Bases:
Protocol
Protocol class for upscalers.
This class is used for typing of abstract attributes of
BaseUpscaler
. MyPy will check if subclasses ofBaseUpscaler
implement the following instance attributes: -num_timesteps
-num_layers
-num_zcells
-num_xcells
-single_feature_shape
However, in comparison to missing abstract functions, no runtime error will be raised if they are missing.See, e.g., https://stackoverflow.com/a/75253719 for an explanation.
- Note: As of now (Python 3.11), each instance method of
BaseUpscaler
or a subclass making use of one of the attributes, needs to have its self argumented annotated with
Upscaler
. In future python versions it should be possible to useclass BaseUpscaler[Upscaler](ABC):...
instead and remove these annotations.
- Attributes:
- angle
- num_layers
- num_timesteps
- num_xcells
- num_zcells
- single_feature_shape
- _abc_impl = <_abc._abc_data object>
- _is_protocol = True
- property angle: float
- property num_layers: int
- property num_timesteps: int
- property num_xcells: int
- property num_zcells: int
- property single_feature_shape: tuple
- Note: As of now (Python 3.11), each instance method of