Skip to content

Commit

Permalink
Tests utils
Browse files Browse the repository at this point in the history
  • Loading branch information
prisae committed Jul 16, 2024
1 parent cb04517 commit c8588a4
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 3 deletions.
19 changes: 16 additions & 3 deletions resmda/reservoir_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,20 @@ def __dir__():
class Simulator:
"""A small 2D Reservoir Simulator.
2D connection-based, single phase, single component system using the Darcy
assumption, backward Euler for time discretization, and finite volume for
space discretization.
2D connection-based, single-phase, single-component system using the Darcy
assumption, employing backward Euler for time discretization and finite
volume for space discretization. It simulates a single-phase fluid (likely
water) with compressibility in a reservoir with constant porosity and a
heterogeneous permeability field. The simulator utilizes SciPy's
``sparse.linalg.solve`` for pressure solutions and calculates
transmissibilities for inter-block connections. Well modeling is handled
through the Peaceman well model for well indices, with constant pressure
boundary conditions for injection and production wells. The simulation
operates on a 2D grid with user-defined dimensions (nx, ny), uses flexible
time steps, and starts from a specified initial pressure condition.
Physical processes accounted for include fluid density changes with
pressure (modeling a slightly compressible fluid) while assuming constant
fluid viscosity."
Created by following the course
**AESM304A - Flow and Simulation of Subsurface processes** at
Expand Down Expand Up @@ -60,7 +71,9 @@ class Simulator:
wells : {ndarray, None}, default: None
Nd array of shape ``(nwells, 3)``, indicating well locations (with cell
indices) and pressure. If None, the default is used, which is
np.array([[0, 0, 180], [self.nx-1, self.ny-1, 120]])
corresponding to a well in the first and in the last cell, with a
pressure of 180 and 120, respectively.
dx, dz : floats, default: 50.0, 10.0
Expand Down
5 changes: 5 additions & 0 deletions tests/test_data_assimilation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from resmda import data_assimilation


def test_all_dir():
assert set(data_assimilation.__all__) == set(dir(data_assimilation))
5 changes: 5 additions & 0 deletions tests/test_reservoir_simulator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from resmda import reservoir_simulator


def test_all_dir():
assert set(reservoir_simulator.__all__) == set(dir(reservoir_simulator))
80 changes: 80 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,90 @@
import scooby
import numpy as np
from numpy.testing import assert_allclose

from resmda import utils


def test_gaussian_covariance():
# Small length, no variance => eye
assert_allclose(utils.gaussian_covariance(4, 4, [0.1, 0.1], 0, 0),
np.eye(4*4))

# Small length, some variance => still eye
assert_allclose(
utils.gaussian_covariance(
nx=4, ny=4, length=[0.1, 0.1], theta=0, variance=1
),
np.eye(4*4)
)

# Simply check some values with variance
x = utils.gaussian_covariance(4, 4, [2, 1], 30, 2)
assert_allclose(np.diag(x), 1.)
assert_allclose(np.diag(x, -1)[3::4], 0)
for i in range(3):
assert_allclose(np.diag(x, -1)[i::4], 0.00024027168)
assert_allclose(np.diag(x, -4), 0.58600724)
for i in [2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]:
assert_allclose(np.diag(x, -i), 0)

# Simply check some values without variance
x = utils.gaussian_covariance(4, 4, [1, 2], 0, 0)
assert_allclose(np.diag(x), 1.)
assert_allclose(np.diag(x, -1)[0], 0.20833333)
assert_allclose(np.diag(x, -3)[1], 0.13466999)
assert_allclose(np.diag(x, -4)[0], 0.6848958)
assert_allclose(np.diag(x, -5)[0], 0.13466999)
assert_allclose(np.diag(x, -7)[1], 0.030032475)
assert_allclose(np.diag(x, -8)[0], 0.20833333)
assert_allclose(np.diag(x, -9)[0], 0.030032475)
assert_allclose(np.diag(x, -11)[1], 0.0004445008)
assert_allclose(np.diag(x, -12)[0], 0.016493056)
assert_allclose(np.diag(x, -13)[0], 0.0004445008)
for i in [2, 6, 10, 14, 15]:
assert_allclose(np.diag(x, -i), 0)


def test_localization_matrix():
# [[ 0, 0, 0, 0],
# [ 4, 5, 0, 0],
# [ 8, 9, 10, 0],
# [12, 13, 14, 15]]
tril = np.tril(np.arange(16).reshape(4, 4))
full = tril + np.tril(tril, -1).T
triu = np.triu(full)

data_positions = np.array([[1, 0]], dtype=int)
solution = np.array([[[4]], [[5]], [[9]], [[13]]])
outtril = utils.localization_matrix(tril, data_positions, (4, 1))
assert_allclose(solution, outtril)
outtriu = utils.localization_matrix(triu, data_positions, (4, 1), 'upper')
assert_allclose(solution, outtriu)
outfull = utils.localization_matrix(full, data_positions, (4, 1), 'full')
assert_allclose(solution, outfull)


def test_random():
assert isinstance(utils.rng(), np.random.Generator)
assert isinstance(utils.rng(11), np.random.Generator)
rng = np.random.default_rng()
assert rng == utils.rng(rng)


def test_Report(capsys):
out, _ = capsys.readouterr() # Empty capsys

# Reporting is done by the external package scooby.
# We just ensure the shown packages do not change (core and optional).
out1 = utils.Report()
out2 = scooby.Report(
core=['numpy', 'scipy', 'numba', 'resmda'],
optional=['matplotlib', 'IPython'],
ncol=3)

# Ensure they're the same; exclude time to avoid errors.
assert out1.__repr__()[115:] == out2.__repr__()[115:]


def test_all_dir():
assert set(utils.__all__) == set(dir(utils))

0 comments on commit c8588a4

Please sign in to comment.