pyopmnearwell.utils.formulas module
Provide useful mathematical formulas for reservoir modelling.
TODO: The typing is off in this module. Instead of returning an ArrayLike, most functions should return an np.ndarray, however that does not work when a float is passed as then an np.float64 or similar is returned. Not sure how to fix this.
- pyopmnearwell.utils.formulas.area_squaredcircle(radius: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], sidelength: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Calculate the area that lies both inside a circle and inside a square centered at the origin.
- Args:
radius (ArrayLike): The radius of the circle. sidelength (ArrayLike): The sidelength of the square.
- Returns:
ArrayLike: The calculated area.
- Raises:
ValueError: If
radius
orsidelength
contain a negative value.- Examples:
>>> area_squaredcircle(3.0, 3.0) 9.0 # Area of a sqare with sidelength 3.0
>>> area_squaredcircle(2.0, 4.0) 12.566370614359172 # Area of a circle with radius 2.0
>>> area_squaredcircle(2.0, 3.0) 6.283185307179586 # Area inside a 2.0
- pyopmnearwell.utils.formulas.cell_size(radii: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Calculate the size of a quadratic cell for a given equivalent well block radius.
- Args:
delta_x (ArrayLike): _description_
- Returns:
(ArrayLike): _description_
- pyopmnearwell.utils.formulas.co2brinepvt(pressure: float, temperature: float, phase_property: Literal['density', 'viscosity'], phase: Literal['CO2', 'water'], OPM: str | Path) float
Call OPM’s
co2brinepvt
to calculate density/viscosity.- Args:
pressure (float): Unit: [Pa]. temperature (float): Unit: [K]. property (Literal[“density”, “viscosity”]): Phase property to return. phase (Literal[“CO2”, “water”]): Phase of interest. OPM: (str | pathlib.Path): Path to OPM installation.
- Returns:
quantity (float): Density (unit: [kg/m^3]) or viscosity (unit: [Pa*s])
- pyopmnearwell.utils.formulas.data_WI(q: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], p_w: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], p_gb: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], well_type: Literal['injector', 'producer'] = 'injector') Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Compute the well productivity index from given data.
\[WI = \frac{q}{p_w - p_{gb}\]- Args:
q (ArrayLike): Injection rate. Unit: [m^3/s]. p_w (ArrayLike): Bottom hole pressure. Unit: [Pa]. p_gb (ArrayLike): Grid block pressure. Unit: [Pa]. well_type (Literal[“injector”, “producer], optional): Calculate WI for injector or producer. Defaults to
"injector"
.- Returns:
WI (ArrayLike): \(WI\). Unit: [m^4*s/kg].
- Raises:
- ValueError: If bottom hole pressure and grid block pressure are equal for any
point.
- pyopmnearwell.utils.formulas.equivalent_well_radius(delta_x: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) ndarray
Calculate the equivalent well block radius for a given quadratic cell size.
- Args:
delta_x (ArrayLike): _description_
- Returns:
(ArrayLike): _description_
- pyopmnearwell.utils.formulas.hydrostatic_fluid(rho: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], height: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], gravity: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] = 9.8067) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Calculate the pressure due to hydrostatic fluid.
This function calculates the pressure due to hydrostatic fluid using the formula:
..math:
P = rho * g * h,
where \(P\) is the pressure, \(rho\) is the fluid density, \(g\) is the acceleration due to gravity, and \(h\) is the height.
- Args:
rho (ArrayLike): Fluid density. Unit [kg/m^3]. height (ArrayLike): Height of the fluid column. Unit [m]. gravity (ArrayLike, optional): Acceleration due to gravity. Unit [m/s^2].
Defaults to
units.GRAVITATIONAL_ACCELERATION
, i.e., \(\approx 9.8\).- Returns:
ArrayLike: Hydrostatic pressure at the given height. Unit [Pa].
- Examples:
>>> hydrostatic_fluid(1000, 10) 98067.0
- pyopmnearwell.utils.formulas.hydrostatic_gas(reference_pressure: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], height: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], temperature: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], molecule_mass: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], gravity: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] = 9.8067) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Calculate the pressure due to a column of gas in hydrostatic equilibrium.
This function calculates the pressure due to a column of gas in hydrostatic equilibrium using the ideal gas law and the hydrostatic equilibrium formula. The formula is:
..math:
P = P_0 * e^((-m * g * h) / (R^* * T)),
where \(P`is the pressure, :math:`P_0\) is the reference pressure, :math:`m`is the molecular mass of the gas, :math:`g`is the acceleration due to gravity, :math:`h`is the height, :math:`R^*`is the universal gas constant, and :math:`T`is the temperature.
- Args:
reference_pressure (ArrayLike): Reference pressure at height 0. Unit [Pa]. height (ArrayLike): Height of the gas column. Unit [m]. temperature (ArrayLike): Temperature. Unit [K]. molecule_mass (ArrayLike): Molecular mass of the gas. Unit [kg/mol]. gravity (ArrayLike, optional): Acceleration due to gravity. Unit [m/s^2]. Defaults to
units.GRAVITATIONAL_ACCELERATION
, i.e., \(\approx 9.8\).- Returns:
ArrayLike: Hydrostatic pressure at the given height. Unit [Pa].
- Examples:
>>> hydrostatic_gas(101325, 5000, 300, 0.029, 9.81) 75819.90376642203
- pyopmnearwell.utils.formulas.peaceman_WI(k_h: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], r_e: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], r_w: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], rho: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], mu: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Compute the well productivity index (adjusted for density and viscosity) from the Peaceman well model.
\[WI = \frac{2 \pi h \mathbf{k} \frac{\mu}{\rho}}{\ln(r_e/r_w)}\]- Args:
k_h (ArrayLike): Permeability times the cell thickness. Unit: [m^3]. r_e (ArrayLike): Equivalent well-block radius. Needs to have the same unit as
r_w
.r_w (ArrayLike): Wellbore radius. Needs to have the same unit as
r_e
. rho (ArrayLike): Density. Unit: [kg/m^3]. mu (ArrayLike): Viscosity. Unit: [Pa*s].- Returns:
WI (ArrayLike): \(WI\). Unit: [m*s].
- pyopmnearwell.utils.formulas.peaceman_matrix_WI(k_h: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], r_e: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], r_w: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
- Compute the well productivity index (without taking into account density and
viscosity) from the Peaceman well model.
\[WI = \frac{2 \pi h \mathbf{k}}{\ln(r_e/r_w)}\]- Args:
k_h (ArrayLike): Permeability times the cell thickness. Unit: [m^3]. r_e (ArrayLike): Equivalent well-block radius. Needs to have the same unit as
r_w
.r_w (ArrayLike): Wellbore radius. Needs to have the same unit as
r_e
.- Returns:
WI (ArrayLike): \(WI\). Unit: [m^3].
- Raises:
ValueError: If r_w is zero for any point. ValueError: If either r_e or r_w contains a negative value
- pyopmnearwell.utils.formulas.pyopmnearwell_correction(angle: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes] = 1.0471975511965976) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Calculate a correction factor that scales cell volume, equivalent radius etc. from a 2D triangle grid to a radial grid.
In pyopmnearwell, when using the cake grid, a 2D triangle grid is used. As the scaling for cell volumes between a radial and a triangular grid is linear, the radial solution can be recovered. This function calculates the ratio
\[r_{radial_grid} / x_{triangle_grid},\]where \(x_{triangle_grid}\) is the altitude of the triangle, s.t. the solution on the triangle grid is equal to the solution on a radial grid with the given cell radii.
- Args:
- angle (ArrayLike): Angle between both sides of the triangle grid. Default is
\(\pi/3\).
- Returns:
ArrayLike: \(r_{radial_grid} / x_{triangle_grid}\)
- pyopmnearwell.utils.formulas.two_phase_peaceman_WI(k_h: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], r_e: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], r_w: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], rho_1: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], mu_1: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], k_r1: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], rho_2: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], mu_2: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes], k_r2: Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]) Buffer | _SupportsArray[dtype[Any]] | _NestedSequence[_SupportsArray[dtype[Any]]] | bool | int | float | complex | str | bytes | _NestedSequence[bool | int | float | complex | str | bytes]
Compute the well productivity index (adjusted for density, viscosity and relative permeabilties) from the Ptwo-phase eaceman well model.
Cf. [A. Yapparova, B. Lamy-Chappuis, S. W. Scott, and T. Driesner, “A Peaceman-type well model for the 3D Control Volume Finite Element Method and numerical simulations of supercritical geothermal resource utilization” 2022, doi: 10.1016/j.geothermics.2022.102516.]
\[WI = \frac{2 \pi h \mathbf{k}}{\ln(r_e/r_w)} \left(\frac{k_{r,1}}{\mu_1} + \frac{k_{r,2}}{\mu_2})\right)\]- Note:
The result is only accurate for fine grid sizes.
- Args:
k_h (ArrayLike): Permeability times the cell thickness. Unit: [m^3]. r_e (ArrayLike): Equivalent well-block radius. Needs to have the same unit as
r_w
.r_w (ArrayLike): Wellbore radius. Needs to have the same unit as
r_e
. rho_1 (ArrayLike): Density of phase 1. Unit: [kg/m^3]. mu_1 (ArrayLike): Viscosity of phase 1. Unit: [Pa*s]. k_r1 (ArrayLike): Relative permeability of phase 1. rho_2 (ArrayLike): Density of phase 2. Unit: [kg/m^3]. mu_2 (ArrayLike): Viscosity of phase 2. Unit: [Pa*s]. k_r2 (ArrayLike): Relative permeability of phase 2.- Returns:
WI (ArrayLike): \(WI\). Unit: [m*s].