Skip to main content

neqsim-flow-assurance

Flow assurance patterns for NeqSim. USE WHEN: predicting hydrate, wax, asphaltene, CO2/H2S corrosion (NORSOK M-506), mineral scale and brine mixing, valve scale drift and remediation, sulfur S8 deposition, metal-loss screening, pipeline hydraulics, DNV-RP-F109/F105/F104/F110/F114 screening, water hammer, slug flow, thermal analysis or inhibitor dosing. Code patterns plus the governing standards for every threat.

ソース情報

リポジトリ
equinor/neqsim
ソースの最終更新活動
2026年10月29日 21:22
検出された SKILL.md の言語
英語
スター
161
フォーク
77

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
neqsim-flow-assurance
description
Flow assurance patterns for NeqSim. USE WHEN: predicting hydrate, wax, asphaltene, CO2/H2S corrosion (NORSOK M-506), mineral scale and brine mixing, valve scale drift and remediation, sulfur S8 deposition, metal-loss screening, pipeline hydraulics, DNV-RP-F109/F105/F104/F110/F114 screening, water hammer, slug flow, thermal analysis or inhibitor dosing. Code patterns plus the governing standards for every threat.
last_verified
2026-09-07
# Flow Assurance Analysis with NeqSim Consolidated guide for all flow assurance threats — hydrate, wax, asphaltene, corrosion, hydraulics, water/liquid hammer screening, slugging, and thermal management — with NeqSim code patterns. > A complete study report with pipeline drawings (route, profiles, hydrate margin, threat matrix, > validation) is produced by `neqsim flow-assurance-report` — see the > `neqsim-flow-assurance-study-report` skill. This skill stays the calculation reference. > A whole subsea SURF network (templates, injection, risers, umbilical, concept comparison) is > generated, solved and documented by `neqsim surf-study` — see the `neqsim-surf-design-study` skill. ## When to Use This Skill - Hydrate formation temperature/pressure prediction - Hydrate inhibitor dosing (MEG, methanol, ethanol) - Wax appearance temperature (WAT) and wax deposition risk - Asphaltene stability screening (de Boer, CII) - CO2 and H2S corrosion rate estimation - Elemental sulfur (S8) deposition risk at pressure/temperature letdown (compressor inlets, control/letdown valves, dry-gas seals, filters) - Pipeline pressure drop and temperature profile - DNV-RP-F109 vertical and lateral on-bottom stability screening - Water hammer/liquid hammer screening for fast valve closure, pump trip, or check-valve slam - Multiphase flow pattern prediction (slug, annular, stratified) - Thermal insulation sizing for subsea pipelines - Arrival temperature and cooldown calculations ## Applicable Standards | Domain | Standards | Key Requirements | |--------|-----------|-----------------| | Pipeline design | DNV-ST-F101, DNV-RP-F104 for CO2, NORSOK L-001, ASME B31.4/B31.8 | Structural design plus composition-specific CO2 phase/hydraulic and lifecycle basis | | Corrosion | NORSOK M-001, DNV-RP-F112, ISO 21457 | Material selection, CO2/H2S corrosion rates | | On-bottom stability | DNV-RP-F109 | Vertical stability, absolute lateral stability, displacement acceptance | | Free spans | DNV-RP-F105 | Free-span response and fatigue assessment | | Global buckling and pipe-soil interaction | DNV-RP-F110, DNV-RP-F114 | Caller-controlled external response and demand-resistance screening | | Subsea systems | NORSOK U-001 | Subsea production-system requirements | | Hydrate management | DNV-RP-F116 | Hydrate prevention and remediation | | GRP piping | ISO 14692 | Non-metallic pipe design | | Pipeline integrity | DNV-RP-F101, DNV-RP-F116, API 1160 | Inspected metal-loss remaining strength and integrity management | For fast acoustic transients, also load `neqsim-water-hammer`. Use `WaterHammerStudy` or MCP `runWaterHammer` with STID route geometry, tagreader event windows, and valve/pump event schedules; use this flow-assurance skill for the broader operating-envelope and mitigation context. For on-bottom stability, load `neqsim-subsea-and-wells` and use the typed `DnvRpF109OnBottomStabilityKernel`. It provides a transparent absolute-static screen and checks externally calculated response displacements. It does not contain generalized design tables, produce dynamic response, qualify environmental or soil models, or claim DNV conformity. A pass still requires independent review. This skill quantifies the **threat** (hydrate curve, WAT, SI, corrosion rate). For the **chemical** answer — which product, minimum effective dose, cocktail compatibility, H2S/O2 scavenger sizing, demulsifier vs oil-in-water spec, and chemical root-cause of a deposit — load `neqsim-production-chemistry` (`neqsim.process.chemistry`) and feed it the numbers computed here. For local dry hydrocarbon gas/oil interface investigations, the existing film boundary has a default-off `setCoupledMassHeatTransferEnabled(true)` numerical option. Read `docs/fluidmechanics/InterphaseHeatMassTransfer.md` for its residual gates and limited positive-composition/finite-transport range. It is not connected to the transient `TwoFluidPipe` source. Zero liquid Reynolds number currently gives an unsupported stratified transfer coefficient and rejects; never interpret the old unit-matrix fallback as stationary-pool evaporation. Keep #4674 physical boundary/full-cycle and #4675 heat/area/diffusion qualification separate from numerical convergence. ## 1. Hydrate Analysis ### EOS Selection for Hydrate Calculations | Aqueous phase | NeqSim Class | Mixing Rule | |---------------|-------------|-------------| | Pure water / fresh water | `SystemSrkCPAstatoil` | `10` | | Water + MEG / methanol / ethanol | `SystemSrkCPAstatoil` | `10` | | **Salt brine / formation water (NaCl, CaCl2, ...)** | `SystemElectrolyteCPAstatoil` | `10` | | Pitzer salt-brine water activity | `SystemPitzer` | `"classic"` | CPA or a consistent activity-based aqueous model is needed for water–hydrocarbon hydrate modeling. **When dissolved salts / electrolytes are present, use `SystemElectrolyteCPAstatoil` or a parameterized `SystemPitzer`** so the salt thermodynamic (hydrate-suppression) effect is captured — plain `SystemSrkCPAstatoil` ignores ion activity and underestimates subcooling margin. For Pitzer hydrate onset, load `neqsim-electrolyte-systems` and read `docs/thermo/pitzer_hydrate_equilibrium.md`. Accept its hand-off of salt mole basis, dataset, explicit CO2-chloride zeta values (and K-Mg theta when both ions are present), pressure grid and operating temperature. Use the standard temperature/pressure/curve operations; the Pitzer route checks the fugacity residual and throws on failed points. Preserve the aqueous reference-state convention and guest Henry limits. Do not label onset calculations as hydrate amounts, kinetics or validated complete drilling-mud predictions. Carry forward the experimental assessment separately from convergence: the mixed-chloride high-pressure cases include errors exceeding 1 K. Do not generalize the NaCl benchmark to all salts, concentrations or pressures. ### Hydrate Formation Temperature ```java // CPA EOS required for accurate water-hydrocarbon modeling SystemInterface fluid = new SystemSrkCPAstatoil(273.15 + 10, 100.0); fluid.addComponent("methane", 0.80); fluid.addComponent("ethane", 0.05); fluid.addComponent("propane", 0.03); fluid.addComponent("CO2", 0.02); fluid.addComponent("water", 0.10); fluid.setMixingRule(10); // CPA mixing rule fluid.setMultiPhaseCheck(true); fluid.setHydrateCheck(true); ThermodynamicOperations ops = new ThermodynamicOperations(fluid); ops.hydrateFormationTemperature(); double hydrateT_C = fluid.getTemperature() - 273.15; ``` `setHydrateCheck(true)` is mandatory: without it `hydrateFormationTemperature()` fails (no hydrate phase) and any wrapper that swallows the exception reports NaN. The fluid must contain `water`. `HydrateRiskMapper` (and MCP `runFlowAssurance` `hydrateRiskMap`) now sets the flag itself and returns `RiskLevel.UNKNOWN` / `RESULT_NOT_AVAILABLE` with `failureReasons` when no equilibrium temperature exists — never treat an unavailable hydrate temperature as safe. ### Hydrate Equilibrium Curve (Multiple Pressures) ```java // Calculate hydrate T at several pressures for the full curve double[] pressures = {20, 40, 60, 80, 100, 120, 150, 200}; double[] hydrateTemps = new double[pressures.length]; for (int i = 0; i < pressures.length; i++) { SystemInterface testFluid = fluid.clone(); testFluid.setPressure(pressures[i]); ThermodynamicOperations testOps = new ThermodynamicOperations(testFluid); testOps.hydrateFormationTemperature(); hydrateTemps[i] = testFluid.getTemperature() - 273.15; } ``` ### Hydrate Inhibitor Dosing (MEG) ```java // Add MEG to suppress hydrate formation temperature SystemInterface inhibitedFluid = new SystemSrkCPAstatoil(273.15 + 4, 100.0); inhibitedFluid.addComponent("methane", 0.80); inhibitedFluid.addComponent("water", 0.15); // 25 wt% MEG in the water + MEG phase: n_MEG = n_water * 18.015 * 0.25 / 0.75 / 62.07 = 0.0145 mol // (0.05 mol MEG per 0.15 mol water would be 53 wt%: amounts are MOLES, never weight percentages) inhibitedFluid.addComponent("MEG", 0.0145); inhibitedFluid.setMixingRule(10); inhibitedFluid.setMultiPhaseCheck(true); inhibitedFluid.setHydrateCheck(true); ThermodynamicOperations ops = new ThermodynamicOperations(inhibitedFluid); ops.hydrateFormationTemperature(); double inhibitedHydrateT = inhibitedFluid.getTemperature() - 273.15; // Compare with uninhibited to get subcooling margin ``` For the **injection rate** that delivers a required wt% in the water phase (including purity and lean/rich MEG bookkeeping), use `neqsim.process.chemistry.hydrate.ThermodynamicHydrateInhibitorPerformance` — see `neqsim-production-chemistry`. Use the CPA curve above for the design concentration and the chemistry model for the rate. ### Salt-Inhibited Hydrate (Formation Water / Brine) ```java // Dissolved salts depress the hydrate temperature — use the electrolyte CPA model SystemInterface brineGas = new SystemElectrolyteCPAstatoil(273.15 + 4, 100.0); brineGas.addComponent("methane", 0.80); brineGas.addComponent("water", 0.18); brineGas.addComponent("Na+", 0.01); // dissociated NaCl brineGas.addComponent("Cl-", 0.01); brineGas.setMixingRule(10); brineGas.setMultiPhaseCheck(true); brineGas.setHydrateCheck(true); ThermodynamicOperations ops = new ThermodynamicOperations(brineGas); ops.hydrateFormationTemperature(); double brineHydrateT = brineGas.getTemperature() - 273.15; // SystemSrkCPAstatoil would miss the salt suppression — always use electrolyte CPA with ions ``` ### MEG Concentration Sweep ```java // Find required MEG concentration for target subcooling double[] megWtPct = {0, 10, 20, 30, 40, 50}; for (double wt : megWtPct) { // wt % MEG is a MASS fraction of the water + MEG mixture: convert to moles (M_water 18.015, M_MEG 62.07 g/mol) double waterMol = 0.20 * (1.0 - wt / 100.0) / 18.015; double megMol = 0.20 * (wt / 100.0) / 62.07; double waterFrac = waterMol / (waterMol + megMol) * 0.20; double megFrac = megMol / (waterMol + megMol) * 0.20; SystemInterface testFluid = new SystemSrkCPAstatoil(273.15, 100.0); testFluid.addComponent("methane", 0.80); testFluid.addComponent("water", waterFrac); testFluid.addComponent("MEG", megFrac); testFluid.setMixingRule(10); testFluid.setHydrateCheck(true); ThermodynamicOperations testOps = new ThermodynamicOperations(testFluid); testOps.hydrateFormationTemperature(); // Record hydrate T vs MEG concentration } ``` **Sweep gotchas (found building an HPHT tie-back, Fogelberg VPbo task):** `hydrateFormationTemperature()` with a rich gas condensate (C7+ pseudo-components) plus water and MEG at 40 wt % MEG did not return (CPA hydrate solver loop, no exception, no timeout). Run every MEG/pressure point of a sweep in a watchdog thread or subprocess with a hard time limit and keep the sweep to at most 30 wt % MEG. If a 40-50 wt % row is still needed, a linear extrapolation (about -4.5 K per 10 wt % at 30-400 bara) is an UNVALIDATED screening number: label it as extrapolated, never use it for a pass/fail margin, and do not let the whole script hang for it. Write the intermediate JSON before the hydrate loop so a kill does not lose the fluid and CVD results. For flowline hydraulics with `PipeBeggsAndBrills` a trial inlet pressure that is too low throws `HydraulicDomainException: Non-positive pipeline pressure` instead of returning a low outlet pressure: catch it inside the chain function and return outlet 0 (infeasible). Letting it propagate out of a bisection silently turns a whole row of the inlet-pressure table into NaN. `ThermodynamicOperations.hydrateFormationTemperature()` is `void`: the answer is left in the fluid temperature, so read `fluid.getTemperature() - 273.15` after the call (`float(ops.hydrateFormationTemperature())` fails with `NoneType`; found in the Mistral Nord VPbo task). A wellstream built with `SystemSrkEos` plus `setHydrateCheck(true)` also under-predicts the hydrate temperature (methane benchmark about -8 K): rebuild the composition in `SystemSrkCPAstatoil` (mixing rule 10) and benchmark methane at 43/76/140 bara against 5/10/15 C before using the numbers (CPA gives -0.03/+0.33/+0.58 K). To benchmark `PipeBeggsAndBrills` against Darcy-Weisbach use a dry single-phase gas (pure methane, 60 C, `setHeatTransferCoefficient` large): the deviation is then 0.2-0.4 %. A lean-gas condensate line cooled to seabed temperature differs by 25-50 % because the liquid holdup is real, so that difference is not a defect. Gas-condensate saturation pressure (Tyrihans cellar task): a bubble-point search on a lean gas-condensate fluid returns a wrong value because the fluid has a dew point; take the saturation pressure of GOR above about 1500 Sm3/Sm3 fluids from the CVD first step (dew point) and record it as a limitation. `hydrateFormationTemperature()` on a GOR 250 oil fluid with 3 mol % water at 200 bara did not converge and left the temperature unchanged: check that the returned temperature differs from the start temperature before reporting it and report `None` as a gap, not as a hydrate-free result. HPHT wellstream hydrates (Erlend / Kristin study): the CPA hydrate solver also stalls (no exception) with the C7+ TBP/plus pseudo-components at 50 bara and 1 mol % water, even without MEG. Rebuild the CPA mixture from the light components only (C1-C6, N2, CO2, water, renormalised), as C7+ barely moves the hydrate temperature; a Kristin-type gas (CGR 300 Sm3/MSm3) with 1 mol % water gave 17.2 / 21.2 / 26.6 / 31.9 C at 50 / 100 / 300 / 600 bara. Do not iterate `PipeBeggsAndBrills` inlet pressure by a fixed point `p_in += p_out_target - p_out`: it stalls at high pressure drop (unconverged tables looked like data). Use a secant solve, treat a `HydraulicDomainException` as outlet pressure 0, store an `ok` flag and exclude `ok == False` rows when interpolating; beyond the last converged rate extend the table with dp proportional to q^2 instead of the last slope. ### MEG/Water Film Conditioned by Dry Gas (pipeline drying after glycol swabbing) Question pattern: "what MEG:H2O ratio does a residual film reach under dry export gas, and why is the gas above the dew-point spec?" Worked task: `2026-09-29_steady_state_megh2o_ratio_during_dry_gas_drying_of_a_meg`. - **Direction:** a 99 wt% MEG film is *drier* than the plateau (about 90 wt% at 6 C, 140 bara), so the gas is the wetter side and the film **absorbs** water. It "dries" only if it starts wetter than the plateau. - **Equilibrium curve:** two-phase `SystemSrkCPAstatoil` TPflashes over an MEG sweep give gas water *and MEG* content versus film composition (gas composition depends on the liquid composition, T and P only). Report film composition on a **gas-free** basis, MEG/(MEG+water); dissolved CO2/CH4 is ~0.8 wt%. MEG is not strictly non-volatile: about 5 ppm wt in the gas at 140 bara. - **Dew-point spec fixes only the water mole fraction** y_in, not the pipe condition. Hand chain: water fugacity continuity, `a_w = y_in * phiV_w(T,P) * P / f0_w(T,P)`, with `f0_w` = IAPWS vapour pressure x Poynting; `a_w` from the CPA liquid fugacity coefficient divided by the pure-water coefficient. Use binary (gas-free) mole fractions when fitting `ln gamma_w` or the fit mis-predicts at high MEG. - **Plateau offset by mass balance:** with a stationary film the gas leaves carrying water and MEG in the film's own ratio, so `(y_out - y_in)/y_in = r * y_MEG / y_in` (about 1.7 %), independent of `K_G` at large NTU. The film inlet zone is stripped of MEG first (a film-free zone grows at ~200 m/day in a 0.4 m, 60 kg/s example). - **Flash per time step is backward Euler:** unconditionally stable, plateau independent of step size; an explicit coding is stable only below `2 / (d y*_H2O / d r)` kg gas per kg film MEG per step. - **Dew point is logarithmic** (~6 % in water content per K at these conditions) and, for CPA, nearly pressure independent at 70-140 bara: reading the same gas as a dew point at pipe pressure adds ~0.9 K. - **Basis traps:** CPA liquid-water dew point is a supercooled-liquid reference below freezing; ISO 18453 / GERG-water uses an ice reference below 273.16 K. These are different phase boundaries. For GERG-water, use `SystemGERGwaterEos`, `setMixingRule(8)`, and a `ThermodynamicOperations` instance's `waterDewPointTemperatureFlash()`; follow the ISO 18453 execution rule in `neqsim-standards-lookup` and the [dew-point guide](../../../docs/standards/dew_point_standards.md). Recalculate outputs from the former non-convergent solver before comparing models. Neither an ideal-gas estimate nor a CPA/GERG difference alone identifies an ISO implementation error. - **Numerics:** for N >= 100 film cells use `solve_ivp(method="BDF")`; LSODA stalls on the film-exhaustion switch. Regularise `r = W/(M + delta)` so a film-free cell cannot return a spurious composition. ## 2. Wax Analysis ### Wax Appearance Temperature (WAT) ```java // Oil system with C7+ fractions for wax prediction SystemInterface oil = new SystemSrkEos(273.15 + 60, 50.0); oil.addComponent("methane", 0.30); oil.addComponent("ethane", 0.10); oil.addTBPfraction("C7", 0.10, 92.0 / 1000, 0.727); oil.addTBPfraction("C10", 0.15, 134.0 / 1000, 0.78); oil.addTBPfraction("C15", 0.15, 206.0 / 1000, 0.83); oil.addPlusFraction("C20", 0.20, 350.0 / 1000, 0.88); oil.getCharacterization().setWaxModel(true); oil.getCharacterization().characterisePlusFraction(); oil.setMixingRule("classic"); ThermodynamicOperations ops = new ThermodynamicOperations(oil); ops.calcWAT(); double wat_C = oil.getTemperature() - 273.15; ``` ### Wax Fraction vs Temperature (PVT Simulation) ```java import neqsim.pvtsimulation.simulation.WaxFractionSim; WaxFractionSim waxSim = new WaxFractionSim(oil); waxSim.setTemperatures(new double[]{333.15, 313.15, 293.15, 273.15}); waxSim.run(); double[] waxFractions = waxSim.getWaxFraction();
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る