A waterflood from scratch
"""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 3box 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 resultsread 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 targetdeck.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