Skip to content

Units and bare numbers

A model has one unit system, ps.Model(units=...): "metric", "field" or "lab". A loaded deck keeps its own (m.units). Every bare number you type is in that system: a pressure in a METRIC model is barsa, in a FIELD model psia. PetroScript does not guess a unit, so a FIELD gas-oil ratio typed in scf/stb instead of Mscf/stb is 1000 times too high and runs. Two exceptions are in the table below: report-step lengths are days in every system, and an absolute temperature (a component’s critical temperature) is K or degR.

The same rule holds everywhere a number goes: a table column, a control’s target, a rule’s threshold, a lift table’s axis. A run’s results come back in the same system, each frame with a unit column.

QuantityFIELDMETRICLAB
Depth, length, thickness, cell size, well diameterftmcm
Pressure (BHP, THP, datum, PVT tables)psiabarsaatma
Oil, water or liquid rate (surface)stb/daysm3/dayscc/hr
Gas rate (surface)Mscf/daysm3/dayscc/hr
Reservoir volume raterb/dayrm3/dayrcc/hr
Oil or water totalstbsm3scc
Gas totalMscfsm3scc
Gas-oil ratio (solution GOR, a GOR rule, a lift-table GOR axis)Mscf/stbsm3/sm3scc/scc
Water-gas or oil-gas ratiostb/Mscfsm3/sm3scc/scc
Water cutfraction, 0 to 1fractionfraction
Water-oil ratiostb/stbsm3/sm3scc/scc
Porosity, saturation, net-to-grossfractionfractionfraction
PermeabilitymDmDmD
Oil formation volume factorrb/stbrm3/sm3rcc/scc
Gas formation volume factorrb/Mscfrm3/sm3rcc/scc
ViscositycPcPcP
Density (surface densities)lb/ft3kg/m3g/cc
Compressibility (rock, water)1/psi1/bar1/atm
TemperaturedegFdegCdegC
Absolute temperature (a component’s critical temperature, a density’s reference temperature)degRKK
Report-step length (ps.Every)daydayday (a LAB deck writes it in hours: ps.Every(1.0) is TSTEP 24)

Three that trip people up:

  • Gas-oil ratio in FIELD is Mscf/stb. A GOR of 800 scf/stb is 0.8. A rule ps.actions.well(prod).gas_oil_ratio > 20.0 in a FIELD model shuts at 20 Mscf/stb.
  • A water cut is a fraction. 50 % is 0.5, in a rule, a lift-table axis and a result.
  • A well diameter is a length. 0.3 ft in FIELD, 0.2 m in METRIC: ps.Perforate(diameter=0.3).

ps.help("units") prints the same rule, and every unit word a ps.Quantity takes.

Where a field states what kind of number it is (a pressure, a length, a rate, a permeability, a temperature, a time), it also takes a ps.Quantity(value, unit), which converts on the way in. A rule’s threshold and a table’s column take bare numbers only, so a Quantity there is refused.

import petroscript as ps
m = ps.load("opm-tests/spe1/SPE1CASE1.DATA") # SPE1: a FIELD deck
assert m.units == "field"
# a datum pressure typed in bar converts to the model's psia
m = m.set("initial/1/datum_pressure", ps.Quantity(330.0, "barsa"))
# a rule's threshold is a bare number in the model's units: 20 Mscf/stb here
producer = m.get("wells/PROD")
rule = ps.actions.When(ps.actions.well(producer).gas_oil_ratio > 20.0,
then=[ps.Shut(well="PROD")], name="HIGH_GOR")
m = m.at(m.start, rule)
assert "WGOR 'PROD' > 20" in ps.compile(m).files["SPE1CASE1.DATA"]
try:
ps.actions.well(producer).gas_oil_ratio > ps.Quantity(20.0, "mscf/stb")
except ValueError as refused:
print(refused) # [units.wrong_kind] an expression's number takes a bare number ...

m.check() looks for numbers that only make sense in another unit system and says so at their address. The quickstart’s datum pressure, typed in psi into a METRIC model, reads:

warning initial/1/datum_pressure [physics.pressure_gradient.other_unit] The datum pressure 3626
is 13.4 times the model's own water column at the datum depth 2420 ...; read in psi it is
0.923 times that column, nearer than the pressure as stated

Fix the number at its address (m.set("initial/1/datum_pressure", 250.0)), or state it as a ps.Quantity with its unit.

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