examples.rate_scheduling

Steering the water front with time-varying injection rates.

Two injectors (SW and NW corners) feed a single producer (NE corner). Their rates are scheduled: for the first 10 steps all of the water enters from the SW corner, thereafter the two injectors share the load equally. The resulting front is correspondingly lopsided.

A rate may be specified as a schedule (an array over time), as done here -- whereupon the wells held constant get broadcast along with it -- or (for feedback control, e.g. shutting wells on water breakthrough) by overriding ResSim.well_controls.

In the figures:

  • "saturation": at t = 0.125, and still at t = 0.25 (the moment of the switch), all of the water has come from the SW. By t = 0.45 a second front has grown from the NW injector, and by t = 0.70 the two have merged into a distinctly lopsided sweep -- compare the symmetric front of examples.quarter_five_spot.
  • "wells": the schedule itself (left), and the oil saturation in the producer (right), which shows that the water only breaks through at the very end (step 27 of 28).
Rate scheduling -- saturation
Rate scheduling -- saturation
Rate scheduling -- wells
Rate scheduling -- wells
 1"""Steering the water front with time-varying injection rates.
 2
 3Two injectors (SW and NW corners) feed a single producer (NE corner).
 4Their rates are *scheduled*: for the first 10 steps all of the water enters from
 5the SW corner, thereafter the two injectors share the load equally.
 6The resulting front is correspondingly lopsided.
 7
 8A rate may be specified as a *schedule* (an array over time), as done here --
 9whereupon the wells held constant get broadcast along with it -- or (for
10feedback control, e.g. shutting wells on water breakthrough) by overriding
11`ResSim.well_controls`.
12
13In the figures:
14
15- "saturation": at t = 0.125, and still at t = 0.25 (the moment of the switch),
16  all of the water has come from the SW. By t = 0.45 a second front has grown
17  from the NW injector, and by t = 0.70 the two have merged into a distinctly
18  lopsided sweep -- compare the symmetric front of `examples.quarter_five_spot`.
19- "wells": the schedule itself (left), and the oil saturation in the producer
20  (right), which shows that the water only breaks through at the very end
21  (step 27 of 28).
22"""
23
24from mpl_tools.place import freshfig
25import numpy as np
26
27from TPFA_ResSim import ResSim
28from TPFA_ResSim.plotting import show
29
30## Setup
31nSteps = 28
32dt = 0.7/nSteps
33
34# Schedule: the SW injector carries everything until step 10, then they share.
35rate_sw = .5*np.ones(nSteps)
36rate_nw = .5*np.ones(nSteps)
37rate_sw[:10] = 1
38rate_nw[:10] = 0
39
40model = ResSim(Lx=1, Ly=1, Nx=64, Ny=64, wells=[
41    dict(name="SW", xy=[0, 0], rate=+rate_sw),
42    dict(name="NW", xy=[0, 1], rate=+rate_nw),
43    dict(name="NE", xy=[1, 1], rate=-1),   # constant: broadcast to the schedule
44])
45
46water_sat0 = model.swc * np.ones(model.Nxy)
47
48## Simulate
49SS, PP = model.sim(dt, nSteps, water_sat0, pbar=False)
50
51## Plot: saturation snapshots
52fig, axs = freshfig("Rate scheduling -- saturation", nrows=2, ncols=2,
53                    sharex=True, sharey=True)
54for ax, k in zip(axs.ravel(), [5, 10, 18, nSteps]):
55    model.plt_field(ax, SS[k], "oil", finalize=False, colorbar=False,
56                    title=f"t = {k*dt:.2f}")
57fig.tight_layout()
58
59## Plot: the schedule itself, and the resulting production
60fig, axs = freshfig("Rate scheduling -- wells", ncols=2, figsize=(9, 3.5))
61
62tt = dt*(1 + np.arange(nSteps))
63for i, rate in enumerate(model.wells.actual_rates[:2]):
64    x, y = model.wells.xy[i]
65    name = model.wells.names[i]
66    axs[0].step(tt, rate, where="post", label=f"Injector {name} @ ({x:.2f}, {y:.2f})")
67axs[0].set(title="Injection rates", xlabel="Time", ylabel="Rate", ylim=(-.05, 1.05))
68axs[0].legend()
69
70prd = [model.xy2ind(*model.wells.xy[2])]
71model.plt_production(axs[1], SS[1:, prd], finalize=False,
72                     labels=model.wells.names[2:])
73fig.tight_layout()
74
75# Regression values, checked by `tests/test_examples.py`.
76__digest__ = dict(sat_final=SS[-1, ::600])
77
78if __name__ == "__main__":
79    show()