Skip to content

A waterflood from scratch

examples/waterflood.py
"""A waterflood from scratch: build a model by keyword, check it, compile it, run it, read it.
One injector in a corner pushes water towards one producer in the opposite corner of a 10 x 10 x 3
box of dead oil over water. The script shows the whole path a new model takes: ``ps.Model(...)``
stated by keyword, ``m.check()``, ``ps.compile(m)``, ``deck.write``, ``deck.run`` and the results
read by name.
Flow keywords it exercises: DIMENS, DX/DY/DZ/TOPS, PORO, PERMX/PERMY/PERMZ, ROCK, PVDO, PVTW,
DENSITY, SWOF, EQUIL, WELSPECS, COMPDAT, WCONPROD, WCONINJE, DATES, SUMMARY.
Run it with ``python examples/waterflood.py``; it writes ``out/waterflood/``.
"""
import petroscript as ps
m = ps.Model(
name="WATERFLOOD",
units="metric",
start="2025-01-01",
grid=ps.grid.Cartesian(shape=(10, 10, 3), dx=50.0, dy=50.0, dz=[4.0, 6.0, 10.0], top=2000.0),
rock=ps.Rock(porosity=0.2, permeability=100.0, vertical_ratio=0.1,
compressibility=5.0e-5, reference_pressure=200.0),
fluid=ps.fluid.OilWater(
oil=ps.pvt.DeadOil(pressure=[50.0, 200.0, 400.0], # barsa
oil_fvf=[1.12, 1.10, 1.08], # rm3/sm3
oil_viscosity=[1.8, 2.0, 2.3]), # cP
water=ps.pvt.Water(reference_pressure=200.0, fvf=1.01, compressibility=4.5e-5,
viscosity=0.4, viscosibility=0.0),
oil_surface_density=850.0, # kg/m3
water_surface_density=1020.0,
),
relperm=[ps.relperm.OilWater(sw=[0.2, 0.4, 0.6, 0.8], krw=[0.0, 0.05, 0.2, 0.5],
krow=[0.9, 0.4, 0.1, 0.0], pcow=[0.0, 0.0, 0.0, 0.0])],
initial=ps.initial.Equilibrium(datum_depth=2000.0, datum_pressure=200.0,
oil_water_contact=2100.0),
wells=[ps.Well(name="INJ", i=1, j=1), ps.Well(name="PROD", i=10, j=10)],
schedule=ps.Schedule(
end="2030-01-01",
report="monthly",
events=[
ps.Event("2025-01-01",
ps.Perforate(well="INJ", k=(1, 3), diameter=0.2),
ps.Perforate(well="PROD", k=(1, 3), diameter=0.2),
ps.Inject(well="INJ", phase="water", rate=350.0, bhp_limit=400.0),
ps.Produce(well="PROD", liquid_rate=350.0, bhp_limit=100.0)),
],
),
summary=ps.Summary(field=["oil_production_rate", "water_production_rate", "pressure"],
wells={"PROD": ["water_cut", "bottom_hole_pressure"]}),
)
for issue in m.check(): # PetroScript's own checks: instant, no simulator
print(issue.severity, issue.address, issue)
deck = ps.compile(m) # a Deck for "opm-flow", the default target
deck.write("out/waterflood") # out/waterflood/WATERFLOOD.DATA
if ps.simulators():
run = deck.run(folder="out/waterflood/run")
cut = run.wells("water_cut").filter(well="PROD")
wet = cut.filter(cut["value"] > 0.01)
print("water breaks through at PROD on", wet["date"][0].date() if len(wet) else "no date yet")
print(f"PROD water cut at the end: {cut['value'][-1]:.2f}")
else:
print("no simulator found (set PETROSCRIPT_FLOW, or put flow on PATH); the deck is in "
"out/waterflood")

PetroScript is licensed under the Apache License 2.0. © 2026 Blauweiss EDV LLC. PetroScript by Blauweiss AI.For AI agents: llms.txt