Skip to content

Miscible and surfactant EOR

PetroScript models miscible displacement and surfactant viscosity as semantic physics intent. Users describe the reservoir behavior they want; compiler lowerers own backend card details.

Attach miscible behavior to a model’s physics=[...] with ps.miscible.Package(...). The package composes with ps.solvent.Package(...) when the chosen miscibility behavior depends on an explicit solvent package; solvent activation and solvent property data remain owned by the solvent namespace.

import petroscript as ps
base = ps.Model(
name="BASE",
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=1.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.20, 0.80], 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, gas_oil_contact=0.0
),
wells=[ps.Well(name="PROD1", i=1, j=1)],
schedule=ps.Schedule(
report=[ps.Every(30.0)],
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),
)
],
),
)
solvent = ps.solvent.Package(
density=45.0,
pvt=ps.solvent.PVT(
rows=[
{"pressure": 14.7, "fvf": 1.0, "viscosity": 0.1},
{"pressure": 3500.0, "fvf": 0.9, "viscosity": 0.2},
]
),
)
miscible = ps.miscible.Package(
transform=ps.miscible.Transform(
rows=[
{"solvent_fraction": 0.0, "miscibility": 0.0},
{"solvent_fraction": 1.0, "miscibility": 1.0},
]
),
pressure_miscibility=ps.miscible.PressureCurve(
rows=[
{"pressure": 1500.0, "miscibility": 0.0},
{"pressure": 3500.0, "miscibility": 1.0},
]
),
normalized_relperm=ps.miscible.RelPerm(
rows=[
{"total_gas_saturation": 0.0, "gas_relperm": 0.0, "oil_relperm": 1.0},
{"total_gas_saturation": 1.0, "gas_relperm": 1.0, "oil_relperm": 0.0},
]
),
residual_oil=ps.miscible.ResidualOil(
rows=[
{"water_saturation": 0.0, "residual_oil_saturation": 0.0},
{"water_saturation": 1.0, "residual_oil_saturation": 0.30},
]
),
critical_gas=ps.miscible.CriticalGas(
rows=[
{"water_saturation": 0.0, "critical_gas_saturation": 0.0},
{"water_saturation": 1.0, "critical_gas_saturation": 0.03},
]
),
todd_longstaff=ps.miscible.Mixing(
regions={1: {"viscosity_parameter": 0.60, "density_parameter": 0.60}}
),
)
model = base.replace(
physics=[solvent, miscible],
regions=ps.Regions(miscible=1), # every cell in miscible region 1 (MISCNUM)
)

Canonical classes (each table’s rows are mappings by column name, or sequences in the columns’ order):

  • ps.miscible.Package
  • ps.miscible.Transform
  • ps.miscible.PressureCurve
  • ps.miscible.RelPerm
  • ps.miscible.ResidualOil
  • ps.miscible.CriticalGas
  • ps.miscible.Mixing

Surfactant viscosity is represented as typed intent under ps.surfactant, but current native simulator evidence blocks executable surfactant activation. The semantic API is still useful because it fails closed with a stable diagnostic instead of silently writing a deck that the simulator will reject.

surfactant = ps.surfactant.Package(
viscosity=ps.surfactant.Viscosity(
rows=[
{"concentration": 0.0, "viscosity": 1.0},
{"concentration": 1.0, "viscosity": 2.0},
]
)
)
ps.testing.assert_issue(
lambda: base.replace(physics=[surfactant]),
code="surfactant.flow.activation_unsupported",
)

Canonical classes:

  • ps.surfactant.Package
  • ps.surfactant.Viscosity
  • Do not author raw backend cards directly.
  • Keep solvent package data under ps.solvent; miscible APIs may depend on it but must not duplicate it.
  • Treat surfactant support as fail-closed until a future slice records native simulator evidence for a runnable activation path.

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