Add production history and a forecast
A history match holds each producer to its observed rates, month by month, and compares what
the model then does (pressures, water cut, gas-oil ratio) with what the field did. In
PetroScript an observed month is a ps.History control: every rate it states is an observation,
and control= names the one the simulator holds the well to. ps.History.from_frame turns a
table of observations into dated events.
import polars as pl
import petroscript as ps
m = ps.load("opm-tests/spe1/SPE1CASE2.DATA") # FIELD: stb/day, Mscf/dayobserved = pl.DataFrame({ # or pl.read_csv("history.csv") "date": ["2015-02-01", "2015-03-01", "2015-04-01"], "well": ["PROD", "PROD", "PROD"], "oil_rate": [19800.0, 19500.0, 19100.0], # stb/day "gas_rate": [25000.0, 26000.0, 27500.0], # Mscf/day})for event in ps.History.from_frame(observed, control="oil_rate"): m = m.at(event.date, *event.changes) # one dated event per month
# the forecast: from the first date after the history, a normal control againm = m.at("2015-05-01", ps.Produce(well="PROD", oil_rate=15000.0, bhp_limit=1000.0))
# ask for the observed rates beside the simulated ones (Flow's WOPRH, WGPRH)m = m.set("summary/history", {"wells": {"PROD": ["oil_production_rate", "gas_production_rate"]}})deck = ps.compile(m).files["SPE1CASE2.DATA"]assert "WCONHIST" in deck and "WOPRH" in decknow = m.control("PROD", at="2015-03-15")assert isinstance(now, ps.History) and now.oil_rate == 19500.0- The frame’s columns are
date,welland any ofoil_rate,water_rate,gas_rate,thp,bhp_limitandstatus, in the model’s units. A pandas frame or a plain mapping of columns works too. - A row with more than one rate needs
control=: one word for every well, or a mapping by well name (control={"PROD": "oil_rate", "GAS1": "gas_rate"}). - A date that is not yet a report time becomes one. A date past the run’s end is refused:
m = m.until(date)first. - A history control’s
bhp_limitis the observed bottom-hole pressure, reported beside the rates; it limits nothing while the well is held to a rate. - One control per well per date: a
ps.Produceat a history date replaces that month’sps.History. Start the forecast at the next date.
After the run, the simulated rates read by name (run.wells("oil_production_rate")); the
observed ones the summary asked for are in the long-form frame under Flow’s own names:
run.frame().filter(pl.col("quantity") == "WOPRH").
PetroScript is licensed under the Apache License 2.0. © 2026 Blauweiss EDV LLC. PetroScript by Blauweiss AI.For AI agents: llms.txt