ps.relperm
ps.relperm.CriticalTolerance
Section titled “ps.relperm.CriticalTolerance”ps.relperm.CriticalTolerance(*, value: ScalarPropertyInput) -> None
The critical-saturation tolerance (TOLCRIT), stated once for the whole model.
ps.relperm.CriticalTolerance(value=1.0e-6) counts a phase immobile where its relative
permeability is 1e-6 or less.
The relative permeability at or below which a phase counts as immobile when the
simulator finds a curve’s critical saturations; stated in the list or in saturation
region 1’s, at relperm/1/critical_tolerance.
value is that relative permeability (dimensionless).
ps.relperm.EndpointScaling
Section titled “ps.relperm.EndpointScaling”ps.relperm.EndpointScaling(*, curve: Literal['drainage', 'imbibition'] = 'drainage', method: Literal['two_point', 'three_point'] = 'two_point', connate_water=None, capillary_connate_water=None, connate_gas=None, capillary_connate_gas=None, critical_water=None, critical_gas=None, critical_oil_to_water=None, critical_oil_to_gas=None, maximum_water=None, maximum_gas=None, maximum_water_relperm=None, maximum_gas_relperm=None, oil_relperm_at_connate_water=None, gas_relperm_at_residual_oil=None, water_relperm_at_critical_oil=None, oil_relperm_at_critical_gas=None, oil_relperm_at_critical_water=None, maximum_gas_oil_capillary_pressure=None, maximum_oil_water_capillary_pressure=None, source: str | None = None) -> None
End-point scaling of the drainage or the imbibition curves (the whole model).
ps.relperm.EndpointScaling(connate_water=0.2, critical_water=0.25) scales every cell’s
drainage curves to a connate water saturation of 0.2 and a critical one of 0.25.
curve says which: the drainage curves (the saturation functions themselves,
scaled by SWL, KRG and the like) or the imbibition curves hysteresis follows
(ISWL, IKRG and the like). Each array is a single value, one value per layer (held in
every cell of its layer) or a full (nx, ny, nz) array, of saturations and relative
permeabilities (fractions) or, for the two capillary-pressure arrays, of pressures in the
model’s units; an array left out takes each cell’s own table value. Drainage scaling
states its method (two- or three-point); the imbibition curves state the largest
capillary pressures, and at least one array.
method is the drainage scaling’s: "two_point" or "three_point" (SCALECRS). The
arrays, each a cell’s own end point (drainage card, then imbibition card):
connate_water, the connate water saturation (SWL, ISWL); capillary_connate_water,
the connate water saturation of the capillary pressure only (SWLPC, ISWLPC); connate_gas
and capillary_connate_gas, the gas’s (SGL, ISGL; SGLPC, ISGLPC); critical_water and
critical_gas, the critical saturations (SWCR, ISWCR; SGCR, ISGCR);
critical_oil_to_water and critical_oil_to_gas, the critical oil saturation in water
and in gas (SOWCR, ISOWCR; SOGCR, ISOGCR); maximum_water and maximum_gas, the largest
saturations (SWU, ISWU; SGU, ISGU); maximum_water_relperm and maximum_gas_relperm, the
relative permeabilities at those (KRW, IKRW; KRG, IKRG); oil_relperm_at_connate_water,
the oil’s at connate water (KRO, IKRO); gas_relperm_at_residual_oil and
water_relperm_at_critical_oil, the gas’s and the water’s at the critical oil saturation
(KRGR, IKRGR; KRWR, IKRWR); oil_relperm_at_critical_gas and
oil_relperm_at_critical_water, the oil’s at the critical gas and water saturations
(KRORG, IKRORG; KRORW, IKRORW); and, for the imbibition curves only,
maximum_gas_oil_capillary_pressure and maximum_oil_water_capillary_pressure, the largest
capillary pressures (IPCG, IPCW). source notes where the numbers come from (a loaded
deck’s card, a paper); the writer does not read it.
Either curve writes ENDSCALE in RUNSPEC, switching end-point scaling on, and its arrays in
PROPS. The imbibition curves need a ps.relperm.Hysteresis that names its family, which
switches hysteresis on (SATOPTS HYSTER), and a drainage EndpointScaling beside them,
which may state no array; without either the model is refused
(hysteresis.imbibition.requires_hysteresis_model,
hysteresis.imbibition.requires_drainage_baseline). It is stated once,
in the list or in saturation region 1’s, at relperm/1/endpoint_scaling (the second
stated, drainage and imbibition both, at relperm/1/endpoint_scaling/2).
ps.relperm.Gas
Section titled “ps.relperm.Gas”ps.relperm.Gas(*, sg: NDArray[numpy.float64], krg: NDArray[numpy.float64], pc: NDArray[numpy.float64], source: str | None = None) -> None
Gas relative permeability and capillary pressure against gas saturation (family II).
ps.relperm.Gas(sg=[0.0, 0.8], krg=[0.0, 0.9], pc=[0.0, 0.0]) is a straight gas curve to 0.9
at a gas saturation of 0.8, with no capillary pressure.
Family II states each phase’s curve on its own (SGFN; GSF beside a pc-less water curve in a gas-water system).
Rows: (sg, krg, pc). Each column is a field taking a list, a tuple or a 1-D array, one value per row, None where the simulator derives the cell; Gas.from_frame(frame) reads them from a frame by name.
sg is each row’s gas saturation, krg the gas’s relative permeability and pc the
gas capillary pressure there (a pressure, a bare number in the model’s units): the gas-oil
one where oil flows, the gas-water one as the storage pair’s GSF. Beside a Water curve that
states its pc in a gas-water system, Flow reads the gas-water capillary pressure from
that curve’s SWFN and not this one. source notes where the numbers come from (a loaded
deck’s card, a paper); the writer does not read it.
It is a statement of ps.Model(relperm=[...]), at relperm/1/gas (saturation region
n’s at relperm/<n>/gas in the {region: [...]} form).
ps.relperm.GasOil
Section titled “ps.relperm.GasOil”ps.relperm.GasOil(*, sg: NDArray[numpy.float64] | None = None, sl: NDArray[numpy.float64] | None = None, krg: NDArray[numpy.float64], krog: NDArray[numpy.float64], pcog: NDArray[numpy.float64], source: str | None = None) -> None
Gas-oil relative permeability and capillary pressure against gas or liquid saturation.
ps.relperm.GasOil(sg=[0.0, 0.8], krg=[0.0, 0.9], krog=[1.0, 0.0], pcog=[0.0, 0.0]) is a pair
of straight gas-oil curves, with no capillary pressure.
The saturation column is a choice: sg (gas saturation, SGOF) or sl (liquid
saturation, the connate water included, SLGOF); state one.
Rows: (sg or sl, krg, krog, pcog). Each column is a field taking a list, a tuple or a 1-D array, one value per row, None where the simulator derives the cell; GasOil.from_frame(frame) reads them from a frame by name.
krg is the gas’s relative permeability, krog the oil’s in gas (connate water
present), and pcog the gas-oil capillary pressure (a pressure, a bare number in the
model’s units), at each row’s saturation. source notes where the numbers come from (a
loaded deck’s card, a paper); the writer does not read it.
It writes SGOF (SLGOF for sl), one table per saturation region. It is a statement of
ps.Model(relperm=[...]), at relperm/1/gas_oil (saturation region n’s at
relperm/<n>/gas_oil in the {region: [...]} form).
ps.relperm.GasWater
Section titled “ps.relperm.GasWater”ps.relperm.GasWater(*, sg: NDArray[numpy.float64], krg: NDArray[numpy.float64], krw: NDArray[numpy.float64], pc: NDArray[numpy.float64], source: str | None = None) -> None
Gas and water relative permeability, gas-water capillary pressure, against gas saturation.
ps.relperm.GasWater(sg=[0.0, 0.8], krg=[0.0, 0.9], krw=[1.0, 0.0], pc=[0.0, 0.0]) is a pair
of straight gas-water curves, with no capillary pressure.
The combined gas-water curve (SGWFN).
Rows: (sg, krg, krw, pc). Each column is a field taking a list, a tuple or a 1-D array, one value per row, None where the simulator derives the cell; GasWater.from_frame(frame) reads them from a frame by name.
sg is each row’s gas saturation, krg the gas’s and krw the water’s relative
permeability, and pc the gas-water capillary pressure there (a pressure, a bare number
in the model’s units). source notes where the numbers come from (a loaded deck’s card,
a paper); the writer does not read it.
It writes SGWFN in a gas-water run, one table per saturation region. It is a statement of
ps.Model(relperm=[...]), at relperm/1/gas_water (saturation region n’s at
relperm/<n>/gas_water in the {region: [...]} form).
ps.relperm.Hysteresis
Section titled “ps.relperm.Hysteresis”ps.relperm.Hysteresis(*, family: Optional[Literal['carlson', 'killough']] = None, scope: Literal['relative_permeability', 'capillary_pressure', 'both'] = 'both', wetting: Literal['saturation_table', 'imbibition_table', 'fully_hysteretic'] = 'imbibition_table', capillary_pressure_scaling: bool = False, capillary_pressure_curvature: float | None = None, wetting_relperm_curvature: float | None = None, cycle_policy: Optional[Literal['alternating_slugs']] = None, lands_parameter: float | None = None, secondary_drainage_reduction: float | None = None, imbibition_linear_fraction: float | None = None, three_phase_switch_threshold: float | None = None) -> None
Relative-permeability hysteresis: the model and the WAG cycles (the whole model).
ps.relperm.Hysteresis(family="killough") turns on Killough’s hysteresis of the relative
permeability and the capillary pressure.
family selects the hysteresis model (Carlson or Killough) with its scope and
wetting curve. Of the two curvature parameters (positive, dimensionless),
capillary_pressure_curvature (EHYSTR item 1) shapes the capillary-pressure scanning
curves Flow follows whenever the scope holds the capillary pressure ("both" or
"capillary_pressure"); wetting_relperm_curvature (item 3) Flow accepts and does not
read, carried because decks state it. cycle_policy and lands_parameter state
water-alternating-gas hysteresis, with its optional secondary-drainage reduction,
imbibition linear fraction and three-phase switch threshold. A deck may state the WAG
cycles without a model (the simulator’s own default then applies), so either half may
stand alone. The imbibition curves’ end points are EndpointScaling(curve="imbibition", ...).
It writes SATOPTS HYSTER in RUNSPEC, switching hysteresis on, and EHYSTR for its model and
WAGHYSTR for its WAG cycles, in PROPS. It is stated once, in the list or in saturation
region 1’s, at relperm/1/hysteresis.
ps.relperm.JFunction
Section titled “ps.relperm.JFunction”ps.relperm.JFunction(*, phase: Literal['water', 'gas'] = 'water', surface_tension: ScalarPropertyInput, gas_oil_surface_tension: Optional[ScalarPropertyInput] = None, porosity_exponent: Optional[ScalarPropertyInput] = None, permeability_exponent: Optional[ScalarPropertyInput] = None, permeability_basis: Optional[Literal['x_direction', 'horizontal_average', 'y_direction', 'vertical', 'user_defined']] = None) -> None
Leverett J-function capillary-pressure scaling: each cell’s curve by its rock (whole model).
ps.relperm.JFunction(surface_tension=30.0) scales the oil-water capillary pressure of each
cell by its porosity and permeability, at a surface tension of 30 dyn/cm.
phase is the phase whose capillary pressure is scaled ("water", the oil-water curve,
or "gas", the gas-oil one); surface_tension the oil-water surface tension and
gas_oil_surface_tension the gas-oil one, each in dyn/cm whatever the model’s units (as
Flow reads JFUNC) and positive; porosity_exponent and permeability_exponent the
exponents of porosity and permeability in the scaling (positive), left to the simulator’s
default (0.5 each) when unstated; permeability_basis which permeability scales a cell
("x_direction", "y_direction", "vertical" or "horizontal_average", the
average of x and y and Flow’s default; "user_defined" writes U, a direction Flow
refuses).
It writes JFUNC in GRID and switches end-point scaling on (ENDSCALE). It is stated once, in
the list or in saturation region 1’s, at relperm/1/j_function.
ps.relperm.LETRelPerm
Section titled “ps.relperm.LETRelPerm”ps.relperm.LETRelPerm(*, water=None, oil=None, gas=None, capillary, source: str | None = None) -> None
A phase pair’s relperm and capillary pressure as a LET correlation (one saturation region).
The curves as LET parameters in place of a table, named by phase: the two phases stated are
the pair, water and oil (SWOFLET) or gas and oil (SGOFLET); a gas-water pair is
refused (it would write SGWFLET, which Flow does not read: state ps.relperm.GasWater).
Each curve is a mapping of its parameters: connate_saturation and
critical_saturation (saturations, 0 <= connate <= critical < 1), and lower,
elevation, top and endpoint_relperm (positive), each 1.0 unless stated.
capillary is the pair’s capillary-pressure fit: lower, elevation and top (1.0
unless stated), initial_pressure and threshold_pressure (pressures in the model’s
units, not negative, 0.0 unless stated). source says where the parameters came from, as
a table’s does. It writes one SWOFLET or SGOFLET record per saturation region and is a
statement of ps.Model(relperm=[...]), at relperm/1/let_rel_perm (saturation region
n’s at relperm/<n>/let_rel_perm in the {region: [...]} form)::
ps.relperm.LETRelPerm( water={"connate_saturation": 0.2, "critical_saturation": 0.2, "lower": 2.0}, oil={"connate_saturation": 0.1, "critical_saturation": 0.1}, capillary={"lower": 1.0, "elevation": 1.0, "top": 1.0},)ps.relperm.MaxCapillaryPressure
Section titled “ps.relperm.MaxCapillaryPressure”ps.relperm.MaxCapillaryPressure(*, maximum_pressure: ScalarPropertyInput) -> None
The largest oil-water capillary pressure the initial water saturation may scale a curve to.
ps.relperm.MaxCapillaryPressure(maximum_pressure=5.0) lets the scaling to the initial
water saturation raise a cell’s oil-water capillary pressure to 5 at most.
Where the start states its water saturation cell by cell
(ps.initial.Equilibrium(initial_water_saturation=...), SWATINIT), Flow scales each
cell’s oil-water capillary pressure to hold it; a cell whose scaled curve would rise above
this limit is held at it instead, and its initial water saturation is computed again. One
per saturation region: state one in every saturation region, or in none.
maximum_pressure is that pressure (positive, a bare number in the model’s units).
It writes PPCWMAX, one record per saturation region, and switches end-point scaling on
(ENDSCALE). It is a statement of ps.Model(relperm=[...]), at
relperm/1/max_capillary_pressure (saturation region n’s at
relperm/<n>/max_capillary_pressure in the {region: [...]} form).
ps.relperm.Oil
Section titled “ps.relperm.Oil”ps.relperm.Oil(*, so: NDArray[numpy.float64], krow: NDArray[numpy.float64], krog: NDArray[numpy.float64], source: str | None = None) -> None
Oil relative permeability in water and in gas against oil saturation (family II).
ps.relperm.Oil(so=[0.0, 0.8], krow=[0.0, 1.0], krog=[0.0, 1.0]) is the oil’s straight curve
in water and in gas, mobile above no oil.
Family II states each phase’s curve on its own: the oil’s for three phases (SOF3). It writes SOF3 wherever oil flows; in an oil-water run Flow reads its family II oil curve from SOF2 instead, which this class does not write.
Rows: (so, krow, krog). Each column is a field taking a list, a tuple or a 1-D array, one value per row, None where the simulator derives the cell; Oil.from_frame(frame) reads them from a frame by name.
so is each row’s oil saturation, krow the oil’s relative permeability in oil and
water alone, and krog in oil, gas and connate water. source notes where the numbers
come from (a loaded deck’s card, a paper); the writer does not read it.
It is a statement of ps.Model(relperm=[...]), at relperm/1/oil (saturation region
n’s at relperm/<n>/oil in the {region: [...]} form).
ps.relperm.OilWater
Section titled “ps.relperm.OilWater”ps.relperm.OilWater(*, sw: NDArray[numpy.float64], krw: NDArray[numpy.float64], krow: NDArray[numpy.float64], pcow: NDArray[numpy.float64], source: str | None = None) -> None
Oil-water relative permeability and capillary pressure against water saturation.
ps.relperm.OilWater(sw=[0.2, 0.8], krw=[0.0, 0.6], krow=[1.0, 0.0], pcow=[0.0, 0.0]) is a
pair of straight oil-water curves from a connate water saturation of 0.2.
Rows: (sw, krw, krow, pcow). Each column is a field taking a list, a tuple or a 1-D array, one value per row, None where the simulator derives the cell; OilWater.from_frame(frame) reads them from a frame by name.
sw is each row’s water saturation; krw the water’s relative permeability, krow
the oil’s in water, and pcow the oil-water capillary pressure there (a pressure, a bare
number in the model’s units). source notes where the numbers come from (a loaded deck’s
card, a paper); the writer does not read it.
It writes SWOF, one table per saturation region. It is a statement of
ps.Model(relperm=[...]), at relperm/1/oil_water (saturation region n’s at
relperm/<n>/oil_water in the {region: [...]} form).
ps.relperm.SaturationOptions
Section titled “ps.relperm.SaturationOptions”ps.relperm.SaturationOptions(*, direct: bool = False, irreversible: bool = False, surface_tension: bool = False) -> None
How the saturation-function regions are read (SATOPTS), stated once for the whole model.
ps.relperm.SaturationOptions(direct=True) lets the x, y and z relperm maps each choose the
curves of their own direction.
direct=True makes the x, y and z relperm region maps (the regions’ relperm_x,
relperm_y and relperm_z) each choose the saturation functions for flow in their own
direction: it writes SATOPTS DIRECT in RUNSPEC (beside HYSTER when the model states
hysteresis).
irreversible and surface_tension are refused by the checks
(regions.saturation_options.irreversible_unsupported,
regions.saturation_options.surface_tension_unsupported): OPM Flow supports neither.
It is stated in the list or in saturation region 1’s, at relperm/1/saturation_options.
ps.relperm.ThreePhase
Section titled “ps.relperm.ThreePhase”ps.relperm.ThreePhase(*, method: Literal['stone1', 'stone2'], exponent: Optional[ScalarPropertyInput] = None, source: str | None = None) -> None
The three-phase method: how the oil’s relative permeability comes from its two-phase curves.
ps.relperm.ThreePhase(method="stone2") takes the oil’s three-phase relative permeability by
Stone’s second method.
Stone’s first method ("stone1", STONE1) or his second ("stone2", STONE2), in any
case; a model that states none takes the simulator’s default. A saturation region’s
statement: in the {region: [...]} form every region states it, all with one method.
exponent is Stone I’s exponent for the region (STONE1EX, dimensionless and positive),
stated in every region or in none, and only with "stone1".
method is the method’s word. source notes where the numbers come from (a loaded
deck’s card, a paper); the writer does not read it.
It is a statement of ps.Model(relperm=[...]), at relperm/1/three_phase (saturation
region n’s at relperm/<n>/three_phase in the {region: [...]} form).
ps.relperm.Water
Section titled “ps.relperm.Water”ps.relperm.Water(*, sw: NDArray[numpy.float64], krw: NDArray[numpy.float64], pc: NDArray[numpy.float64] | None = None, source: str | None = None) -> None
Water relative permeability and capillary pressure against water saturation (family II).
ps.relperm.Water(sw=[0.2, 1.0], krw=[0.0, 1.0]) is a straight water curve from a connate
saturation of 0.2.
Family II states each phase’s curve on its own (SWFN). Without pc, in a gas-water
system the curve is the storage system’s water curve (WSF), beside its gas curve;
elsewhere it writes SWFN with pc 0.
Rows: (sw, krw, pc). Each column is a field taking a list, a tuple or a 1-D array, one value per row, None where the simulator derives the cell; Water.from_frame(frame) reads them from a frame by name.
sw is each row’s water saturation, krw the water’s relative permeability and pc
the oil-water capillary pressure there, or in a gas-water system the gas-water one, which
Flow reads from this curve beside an SGFN gas curve (a pressure, a bare number in the
model’s units). source notes where the numbers come from (a loaded deck’s card, a
paper); the writer does not read it.
It is a statement of ps.Model(relperm=[...]), at relperm/1/water (saturation region
n’s at relperm/<n>/water in the {region: [...]} form).
PetroScript is licensed under the Apache License 2.0. © 2026 Blauweiss EDV LLC. PetroScript by Blauweiss AI.For AI agents: llms.txt