Skip to content

Diffusion, dispersion, and EDIT operations

PetroScript models transport as reservoir physics and bounded grid-array intent. Users name diffusion, dispersion, and array adjustments; the compiler owns the Flow/ECL keyword spelling and section placement.

Molecular diffusion describes component spreading caused by concentration gradients. Dispersion describes grid-cell mixing tied to flow through the rock. Some dispersion benchmark decks also adjust a bounded part of a grid array before simulation begins. PetroScript represents those adjustments as semantic array operations rather than raw keyword rows.

Molecular diffusion is a property of the fluid: ps.pvt.Diffusion(...) is the fluid system’s diffusion=, and the rock’s dispersivity= states dispersion:

import petroscript as ps
diffusion = ps.pvt.Diffusion(
oil_molecular_weight=16.043,
gas_molecular_weight=2.016,
gas_in_gas=6.2726,
oil_in_gas=6.2726,
)
fluid = ps.fluid.BlackOil(
oil=ps.pvt.DeadOil(pressure=[39.95, 40.05], oil_fvf=[0.0271, 0.0270],
oil_viscosity=[0.0126, 0.0126]),
gas=ps.pvt.DryGas(pressure=[39.95, 40.05], gas_fvf=[0.0290, 0.0289],
gas_viscosity=[0.0094, 0.0094]),
oil_surface_density=0.6785,
water_surface_density=999.70,
gas_surface_density=0.0850,
diffusion=diffusion,
)
rock = ps.Rock(porosity=0.4, permeability=101.3, vertical_ratio=1.0,
compressibility=4.3e-5, reference_pressure=40.0, dispersivity=1.0)

ps.pvt.Diffusion carries the DIFFC record: oil and gas molecular weights, gas-in-gas and oil-in-gas, then the optional gas-in-oil and oil-in-oil pair (supplied together or not at all), and switches on the DIFFUSE package.

Use ps.pvt.Diffusion() without coefficients when a target physics model supplies its own diffusion model. Use named coefficient arguments when a black-oil diffusion coefficient row is required. A gas-water storage model states its component diffusion as ps.storage.Diffusion(formulation=..., regions=...) instead.

ps.Rock(dispersivity=...) accepts a scalar or a (nx, ny, nz) cell tensor. The value is a dispersion coefficient field, not a keyword-card record.

Static grid adjustments are semantic grid-edit operations in the model’s edits=:

edits = (
ps.grid.Scale(target="porosity", by=0.1, cells=ps.Box(i=(51, 100))),
ps.grid.Add(target="dispersion_coefficient", value=1000.0, cells=ps.Box(i=(51, 100))),
)

The public API names the array a statement edits by its semantic name (porosity, pore_volume, dispersion_coefficient) and the cells by a 1-based ps.Box. It does not expose EDIT, OPERATE, ADDX, MULTX, or deck-row constructors as user-facing authoring primitives.

  • Diffusion molecular weights and coefficients must be positive finite numbers.
  • Dispersion coefficients may be scalar or shaped like the grid.
  • ps.Box(...) uses 1-based inclusive (start, end) ranges for i, j, and k; omitted axes mean the full axis.
  • Do not pass raw keyword strings such as "DIFFUSE" or "DISPERC" to public constructors.
  • Name the array a ps.grid.Add or ps.grid.Scale edits by its semantic name, not its deck keyword; a name outside the listed arrays is refused.
  • Keep dispersion tensors compatible with the grid dimensions; the compiler’s property validation checks the final shape during rendering.
  • Prefer a narrow operation over a new framework: add a semantic array name or operation only when a failing test proves the need.

For the OPM Flow target path, current lowerers emit:

  • DIFFUSE in RUNSPEC when diffusion is enabled;
  • DISPERC in GRID, before EDIT, when a dispersion coefficient is present;
  • EDIT/OPERATE for bounded semantic grid-array operations;
  • DIFFC in PROPS when diffusion coefficients are supplied.

The examples under tests/fixtures/examples/g9/ include compact semantic reconstructions of DISPERC_FINGERS, DISPERC_INJECTION, and BO_DIFFUSE_CASE1; each is backed by native fixture Flow evidence and generated PetroScript Flow evidence.

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