Skip to content

Phase formulations

PetroScript treats phase-system choice as reservoir semantics, not as a public keyword API. The fluid system’s class is the formulation, and the compiler lowers it to the cards required by OPM Flow.

import petroscript as ps
water = ps.pvt.Water(reference_pressure=3000.0, fvf=1.0, compressibility=3.0e-6,
viscosity=0.5, viscosibility=0.0)
gas = ps.pvt.DryGas(pressure=[14.7, 5000.0], gas_fvf=[200.0, 0.6],
gas_viscosity=[0.01, 0.03])
oil = ps.pvt.DeadOil(pressure=[14.7, 3500.0], oil_fvf=[1.06, 1.0], oil_viscosity=[1.0, 1.2])
black_oil = ps.fluid.BlackOil(oil=oil, gas=gas, water=water, oil_surface_density=53.0,
gas_surface_density=0.06, water_surface_density=64.0)
oil_water = ps.fluid.OilWater(oil=oil, water=water, oil_surface_density=53.0,
water_surface_density=64.0)
gas_water = ps.fluid.GasWater(gas=gas, water=water, gas_surface_density=0.06,
water_surface_density=64.0)

A ps.fluid.GasWater is the gas-water formulation, so a model given that system needs nothing more:

model = ps.Model(
name="GAS_WATER_CASE",
units="field",
start="2020-01-01",
grid=ps.grid.Cartesian(shape=(2, 2, 1), dx=500.0, dy=500.0, dz=40.0, top=8000.0),
rock=ps.Rock(porosity=0.2, permeability=100.0, vertical_ratio=0.1,
compressibility=3.0e-6, reference_pressure=3000.0),
fluid=gas_water,
relperm=[ps.relperm.GasWater(sg=[0.0, 0.8], krg=[0.0, 1.0], krw=[1.0, 0.0],
pc=[0.0, 0.0])],
initial=ps.initial.Equilibrium(datum_depth=8400.0, datum_pressure=4700.0,
gas_water_contact=9000.0),
schedule=ps.Schedule(end="2021-01-01"),
)

The formulation is inspectable in tests as the system’s class:

assert isinstance(model.fluid, ps.fluid.GasWater)
  • Gas + water with no oil is the gas-water formulation. The model reads it off the fluid system’s class (ps.fluid.GasWater), exactly as the importer reads it off a deck’s bare GAS/WATER cards. A ps.fluid.BlackOil that holds only gas and water is refused when the model is built, naming ps.fluid.GasWater.
  • A model built from scratch states no phase slate, so its formulation cannot contradict its fluid. The slate a loaded deck keeps on Model.dimensions is checked: a gas-water slate with no formulation is refused (phases.formulation.undeclared), and a formulation that contradicts the slate’s phases is refused by name (phases.formulation.inconsistent_phases).
  • Black-oil intent is ps.fluid.BlackOil, and an oil-water system is ps.fluid.OilWater; water stays explicit as the system’s water table.
  • Vaporized-water intent is a gas-water system whose gas table is a ps.pvt.VaporizedWaterGasPVT (the PVTGW body). A vaporized-water slate without that body, or without gas and water, is refused with stable issue codes instead of emitting an invalid generated deck.
  • Saturation options that OPM Flow recognizes only at their defaults are rejected with diagnostics instead of being emitted as fake support.

Stable issue codes for this surface include:

  • phases.formulation.undeclared
  • phases.formulation.inconsistent_phases
  • phases.vaporized_water.requires_gas_water
  • phases.vaporized_water.pvtgw_required
  • phases.vaporized_water.salt_table_required
  • regions.saturation_options.irreversible_unsupported
  • regions.saturation_options.surface_tension_unsupported

Keyword names may appear in compiler tests and coverage ledgers, but they are not public factory names, method names, or string-DSL arguments.

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