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.
Miscible package
Section titled “Miscible package”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.Packageps.miscible.Transformps.miscible.PressureCurveps.miscible.RelPermps.miscible.ResidualOilps.miscible.CriticalGasps.miscible.Mixing
Surfactant viscosity intent
Section titled “Surfactant viscosity intent”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.Packageps.surfactant.Viscosity
API law
Section titled “API law”- 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