Multisegment wellbores
A multisegment wellbore divides a well’s flow path into numbered segments so the
simulator resolves pressure and holdup along the tubing and through completion
devices. PetroScript models this with ps.wells.Segments: its segments rows
describe the segment tree below the top segment, each flowing into its parent,
and its connections rows place the well’s perforated cells on a branch. Typed
device objects (ps.wells.Valve, ps.wells.ICD, ps.wells.AICD) describe flow
control hardware on individual segments, each naming its well and the segment’s
number. Each is a change a ps.Event dates. The compiler owns all simulator
keyword layouts and the multisegment dimension bookkeeping.
Authoring a segmented producer with an autonomous ICD
Section titled “Authoring a segmented producer with an autonomous ICD”An autonomous inflow-control device (AICD) chokes back high-mobility fluids
(water, gas) by making its pressure drop depend on the flowing mixture’s density
and viscosity. The device is
ps.wells.AICD, and the mixture is
characterized per phase: the oil/water/gas flowing-fraction exponents of the
density and viscosity mixture laws are mappings by phase ({"oil": 1.1, "water": 1.2, "gas": 1.3}), and the overall density exponent of the pressure-drop law is density_exponent.
import petroscript as ps
group = ps.Group(name="FIELD")segments = ps.wells.Segments( well="PROD1", top_depth=2510.0, segments=[ {"number": 2, "branch": 1, "parent": 1, "length": 50.0, "depth": 0.0, "diameter": 0.152, "roughness": 1.0e-5}, {"number": 3, "branch": 2, "parent": 2, "length": 0.1, "depth": 0.0, "diameter": 0.152, "roughness": 1.0e-5}, ], connections=[ {"i": 2, "j": 2, "k": 1, "branch": 2, "start_length": 0.0, "end_length": 0.1}, ],)device = ps.wells.AICD( well="PROD1", segment=3, strength=7.5e-5, length=-0.028975, calibration_density=1020.0, calibration_viscosity=0.48, emulsion_critical_fraction=0.7, flow_rate_exponent=2.2, viscosity_exponent=0.5, density_mixture_exponents={"oil": 1.1, "water": 1.2, "gas": 1.3}, viscosity_mixture_exponents={"oil": 0.7, "water": 0.8, "gas": 0.9}, density_exponent=0.75,)
model = ps.Model( name="SEGMENTED_PRODUCER", 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=2510.0, datum_pressure=3000.0, oil_water_contact=2600.0, gas_oil_contact=0.0 ), groups=[group], wells=[ ps.Well(name="PROD1", i=2, j=2, group=group), ps.Well(name="INJ1", i=1, j=1, group=group), ], 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.Perforate(well="INJ1", k=(1, 1), diameter=0.3), ps.Produce(well="PROD1", oil_rate=150.0, bhp_limit=2500.0), ps.Inject(well="INJ1", phase="water", rate=300.0, bhp_limit=4500.0), segments, device, ) ], ),)The mixture-exponent arguments are optional and AICD-specific: spiral ICDs
(ps.wells.ICD) and segment valves do not accept them, and a device
without them emits the same short record as before. A mixture law states all three phases’
exponents (1.0 is the neutral one); density_exponent must be non-negative.
Segment geometry and dimension boundaries
Section titled “Segment geometry and dimension boundaries”Segment geometry is expressed on each segments row (length, depth change,
diameter, roughness, and where they are not the pipe’s own, cross_section_area
and volume) and on ps.wells.Segments itself (top_depth,
top_length, top_volume, the incremental-vs-absolute length_depth_mode, and
the hydrostatic/friction/acceleration pressure_drop_model). A connections
row may also state the direction the connection penetrates its cell
(direction, "x", "y" or "z"), the last cell of a range along it
(end_range), the depth its pressure is referred to (depth), its
thermal_length, and the number of the segment it joins (segment; left out,
OPM Flow joins it to its branch’s segment nearest it). Adding
"direction": "z", "depth": 2510.0, "segment": 3 to the row above writes
2 2 1 2 0 0.1 Z 1* 2510 1* 3 / under COMPSEGS. The remaining
simulator-side wellbore columns are not part of the semantic surface because
OPM Flow does not support them:
- the drift-flux multiphase segment model (only the homogeneous default runs),
- display coordinates and pipe-wall thermal columns on the segment records,
- chord-link dimensioning (the simulator ignores it; the compiler leaves the slot defaulted).
The compiler computes multisegment dimensions from the authored segment trees;
ps.Capacity(multisegment_wells=..., segments_per_well=..., branches_per_well=...)
reserves more than the model holds.
PetroScript is licensed under the Apache License 2.0. © 2026 Blauweiss EDV LLC. PetroScript by Blauweiss AI.For AI agents: llms.txt