Skip to content

Close the transient/dynamics parity gap: sustained severe slugging, liquid-rich stability, and a published controls benchmark #3298

Description

@EvenSol

Summary

NeqSim's dynamic infrastructure is strong — 4 integrators, 45 equipment classes with runTransient, 7 control structures, MPC, and a DynamicCapability audit framework that has no commercial equivalent. Steady-state TwoFluidPipe reached reference parity in #3077/#3078 (+1.4 / +1.6 / +0.1 / −2.7 % dP, −2.4…+3.5 % hold-up across the 4/7/10/12 MSm³/d sweep).

What is not at parity is transient multiphase physics. Three named defects block it, and they are the reason olga-simulation-agent exists to delegate. This epic closes them.

Scope explicitly excludes re-litigating steady-state closures — that work landed and is validated.

Current state (measured, not estimated)

Working

Blocking defects

D1 — Severe slugging limit cycle is damped, not sustained. (highest value)
On the Tengesdal (2002) benchmark, the instability starts ≈30 s, decays to flat by ≈100 s, then blows up numerically after ≈265 s.

quantity reference sim NeqSim measured (experiment)
riser-base swing 34.9 kPa (0.278 heads) no limit cycle (P10–P90 1.96 kPa) 98 kPa (0.78 heads)
cycle period 21.7 s none 38 s

Root cause is identified, not speculative: calcOutletFlux clamps reversed phase velocities to 0 with no diagnostic (isTransientOutletBackflowClamped() is true, liquid_outlet_min == 0.0 exactly). Severe slugging requires liquid fallback at the riser top — the clamp forbids the mechanism, so the riser packs to the 0.95 hold-up clamp and stays. The fix is the outlet BC / interfacial-pressure coupling, not a hold-up closure. The flowline already agrees to 1 %; the disagreement is entirely in the riser.

D2 — Liquid-rich transient packs without bound.
The interfacial-pressure term is correct but explicit, forcing CFL ≈ 0.05. Folding it into the IMEX implicit pressure solve couples the phase momentum equations to the void-fraction wave. Currently @Disabled in TwoFluidPipeTransientNullTest.

D3 — CoupledPressureMomentumSolver stalls with a silent no-progress return.
runTransient returns getElapsedTimeSeconds() == 0. Isolation (50 × 0.1 s steps):

config steps ok t_end
legacy / interfacial only / backflow only 50 5.00 s
coupled (± interfacial ± backflow) 8 0.77 s

Mechanism: iters == 12 == maximumIterations, residual ≈6e-7 > relativeVolumeTolerance 1e-7 → converged=falseadaptiveDtFactor *= 0.5; currentStep--; continue; without decrementing timeRemaining, so every substep is rejected and the call silently advances nothing. Halving dt does not recover.
API gap: setMaximumIterations / setRelativeVolumeTolerance exist on the solver but there is no accessor from TwoFluidPipe, so the gate is untunable by a user. Same for pressureCorrectionLimited, computed then never surfaced.

Secondary

  • Regime misclassification at high hold-up: 39 % hold-up classified ANNULAR; D=0.30 m → ANNULAR 20/20 vs D=0.50 m → STRATIFIED_WAVY 20/20 at near-identical hold-up. A friction form cannot repair a misclassified regime — an annular-film friction model was implemented and reverted (made it worse: +13.2 % vs +1.4 %).
  • Three-phase free water steady solve does not converge (4078 iters / 1200 s wall-clock; profile is stationary to 0.01 bar but the criterion never trips).
  • 4 @Disabled transient tests; 6 UNCLASSIFIED_DYNAMIC capability declarations unaudited.
  • PipeBeggsAndBrills.runTransient has no mass-storage term — documented as not fixable in that class (needs a second boundary condition); route users to TwoFluidPipe.

Workstreams

WS1 — Sustained severe slugging (unblocks the headline capability)

  • Replace the calcOutletFlux one-way clamp with a signed outlet BC permitting liquid fallback
  • Surface a sticky diagnostic mirroring isSteadyStatePressureFloorLimited()never clamp silently
  • Couple interfacial pressure into the implicit solve at the outlet
  • Accept: Tengesdal test 3 produces a sustained limit cycle; riser-base swing within ±30 % of 98 kPa and period within ±30 % of 38 s; flowline hold-up unchanged (0.342 ±1 %); no blow-up over ≥600 s

WS2 — IMEX implicit interfacial pressure (unblocks liquid-rich)

  • Fold the interfacial-pressure term into the implicit pressure solve
  • Re-enable both @Disabled TwoFluidPipeTransientNullTest cases
  • Accept: liquid-rich null test bounded over 4 h; CFL ≥ 0.5 usable; mass balance still closes to the digit

WS3 — Coupled-solver robustness (prerequisite for WS1/WS2)

  • Never return zero elapsed time silently — throw or expose a sticky diagnostic
  • Expose solver gate (maximumIterations, relativeVolumeTolerance, pressureCorrectionLimited) through TwoFluidPipe
  • Make the tolerance achievable within the cap, or make the cap adaptive
  • Accept: coupled config runs 50/50 steps on Tengesdal; outlet rate compared against the stored reference trace (0.375–4.03 kg/s) — note the existing ledger test satisfies itself by construction; the outlet rate is the real gate

WS4 — High-hold-up regime map

  • Fix the annular/slug branch above ~0.3 hold-up
  • Acquire an inclined/high-hold-up regime-map validation basis before touching closures
  • Accept: D=0.30 m and D=0.50 m at equal hold-up classify consistently; no dP regression on the reference sweep

WS5 — Controls parity benchmark (the un-evidenced half)

There is no published NeqSim controls benchmark. We have MPC, cascade, split-range, override, ratio, feed-forward and anti-surge — and no artefact a reviewer can cite.

  • Define 5–8 canonical loops (level, pressure, cascade temperature, split-range, anti-surge recycle, compressor speed/recycle coordination)
  • Publish setpoint-step and disturbance-rejection metrics via ControllerPerformanceMetrics (IAE, overshoot, settling time)
  • Wire into AgentBenchmarkSuite
  • Accept: a citable, CI-run controls benchmark page

WS6 — Capability audit closure

  • Audit the 6 UNCLASSIFIED_DYNAMIC declarations into real categories
  • CI gate: no new UNCLASSIFIED_DYNAMIC without an ADR
  • Accept: DynamicCapabilityReport shows 100 % audited

Sequencing

WS3 (solver robustness)  ──►  WS1 (severe slugging)  ──►  WS4 (regime map)
        └──────────────────►  WS2 (IMEX liquid-rich)
WS5 (controls benchmark)  ──  independent, parallelisable
WS6 (capability audit)    ──  independent, low effort

WS3 first — WS1 and WS2 both terminate in the coupled solver, and its silent stall will mask their results.

Hard-won constraints (do not re-litigate)

  • Do not chase D1 in the hold-up closures. Defects 1 and 2 there are fixed; the remaining blocker is the outlet BC.
  • Drift-flux for the slug closure is a trap. It fixes direction (ratio → 10.22) but fails TwoFluidPipePhaseDegeneracyTest: C0>1 + finite v_d keeps α_G<1 at zero liquid; the Zuber-Findlay (1-α_G)^n fix kills the inclination response again.
  • Do not apply separated friction in ANNULAR. Measured +14.7 % at 10 MSm³/d and pressure floor at 12.
  • Do not tune to a specific commercial trace in public artefacts. Equinor-internal comparison is licensed; public repos need an independent basis.
  • ⚠️ Always run the regime probe before touching a closure. An Andritsos-Hanratty interfacial friction model was implemented, measured byte-identical, and reverted — because the line was 100 % ANNULAR and the closure was inert.
  • ⚠️ Dimension-check every criterion. The Kelvin-Helmholtz criterion was dimensionally wrong (spurious extra h_G) and produced a fake "improvement" that vanished on fixing it.

Definition of done

  • Sustained severe-slugging limit cycle within ±30 % of experiment on amplitude and period
  • Liquid-rich transient bounded; both @Disabled null tests re-enabled
  • Coupled solver runs the benchmark end-to-end with a tunable, surfaced gate
  • Published controls benchmark in CI
  • 100 % DynamicCapability audited
  • Docs updated: TWOFLUIDPIPE_MODEL.md, two_fluid_model.md, neqsim-dynamic-simulation + neqsim-flow-assurance skills
  • olga-simulation-agent routing guidance updated to reflect what NeqSim can now own

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions