pywaterflood.aquifer

Functions for estimating aquifer influx using van Everdingen-Hurst models.

Through some accident of nature, oil tends to migrate through aquifers from where it was generated to traps that eventually become the reservoirs we know and love. This means that almost all reservoirs have associated aquifers. As oil is produced from these reservoirs, the aquifer water enters the reservoir, providing pressure support and sometimes being co-produced. van Everdingen and Hurst set out to model the reservoir-aquifer interaction in the 1940s. At the time, their calculations were provided to petroleum engineers in the form of tables, but with modern computing, we can improve upon that.

Further reading

Petrowiki on water influx models

van Everdingen and Hurst, 1949, https://doi.org/10.2118/949305-G

Klins et al, 1988, http://dx.doi.org/10.2118/15433-PA

Functions

effective_reservoir_radius(→ float)

Calculate effective reservoir_radius

aquifer_production(→ numpy.typing.NDArray)

Calculate cumulative aquifer production.

water_dimensionless(→ numpy.typing.NDArray[numpy.float64])

Calculate the radial aquifer dimensionless water influx.

water_dimensionless_infinite(...)

Calculate infinite acting radial aquifer dimensionless water influx.

get_bessel_roots(→ numpy.typing.NDArray[numpy.float64])

Find roots of Bessel function in Klins.

klins_pressure_dimensionless(...)

Dimensionless pressure for a finite aquifer over time.

klins_water_dimensionless_finite(...)

Solve for water influx from Klins' finite radial reservoir.

Module Contents

pywaterflood.aquifer.effective_reservoir_radius(reservoir_pore_volume: float, porosity: float, thickness: float, flow_solid_angle: float = 360) float[source]

Calculate effective reservoir_radius

Parameters:
  • reservoir_pore_volume (float) – water pore volume in reservoir bbl

  • porosity (float) – porosity fraction, ranges from 0-1

  • thickness (float) – pay thickness in feet

  • flow_solid_angle (float) – solid angle between well and reservoir in degrees, ranges from 0-360

Returns:

effective reservoir radius, $r_o$, in feet

Return type:

float

pywaterflood.aquifer.aquifer_production(delta_pressure: numpy.typing.NDArray, t_d: numpy.typing.NDArray, r_ed: float, method: Literal['marsal-walsh', 'klins'] = 'klins', aquifer_constant: float = 1.0) numpy.typing.NDArray[source]

Calculate cumulative aquifer production.

Parameters:
  • delta_pressure (NDArray) – change in reservoir pressure

  • t_d (NDArray) – dimensionless time

  • r_ed (float) – dimensionless radius, \(r_a/r_o\)

  • method (Literal str) – choose ‘marsal-walsh’ or ‘klins’ approximation

  • aquifer_constant (float) –

    aquifer constant in RB/psi

    \(1.119 hfr^2_o \phi c_t\)

Returns:

Cumulative production from the aquifer

Return type:

NDArray

pywaterflood.aquifer.water_dimensionless(time_d: float | numpy.typing.NDArray[numpy.float64], r_ed: float, method: Literal['marsal-walsh', 'klins'] = 'klins') numpy.typing.NDArray[numpy.float64][source]

Calculate the radial aquifer dimensionless water influx.

This acts as if the aquifer were infinite-acting if \(\max t_d < 0.4 (r_{ed}^2 - 1)\)

Parameters:
  • time_D (float | NDArray[np.float64]) – dimensionless time

  • r_ed (float) – dimensionless radius, \(r_a/r_o\)

  • method (Literal str) – choose ‘marsal-walsh’ or ‘klins’ approximation

Return type:

NDArray[np.float64]

pywaterflood.aquifer.water_dimensionless_infinite(time_D: float | numpy.typing.NDArray[numpy.float64], method: Literal['marsal-walsh', 'klins'] = 'marsal-walsh') numpy.typing.NDArray[numpy.float64][source]

Calculate infinite acting radial aquifer dimensionless water influx.

Parameters:

time_D (float | NDArray[np.float64]) – dimensionless time

Returns:

dimensionless water influx

Return type:

NDArray[np.float64]

pywaterflood.aquifer.get_bessel_roots(r_ed: float, n_max: int, root_choice: Literal['alpha', 'beta'] = 'beta') numpy.typing.NDArray[numpy.float64][source]

Find roots of Bessel function in Klins.

Comes from Klins, 1988, eq 9,

\[J_1(\beta_n r_{eD}) Y_1(\beta_n) - J_1(\beta_n) Y_1(\beta_n r_{eD})\]

and eq 16

\[J_1(\alpha_n r_{eD}) Y_0(\alpha_n) - Y_1(\alpha_n) J_0(\alpha_n r_{eD})\]
Parameters:
  • r_ed (float) – dimensionless reservoir radius, \(r_o/r_a\)

  • n_max (int) – number of roots to find

  • root_choice (str) –

    which roots to get.

    for eq 9, beta, for eq 16, alpha

Returns:

  • numpy array – roots of the function

  • Reference

  • ———

  • Klins, M. A., Bouchard, A. J., and C. L. Cable.

  • ”A Polynomial Approach to the van Everdingen-Hurst Dimensionless Variables for

  • Water Encroachment.” SPE Res Eng 3 (1988) (320-326.)

  • doi (<https://doi.org/10.2118/15433-PA>)

pywaterflood.aquifer.klins_pressure_dimensionless(t_d: numpy.typing.NDArray[numpy.float64], r_ed: float, max_terms: int = 20) numpy.typing.NDArray[numpy.float64][source]

Dimensionless pressure for a finite aquifer over time.

Parameters:
  • t_d (numpy array) – dimensionless time

  • r_ed (float) – dimensionless radius

  • max_terms (int, defaults to 20) – Number of terms in the infinite series to include. Klins used 2.

Returns:

dimensionless pressure

Return type:

NDArray

pywaterflood.aquifer.klins_water_dimensionless_finite(t_d: numpy.typing.NDArray[numpy.float64], r_ed: float, max_terms: int = 20) numpy.typing.NDArray[numpy.float64][source]

Solve for water influx from Klins’ finite radial reservoir.

Parameters:
  • t_d (NDArray[np.float64]) – dimensionless time

  • r_ed (float) – dimensionless radius

  • max_terms (int, optional) – Number of terms in the infinite series to include when approximating the solution, by default 20

Returns:

\(W_d\), dimensionless water influx

Return type:

NDArray[np.float64]