Skip to content

ps.initial

ps.initial.CompositionVsDepth(*, depth: NDArray[numpy.float64], mole_fraction: dict[str, NDArray[numpy.float64]]) -> None

Overall mole fractions against depth, for one equilibration region.

ps.initial.CompositionVsDepth(depth=[2400.0, 2600.0], mole_fraction={"CO2": [0.01, 0.02], "C1": [0.70, 0.68], "C10": [0.29, 0.30]}).

depth is the depths, strictly rising, in the model’s units, and mole_fraction each component’s mole fraction at each depth, by the component’s name, one column per component and one value per depth. Each fraction is from 0 to 1, and the fractions at each depth sum to 1 within 1e-6. A uniform composition is a one-depth table. It writes ZMFVD (PROPS), the fractions in its holder’s component order. ps.storage.Package(initial_composition=...) holds it, at physics/storage/initial_composition; ps.load reads it back.

ps.initial.ConstantTemperature(*, temperature: ScalarPropertyInput) -> None

The reservoir’s initial temperature, the same in every cell (RTEMP).

ps.initial.ConstantTemperature(temperature=80.0) starts every cell at 80 degrees.

temperature is a temperature, a bare number in the model’s units (degF in FIELD, degC in METRIC and LAB). A thermal model (ps.thermal.Package(initial_temperature=), at physics/thermal/initial_temperature) and a storage package (ps.storage.Package(temperature=), at physics/storage/temperature) state it, as they state a TemperatureVsDepth; it writes RTEMP in SOLUTION.

ps.initial.Equilibrium(*, datum_depth: ScalarPropertyInput, datum_pressure: ScalarPropertyInput, oil_water_contact: Optional[ScalarPropertyInput] = None, gas_water_contact: Optional[ScalarPropertyInput] = None, gas_oil_contact: Optional[ScalarPropertyInput] = None, solution_gor_by_depth: RsVsDepth | None = None, vaporized_oil_by_depth: RvVsDepth | None = None, bubble_point_by_depth: PbVsDepth | None = None, dew_point_by_depth: PdVsDepth | None = None, vaporized_water_by_depth: RvwVsDepth | None = None, temperature_by_depth: TemperatureVsDepth | None = None, composition_by_depth: CompositionVsDepth | None = None, report_datum_depth: Union[ScalarPropertyInput, tuple[ScalarPropertyInput, ...], collections.abc.Mapping[str, tuple[ScalarPropertyInput, ...]], NoneType] = None, threshold_pressures: tuple[ThresholdPressure, ...] = (), vaporization_controls: VaporizationControls | None = None, initial_water_saturation=None, oil_water_capillary_pressure: ScalarPropertyInput = 0, gas_oil_capillary_pressure: ScalarPropertyInput = 0, use_dissolved_gas_table: bool | None = None, use_vaporized_oil_table: bool | None = None, use_vaporized_water_table: bool | None = None, accuracy: Optional[ScalarPropertyInput] = None, pressure_table_points: int | None = None, source: str | None = None) -> None

The initial state in equilibrium: the datum, the contacts and the depth tables.

The simulator starts the reservoir in gravity equilibrium: it takes the pressure at one depth and integrates each phase’s pressure up and down the column, with the contacts splitting the phases.

  • datum_depth and datum_pressure: one depth and the pressure there (ft and psia in FIELD, m and barsa in METRIC).
  • oil_water_contact for a column with an oil leg, or gas_water_contact for a gas column over water: one of the two (both is refused); a water-only model states neither.
  • gas_oil_contact: the top of the oil leg. Required wherever gas and oil both flow ([initialization.equil.required_value]); a model with no gas cap states it above the reservoir’s top.
  • solution_gor_by_depth (ps.initial.RsVsDepth) or bubble_point_by_depth (ps.initial.PbVsDepth): how much gas a live oil holds at each depth. A live oil needs one, unless the datum is at the gas-oil contact ([physics.initial.depth_table_missing], [physics.initial.datum_off_gas_oil_contact]).
  • initial_water_saturation: a fraction, one value, one per layer or a full array.

Common mistake: a datum pressure typed in the other unit system (psi into a METRIC model). m.check() then warns at initial/1/datum_pressure ([physics.pressure_gradient.other_unit]).

One Equilibrium states every equilibration region, or initial={region: Equilibrium} states one per region (numbered from 1), the statements that hold for the whole model (threshold_pressures, initial_water_saturation, vaporization_controls, report_datum_depth, pressure_table_points) on region 1’s. Each depth and pressure is a bare number in the model’s units, or a ps.Quantity.

It writes EQUIL in SOLUTION with the depth tables it states (RSVD, RVVD, PBVD, PDVD, RVWVD, and RTEMPVD while no thermal or storage package states the temperature), DATUM, DATUMR or DATUMRX for report_datum_depth, VAPPARS for vaporization_controls, the thresholds’ THPRES (THPRESFT in GRID), SWATINIT in PROPS for initial_water_saturation and EQLDIMS item 2 for pressure_table_points. An equation-of-state fluid’s composition_by_depth writes ZMFVD in PROPS, one table per equilibration region. It is ps.Model(initial=...), at initial/1 (region n’s at initial/<n> in the per-region form), each field below it: initial/1/datum_pressure.

An oil column with a gas cap above 2400 m and water below 2600 m, at 250 barsa at 2500 m: ps.initial.Equilibrium(datum_depth=2500.0, datum_pressure=250.0, oil_water_contact=2600.0, gas_oil_contact=2400.0). The quickstart’s gas field over water:

import petroscript as ps state = ps.initial.Equilibrium(datum_depth=2420.0, datum_pressure=250.0, # m, barsa … gas_water_contact=2450.0) # m state.gas_water_contact # ps.Model(initial=state), at initial/1 2450.0

A live oil under a gas cap, its dissolved gas by depth (FIELD: ft, psia, Mscf/stb):

live = ps.initial.Equilibrium( … datum_depth=8400.0, datum_pressure=4800.0, oil_water_contact=8450.0, … gas_oil_contact=8200.0, … solution_gor_by_depth=ps.initial.RsVsDepth(depth=[8200.0, 8450.0], … solution_gor=[1.27, 1.27]))

ps.initial.ExplicitState(*, pressure, water_saturation=None, vaporized_water_gas_ratio=None, gas_saturation=None, oil_saturation=None, solution_gor=None, solution_gas_water_ratio=None, vaporized_oil_gas_ratio=None, temperature=None, mole_fraction=None) -> None

The initial state stated cell by cell instead of an equilibrium.

ps.initial.ExplicitState(pressure=[248.0, 250.0, 252.0], water_saturation=0.2) starts each layer at its own pressure and every cell at a water saturation of 0.2.

The pressure, and the saturations and solution ratios a run states with it, each named as a run’s cell arrays name it (run.initial["gas_saturation"] states gas_saturation=), and each a single value, one value per layer (pressure=[4790.0, 4800.0, 4810.0], held in every cell of its layer) or a full (nx, ny, nz) array. pressure is a pressure (a bare number in the model’s units, or a ps.Quantity), the saturations fractions of the pore volume, and the ratios and temperature bare numbers in the model’s units. mole_fraction is an equation-of-state fluid’s overall mole fraction of each component, by its name, each cell’s summing to 1 within 1e-6 (a component left unstated is 0).

Each array writes its own card in SOLUTION: PRESSURE, SWAT, SGAS, SOIL, RS, RSW, RV, RVW, TEMPI and ZMF (component-major, in the component table’s order). It is ps.Model(initial=...), at initial, each field below it: initial/pressure.

ps.initial.PbVsDepth(*, source: str | None = None, depth: NDArray[numpy.float64], bubble_point_pressure: NDArray[numpy.float64]) -> None

The bubble-point pressure against depth (PBVD), one equilibration region.

ps.initial.PbVsDepth(depth=[2400.0, 2600.0], bubble_point_pressure=[230.0, 240.0]) starts the oil at a bubble point of 230 at 2400 and 240 at 2600.

depth is each row’s depth (a length) and bubble_point_pressure the oil’s bubble-point pressure there (a pressure), bare numbers 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 PBVD in SOLUTION (one Equilibrium’s table for each of its equilibration regions). Flow reads it as it reads RSVD, while the Equilibrium’s use_dissolved_gas_table is True. It is the bubble_point_by_depth of a ps.initial.Equilibrium, at initial/1/bubble_point_by_depth.

Rows: (depth, bubble_point_pressure). Each column is a field taking a list, a tuple or a 1-D array, one value per row; PbVsDepth.from_frame(frame) reads them from a frame by name.

ps.initial.PdVsDepth(*, source: str | None = None, depth: NDArray[numpy.float64], dew_point_pressure: NDArray[numpy.float64]) -> None

The dew-point pressure against depth (PDVD), one equilibration region.

ps.initial.PdVsDepth(depth=[2400.0, 2600.0], dew_point_pressure=[230.0, 240.0]) starts the gas at a dew point of 230 at 2400 and 240 at 2600.

depth is each row’s depth (a length) and dew_point_pressure the gas’s dew-point pressure there (a pressure), bare numbers 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 PDVD in SOLUTION (one Equilibrium’s table for each of its equilibration regions). Flow reads it as it reads RVVD, while the Equilibrium’s use_vaporized_oil_table is True. It is the dew_point_by_depth of a ps.initial.Equilibrium, at initial/1/dew_point_by_depth.

Rows: (depth, dew_point_pressure). Each column is a field taking a list, a tuple or a 1-D array, one value per row; PdVsDepth.from_frame(frame) reads them from a frame by name.

ps.initial.Restart(*, case: Annotated[str, Strict(strict=True)], step: Union[Annotated[int, Strict(strict=True)], DayInput], content_hash: Optional[Annotated[str, Strict(strict=True)]] = None, initial_water_saturation=None, skip_history: bool = True, threshold_pressures: Union[tuple[ThresholdPressure, ...], Literal['restart_file']] = ()) -> None

The initial state read from a previous run’s restart file.

ps.initial.Restart(case="history", step="2025-01-01") starts from the state the run named history wrote on that date. Writes RESTART, and SKIPREST when skip_history.

case names the run that wrote the file: its deck root name, optionally under a relative directory (both pinned OPM Flow releases resolve it relative to the deck), never an absolute path or a file name. step is the point on that file: a report-step number (the deck’s RSNUM), or a day (a date or its text, '2025-01-01'), resolved against this model’s schedule. The simulator reads the state; PetroScript only states which case and which point, and no restart file is opened here or anywhere else in the library. content_hash is provenance recorded at import when the referenced file happens to be readable; it makes drift detectable and is never load-bearing.

initial_water_saturation is the whole-grid array of manual 8.3.342: a PROPS declaration that re-scales the capillary pressure curves and is sized by the model’s own dimensions, so it is stated beside a restart the same way it is stated beside contacts. Whether the referenced file holds the scaled pressures this needs is the simulator’s to answer: OPM Flow stops the run when they are missing, naming the vector it wanted.

skip_history says which of the two restart postures this run takes, and it is not derivable from the restart alone. Stated (SKIPREST, manual 12.3.221) the schedule IS the history and the simulator walks it up to the restart point, so the schedule has to reach it. Unstated, the schedule is a CONTINUATION the simulator appends after the restart point, and its own length says nothing about which points are reachable. Both postures were measured on both pinned releases from one parent run: with the keyword, a schedule that stops short fails; without it, the same short schedule runs and the log counts the restart point plus the schedule’s own steps.

It writes RESTART (the case and the report step), SKIPREST at the head of the schedule while skip_history holds, SWATINIT for initial_water_saturation and, for threshold_pressures, EQLOPTS THPRES with THPRES rows ("restart_file": EQLOPTS THPRES alone). It is ps.Model(initial=...), at initial, each field below it: initial/case.

ps.initial.RsVsDepth(*, source: str | None = None, depth: NDArray[numpy.float64], solution_gor: NDArray[numpy.float64]) -> None

The initial solution gas-oil ratio against depth (RSVD), one equilibration region.

ps.initial.RsVsDepth(depth=[2400.0, 2600.0], solution_gor=[120.0, 100.0]) starts the oil with 120 of dissolved gas at 2400 and 100 at 2600.

depth is each row’s depth (a length) and solution_gor the oil’s dissolved gas-oil ratio there (surface gas per surface oil), bare numbers 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 RSVD in SOLUTION (one Equilibrium’s table for each of its equilibration regions), and Flow reads it while the Equilibrium’s use_dissolved_gas_table is True, which stating the table makes it unless the flag is stated. It is the solution_gor_by_depth of a ps.initial.Equilibrium, at initial/1/solution_gor_by_depth.

Rows: (depth, solution_gor). Each column is a field taking a list, a tuple or a 1-D array, one value per row; RsVsDepth.from_frame(frame) reads them from a frame by name.

ps.initial.RvVsDepth(*, source: str | None = None, depth: NDArray[numpy.float64], vaporized_oil_gas_ratio: NDArray[numpy.float64]) -> None

The initial vaporized oil-gas ratio against depth (RVVD), one equilibration region.

ps.initial.RvVsDepth(depth=[2400.0, 2600.0], vaporized_oil_gas_ratio=[1.0e-4, 0.5e-4]) starts the gas carrying 1e-4 of oil at 2400 and 0.5e-4 at 2600.

depth is each row’s depth (a length) and vaporized_oil_gas_ratio the gas’s vaporized oil-gas ratio there (surface oil per surface gas), bare numbers 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 RVVD in SOLUTION (one Equilibrium’s table for each of its equilibration regions), and Flow reads it while the Equilibrium’s use_vaporized_oil_table is True, which stating the table makes it unless the flag is stated. It is the vaporized_oil_by_depth of a ps.initial.Equilibrium, at initial/1/vaporized_oil_by_depth.

Rows: (depth, vaporized_oil_gas_ratio). Each column is a field taking a list, a tuple or a 1-D array, one value per row; RvVsDepth.from_frame(frame) reads them from a frame by name.

ps.initial.RvwVsDepth(*, source: str | None = None, depth: NDArray[numpy.float64], vaporized_water_gas_ratio: NDArray[numpy.float64]) -> None

The initial vaporized water-gas ratio against depth (RVWVD), one equilibration region.

ps.initial.RvwVsDepth(depth=[2400.0, 2600.0], vaporized_water_gas_ratio=[2.0e-5, 2.0e-5]) starts the gas carrying 2e-5 of water at every depth.

depth is each row’s depth (a length) and vaporized_water_gas_ratio the gas’s vaporized water-gas ratio there (surface water per surface gas), bare numbers 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 RVWVD in SOLUTION (one Equilibrium’s table for each of its equilibration regions), and Flow reads it while the Equilibrium’s use_vaporized_water_table is True, which stating the table makes it unless the flag is stated. It is the vaporized_water_by_depth of a ps.initial.Equilibrium, at initial/1/vaporized_water_by_depth.

Rows: (depth, vaporized_water_gas_ratio). Each column is a field taking a list, a tuple or a 1-D array, one value per row; RvwVsDepth.from_frame(frame) reads them from a frame by name.

ps.initial.TemperatureVsDepth(*, depth: NDArray[numpy.float64], temperature: NDArray[numpy.float64]) -> None

The initial reservoir temperature against depth (RTEMPVD), one equilibration region.

ps.initial.TemperatureVsDepth(depth=[2000.0, 3000.0], temperature=[80.0, 110.0]) starts the region at 80 degrees at a depth of 2000 and 110 at 3000, interpolated between.

depth (a length, not falling from row to row) and temperature (a temperature) are bare numbers in the model’s units. It writes RTEMPVD in SOLUTION, one table for each equilibration region; ps.load reads TEMPVD, its other name, as RTEMPVD. A thermal model (ps.thermal.Package(initial_temperature=), at physics/thermal/initial_temperature) or a storage package (ps.storage.Package(temperature=), at physics/storage/temperature) states it; a run with neither states it on its equilibrium, ps.initial.Equilibrium(temperature_by_depth=), at initial/1/temperature_by_depth, which is written only while no package states a temperature.

Rows: (depth, temperature). Each column is a field taking a list, a tuple or a 1-D array, one value per row; TemperatureVsDepth.from_frame(frame) reads them from a frame by name.

ps.initial.ThresholdPressure(*, from_region: Optional[Annotated[int, Strict(strict=True)]] = None, to_region: Optional[Annotated[int, Strict(strict=True)]] = None, fault: str | None = None, pressure: Optional[ScalarPropertyInput] = None) -> None

Threshold pressure between two equilibration regions, or across a fault.

ps.initial.ThresholdPressure(from_region=1, to_region=2, pressure=5.0): no flow crosses between equilibration regions 1 and 2 until the potential difference passes 5.

A stated pressure (a pressure: a bare number in the model’s units, or a ps.Quantity) is the potential difference that must be exceeded before flow crosses: between the regions from_region and to_region (THPRES), or across the fault fault names (THPRESFT, one of the model’s ps.Fault names). A threshold states one of the two. On a region pair, leaving it unstated asks the simulator to derive the threshold from the initial conditions instead, which is a different declaration from a stated zero: a computed threshold initially isolates the pair, while zero leaves it open. A fault’s threshold is always stated, and not negative: Flow derives none across a fault. Both forms sit in one list, the threshold_pressures of ps.initial.Equilibrium (region 1’s in the per-region form) or of ps.initial.Restart.

A region pair writes a THPRES row in SOLUTION and switches the thresholds on (EQLOPTS THPRES in RUNSPEC); a fault writes a THPRESFT row in GRID. The n-th of the list is at initial/1/threshold_pressures/<n> (a restart’s at initial/threshold_pressures/<n>).

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