Skip to content

ps.groups

ps.groups.Branch() -> None

A pipeline of the extended production network, from one node to the next (BRANPROP).

ps.groups.Branch(name="b1", from_node=inlet, to_node=sink, uses_no_pressure_loss=True) carries the production of the node inlet to sink with no pressure drop.

The pressure drop along it is read from lift_table (a ps.lift.ProductionTable), or is none (uses_no_pressure_loss), or the branch is out of the network (is_disabled). A branch is held in ps.groups.Network(branches=[...]), its address network/branches/<n>, counted from 1.

ps.groups.Economics(*, group: Group, minimum_oil_rate: Optional[ScalarPropertyInput] = None, minimum_gas_rate: Optional[ScalarPropertyInput] = None, maximum_water_cut: Optional[ScalarPropertyInput] = None, maximum_gas_oil_ratio: Optional[ScalarPropertyInput] = None, maximum_water_gas_ratio: Optional[ScalarPropertyInput] = None) -> None

A group’s economic limits (GECON): the rates and ratios its production is tested against.

ps.groups.Economics(group=north, minimum_oil_rate=50.0, maximum_water_cut=0.95) tests north against an oil rate of 50 and a water cut of 0.95.

Each stated limit is a threshold the group’s production is tested against; an unstated one is left to the simulator. At least one is stated, each positive. In Flow, an oil or gas rate below its minimum closes every well under the group; a ratio past its maximum calls for a workover, which the card states as none, so Flow takes no action on it. It is stated in ps.Event(date, ...), at schedule/<date>/<group>/economics. The rates are surface rates and the gas-oil and water-gas ratios surface ratios, in the model’s units; the water cut is a fraction.

ps.groups.Efficiency(*, group: Group, factor: ScalarPropertyInput, network_propagation: Optional[Literal['apply_factor', 'ignore_factor']] = None) -> None

A group’s efficiency (up-time) factor (GEFAC): the fraction of the time it flows.

ps.groups.Efficiency(group=north, factor=0.95) counts the rates of north, a group down 5% of the time, at 95% where they are summed into its parent and its cumulatives.

It is stated in ps.Event(date, ...), at schedule/<date>/<group>/efficiency, and holds from that date; factor is positive and dimensionless.

ps.groups.FuelGas(*, group: Group, intent: Literal['rate', 'fraction_of_produced'], consumption_rate: Optional[ScalarPropertyInput] = None, produced_gas_fraction: Optional[ScalarPropertyInput] = None) -> None

A group’s fuel gas (GCONSUMP): the gas it consumes, taken from what it produces.

ps.groups.FuelGas(group=north, intent="rate", consumption_rate=5000.0) burns 5000 of the gas north produces as fuel, a surface gas rate in the model’s units.

intent="fraction_of_produced" states a fraction instead (produced_gas_fraction=0.05), written as GCONSUMP item 2’s negative value (-0.05). Flow 2026.04 reads item 2 as a gas rate only (opm-common’s GConSump), so it takes that value as a consumption rate of -0.05, not as 5% of the group’s gas. It is stated in ps.Event(date, ...), at schedule/<date>/<group>/fuel_gas.

ps.groups.GasLift(*, well, enabled: bool = True, maximum_lift_gas_rate: Optional[ScalarPropertyInput] = None, weight_factor: Optional[ScalarPropertyInput] = None, minimum_lift_gas_rate: Optional[ScalarPropertyInput] = None, gas_factor: Optional[ScalarPropertyInput] = None, enforce_gas_limit: bool | None = None) -> None

A well’s part in gas-lift optimization (WLIFTOPT): whether and how much lift gas it gets.

ps.groups.GasLift(well="P1", maximum_lift_gas_rate=50000.0) lets the lift optimizer give P1 up to 50000 of lift gas.

enabled=False holds the well’s lift gas fixed at maximum_lift_gas_rate instead, or, with no maximum_lift_gas_rate, where it stands. Enabled with no maximum_lift_gas_rate, the most the optimizer gives the well is the largest lift-gas value of the well’s ps.lift.ProductionTable. It holds the well by its name (well="P1"; a ps.Well given is read by its name). It is stated in ps.Event(date, ...), at schedule/<date>/<well>/gas_lift; the lift-gas rates are gas rates in the model’s units.

ps.groups.GasLiftOptimization(*, scope: Literal['field', 'group', 'well'], group: Group | None = None, well=None, maximum_lift_gas_rate: Optional[ScalarPropertyInput] = None, maximum_total_gas_rate: Optional[ScalarPropertyInput] = None, incremental_gas_rate: Optional[ScalarPropertyInput] = None, minimum_economic_gradient: Optional[ScalarPropertyInput] = None, optimization_interval: Optional[ScalarPropertyInput] = None, use_newton: bool | None = None) -> None

Gas-lift optimization: how the field’s lift gas is shared out, and a group’s or well’s cap.

ps.groups.GasLiftOptimization(scope="field", incremental_gas_rate=10000.0, minimum_economic_gradient=0.001) shares the field’s lift gas out in steps of 10000 while each step still gains 0.001 of oil per unit of gas.

scope says what is stated: "field" the optimization itself (LIFTOPT); "group" a group’s limits on lift gas (GLIFTOPT), which Flow refuses unless a LIFTOPT stands before it, so the field’s scope is stated at or before the group’s date; "well" a well’s largest lift gas (WLIFTOPT), as ps.groups.GasLift states it. A well’s scope holds the well by its name (well="P1"; a ps.Well given is read by its name). It is stated in ps.Event(date, ...), at schedule/<date>/gas_lift_optimization for the field and schedule/<date>/<group or well>/gas_lift_optimization otherwise. The rates are gas rates in the model’s units.

ps.groups.GasSales(*, group: Group, sales_rate: ScalarPropertyInput, maximum_rate: Optional[ScalarPropertyInput] = None, minimum_rate: Optional[ScalarPropertyInput] = None, action: Literal['none', 'reduce_group_gas_rate'] = 'none') -> None

A group’s gas sales target (GCONSALE): the gas it sells, the surplus re-injected.

ps.groups.GasSales(group=north, sales_rate=500000.0, maximum_rate=600000.0, action="reduce_group_gas_rate") sells the gas of north at 500000 and re-injects the surplus; past 600000 its gas production is cut.

It is stated in ps.Event(date, ...), at schedule/<date>/<group>/gas_sales; the rates are surface gas rates in the model’s units.

ps.groups.GuideRates(*, phase: Literal['total_rate', 'oil', 'water', 'gas', 'liquid', 'formula'], minimum_interval: ScalarPropertyInput = 0, potential_exponent: ScalarPropertyInput, denominator_constant: ScalarPropertyInput, ratio1_coefficient: ScalarPropertyInput, ratio1_exponent: ScalarPropertyInput, ratio2_coefficient: ScalarPropertyInput, ratio2_exponent: ScalarPropertyInput, incremental: bool = True, damping_factor: Optional[ScalarPropertyInput] = None, use_free_gas_only: bool | None = None, minimum_guide_rate: Optional[ScalarPropertyInput] = None) -> None

The guide-rate formula (GUIDERAT): how a group’s target is shared among its producers.

ps.groups.GuideRates(phase="oil", potential_exponent=1.0, denominator_constant=1.0, ratio1_coefficient=0.5, ratio1_exponent=1.0, ratio2_coefficient=0.0, ratio2_exponent=0.0) weighs each well’s oil potential down as its water-oil ratio rises.

A guide rate is pA / (B + C*wD + E*g**F), p the potential of phase and w and g the water and gas ratios read against it (for "gas", w is the water-gas ratio and g the oil-gas ratio); A to F are potential_exponent, denominator_constant, ratio1_coefficient, ratio1_exponent, ratio2_coefficient and ratio2_exponent, each dimensionless. Flow gives every producer with no guide rate of its own (ps.wells.GuideRate) its guide rate by the formula, and every group whose ps.groups.ProductionTarget(guide_phase=) is "formula"; injectors take none from it. It is stated in ps.Event(date, ...), at schedule/<date>/guide_rates, and minimum_interval is in days in every unit system.

Flow runs the formula of "oil" or "gas" only. "water" and "total_rate" write GUIDERAT’s WAT and RAT, which m.check() passes and Flow refuses when it loads the deck; "liquid" and "formula" have no GUIDERAT word, m.check() passes them too, and ps.compile refuses them with a plain ValueError whose message starts [target.choice.unknown]: not a ps.PetroScriptError, with no .code.

The six coefficients A to F are stated, never assumed: Flow’s own default for each is 0, which leaves the denominator at zero, where Flow sets every guide rate to zero with a warning (GuideRateModel::eval), so no default stands for “the formula the author meant”; a loaded GUIDERAT states all six, as a deck must.

ps.groups.InjectionTarget(*, group: Group, phase: Literal['oil', 'water', 'gas'], rate: Union[ScalarPropertyInput, Expression, NoneType] = None, reservoir_volume: Union[ScalarPropertyInput, Expression, NoneType] = None, reinjection_fraction: Union[ScalarPropertyInput, Expression, NoneType] = None, voidage_replacement: Union[ScalarPropertyInput, Expression, NoneType] = None, control: Optional[Literal['parent']] = None, rate_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, reservoir_volume_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, reinjection_fraction_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, voidage_replacement_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, available_to_parent: bool | None = None, guide_rate: Optional[ScalarPropertyInput] = None, guide_basis: Optional[Literal['net_voidage', 'rate', 'reservoir_volume', 'voidage']] = None, reinjection_source_group: Group | None = None, voidage_source_group: Group | None = None, phase_word: str | None = None) -> None

A group’s injection control of phase (GCONINJE), a well’s ps.Inject rule.

The one quantity given bare is the group’s target: rate (the phase’s surface rate), reservoir_volume, reinjection_fraction (of the gas or water the group produces) or voidage_replacement (of the voidage it produces); a reinjection or voidage target takes the others below it as limits (rate_limit, …)::

ps.groups.InjectionTarget(group=field, phase="water", voidage_replacement=1.0)

control="parent" puts the group under its parent’s control, its quantities limits; a group that states no target and no control holds its limits alone. available_to_parent says whether a parent group may set the group’s rate from its guide rate.

It is stated in ps.Event(date, ...), at schedule/<date>/<group>/injection_target, and holds from that date. In the model’s units, rate is a surface rate of phase and reservoir_volume a reservoir rate; reinjection_fraction and voidage_replacement are dimensionless. A target may be a ps.actions.UserQuantity the run evaluates.

ps.groups.Network() -> None

The production network: its nodes and the pipelines between them, to a terminal pressure.

ps.groups.Network(name="n1", nodes=[inlet, sink], branches=[branch]) is an extended network of two nodes and the branch between them; ps.Model(network=) holds it from the start.

An extended network (kind="extended") states its own nodes and branches (NETWORK in RUNSPEC, BRANPROP, NODEPROP, NEFAC); a standard one (kind="standard") is the group tree’s pipelines, one node per group (GRUPNET). Its address is network (network/nodes/<n>, network/branches/<n>). A model with a network flows oil, water and gas, or it is refused (schedule.networks.requires_three_phases).

ps.groups.Node() -> None

A node of the production network, where pipelines meet; a terminal one holds a pressure.

ps.groups.Node(name="N1", terminal_pressure=20.0) is a terminal node held at a pressure of 20; a ps.groups.Branch joins two nodes.

An extended network writes its nodes in NODEPROP (and their efficiencies in NEFAC); a standard one writes one node per group in GRUPNET. A node is held in ps.groups.Network(nodes=[...]), its address network/nodes/<n>, counted from 1. terminal_pressure is in the model’s pressure unit.

ps.groups.PressureMaintenance(*, group: Group, intent: Literal['gas_injection', 'oil_injection', 'water_injection', 'production', 'disabled'], region: int, fluid_in_place_set: str | None = None, basis: Optional[Literal['gas_reservoir_injection', 'gas_surface_injection', 'oil_reservoir_injection', 'oil_surface_injection', 'production_reservoir_volume', 'water_reservoir_injection', 'water_surface_injection']] = None, pressure: Optional[ScalarPropertyInput] = None, alpha: Optional[ScalarPropertyInput] = None, beta: Optional[ScalarPropertyInput] = None) -> None

A group maintaining a fluid-in-place region’s average pressure (GPMAINT).

region is held at pressure by adjusting the group’s flow basis names, with the controller’s constants alpha and beta. A region is named by its number: in the model’s fluid-in-place map (ps.Regions(fluid_in_place=)), or in the set fluid_in_place_set names (a key of ps.Regions(fluid_in_place_sets=)); 0 is the whole field::

ps.groups.PressureMaintenance(
group=field, intent="water_injection", basis="water_surface_injection",
region=2, fluid_in_place_set="ABC", pressure=250.0, alpha=70.0, beta=90.0,
)

In the model’s units, pressure is the target pressure, alpha the controller’s proportional constant (a reservoir-volume rate per unit pressure, the rate per day, or per hour in a lab model) and beta its integral time constant, in days, or in hours in a lab model, as GPMAINT reads them. All three are stated, each positive, unless intent is "disabled", which stops the maintenance and takes no basis. It is stated in ps.Event(date, ...), at schedule/<date>/<group>/pressure_maintenance.

ps.groups.ProductionTarget(*, group: Group, oil_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, water_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, gas_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, liquid_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, reservoir_volume: Union[ScalarPropertyInput, Expression, NoneType] = None, control: Optional[Literal['parent']] = None, oil_rate_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, water_rate_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, gas_rate_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, liquid_rate_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, reservoir_volume_limit: Union[ScalarPropertyInput, Expression, NoneType] = None, on_violation: Optional[Literal['none', 'shut_worst_well', 'rate']] = None, on_water_violation: Optional[Literal['none', 'rate']] = None, on_gas_violation: Optional[Literal['none', 'rate']] = None, on_liquid_violation: Optional[Literal['none', 'rate']] = None, available_to_parent: bool | None = None, guide_rate: Optional[ScalarPropertyInput] = None, guide_phase: Optional[Literal['oil', 'water', 'gas', 'liquid', 'formula']] = None) -> None

A group’s production control (GCONPROD), the control rule of a well’s ps.Produce.

The one quantity given bare is the group’s target, and every other quantity is a limit (water_rate_limit, …)::

ps.groups.ProductionTarget(group=north, oil_rate=5000.0, water_rate_limit=2000.0)

control="parent" puts the group under its parent’s control: the parent sets the target, so every stated quantity is a limit. A group that states no target and no control holds its limits alone. available_to_parent says whether a parent group may set the group’s rate from its guide rate.

It is stated in ps.Event(date, ...), at schedule/<date>/<group>/production_target, and holds from that date. In the model’s units, oil_rate, water_rate, gas_rate and liquid_rate and their limits are surface rates and reservoir_volume a reservoir rate; a target may be a ps.actions.UserQuantity the run evaluates.

ps.groups.Satellite(*, group: Group, oil_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, water_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, gas_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, reservoir_volume: Union[ScalarPropertyInput, Expression, NoneType] = None, lift_gas_rate: Union[ScalarPropertyInput, Expression, NoneType] = None, phase: Optional[Literal['oil', 'water', 'gas']] = None, rate: Union[ScalarPropertyInput, Expression, NoneType] = None) -> None

A satellite group’s production or injection from this date (GSATPROD, GSATINJE).

Its rates are stated, not simulated.

ps.groups.Satellite(group=sat, oil_rate=500.0) states the group’s production rates (oil_rate, water_rate, gas_rate, reservoir_volume, lift_gas_rate); ps.groups.Satellite(group=sat, phase="gas", rate=2e6) its injection of one phase.

A statement holds a production or an injection, never both. It is stated in ps.Event(date, ...), at schedule/<date>/<group>/satellite. The rates are surface rates in the model’s units (reservoir_volume a reservoir rate), each positive.

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