Skip to content

ps.wells

ps.wells.AICD(*, well, segment: int, end_segment: int | None = None, strength: Optional[ScalarPropertyInput] = None, length: Optional[ScalarPropertyInput] = None, calibration_density: Optional[ScalarPropertyInput] = None, calibration_viscosity: Optional[ScalarPropertyInput] = None, emulsion_critical_fraction: float | None = None, emulsion_transition_width: float | None = None, maximum_emulsion_ratio: float | None = None, scaling_mode: int | None = None, calibration_rate: Optional[ScalarPropertyInput] = None, status: Optional[Literal['open', 'shut']] = None, flow_rate_exponent: float | None = None, viscosity_exponent: float | None = None, density_mixture_exponents: dict[typing.Literal['oil', 'water', 'gas'], float] | None = None, viscosity_mixture_exponents: dict[typing.Literal['oil', 'water', 'gas'], float] | None = None, density_exponent: float | None = None) -> None

An autonomous inflow-control device on a segment, or each of a range (WSEGAICD).

ps.wells.AICD(well="P1", segment=5, strength=0.0002, length=10.0, calibration_density=1000.0, calibration_viscosity=1.0, flow_rate_exponent=2.1, viscosity_exponent=0.5) puts an autonomous inflow-control device on segment 5 of P1.

Beside a spiral device’s fields it states how its pressure drop scales: the flow-rate and viscosity exponents, and optionally the density exponent and the per-phase mixture exponents of density and viscosity, a mapping by phase (density_mixture_exponents={"oil": 1.0, "water": 1.0, "gas": 1.0}).

A device is written with strength, length, calibration_density, calibration_viscosity, flow_rate_exponent and viscosity_exponent: the constructor takes one without them, and ps.compile refuses it, and refuses a device on a well whose ps.wells.Segments the model does not state. For a well introduced after the start, a device it is introduced with is stated in the start’s Event, written with the well’s own block; stated after the start, on or before the date the well is introduced, it is refused (schedule.event.start_only). The address is schedule/<date>/<well>/aicd. The numbers are in the model’s units, strength a pressure * time2 / (volume2 * density), the dimension Flow reads WSEGAICD item 4 in (the time a day, an hour in a lab model; the volume a geometric volume, cubic feet in a field model); the exponents are dimensionless.

ps.wells.ControlDefaults(*, producer_bhp: Union[ScalarPropertyInput, Expression], injector_bhp: Union[ScalarPropertyInput, Expression]) -> None

The bottom-hole pressure a well control that states none takes from here on (FBHPDEF).

ps.wells.ControlDefaults(producer_bhp=50.0, injector_bhp=400.0) gives a control that states no bottom-hole pressure 50 for a producer and 400 for an injector, from this date.

producer_bhp is a producer’s BHP target and injector_bhp an injector’s BHP limit, both stated, in the model’s pressure unit. It is stated in ps.Event(date, ...), at schedule/<date>/control_defaults.

ps.wells.Cycling(*, well, injection_period: ScalarPropertyInput, shut_period: ScalarPropertyInput, ramp_up_period: Optional[ScalarPropertyInput] = None, maximum_timestep: Optional[ScalarPropertyInput] = None, respect_windows: bool = True) -> None

The selected wells’ cycle of open and shut periods from this date (WCYCLE).

ps.wells.Cycling(well="I1", injection_period=30.0, shut_period=10.0) injects through I1 for 30 days, shuts it for 10, and repeats.

Flow cycles any well, producer or injector: injection_period is how long each cycle keeps it open. The periods are in days in every unit system. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/cycling.

ps.wells.DamageFactorCorrection(*, well, coefficient: ScalarPropertyInput, exponent: ScalarPropertyInput, offset: ScalarPropertyInput = 0) -> None

The selected gas wells’ non-Darcy D factors from Dake’s correlation (WDFACCOR).

ps.wells.DamageFactorCorrection(well="G1", coefficient=1.2e-07, exponent=-1.1045) gives gas well G1 connection D factors from Dake’s correlation, the cell’s permeability to the power -1.1045, its porosity left out.

coefficient is in the model’s units of viscosity * time * area / (permeability * gas surface volume), the dimension Flow reads WDFACCOR item 2 in; exponent and offset are dimensionless. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/damage_factor_correction.

ps.wells.Economics(*, well, 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, workover_scope: Optional[Literal['well', 'completion', 'completion_and_below', 'rate']] = None, follow_on_well=None, end_run_on_trigger: bool = False, test_basis: Literal['surface_rate', 'potential_rate'] = 'surface_rate') -> None

Well-level economic limits on the selected wells (WECON).

The well a workover opens next is follow_on_well, by its name (a ps.Well given is read by its name).

ps.wells.Economics(well="P*", minimum_oil_rate=20.0, maximum_water_cut=0.95, workover_scope="well") closes each P well whose oil rate falls under 20 or whose water cut passes 0.95.

A rate below its minimum closes the well. A ratio past its maximum closes the well (workover_scope="well") or the completion with the worst ratio ("completion"), every connection in it: each connection is a completion of its own unless ps.wells.Lump numbers several as one, whose ratio is taken over their summed rates, and the well closes when it has no open completion left. With no workover_scope a ratio past its maximum takes no action (WECON item 7 is left NONE), and so with "rate": it is written as item 10’s RATE, the surface-rate basis test_basis="surface_rate" states, not as a workover, and beside test_basis="potential_rate" it is refused when the model is compiled. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/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.wells.Efficiency(*, well, factor: ScalarPropertyInput, network_propagation: Optional[Literal['apply_factor', 'ignore_factor']] = None) -> None

The selected wells’ efficiency (up-time) factor (WEFAC): the fraction of the time they flow.

ps.wells.Efficiency(well="P*", factor=0.9) counts the rates of each well whose name starts with P at 90% where they are summed into groups and cumulatives.

It is stated in ps.Event(date, ...), at schedule/<date>/<well>/efficiency (a pattern or a list’s name quoted: schedule/<date>/'P*'/efficiency), and holds from that date; factor is positive and dimensionless.

ps.wells.FilterCake(*, well, fraction: ScalarPropertyInput, completion_i: int | None = None, completion_j: int | None = None, completion_k: int | None = None) -> None

A cleaning of the filter cake on the selected injectors’ connections (WINJCLN).

ps.wells.FilterCake(well="I1", fraction=0.4, completion_i=5, completion_j=5, completion_k=3) cleans 40% of the filter cake on I1’s connection in cell (5, 5, 3).

fraction is the fraction removed, from 0 to 1. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/filter_cake.

ps.wells.GuideRate(*, well, guide_rate: Optional[ScalarPropertyInput] = None, phase: Literal['total_rate', 'oil', 'water', 'gas', 'liquid', 'formula'] = 'total_rate', under_group_control: bool | None = None, scale: Optional[ScalarPropertyInput] = None) -> None

A well’s guide rate: its share of its group’s target under group control (WGRUPCON).

ps.wells.GuideRate(well="P1", guide_rate=200.0, phase="oil") weighs P1’s share of its group’s oil target at 200 against the guide rates of the wells beside it.

A producer with no guide rate of its own takes one from ps.groups.GuideRates’ formula when the model states one. guide_rate is a surface rate of phase in the model’s units, and Flow reads it as one: a liquid surface rate for "oil" and "water", a gas surface rate for "gas", and for "total_rate" a surface rate of the phase the injector injects; scale is dimensionless. The default phase, "total_rate", is an injector’s: a producer states "oil", "water" or "gas", because Flow 2026.04 aborts the run when it computes a producer’s guide rate of RAT (m.check() passes it). It is stated in ps.Event(date, ...), at schedule/<date>/<well>/guide_rate.

ps.wells.HistoryControl(*, control: Optional[Literal['oil_rate', 'water_rate', 'gas_rate', 'liquid_rate', 'reservoir_volume', 'bottom_hole_pressure']] = None, end_run_on_bhp_switch: bool = False) -> None

Hold every history-matched producer to one control from this date (WHISTCTL).

ps.wells.HistoryControl(control="liquid_rate") holds each ps.History well to its observed liquid rate whatever its own record names; control left out returns each well to the control its own record names. end_run_on_bhp_switch=True writes item 2 as YES, which asks the run to stop when a well switches to its bottom-hole pressure limit; Flow 2026.04 does not support it and refuses the deck.

It is stated in ps.Event(date, ...), at schedule/<date>/history_control.

ps.wells.ICD(*, well, segment: int, end_segment: int | None = None, strength: Optional[ScalarPropertyInput] = None, length: Optional[ScalarPropertyInput] = None, calibration_density: Optional[ScalarPropertyInput] = None, calibration_viscosity: Optional[ScalarPropertyInput] = None, emulsion_critical_fraction: float | None = None, emulsion_transition_width: float | None = None, maximum_emulsion_ratio: float | None = None, scaling_mode: int | None = None, calibration_rate: Optional[ScalarPropertyInput] = None, status: Optional[Literal['open', 'shut']] = None) -> None

A spiral inflow-control device on a segment, or on each segment of a range (WSEGSICD).

ps.wells.ICD(well="P1", segment=7, end_segment=9, strength=0.002, length=10.0) puts one on each of P1’s segments 7 to 9. strength and length state the device; the calibration density, viscosity and rate and the emulsion data are optional.

The constructor takes a device without strength or length, and ps.compile refuses it, and refuses a device on a well whose ps.wells.Segments the model does not state. For a well introduced after the start, a device it is introduced with is stated in the start’s Event, written with the well’s own block; stated after the start, on or before the date the well is introduced, it is refused (schedule.event.start_only). The address is schedule/<date>/<well>/icd. The numbers are in the model’s units: strength a pressure * time2 / volume2, the dimension Flow reads WSEGSICD item 4 in (the time a day, an hour in a lab model; the volume a geometric volume, cubic feet in a field model); length a length; the calibration density, viscosity and rate their own quantities.

ps.wells.InjectedStream(*, well, temperature: Optional[ScalarPropertyInput] = None, pressure: Optional[ScalarPropertyInput] = None, filtrate_concentration: Union[ScalarPropertyInput, UserQuantity, NoneType] = None, polymer_concentration: Optional[ScalarPropertyInput] = None, salinity: Optional[ScalarPropertyInput] = None, polymer_from_group: Group | None = None, tracers=<factory>, solvent_fraction: Optional[ScalarPropertyInput] = None, foam_concentration: Optional[ScalarPropertyInput] = None, microbe_concentration: Optional[ScalarPropertyInput] = None, oxygen_concentration: Optional[ScalarPropertyInput] = None, urea_concentration: Optional[ScalarPropertyInput] = None, molecular_weight_table: int | None = None, water_skin_pressure_table: int | None = None, polymer_skin_pressure_table: int | None = None, composition: str | None = None) -> None

What the selected injectors’ stream carries from this date.

One statement states what the stream carries, each quantity written as its own card: the temperature, alone (WTEMP) or with its pressure (WINJTEMP); the filtrate the water carries (WINJFCNC); the polymer, with the salinity beside it (WPOLYMER); the salinity of a stream that states no polymer (WSALT); the tracers (WTRACER); the solvent (WSOLVENT); the foam (WFOAM); the microbes, oxygen and urea (WMICP); the polymer’s molecular-weight table (WPMITAB) and skin-pressure tables (WSKPTAB); and the storage composition the gas carries (WINJGAS), one ps.storage.Package(compositions=) declares::

ps.wells.InjectedStream(well="I1", temperature=200.0)
ps.wells.InjectedStream(well="I1", polymer_concentration=1.2, salinity=30.0)
ps.wells.InjectedStream(well="I1", tracers={"TR1": 1.0})
ps.wells.InjectedStream(well="I1", composition="CO2MIX")

The start’s Event states the streams the deck states before its first time card; a stream that states a temperature is written at the head after the wells’ controls, and so is the composition a start stream names, in the order stated; what else a stream states is written where the start states it.

What the stream carries needs its package in the model’s physics=[...], and the model refuses it without one: a temperature ps.thermal.Package (wells.injection_temperature.requires_thermal); a polymer, its molecular-weight table or its skin-pressure tables ps.polymer.Package (polymer.controls.package_missing); a salinity with no polymer ps.brine.Package (brine.controls.package_missing); a solvent ps.solvent.Package (solvent.controls.package_missing); a foam ps.foam.Package (foam.controls.package_missing); the microbes ps.micp.Package (micp.controls.package_missing); a composition ps.storage.Package (storage.controls.package_missing). A tracer is one the model declares (ps.Model(passive_tracers=); tracer.control.tracer_unknown otherwise).

In the model’s units, the temperature and pressure are a temperature and a pressure; the polymer, salt, foam, microbe, oxygen and urea concentrations a mass per volume; the filtrate in parts per million and the solvent a fraction of the injected gas. A tracer’s concentration is in the tracer’s own unit, which Flow reads as written, unconverted (ps.tracer.Tracer(units=) labels it). It is stated in ps.Event(date, ...), at schedule/<date>/<well>/injected_stream.

ps.wells.InjectionDamage(*, well, geometry: Literal['radial', 'linear'], permeability: ScalarPropertyInput, porosity: ScalarPropertyInput, wellbore_radius: Optional[ScalarPropertyInput] = None, fracture_area: Optional[ScalarPropertyInput] = None, completion_i: int | None = None, completion_j: int | None = None, completion_k: int | None = None) -> None

The filter cake on the selected injectors’ connections: its shape and its rock (WINJDAM).

ps.wells.InjectionDamage(well="I1", geometry="radial", permeability=1.0, porosity=0.25) gives the connections of injector I1 a radial filter cake of permeability 1 and porosity 0.25.

In the model’s units, permeability is a permeability, porosity a fraction, wellbore_radius a length and fracture_area an area. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/injection_damage.

ps.wells.InjectionMultiplier(*, well, pressure: ScalarPropertyInput, mobility_factor: ScalarPropertyInput, reversibility: Literal['well_reversible', 'completion_reversible', 'completion_irreversible'] = 'well_reversible', completion_i: int | None = None, completion_j: int | None = None, completion_k: int | None = None) -> None

A pressure-dependent injectivity multiplier on the selected injectors (WINJMULT).

ps.wells.InjectionMultiplier(well="I1", pressure=300.0, mobility_factor=0.02) raises the injectivity of I1 by 0.02 for each unit of bottom-hole pressure above 300, and lowers it again as the pressure falls.

Above pressure the multiplier is 1 + mobility_factor times the excess, below it 1; reversibility says which pressure is read and whether a raised multiplier falls again. pressure is in the model’s pressure unit and mobility_factor per unit of it. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/injection_multiplier.

ps.wells.Lump(*, well, i: int | None = None, j: int | None = None, k: tuple[int | None, int | None] | None = None, completion: int) -> None

Make a well’s connections in a run of layers one numbered completion (COMPLUMP).

ps.wells.Lump(well="P1", i=10, j=10, k=(3, 5), completion=2) makes P1’s connections in layers 3 to 5 of column (10, 10) its completion 2: a status change that names completions (ps.Shut(well="P1", completions=2)) reaches them. An axis left out selects every connection along it (ps.wells.Lump(well="P1", k=(3, 5), completion=2) takes those layers in every column), and a layer bound left None is open (k=(3, None) is layer 3 and every layer below it). The model refuses a selection that reaches no connection the well perforates (wells.completion.undeclared).

For a well introduced after the start, a lump it is introduced with is stated in the start’s Event, written with the well’s own block; stated after the start, on or before the date the well is introduced, it is refused (schedule.event.start_only). The address is schedule/<date>/<well>/lump.

ps.wells.NonDarcyFactor(*, well, factor: ScalarPropertyInput) -> None

Set the selected gas wells’ non-Darcy flow factor from this date (WDFAC).

ps.wells.NonDarcyFactor(well="G1", factor=1e-5): the factor D of the well’s rate-dependent skin, D times the gas rate, as ps.wells.Efficiency(factor=) states its factor. Only a gas well takes one.

factor is a skin per unit of surface gas rate, in the model’s units. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/non_darcy_factor.

ps.wells.PressureAveraging(*, well=None, inner_block_weight: Optional[ScalarPropertyInput] = None, pore_volume_inner_weight: bool = False, connection_factor_weight: Optional[ScalarPropertyInput] = None, depth_correction: Optional[Literal['wellbore', 'reservoir', 'none']] = None, connections: Optional[Literal['open_only', 'open_and_closed']] = None, reference_depth: Optional[ScalarPropertyInput] = None) -> None

How a well’s block-average pressure is calculated (WPAVE, WWPAVE, WPAVEDEP).

It holds for the wells well names, or for every well when it names none. ps.wells.PressureAveraging(well="P1", reference_depth=2420.0) reports P1’s average at that depth in place of its bottom-hole reference depth; the reference depth is a well’s own, stated alone or beside the calculation.

Naming no well it writes WPAVE, every well’s, at schedule/<date>/pressure_averaging; naming wells it writes WWPAVE for the calculation and WPAVEDEP for reference_depth, at schedule/<date>/<well>/pressure_averaging. The weights are fractions from 0 to 1 and reference_depth a depth in the model’s length unit.

ps.wells.ProductivityIndex(*, well, value: ScalarPropertyInput) -> None

The selected wells’ productivity or injectivity index from this date (WELPI).

ps.wells.ProductivityIndex(well="P1", value=12.5) rescales the open connections of P1 so its productivity index is 12.5 from this date.

value is a surface rate per unit of pressure drawdown, in the model’s units. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/productivity_index.

ps.wells.ProductivityMultiplier(*, well, factor: ScalarPropertyInput, i: int | None = None, j: int | None = None, k: int | None = None, first_completion: int | None = None, last_completion: int | None = None) -> None

A multiplier on the selected wells’ connection factors from this date (WPIMULT).

ps.wells.ProductivityMultiplier(well="P1", factor=0.5, k=3) halves the connection factors of P1’s connections in layer 3.

i, j, k and the completion range select the connections; left out, every one. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/productivity_multiplier; factor is dimensionless.

ps.wells.Regroup(*, well, group) -> None

Move the selected wells into another group from this date (WELSPECS restated).

ps.wells.Regroup(well="P1", group="NORTH"): P1 flows under NORTH from here on. The group is one of the model’s groups, named as a well is. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/regroup.

ps.wells.Segments(*, well, segments=(), connections=(), top_depth: Optional[ScalarPropertyInput] = None, top_length: ScalarPropertyInput = 0.0, top_volume: Optional[ScalarPropertyInput] = None, length_depth_mode: Literal['incremental', 'absolute'] = 'incremental', pressure_drop_model: Literal['hydrostatic_friction_acceleration', 'hydrostatic_friction', 'hydrostatic_only'] = 'hydrostatic_friction_acceleration', flow_model: Optional[Literal['homogeneous']] = None) -> None

A segmented well’s tree (WELSEGS) and where its connections join it (COMPSEGS).

The well is given by its name (well="P1"; a ps.Well given is read by its name)::

ps.wells.Segments(
well="P1",
top_depth=2000.0,
segments=[{"number": 2, "branch": 1, "parent": 1, "length": 100.0, "depth": 10.0,
"diameter": 0.1, "roughness": 1e-5}],
connections=[{"i": 10, "j": 10, "k": 3, "branch": 1, "start_length": 2000.0,
"end_length": 2100.0}],
)

The top segment is segment 1 (top_depth, top_length, top_volume); each row of segments is a segment below it, flowing into its parent. Each row of connections places one of the well’s connections (a ps.Perforate’s cell) on a branch. A row given as a tuple is read by its columns in order and printed as the mapping. In the start’s Event the statement states the well’s tree; at a later date it restates the tree, the connections, or both, each a card of its own (WELSEGS, COMPSEGS), from that date.

For a well introduced after the start, the tree it is introduced with is stated in the start’s Event and written with the well’s own block; stated after the start, on or before the date the well is introduced, it is refused (schedule.event.start_only), and after that date it is a restatement. The address is schedule/<date>/<well>/segments. The lengths, depths, diameters and roughness are in the model’s length unit, the areas and volumes in its area and volume units.

ps.wells.Skin(*, well, i: int | None = None, j: int | None = None, k: tuple[int | None, int | None] | None = None, skin_factor: float) -> None

Give a well’s connections in a run of layers a skin factor from this date (CSKIN).

ps.wells.Skin(well="P1", i=10, j=10, k=(1, 3), skin_factor=2.5) gives P1’s connections in layers 1 to 3 of column (10, 10) the skin 2.5; ps.Perforate’s skin_factor is the skin a connection is made with, and this statement changes it where it is stated. An axis left out selects every connection along it, and a layer bound left None is open (k=(3, None) is layer 3 and every layer below it). The model refuses a selection that reaches no connection the well perforates (wells.completion.undeclared).

For a well introduced after the start, a skin it is introduced with is stated in the start’s Event, written with the well’s own block; stated after the start, on or before the date the well is introduced, it is refused (schedule.event.start_only). The address is schedule/<date>/<well>/skin; skin_factor is dimensionless.

ps.wells.Survey(*, well, rft: Optional[Literal['once', 'at_report_steps', 'at_timesteps', 'on_first_open']] = None, plt: Optional[Literal['once', 'at_report_steps', 'at_timesteps']] = None, segments: Optional[Literal['once', 'at_report_steps', 'at_timesteps']] = None) -> None

Ask for the selected wells’ downhole surveys from this date (WRFTPLT).

ps.wells.Survey(well="P1", rft="once", plt="at_report_steps") writes P1’s pressure survey (RFT) once and its flow profile (PLT) at every report step. Each survey is asked for “once”, “at_report_steps”, “at_timesteps”, or (the RFT alone) “on_first_open”, when the well first opens; a survey left out is not asked for. One that asks for none, ps.wells.Survey(well="P1"), stops the surveys asked for before (WRFTPLT NO NO NO). segments is a segmented well’s survey of its segments’ pressures and rates. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/survey.

ps.wells.TargetMultiplier(*, well, quantity: Literal['oil_rate', 'water_rate', 'gas_rate', 'liquid_rate', 'artificial_lift_quantity'], factor: ScalarPropertyInput) -> None

Multiply one rate of the wells’ controls by factor (WTMULT).

ps.wells.TargetMultiplier(well="P1", quantity="oil_rate", factor=1.2) raises P1’s oil rate target or limit by 20% from this date.

quantity names the rate: the oil, water, gas or liquid rate, or a producer’s "artificial_lift_quantity" (WTMULT LIFT, the value its lift table reads); factor is dimensionless. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/multiplier/<n>, numbered from 1 among the well’s multipliers at that date.

ps.wells.Trajectory(*, branch: int | None = None, points, connections=()) -> None

A well’s path along one branch (WELTRAJ) and the connections along it (COMPTRAJ).

Its well holds it: ps.Well(..., trajectories=[ps.wells.Trajectory(branch=1, points=[...])]).

points are (measured_depth, x, y, depth) rows in order along the path; connections are the perforated intervals, each a mapping of a connection’s fields ({"top": 2300.0, "bottom": 2450.0}).

Both cards are written in the block that declares the well. The address is wells/<well>/trajectories/<n>, counted from 1. The depths and coordinates are in the model’s length unit; a connection’s top and bottom are measured depths or true vertical depths by its reference.

ps.wells.Valve(*, well, segment: int, status: Literal['open', 'shut'] = 'open', flow_coefficient: float | None = None, flow_area: Optional[ScalarPropertyInput] = None, pipe_length: Optional[ScalarPropertyInput] = None, pipe_diameter: Optional[ScalarPropertyInput] = None, pipe_roughness: Optional[ScalarPropertyInput] = None, pipe_area: Optional[ScalarPropertyInput] = None, maximum_area: Optional[ScalarPropertyInput] = None) -> None

A valve on one segment of a segmented well (WSEGVALV).

ps.wells.Valve(well="P1", segment=12, flow_coefficient=0.7, flow_area=1e-4) puts a valve on segment 12 of P1’s segment tree (ps.wells.Segments); status="shut" closes it. The pipe fields describe the valve’s own pipe where it differs from the segment’s, and maximum_area the valve’s largest flow area.

The segment is one of the well’s ps.wells.Segments tree, which the model states; ps.compile refuses a valve on a well with none. For a well introduced after the start, a valve it is introduced with is stated in the start’s Event, written with the well’s own block; stated after the start, on or before the date the well is introduced, it is refused (schedule.event.start_only). The address is schedule/<date>/<well>/valve. The lengths, diameter and roughness are in the model’s length unit and the areas in its area unit; flow_coefficient is dimensionless.

ps.wells.WellList(*, name: str, wells, action: Literal['new', 'add', 'delete', 'move'] = 'new') -> None

A named list of wells, opened or edited at its date (WLIST).

ps.wells.WellList(name="NORTH", wells=["P1", "P2"]) opens the list, and a later statement names it by the list itself (well=north) or by its name (well=ps.actions.well(lists= "NORTH")); a string is always about wells. A card that names a list is written with the list ('*NORTH'), not with the wells it holds then. A list is edited as the run goes on: action="add" extends a list an earlier statement opened, "delete" takes the named wells out of it, and "move" takes them out of whatever list holds them and puts them in this one.

name is 1 to 7 letters, digits, - or _, a letter first. It is stated in ps.Event(date, ...), at schedule/<date>/'*<name>'/well_list.

ps.wells.WellTest(*, well, interval: int | float | Quantity, reasons: frozenset[typing.Literal['physical', 'economic', 'group_economic']] = frozenset({'physical'}), maximum_tests: int | None = None, startup_period: Optional[ScalarPropertyInput] = None) -> None

Periodic tests that reopen the selected wells when they can flow again (WTEST).

ps.wells.WellTest(well="P1", interval=30.0, reasons={"physical", "economic"}) tests P1 every 30 days when it was shut for a physical or an economic reason, and opens it if it can flow.

The reason item is a SET of letters, not one letter: the manual calls it a list of reasons, and the two orderings of the same pair were measured to be one run on both supported releases. Each letter is validated on its own — a token whose first characters are legal is still refused if a later one is not.

reasons is any collection of “physical”, “economic” and “group_economic”, read as a set. interval and startup_period are in days in every unit system. It is stated in ps.Event(date, ...), at schedule/<date>/<well>/well_test.

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