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=false → adaptiveDtFactor *= 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)
WS2 — IMEX implicit interfacial pressure (unblocks liquid-rich)
WS3 — Coupled-solver robustness (prerequisite for WS1/WS2)
WS4 — High-hold-up regime map
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.
WS6 — Capability audit closure
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
Summary
NeqSim's dynamic infrastructure is strong — 4 integrators, 45 equipment classes with
runTransient, 7 control structures, MPC, and aDynamicCapabilityaudit framework that has no commercial equivalent. Steady-stateTwoFluidPipereached 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-agentexists 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
TwoFluidPipeat reference parity (fix(pipeline): real gas viscosity in the stratified level solver, Bendiksen drift velocity, reachable annular criterion #3077, fix(pipeline): give the slug closure its gravity term, and make the physical defaults the defaults #3078); three-phase dP +16.9 % (was +189.5 %)TwoFluidPipe.runTransientis a genuinely conservative scheme: null test 0.00 bar drift over 4 h; mass balance closes to the digit (−197.9 t both by inventory and by ∫(ṁ_in − ṁ_out)dt); inlet settles within −0.13 % of reference on a rate stepBlocking 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.
Root cause is identified, not speculative:
calcOutletFluxclamps reversed phase velocities to 0 with no diagnostic (isTransientOutletBackflowClamped()is true,liquid_outlet_min == 0.0exactly). 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
@DisabledinTwoFluidPipeTransientNullTest.D3 —
CoupledPressureMomentumSolverstalls with a silent no-progress return.runTransientreturnsgetElapsedTimeSeconds() == 0. Isolation (50 × 0.1 s steps):Mechanism:
iters == 12 == maximumIterations, residual ≈6e-7 >relativeVolumeTolerance1e-7 →converged=false→adaptiveDtFactor *= 0.5; currentStep--; continue;without decrementingtimeRemaining, so every substep is rejected and the call silently advances nothing. Halving dt does not recover.API gap:
setMaximumIterations/setRelativeVolumeToleranceexist on the solver but there is no accessor fromTwoFluidPipe, so the gate is untunable by a user. Same forpressureCorrectionLimited, computed then never surfaced.Secondary
@Disabledtransient tests; 6UNCLASSIFIED_DYNAMICcapability declarations unaudited.PipeBeggsAndBrills.runTransienthas no mass-storage term — documented as not fixable in that class (needs a second boundary condition); route users toTwoFluidPipe.Workstreams
WS1 — Sustained severe slugging (unblocks the headline capability)
calcOutletFluxone-way clamp with a signed outlet BC permitting liquid fallbackisSteadyStatePressureFloorLimited()— never clamp silentlyWS2 — IMEX implicit interfacial pressure (unblocks liquid-rich)
@DisabledTwoFluidPipeTransientNullTestcasesWS3 — Coupled-solver robustness (prerequisite for WS1/WS2)
maximumIterations,relativeVolumeTolerance,pressureCorrectionLimited) throughTwoFluidPipeWS4 — High-hold-up regime map
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.
ControllerPerformanceMetrics(IAE, overshoot, settling time)AgentBenchmarkSuiteWS6 — Capability audit closure
UNCLASSIFIED_DYNAMICdeclarations into real categoriesUNCLASSIFIED_DYNAMICwithout an ADRDynamicCapabilityReportshows 100 % auditedSequencing
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)
TwoFluidPipePhaseDegeneracyTest:C0>1+ finitev_dkeeps α_G<1 at zero liquid; the Zuber-Findlay(1-α_G)^nfix kills the inclination response again.h_G) and produced a fake "improvement" that vanished on fixing it.Definition of done
@Disablednull tests re-enabledDynamicCapabilityauditedTWOFLUIDPIPE_MODEL.md,two_fluid_model.md,neqsim-dynamic-simulation+neqsim-flow-assuranceskillsolga-simulation-agentrouting guidance updated to reflect what NeqSim can now own