Chapter 1 — The shortest model that writes a deck
One import, one value, one compile, no configuration:
import petroscript as ps
model = ps.Model( name="HELLO", units="field", start="2020-01-01", grid=ps.grid.Cartesian(shape=(2, 2, 1), dx=500.0, dy=500.0, dz=40.0, top=2500.0), rock=ps.Rock(porosity=0.25, permeability=100.0, vertical_ratio=0.1, compressibility=4.0e-6, reference_pressure=3000.0), fluid=ps.fluid.OilWater( oil=ps.pvt.DeadOil(pressure=[14.7, 3500.0], oil_fvf=[1.06, 1.0], oil_viscosity=[1.0, 1.2]), water=ps.pvt.Water(reference_pressure=3000.0, fvf=1.0, compressibility=3.0e-6, viscosity=0.5, viscosibility=0.0), oil_surface_density=53.0, water_surface_density=64.0, ), relperm=[ps.relperm.OilWater(sw=[0.2, 0.8], krw=[0.0, 1.0], krow=[1.0, 0.0], pcow=[0.0, 0.0])], initial=ps.initial.Equilibrium(datum_depth=2520.0, datum_pressure=3000.0, oil_water_contact=2600.0), wells=[ps.Well(name="PROD1", i=1, j=1)], schedule=ps.Schedule( end="2020-01-31", events=[ps.Event("2020-01-01", ps.Perforate(well="PROD1", k=(1, 1), diameter=0.3), ps.Produce(well="PROD1", oil_rate=220.0, bhp_limit=1200.0))], ),)ps.compile(model).write("hello") # hello/HELLO.DATAps.Model is the whole case as one frozen value, stated by keyword in the model’s unit
system. ps.compile(model) makes the deck in memory and .write(folder) writes it.
Everything the package publishes is reachable as ps.<name> or ps.<namespace>.<name>:
there is one import and it is the one above.
Nothing is edited in place. A change to a case that already exists is a verb that returns a
new model, m.at(date, ...) for a dated change and m.set(address, value) for a fact, and
the same verbs edit a deck read with ps.load.
The value is also the short path to a test: read what the model states, by address, rather than the deck text.
assert model.get("wells/PROD1").i == 1assert model.find("schedule/*/PROD1/*") == [ "schedule/2020-01-01/PROD1/perforation/1", "schedule/2020-01-01/PROD1/control",]Three habits carry over from here into every other chapter:
- Look names up rather than guess them.
ps.help(ps.Produce)prints a class’s fields, the card it writes and where the model holds it;ps.help("WCONPROD")names the class that writes a keyword;ps.help("FOPR")the name a summary result is read by;ps.help()lists the classes, namespaces and topics. - A wrong name answers with the nearest one.
ps.Produce(bhp_limt=...)is refused withdid you mean 'bhp_limit'?. You do not have to be right the first time; you have to read the refusal. - A deck answers too. Where
ps.helpnames no class for a keyword,ps.loada deck that states it andm.to_python(folder)prints the statement that holds it.
PetroScript is licensed under the Apache License 2.0. © 2026 Blauweiss EDV LLC. PetroScript by Blauweiss AI.For AI agents: llms.txt