minires⚓︎
Forward simulator backed by MiniRes, a two-phase (water/oil) TPFA reservoir simulator.
MiniRes (https://github.com/patnr/MiniRes) is a pure-Python toy simulator: no binary, no licence, no deck, no scratch folder. It is therefore the cheapest way to drive PET with actual two-phase flow -- in a tutorial, in CI, or as the reference case when developing a scheme -- rather than with an ODE.
Install it alongside PET with pip install PET[minires].
The simulator section of the config configures it, e.g.
[simulator]
reporttype = "steps"
reportpoint = [2, 4, 6, 8, 10]
datatype = ["WWCT:PRD1", "WOPR:PRD1", "FWIR"]
dt = 0.025
parallel = 1
[simulator.model]
Nx = 32
Ny = 32
por = 0.2
[[simulator.model.wells]]
name = "INJ1"
xy = [0.1, 0.1]
rate = 1.0
[[simulator.model.wells]]
name = "PRD1"
xy = [0.9, 0.9]
rate = -1.0
[simulator.model] is passed to minires.ResSim as it stands (its
wells are MiniRes well records), less the permeability, which is what the
ensemble state supplies, one field per member.
Conventions, all of which this module owns -- MiniRes itself is agnostic:
- Report points are step indices,
1 .. nSteps, since MiniRes takes a uniformdt. Usereporttype = "steps". A dated case can map them withreportdates. - Field ordering. MiniRes is C-major (x is the first axis); Eclipse, and
hence most of PET's tooling, is Fortran-ordered.
field_order(default"C") says which the state vector is in, and is applied on the way in and on the way out (the adjoint). - Data types are named as Eclipse's summary vectors,
<quantity>:<well>for a well and<quantity>for the field, so observed-data files,datatypefilters and localization tooling need no adaptation. Rates are positive as produced/injected, and areal (MiniRes has no thickness). - Units are whatever the config poses the model in. Set
cdarcy = 0.008527in[simulator.model]for metric (m, day, bar, mD, cP), as Eclipse does.
DIFFERENTIABLE = ('WOPR', 'WWPR', 'WWCT')
⚓︎
The quantities :meth:MiniRes.run_fwd_sim can also produce an adjoint for.
FIELD_QUANTITIES = ('FOPR', 'FWPR', 'FWIR', 'FOPT', 'FWPT', 'FWIT')
⚓︎
Field rates and their cumulatives.
WELL_QUANTITIES = ('WOPR', 'WWPR', 'WLPR', 'WWIR', 'WWCT', 'WBHP')
⚓︎
Per-well quantities: oil/water/liquid production rate, water injection rate, water cut, BHP.
MiniRes
⚓︎
PET forward simulator: one MiniRes run per ensemble member.
Satisfies :class:ensemble.protocols.ForwardSimulator. Every member runs
on its own deepcopy of the model, so nothing is shared and the class is
picklable -- which is what parallel > 1 (p_map) requires. MiniRes
drops its cached pressure preconditioner on copy for exactly this reason.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
input_dict
|
dict
|
The parsed
|
required |
adjoint_frame(model, SS, PP)
⚓︎
Each datum's sensitivity to the state, as the frame the ensemble stacks into (nd, nx, ne).
MiniRes's adjoint (minires.tlm) gives the gradient of one scalar
per backward sweep, at about the cost of one simulation -- so a full
Jacobian costs one sweep per datum. That is affordable on the grids this
simulator is for, and is what PET's adjoint-based analyses want.
Only quantities that are a function of the saturation at the well's
cells are covered (:data:DIFFERENTIABLE), and only at rate-controlled
completions, whose rate is then a constant of the objective. A
BHP-controlled well's rate is itself a function of (S, P); that
derivative has to be worked into the seed by hand, so it is refused
rather than silently dropped.
records(model, SS)
⚓︎
One dict per report point, keyed by data type -- what the ensemble collects.
run_fwd_sim(state, member_index=0, **kwargs)
⚓︎
Simulate one realisation; return its records (and adjoint), or False if it failed.
set_permeability(model, state)
⚓︎
Write the member's field into the model, as its (isotropic) permeability.
setup_fwd_run(level=None, **kwargs)
⚓︎
Select the fidelity level's configuration, when the config gives levels.
well_report(model, SS)
⚓︎
Every reportable quantity, as (nWell or 1, nSteps) arrays, from the run's well operation.
MiniRes reports one total rate per completion (signed: positive
injects). The phase split is the cell's fractional flow -- the same
Fluid.fractional_flow the transport uses -- and the completions are
summed into wells by Wells.group.
build_model(spec)
⚓︎
Build the minires.ResSim that [simulator.model] describes.
por and active may be given as scalars; the wells are MiniRes well
records (xy/path, rate/bhp, rw/WI, name).