Class TwoFluidPipe

All Implemented Interfaces:
Serializable, Runnable, CapacityConstrainedEquipment, PipeLineInterface, ProcessEquipmentInterface, TwoPortInterface, ProcessElementInterface, SimulationInterface, NamedInterface

public class TwoFluidPipe extends Pipeline
Two-fluid transient multiphase pipe model.

Implements a full two-fluid model for 1D transient multiphase pipeline flow. Unlike the drift-flux based TransientPipe, this model solves separate momentum equations for each phase, providing more accurate predictions for:

  • Countercurrent flow
  • Slug flow dynamics
  • Terrain-induced liquid accumulation
  • Transient pressure waves

Conservation Equations

  • Gas Mass: ∂/∂t(α_g·ρ_g·A) + ∂/∂x(α_g·ρ_g·v_g·A) = Γ_g
  • Liquid Mass: ∂/∂t(α_L·ρ_L·A) + ∂/∂x(α_L·ρ_L·v_L·A) = Γ_L
  • Gas Momentum: ∂/∂t(α_g·ρ_g·v_g·A) + ∂/∂x(α_g·ρ_g·v_g²·A + α_g·P·A) = S_g
  • Liquid Momentum: ∂/∂t(α_L·ρ_L·v_L·A) + ∂/∂x(α_L·ρ_L·v_L²·A + α_L·P·A) = S_L
  • Mixture Energy: (optional)

Usage Example

// Create two-phase fluid
SystemInterface fluid = new SystemSrkEos(300, 50);
fluid.addComponent("methane", 0.85);
fluid.addComponent("n-pentane", 0.15);
fluid.setMixingRule("classic");
fluid.setMultiPhaseCheck(true);

// Create inlet stream
Stream inlet = new Stream("inlet", fluid);
inlet.setFlowRate(10, "kg/sec");
inlet.run();

// Create two-fluid pipe
TwoFluidPipe pipe = new TwoFluidPipe("Pipeline", inlet);
pipe.setLength(5000); // 5 km
pipe.setDiameter(0.3); // 300 mm
pipe.setNumberOfSections(100);

// Set terrain profile
double[] elevations = new double[100];
for (int i = 0; i < 100; i++) {
  elevations[i] = 50.0 * Math.sin(i * Math.PI / 50); // Undulating terrain
}
pipe.setElevationProfile(elevations);

// Initialize steady state
pipe.run();

// Transient simulation
UUID id = UUID.randomUUID();
for (int step = 0; step < 1000; step++) {
  pipe.runTransient(0.1, id); // 0.1 second steps
}

// Get results
double[] pressures = pipe.getPressureProfile();
double[] holdups = pipe.getLiquidHoldupProfile();
double liquidInventory = pipe.getLiquidInventory("m3");

References

  • Bendiksen, K.H. et al. (1991) - The Dynamic Two-Fluid Model OLGA
  • Taitel, Y. and Dukler, A.E. (1976) - Flow regime transitions
  • Issa, R.I. and Kempf, M.H.W. (2003) - Simulation of slug flow
Version:
1.0
Author:
Even Solbraa
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      See Also:
    • logger

      private static final org.apache.logging.log4j.Logger logger
    • length

      private double length
      Total pipe length (m).
    • diameter

      private double diameter
      Pipe inner diameter (m).
    • roughness

      private double roughness
      Pipe wall roughness (m).
    • numberOfSections

      private int numberOfSections
      Number of computational cells.
    • elevationProfile

      private double[] elevationProfile
      Elevation profile at each section (m).
    • sections

      private TwoFluidSection[] sections
      Pipe sections with state.
    • dx

      private double dx
      Minimum spatial step size across all sections (m). Used for CFL calculation. Equal to uniform dx when sectionLengths is null.
    • sectionLengths

      private double[] sectionLengths
      Per-section lengths for non-uniform mesh (m). When null, all sections use uniform dx. Length must equal numberOfSections and sum to total pipe length.
    • simulationTime

      private double simulationTime
      Current simulation time (s).
    • maxSimulationTime

      private double maxSimulationTime
      Maximum simulation time (s).
    • cflNumber

      private double cflNumber
      CFL number for time stepping (0 < CFL < 1).
    • equations

      private TwoFluidConservationEquations equations
      Conservation equations solver.
    • timeIntegrator

      private TimeIntegrator timeIntegrator
      Time integrator.
    • flowRegimeDetector

      private FlowRegimeDetector flowRegimeDetector
      Flow regime detector.
    • accumulationTracker

      private LiquidAccumulationTracker accumulationTracker
      Liquid accumulation tracker.
    • slugTracker

      private SlugTracker slugTracker
      Slug tracker (simplified model).
    • lagrangianSlugTracker

      private LagrangianSlugTracker lagrangianSlugTracker
      Lagrangian slug tracker (OLGA-style full tracking).
    • slugTrackingMode

      private TwoFluidPipe.SlugTrackingMode slugTrackingMode
      Current slug tracking mode.
    • inletBCType

      private TwoFluidPipe.BoundaryCondition inletBCType
      Inlet boundary condition type.
    • outletBCType

      private TwoFluidPipe.BoundaryCondition outletBCType
      Outlet boundary condition type.
    • outletPressure

      private double outletPressure
      Outlet pressure (Pa).
    • outletPressureSet

      private boolean outletPressureSet
      Flag indicating if outlet pressure was explicitly set.
    • inletPressure

      private double inletPressure
      Inlet pressure (Pa) - used when inletBCType is CONSTANT_PRESSURE.
    • inletPressureSet

      private boolean inletPressureSet
      Flag indicating if inlet pressure was explicitly set.
    • inletMassFlow

      private double inletMassFlow
      Inlet mass flow (kg/s) - used when inletBCType is CONSTANT_FLOW.
    • inletMassFlowSet

      private boolean inletMassFlowSet
      Flag indicating if inlet mass flow was explicitly set.
    • includeEnergyEquation

      private boolean includeEnergyEquation
      Include energy equation.
    • includeMassTransfer

      private boolean includeMassTransfer
      Include mass transfer (flash/condensation).
    • enableHeatTransfer

      private boolean enableHeatTransfer
      Enable heat transfer from surroundings.
    • surfaceTemperature

      private double surfaceTemperature
      Surface temperature for heat transfer (K).
    • heatTransferCoefficient

      private double heatTransferCoefficient
      Heat transfer coefficient (W/(m²·K)).
    • heatTransferProfile

      private double[] heatTransferProfile
      Heat transfer coefficient profile along pipe (W/(m²·K)).
    • surfaceTemperatureProfile

      private double[] surfaceTemperatureProfile
      Surface temperature profile along pipe (K).
    • wallThickness

      private double wallThickness
      Pipe wall thickness (m).
    • wallDensity

      private double wallDensity
      Pipe wall density (kg/m³) - steel default.
    • wallHeatCapacity

      private double wallHeatCapacity
      Pipe wall specific heat capacity (J/(kg·K)) - steel default.
    • wallTemperatureProfile

      private double[] wallTemperatureProfile
      Pipe wall temperature profile (K).
    • soilThermalResistance

      private double soilThermalResistance
      Soil/burial thermal resistance (m²·K/W).
    • thermalCalculator

      private MultilayerThermalCalculator thermalCalculator
      Multi-layer thermal calculator for OLGA-style radial heat transfer.
    • useMultilayerThermalModel

      private boolean useMultilayerThermalModel
      Enable multi-layer thermal model (vs simple U-value).
    • enableJouleThomson

      private boolean enableJouleThomson
      Enable Joule-Thomson effect.
    • hydrateFormationTemperature

      private double hydrateFormationTemperature
      Hydrate formation temperature (K).
    • waxAppearanceTemperature

      private double waxAppearanceTemperature
      Wax appearance temperature (K).
    • localLossKFactors

      private Map<Double,Double> localLossKFactors
      K-factors for local losses (bends, valves, fittings) at specific positions. Key = position (m), Value = K-factor (dimensionless loss coefficient).
    • equivalentLengthFittings

      private double equivalentLengthFittings
      Total equivalent length of fittings (m). Used when individual positions are not specified. The equivalent length is added to the total pipe length for friction calculation.
    • numberOf90DegreeBends

      private int numberOf90DegreeBends
      Number of 90-degree bends. K-factor = 0.3-0.5 per bend typically.
    • numberOf45DegreeBends

      private int numberOf45DegreeBends
      Number of 45-degree bends. K-factor = 0.15-0.25 per bend typically.
    • inletLossCoefficient

      private double inletLossCoefficient
      Inlet loss coefficient. K-factor for inlet effects (sharp-edge inlet K ~ 0.5, bell-mouth K ~ 0.05).
    • outletLossCoefficient

      private double outletLossCoefficient
      Outlet loss coefficient. K-factor for outlet effects (sudden expansion K ~ 1.0).
    • hydrateRiskSections

      private boolean[] hydrateRiskSections
      Sections flagged for hydrate risk.
    • waxRiskSections

      private boolean[] waxRiskSections
      Sections flagged for wax risk.
    • insulationType

      private TwoFluidPipe.InsulationType insulationType
      Current insulation type.
    • enableSlugTracking

      private boolean enableSlugTracking
      Enable slug tracking.
    • outletSlugCount

      private int outletSlugCount
      Outlet slug statistics.
    • totalSlugVolumeAtOutlet

      private double totalSlugVolumeAtOutlet
    • lastSlugArrivalTime

      private double lastSlugArrivalTime
    • maxSlugLengthAtOutlet

      private double maxSlugLengthAtOutlet
    • maxSlugVolumeAtOutlet

      private double maxSlugVolumeAtOutlet
    • countedOutletSlugs

      private Set<Integer> countedOutletSlugs
      Track which slugs have already been counted at outlet (by slug ID).
    • olgaModelType

      private TwoFluidPipe.OLGAModelType olgaModelType
      Current OLGA model type. Default is FULL for best accuracy.
    • minimumLiquidHoldup

      private double minimumLiquidHoldup
      Base minimum liquid holdup for stratified flow (OLGA-style constraint).

      OLGA enforces a minimum holdup to prevent unrealistically low values at high gas velocities. This is based on the observation that even at high velocities, a thin liquid film remains on the pipe wall in stratified/annular flow.

      The actual minimum applied is the maximum of:

      • This base value (default 1%)
      • A multiple of the no-slip holdup (lambdaL * minimumSlipFactor)

      This ensures the minimum is physically reasonable for both lean gas (low liquid loading) and rich gas condensate (high liquid loading) systems.

      Reference: Bendiksen et al. (1991) "The Dynamic Two-Fluid Model OLGA" - SPE Production Engineering

    • minimumSlipFactor

      private double minimumSlipFactor
      Slip factor applied to no-slip holdup to calculate adaptive minimum.

      The adaptive minimum holdup is calculated as: lambdaL * minimumSlipFactor. For gas-dominant systems, typical slip ratios range from 1.5-3.0. Default value of 2.0 means minimum holdup is twice the no-slip value, which accounts for liquid accumulation due to slip. This prevents the minimum from being unrealistically high for lean gas systems with very low liquid loading.

    • useAdaptiveMinimumOnly

      private boolean useAdaptiveMinimumOnly
      Use only adaptive (correlation-based) minimum, without absolute floor.

      When true, the minimum holdup is calculated purely from flow correlations (Beggs-Brill type) without enforcing the absolute minimumLiquidHoldup floor. This allows the model to predict very low holdups for lean gas systems where the physical holdup may be below 1%.

      Default is true for better handling of lean gas systems.

    • enforceMinimumSlip

      private boolean enforceMinimumSlip
      Enable OLGA-style minimum slip constraint.

      When enabled (default), enforces a minimum liquid holdup in gas-dominant stratified flow, matching OLGA behavior. When disabled, holdup can approach no-slip values at high velocities (Beggs-Brill style).

    • minimumFilmThickness

      private double minimumFilmThickness
      Minimum film thickness for annular flow (m).

      In high gas velocity annular flow, OLGA maintains a minimum liquid film on the pipe wall. This prevents unrealistically low holdup predictions. Default 0.1mm based on typical measurements.

    • annularEntrainmentFraction

      private double annularEntrainmentFraction
      Entrainment fraction in annular flow.

      Fraction of liquid entrained as droplets in the gas core. Affects the distribution between film flow and droplet flow in annular regime. OLGA uses Ishii-Mishima correlation.

    • enableAnnularFilmModel

      private boolean enableAnnularFilmModel
      Enable OLGA-style annular film model.

      When enabled, uses OLGA's annular film model which accounts for: - Minimum film thickness on pipe wall - Liquid entrainment in gas core - Wave formation and droplet deposition

    • enableTerrainTracking

      private boolean enableTerrainTracking
      Enable full OLGA-style terrain tracking.

      When enabled, uses OLGA's terrain tracking algorithm which: - Identifies all low points and high points - Tracks liquid accumulation in valleys - Models terrain-induced slugging - Handles severe slugging in risers

    • terrainSlugCriticalHoldup

      private double terrainSlugCriticalHoldup
      Critical holdup for terrain-induced slug initiation.

      When liquid holdup in a low point exceeds this value, a terrain-induced slug is initiated. Default 0.6 based on OLGA recommendations.

    • liquidFallbackCoefficient

      private double liquidFallbackCoefficient
      Liquid fallback coefficient for uphill sections.

      Controls how much liquid falls back in uphill sections when gas velocity is insufficient to carry liquid upward. Higher values mean more liquid accumulation. OLGA default ~0.3.

    • enableSevereSlugModel

      private boolean enableSevereSlugModel
      Enable severe slugging detection and modeling.

      Severe slugging occurs at riser bases when liquid periodically blocks gas flow. This cyclic phenomenon can cause large pressure and flow oscillations.

    • useOLGAFlowRegimeMap

      private boolean useOLGAFlowRegimeMap
      Use OLGA flow regime map instead of Taitel-Dukler.

      OLGA's flow regime map differs from Taitel-Dukler in several ways: - Different transition criteria for stratified wavy to slug - Accounts for pipe roughness effects - Better handling of inclined flow - Hysteresis in regime transitions

    • flowRegimeHysteresis

      private double flowRegimeHysteresis
      Flow regime transition hysteresis factor.

      OLGA uses hysteresis to prevent rapid switching between flow regimes. A value of 0.1 means 10% hysteresis band around transition boundaries.

    • thermodynamicUpdateInterval

      private int thermodynamicUpdateInterval
      Update thermodynamics every N steps.
    • ssUnderRelaxation

      private double ssUnderRelaxation
      Under-relaxation factor for steady-state pressure and holdup updates.

      Values between 0 and 1. Lower values improve stability at the cost of slower convergence. Default 0.5; the solver ramps from 0.3 up to this value over the first iterations.

    • ssFlashInterval

      private int ssFlashInterval
      Flash calculation interval during steady-state iterations.

      A TP-flash is performed for every section only every ssFlashInterval iterations. Reducing flash frequency from every iteration to every 5th cuts the dominant cost of the steady-state solver without significantly affecting accuracy.

    • ssMaxWallClockTime

      private double ssMaxWallClockTime
      Maximum wall-clock time for the steady-state solver (seconds).

      If the solver has not converged within this time, it stops with the best available profile and logs a warning. Prevents truly infinite run times for difficult configurations.

    • currentStep

      private int currentStep
      Current step count.
    • enableAdaptiveTimestepping

      private boolean enableAdaptiveTimestepping
      Enable adaptive timestepping that detects instability and reduces dt automatically.

      When enabled, the solver: (1) recomputes CFL-stable dt each sub-step based on current velocities, (2) detects instability (diverging pressure/holdup) and halves dt with retry, (3) grows dt back toward the CFL limit when stable.

    • adaptiveMaxPressure

      private double adaptiveMaxPressure
      Maximum pressure allowed before adaptive dt reduction triggers (Pa). Default 1000 bara.
    • adaptiveMaxPressureChangeRatio

      private double adaptiveMaxPressureChangeRatio
      Maximum allowed pressure change ratio per sub-step before triggering dt reduction. Default 0.2 (200% change per sub-step — catches genuine blow-up, not normal transient dynamics).
    • adaptiveDtFactor

      private transient double adaptiveDtFactor
      Current adaptive dt multiplier (starts at 1.0, reduced on instability, slowly grows back).
    • MIN_ADAPTIVE_DT_FACTOR

      private static final double MIN_ADAPTIVE_DT_FACTOR
      Minimum adaptive dt factor to prevent timestep from becoming infinitesimally small.
      See Also:
    • ADAPTIVE_DT_GROWTH

      private static final double ADAPTIVE_DT_GROWTH
      Growth rate for adaptive dt factor per stable sub-step (multiplicative). Controls how quickly the timestep recovers after a reduction.
      See Also:
    • isTransientMode

      private boolean isTransientMode
      Flag indicating transient mode (inlet P is free, not fixed from stream).
    • pressureProfile

      private double[] pressureProfile
      Pressure profile (Pa).
    • temperatureProfile

      private double[] temperatureProfile
      Temperature profile (K).
    • liquidHoldupProfile

      private double[] liquidHoldupProfile
      Liquid holdup profile.
    • gasVelocityProfile

      private double[] gasVelocityProfile
      Gas velocity profile (m/s).
    • liquidVelocityProfile

      private double[] liquidVelocityProfile
      Liquid velocity profile (m/s).
    • referenceFluid

      private SystemInterface referenceFluid
      Reference fluid for flash calculations.
  • Constructor Details

    • TwoFluidPipe

      public TwoFluidPipe(String name)
      Constructor with name only.
      Parameters:
      name - Equipment name
    • TwoFluidPipe

      public TwoFluidPipe(String name, StreamInterface inStream)
      Constructor with inlet stream.
      Parameters:
      name - Equipment name
      inStream - Inlet stream
  • Method Details

    • initSubModels

      private void initSubModels()
      Initialize sub-models.
    • initializeSections

      private void initializeSections()
      Initialize pipe sections with inlet conditions.
    • runSteadyState

      private void runSteadyState()
      Run steady-state initialization.

      Uses a two-phase approach for robust convergence:

      • Phase 1 — Forward march: Single sweep from inlet to outlet computing pressure and holdup section-by-section without flash calculations. Provides a physically consistent initial profile.
      • Phase 2 — Iterative refinement: Under-relaxed fixed-point iteration with sparse flash updates (every ssFlashInterval iterations) to account for condensation effects. Includes a wall-clock time guard to prevent infinite run times.
    • updateThermodynamicsWithCondensation

      private void updateThermodynamicsWithCondensation(double massFlow, double[] localMDotGas, double[] localMDotLiq)
      Update thermodynamics along pipe with condensation tracking.

      Performs TP-flash at each section to determine local phase fractions accounting for condensation/vaporization. This is critical for gas systems with water where liquid may condense as pressure drops and temperature decreases along the pipeline.

      Parameters:
      massFlow - Total mass flow rate [kg/s]
      localMDotGas - Array to store local gas mass flow rates [kg/s]
      localMDotLiq - Array to store local liquid mass flow rates [kg/s]
    • updateTemperatureProfile

      private void updateTemperatureProfile(double massFlow, double area)
      Update temperature profile along the pipe accounting for heat transfer.

      Steady-state energy balance: m_dot * Cp * dT/dx = -h * π * D * (T - T_surface) - μ_JT * dP/dx

      Parameters:
      massFlow - Total mass flow rate [kg/s]
      area - Pipe cross-sectional area [m²]
    • updateTransientTemperature

      private void updateTransientTemperature(double massFlow, double area, double dt)
      Update temperature profile for transient simulation including pipe wall thermal mass.

      Solves coupled fluid-wall energy equations:

      • Fluid: ρ_f * Cp_f * A * dT_f/dt = -m_dot * Cp_f * dT_f/dx - h_i * π * D * (T_f - T_w)
      • Wall: ρ_w * Cp_w * A_w * dT_w/dt = h_i * π * D * (T_f - T_w) - h_o * π * D_o * (T_w - T_amb)

      If multi-layer thermal model is enabled, uses MultilayerThermalCalculator for accurate radial heat transfer through multiple layers (steel, insulation, coatings, etc.).

      Parameters:
      massFlow - Total mass flow rate [kg/s]
      area - Pipe cross-sectional area [m²]
      dt - Time step [s]
    • updateTransientTemperatureMultilayer

      private void updateTransientTemperatureMultilayer(double massFlow, double area, double dt, double Cp, double muJT)
      Update temperature using multi-layer thermal model.

      This method implements OLGA-style radial heat transfer through multiple concentric layers. The heat transfer calculation uses:

      • Inner convective resistance from fluid to pipe wall
      • Conductive resistance through each layer
      • Thermal mass storage in each layer for transient response
      • Outer convective/conductive resistance to ambient
      Parameters:
      massFlow - Total mass flow rate [kg/s]
      area - Pipe cross-sectional area [m²]
      dt - Time step [s]
      Cp - Fluid heat capacity [J/(kg·K)]
      muJT - Joule-Thomson coefficient [K/Pa]
    • calculateInnerHTC

      private double calculateInnerHTC(double massFlow, double area)
      Calculate inner (fluid-side) heat transfer coefficient based on flow conditions.

      Uses Dittus-Boelter correlation for turbulent flow, constant Nusselt for laminar.

      Parameters:
      massFlow - Mass flow rate [kg/s]
      area - Pipe cross-sectional area [m²]
      Returns:
      Inner HTC in W/(m²·K)
    • calculateLocalHoldup

      private double[] calculateLocalHoldup(TwoFluidSection sec, TwoFluidSection prev, double mDotGas, double mDotLiq, double area)
      Calculate local liquid holdup using OLGA-style models with terrain effects.

      Supports multiple model types:

      • FULL OLGA: Momentum balance for stratified, film model for annular, Dukler for slug
      • SIMPLIFIED OLGA: Empirical correlations with minimum slip constraint
      • DRIFT_FLUX: Original NeqSim drift-flux model
      Parameters:
      sec - Current section
      prev - Previous section (upstream)
      mDotGas - Gas mass flow rate [kg/s]
      mDotLiq - Liquid mass flow rate [kg/s]
      area - Pipe cross-sectional area [m²]
      Returns:
      Array with [liquidHoldup, gasHoldup]
    • calculateDriftFluxHoldup

      private double calculateDriftFluxHoldup(double vsG, double vsL, double rhoG, double rhoL, double sigma, double inclination)
      Calculate holdup using original drift-flux model.

      Uses the drift-flux model: v_G = C_0 * v_m + v_gj where:

      • C_0 = distribution coefficient (~1.0-1.2 for pipe flow)
      • v_gj = drift velocity (gas rises relative to mixture)
      Parameters:
      vsG - Gas superficial velocity [m/s]
      vsL - Liquid superficial velocity [m/s]
      rhoG - Gas density [kg/m³]
      rhoL - Liquid density [kg/m³]
      sigma - Surface tension [N/m]
      inclination - Pipe inclination [radians]
      Returns:
      Liquid holdup [-]
    • calculateStratifiedHoldupOLGA

      private double calculateStratifiedHoldupOLGA(double vsG, double vsL, double rhoG, double rhoL, double muG, double muL, double sigma, double D, double theta)
      Calculate stratified flow liquid holdup using OLGA-style momentum balance.

      This method implements the OLGA approach for stratified flow, where the liquid level is determined by a momentum balance between the phases. The key principle is that at equilibrium, the pressure gradient must be equal in both phases.

      The momentum balance accounts for:

      • Wall friction in each phase (τ_wG, τ_wL)
      • Interfacial friction between phases (τ_i)
      • Gravity component for inclined pipes

      Uses exact circular segment geometry for wetted perimeters and areas, which is critical for accurate holdup prediction at low liquid fractions (lean gas systems).

      Reference: Bendiksen et al. (1991) "The Dynamic Two-Fluid Model OLGA: Theory and Application" SPE Production Engineering, May 1991, pp. 171-180

      Parameters:
      vsG - Gas superficial velocity [m/s]
      vsL - Liquid superficial velocity [m/s]
      rhoG - Gas density [kg/m³]
      rhoL - Liquid density [kg/m³]
      muG - Gas dynamic viscosity [Pa·s]
      muL - Liquid dynamic viscosity [Pa·s]
      sigma - Surface tension [N/m]
      D - Pipe diameter [m]
      theta - Pipe inclination [radians]
      Returns:
      Equilibrium liquid holdup [-]
    • calculateAnnularHoldupOLGA

      private double[] calculateAnnularHoldupOLGA(double vsG, double vsL, double rhoG, double rhoL, double muG, double muL, double sigma, double D, double theta)
      Calculate liquid holdup for annular flow using OLGA-style film model.

      In annular flow, liquid exists as a thin film on the pipe wall and as entrained droplets in the gas core. OLGA models this using:

      • Film flow momentum balance
      • Entrainment/deposition equilibrium
      • Minimum film thickness constraint

      Reference: Bendiksen et al. (1991) and OLGA Technical Manual

      Parameters:
      vsG - Gas superficial velocity [m/s]
      vsL - Liquid superficial velocity [m/s]
      rhoG - Gas density [kg/m³]
      rhoL - Liquid density [kg/m³]
      muG - Gas dynamic viscosity [Pa·s]
      muL - Liquid dynamic viscosity [Pa·s]
      sigma - Surface tension [N/m]
      D - Pipe diameter [m]
      theta - Pipe inclination [radians]
      Returns:
      Array with [total liquid holdup, film holdup, entrained fraction]
    • calculateSlugHoldupOLGA

      private double calculateSlugHoldupOLGA(double vsG, double vsL, double rhoG, double rhoL, double muL, double sigma, double D, double theta)
      Calculate liquid holdup for slug flow using OLGA model.

      OLGA models slug flow as a sequence of liquid slugs separated by gas bubbles (Taylor bubbles). The average holdup is determined by:

      • Slug body holdup (typically 0.7-1.0)
      • Film holdup under Taylor bubble
      • Slug frequency and length
      Parameters:
      vsG - Gas superficial velocity [m/s]
      vsL - Liquid superficial velocity [m/s]
      rhoG - Gas density [kg/m³]
      rhoL - Liquid density [kg/m³]
      muL - Liquid dynamic viscosity [Pa·s]
      sigma - Surface tension [N/m]
      D - Pipe diameter [m]
      theta - Pipe inclination [radians]
      Returns:
      Slug flow average liquid holdup [-]
    • applyTerrainAccumulation

      private double applyTerrainAccumulation(TwoFluidSection sec, TwoFluidSection prev, double baseHoldup)
      Calculate terrain-induced liquid accumulation enhancement using OLGA methodology.

      This implements the full OLGA terrain tracking algorithm which accounts for:

      • Low Point Accumulation: Liquid pools in valleys due to gravity. The volume of accumulated liquid depends on the depth of the valley and gas carrying capacity.
      • Uphill Liquid Fallback: When gas velocity is below critical velocity, liquid falls back. The critical velocity is based on Taitel-Dukler flooding criterion.
      • Downhill Drainage: Liquid accelerates on downhill sections, reducing holdup.
      • Riser Base Accumulation: Special treatment for transition from horizontal/downhill to steep uphill (severe slugging potential).
      • Terrain-Induced Slugging: When low-point holdup exceeds critical value, slugs form and surge out.

      Reference: Bendiksen et al. (1991) "The Dynamic Two-Fluid Model OLGA: Theory and Application" SPE Production Engineering, May 1991, pp. 171-180

      Parameters:
      sec - Current pipe section
      prev - Previous pipe section
      baseHoldup - Base holdup from flow regime correlation
      Returns:
      Enhanced holdup accounting for terrain effects
    • checkTerrainSlugEvents

      private void checkTerrainSlugEvents(double dt)
      Check for and handle terrain-induced slug events.

      Called during transient simulation to detect when accumulated liquid in low points reaches critical level and triggers a terrain-induced slug.

      Parameters:
      dt - Time step (s)
    • estimatePressureGradient

      private double estimatePressureGradient(TwoFluidSection sec)
      Estimate pressure gradient for steady-state initialization.

      Uses Haaland equation (explicit approximation to Colebrook-White) for friction factor, consistent with AdiabaticPipe and PipeBeggsAndBrills.

      Parameters:
      sec - Current pipe section
      Returns:
      Pressure gradient estimate (Pa/m)
    • calcDarcyFrictionFactor

      private double calcDarcyFrictionFactor(double rho, double velocity, double D, double mu)
      Calculate Darcy friction factor using the Haaland equation.
      Parameters:
      rho - fluid density (kg/m3)
      velocity - flow velocity (m/s)
      D - pipe diameter (m)
      mu - dynamic viscosity (Pa.s)
      Returns:
      Darcy friction factor
    • updateWaterOilHoldups

      private void updateWaterOilHoldups(TwoFluidSection sec, TwoFluidSection prev, double alphaL, double area)
      Update water and oil holdups for three-phase flow with terrain effects.

      Water is denser than oil, so it tends to accumulate in valleys (low spots) more than oil. This method calculates the local water cut which can vary along the pipe based on:

      • Gravity segregation: water settles faster in low-velocity regions
      • Terrain effects: water accumulates more in valleys
      • Slip between oil and water phases
      Parameters:
      sec - Current section
      prev - Previous section (upstream)
      alphaL - Total liquid holdup
      area - Pipe cross-sectional area
    • run

      public void run(UUID id)
      Description copied from class: Pipeline

      In this method all thermodynamic and unit operations will be calculated in a steady state calculation.

      Specified by:
      run in interface SimulationInterface
      Overrides:
      run in class Pipeline
      Parameters:
      id - UUID
    • runTransient

      public void runTransient(double dt, UUID id)
      Run transient simulation for specified time step.
      Specified by:
      runTransient in interface SimulationInterface
      Overrides:
      runTransient in class Pipeline
      Parameters:
      dt - Requested time step (s)
      id - Calculation identifier
    • validateAndCorrectState

      private void validateAndCorrectState(double[][] U_new, double[][] U_prev)
      Validate and correct state vector to prevent numerical instabilities.
      Parameters:
      U_new - New state to validate
      U_prev - Previous state for fallback
    • validateSectionStates

      private void validateSectionStates()
      Validate section states and fix any numerical issues.
    • calcStableTimeStep

      private double calcStableTimeStep()
      Calculate stable time step using CFL condition.
      Returns:
      stable time step [s]
    • calcConvectiveTimeStep

      private double calcConvectiveTimeStep()
      Calculate stable time step using convective CFL (material velocities only, no sound speed). Used by the IMEX pressure correction method which handles acoustic waves implicitly.

      dt_convective = CFL * dx / max(|v_G|, |v_L|)

      Typically 10-100x larger than the acoustic CFL for gas-liquid flows.

      Returns:
      stable convective time step (s)
    • updateThermodynamics

      private void updateThermodynamics()
      Update thermodynamic properties using flash calculations.
    • reconstructPressureProfile

      private void reconstructPressureProfile()
      Reconstruct pressure profile from the evolved conservative variables.

      After mass and momentum are updated by the time integrator, the pressure at each section must be recomputed. The method handles different boundary condition types:

      • CONSTANT_PRESSURE: Fixed pressure (Dirichlet BC) - backward march from outlet
      • CLOSED: Zero gradient (Neumann BC, dp/dx = 0) - pressure floats based on interior

      When both boundaries are CLOSED, pressure evolves from the interior state without external forcing, allowing the system to reach true equilibrium.

    • reconstructPressureClosedSystem

      private void reconstructPressureClosedSystem()
      Reconstruct pressure for fully closed system (both ends CLOSED).

      In a closed system, there is no external pressure reference. The simplest stable approach is to NOT modify interior pressures (let them evolve naturally from the transient momentum equations), and ONLY apply Neumann BC at the boundaries.

      The key insight: the time integrator has already evolved the conservative variables (mass, momentum) consistently. We should not fight that by imposing additional pressure changes. Instead, we just ensure the boundaries have zero pressure gradient.

    • reconstructPressureOutletClosed

      private void reconstructPressureOutletClosed()
      Reconstruct pressure when outlet is CLOSED (Neumann BC at outlet).

      Use forward marching from inlet reference, then apply Neumann BC at outlet.

    • applyBoundaryConditions

      private void applyBoundaryConditions()
      Apply boundary conditions.
    • applyCharacteristicInletBC

      private void applyCharacteristicInletBC(TwoFluidSection inlet)
      Apply characteristic (Riemann-invariant) boundary condition at inlet.

      For subsonic inflow, there are two incoming characteristics (one from outside with boundary data, one from interior). The gas-phase Riemann invariants are:

      • J+ = v + 2c/(gamma-1) : right-running, carries information from outside at inlet
      • J- = v - 2c/(gamma-1) : left-running, carries information from interior

      At the inlet, J+ is specified from the boundary data (inlet stream) and J- is extrapolated from the interior (cell 1). The boundary state is solved from the intersection.

      Parameters:
      inlet - the inlet section to update
    • applyCharacteristicOutletBC

      private void applyCharacteristicOutletBC(TwoFluidSection outlet)
      Apply characteristic (Riemann-invariant) boundary condition at outlet.

      For subsonic outflow, there is one incoming characteristic from outside (back-pressure) and one outgoing from interior. At the outlet:

      • J- = v - 2c/(gamma-1) : left-running, carries boundary data (back-pressure)
      • J+ = v + 2c/(gamma-1) : right-running, carries information from interior
      Parameters:
      outlet - the outlet section to update
    • updateOutletStream

      private void updateOutletStream()
      Update outlet stream with current outlet conditions.
    • updateResultArrays

      private void updateResultArrays()
      Update result arrays from section states.

      Array length equals numberOfSections, with each element representing the section midpoint values.

    • getLiquidInventory

      public double getLiquidInventory(String unit)
      Get total liquid inventory in the pipe.

      Calculates inventory from conservative mass per length, converted to volume using local liquid density. This ensures consistency with the solver's mass tracking.

      Parameters:
      unit - Volume unit ("m3", "bbl", "L")
      Returns:
      Liquid volume
    • getPressureProfile

      public double[] getPressureProfile()
      Get pressure profile.
      Specified by:
      getPressureProfile in interface PipeLineInterface
      Overrides:
      getPressureProfile in class Pipeline
      Returns:
      Pressure at each section (Pa)
    • getTemperatureProfile

      public double[] getTemperatureProfile()
      Get temperature profile.
      Specified by:
      getTemperatureProfile in interface PipeLineInterface
      Overrides:
      getTemperatureProfile in class Pipeline
      Returns:
      Temperature at each section (K)
    • getLiquidHoldupProfile

      public double[] getLiquidHoldupProfile()
      Get liquid holdup profile.

      For consistency with oil and water holdups, the liquid holdup is calculated as the sum of oil and water holdups.

      Specified by:
      getLiquidHoldupProfile in interface PipeLineInterface
      Overrides:
      getLiquidHoldupProfile in class Pipeline
      Returns:
      Holdup at each section (0-1)
    • getWaterCutProfile

      public double[] getWaterCutProfile()
      Get water cut profile along the pipeline.

      For three-phase flow, water cut can vary along the pipeline as water accumulates in low spots (valleys) due to its higher density compared to oil.

      Returns:
      Water cut at each section (0-1, fraction of liquid that is water)
    • getWaterHoldupProfile

      public double[] getWaterHoldupProfile()
      Get water holdup profile along the pipeline.
      Returns:
      Water holdup at each section (0-1, fraction of pipe area occupied by water)
    • getOilHoldupProfile

      public double[] getOilHoldupProfile()
      Get oil holdup profile along the pipeline.
      Returns:
      Oil holdup at each section (0-1, fraction of pipe area occupied by oil)
    • getGasVelocityProfile

      public double[] getGasVelocityProfile()
      Get gas velocity profile.
      Returns:
      Gas velocity at each section (m/s)
    • getLiquidVelocityProfile

      public double[] getLiquidVelocityProfile()
      Get liquid velocity profile.
      Returns:
      Liquid velocity at each section (m/s)
    • getOilVelocityProfile

      public double[] getOilVelocityProfile()
      Get oil velocity profile along the pipeline.

      When water-oil slip is enabled, this returns the independent oil velocity. Otherwise, it returns the combined liquid velocity.

      Returns:
      Oil velocity at each section (m/s)
    • getWaterVelocityProfile

      public double[] getWaterVelocityProfile()
      Get water velocity profile along the pipeline.

      When water-oil slip is enabled, this returns the independent water velocity. Otherwise, it returns the combined liquid velocity.

      Returns:
      Water velocity at each section (m/s)
    • getOilWaterSlipProfile

      public double[] getOilWaterSlipProfile()
      Get oil-water velocity slip profile along the pipeline.

      Returns the difference between oil and water velocities (vOil - vWater). Positive values indicate oil is flowing faster than water.

      Returns:
      Oil-water slip velocity at each section (m/s)
    • getFlowRegimeProfile

      public PipeSection.FlowRegime[] getFlowRegimeProfile()
      Get flow regime at each section.
      Returns:
      Array of flow regimes
    • getPositionProfile

      public double[] getPositionProfile()
      Get position array for plotting.
      Returns:
      Position along pipe (m), one value per section at section midpoint
    • getSimulationTime

      public double getSimulationTime()
      Get current simulation time.
      Returns:
      Time (s)
    • getAccumulationTracker

      public LiquidAccumulationTracker getAccumulationTracker()
      Get accumulation tracker for detailed analysis.
      Returns:
      Accumulation tracker
    • getSlugTracker

      public SlugTracker getSlugTracker()
      Get slug tracker for slug statistics (simplified model).
      Returns:
      Slug tracker
    • getLagrangianSlugTracker

      public LagrangianSlugTracker getLagrangianSlugTracker()
      Get Lagrangian slug tracker for OLGA-style slug tracking.
      Returns:
      Lagrangian slug tracker
    • getSlugTrackingMode

      public TwoFluidPipe.SlugTrackingMode getSlugTrackingMode()
      Get current slug tracking mode.
      Returns:
      slug tracking mode
    • setSlugTrackingMode

      public void setSlugTrackingMode(TwoFluidPipe.SlugTrackingMode mode)
      Set slug tracking mode.

      Available modes:

      • SIMPLIFIED: Simple slug unit model with basic tracking
      • LAGRANGIAN: Full OLGA-style Lagrangian tracking with wake effects, frequency-based initiation, and detailed statistics
      • DISABLED: No slug tracking
      Parameters:
      mode - slug tracking mode
    • configureLagrangianSlugTracking

      public void configureLagrangianSlugTracking(boolean enableInletGeneration, boolean enableTerrainGeneration, boolean enableWakeEffects)
      Configure Lagrangian slug tracker parameters.

      This method provides access to advanced slug tracking configuration for the OLGA-style Lagrangian model.

      Parameters:
      enableInletGeneration - enable hydrodynamic slug generation at inlet
      enableTerrainGeneration - enable terrain-induced slug generation
      enableWakeEffects - enable wake interaction between slugs
    • getSlugTrackingStatisticsJson

      public String getSlugTrackingStatisticsJson()
      Get slug tracking statistics as JSON string.
      Returns:
      JSON string with slug statistics
    • trackOutletSlugs

      private void trackOutletSlugs()
      Track slugs arriving at outlet and collect statistics. Each slug is only counted once when it first reaches the outlet region.
    • trackOutletSlugsLagrangian

      private void trackOutletSlugsLagrangian()
      Track slugs arriving at outlet using Lagrangian tracker.
    • getOutletSlugCount

      public int getOutletSlugCount()
      Get number of slugs that have arrived at outlet.
      Returns:
      Outlet slug count
    • getTotalSlugVolumeAtOutlet

      public double getTotalSlugVolumeAtOutlet()
      Get total liquid volume delivered by slugs at outlet.
      Returns:
      Total slug volume (m³)
    • getLastSlugArrivalTime

      public double getLastSlugArrivalTime()
      Get time of last slug arrival at outlet.
      Returns:
      Time (s)
    • getMaxSlugLengthAtOutlet

      public double getMaxSlugLengthAtOutlet()
      Get maximum slug length observed at outlet.
      Returns:
      Max length (m)
    • getMaxSlugVolumeAtOutlet

      public double getMaxSlugVolumeAtOutlet()
      Get maximum slug volume observed at outlet.
      Returns:
      Max volume (m³)
    • getSlugStatisticsSummary

      public String getSlugStatisticsSummary()
      Get slug statistics summary string.
      Returns:
      Statistics summary
    • setLength

      public void setLength(double length)
      Set pipe length.
      Specified by:
      setLength in interface PipeLineInterface
      Overrides:
      setLength in class Pipeline
      Parameters:
      length - Length (m)
    • getLength

      public double getLength()
      Get pipe length.
      Specified by:
      getLength in interface PipeLineInterface
      Overrides:
      getLength in class Pipeline
      Returns:
      Length (m)
    • setDiameter

      public void setDiameter(double diameter)
      Set pipe diameter.
      Specified by:
      setDiameter in interface PipeLineInterface
      Overrides:
      setDiameter in class Pipeline
      Parameters:
      diameter - Diameter (m)
    • getDiameter

      public double getDiameter()
      Get pipe diameter.
      Specified by:
      getDiameter in interface PipeLineInterface
      Overrides:
      getDiameter in class Pipeline
      Returns:
      Diameter (m)
    • setRoughness

      public void setRoughness(double roughness)
      Set pipe wall roughness.
      Parameters:
      roughness - Roughness (m)
    • getRoughness

      public double getRoughness()
      Get pipe wall roughness.
      Returns:
      Roughness (m)
    • setNumberOfSections

      public void setNumberOfSections(int numberOfSections)
      Set number of computational sections.
      Parameters:
      numberOfSections - Number of sections
    • setSectionLengths

      public void setSectionLengths(double[] lengths)
      Set per-section lengths for non-uniform mesh.

      Enables variable spatial resolution along the pipe. Use shorter sections at elevation changes, risers, and dips where flow regime transitions occur, and longer sections in uniform horizontal/vertical runs. This follows the same approach used in OLGA and LedaFlow for optimising accuracy without unnecessary computational cost.

      The array length determines the number of sections. The sum of all lengths must equal the total pipe length (set via setLength(double)). The CFL time step will be governed by the smallest section length.

      Parameters:
      lengths - Array of section lengths (m), one per computational cell
      Throws:
      IllegalArgumentException - if lengths is null or empty
    • getSectionLengths

      public double[] getSectionLengths()
      Get per-section lengths. Returns null if uniform mesh is used.
      Returns:
      Array of section lengths (m) or null for uniform mesh
    • generateRefinedMesh

      public void generateRefinedMesh(int baseSections, double refinementFactor)
      Generate a non-uniform mesh with refinement at elevation changes.

      Automatically creates finer sections where the elevation profile has large gradients (risers, dips, terrain changes) and coarser sections in uniform regions. The refinement factor controls how much finer the mesh is at elevation changes relative to flat sections.

      This follows OLGA/LedaFlow best practice: short sections (units to tens of pipe diameters) at elevation breaks, longer sections (50-200 m) on uniform runs.

      Parameters:
      baseSections - Base number of sections for uniform regions
      refinementFactor - How much finer to make sections at elevation changes (2-10)
    • getNumberOfSections

      public int getNumberOfSections()
      Get number of sections.
      Returns:
      Number of sections
    • setElevationProfile

      public void setElevationProfile(double[] elevations)
      Set elevation profile.
      Parameters:
      elevations - Elevation at each section (m)
    • setOutletPressure

      public void setOutletPressure(double pressure)
      Set outlet pressure.
      Specified by:
      setOutletPressure in interface PipeLineInterface
      Specified by:
      setOutletPressure in interface TwoPortInterface
      Overrides:
      setOutletPressure in class Pipeline
      Parameters:
      pressure - Pressure (Pa)
    • setInletBoundaryCondition

      public void setInletBoundaryCondition(TwoFluidPipe.BoundaryCondition bcType)
      Set inlet boundary condition type.

      Options:

      • STREAM_CONNECTED (default): Flow rate, temperature, composition from inlet stream
      • CONSTANT_FLOW: Use explicit mass flow set via setInletMassFlow()
      • CONSTANT_PRESSURE: Use explicit pressure set via setInletPressure()
      Parameters:
      bcType - the inlet boundary condition type
    • setOutletBoundaryCondition

      public void setOutletBoundaryCondition(TwoFluidPipe.BoundaryCondition bcType)
      Set outlet boundary condition type.

      Options:

      • CONSTANT_PRESSURE (default): Fixed pressure at outlet
      • CONSTANT_FLOW: Fixed mass flow at outlet (requires inlet pressure BC)
      • STREAM_CONNECTED: Pressure from downstream equipment
      • CLOSED: Zero flow velocity (blocked/shut-in) - pressure floats
      Parameters:
      bcType - the outlet boundary condition type
    • getInletBoundaryCondition

      public TwoFluidPipe.BoundaryCondition getInletBoundaryCondition()
      Get inlet boundary condition type.
      Returns:
      the inlet boundary condition type
    • getOutletBoundaryCondition

      public TwoFluidPipe.BoundaryCondition getOutletBoundaryCondition()
      Get outlet boundary condition type.
      Returns:
      the outlet boundary condition type
    • setInletMassFlow

      public void setInletMassFlow(double massFlow)
      Set inlet mass flow for CONSTANT_FLOW boundary condition.
      Parameters:
      massFlow - Mass flow rate (kg/s)
    • setInletMassFlow

      public void setInletMassFlow(double massFlow, String unit)
      Set inlet mass flow with unit for CONSTANT_FLOW boundary condition.
      Parameters:
      massFlow - Mass flow rate value
      unit - Unit ("kg/s", "kg/hr", "kg/sec", "ton/hr")
    • setInletPressure

      public void setInletPressure(double pressure)
      Set inlet pressure for CONSTANT_PRESSURE boundary condition.
      Specified by:
      setInletPressure in interface TwoPortInterface
      Overrides:
      setInletPressure in class TwoPortEquipment
      Parameters:
      pressure - Pressure (Pa)
    • setInletPressure

      public void setInletPressure(double pressure, String unit)
      Set inlet pressure with unit.
      Parameters:
      pressure - Pressure value
      unit - Pressure unit ("Pa", "bara", "barg", "psia")
    • setOutletPressure

      public void setOutletPressure(double pressure, String unit)
      Set outlet pressure with unit.
      Specified by:
      setOutletPressure in interface TwoPortInterface
      Overrides:
      setOutletPressure in class TwoPortEquipment
      Parameters:
      pressure - Pressure value
      unit - Pressure unit ("Pa", "bara", "barg", "psia")
    • closeOutlet

      public void closeOutlet()
      Close the pipe outlet (blocked/shut-in condition).

      Sets outlet boundary condition to CLOSED, meaning zero flow velocity at outlet. Pressure will build up during transient simulation as mass accumulates in the pipe. Useful for:

      • Shut-in scenario analysis
      • Pressure surge/water hammer studies
      • Line packing simulations
      • Emergency shutdown modeling
    • openOutlet

      public void openOutlet()
      Open the pipe outlet with constant pressure boundary condition.

      Restores outlet to CONSTANT_PRESSURE boundary condition. The outlet pressure is set to the value previously set via setOutletPressure(), or defaults to 1 bara if not set.

    • openOutlet

      public void openOutlet(double pressure, String unit)
      Open the pipe outlet with specified pressure.
      Parameters:
      pressure - Outlet pressure value
      unit - Pressure unit ("Pa", "bara", "barg", "psia")
    • closeInlet

      public void closeInlet()
      Close the pipe inlet (blocked/no inflow condition).

      Sets inlet boundary condition to CLOSED, meaning zero flow velocity at inlet. Pressure will decrease during transient simulation as mass leaves the pipe. Useful for:

      • Blowdown simulation
      • Depressurization studies
      • Emergency shutdown with upstream closure
    • openInlet

      public void openInlet()
      Open the pipe inlet with stream-connected boundary condition.

      Restores inlet to STREAM_CONNECTED boundary condition, using flow rate, temperature, and composition from the connected inlet stream.

    • isOutletClosed

      public boolean isOutletClosed()
      Check if outlet is closed.
      Returns:
      true if outlet boundary condition is CLOSED
    • isInletClosed

      public boolean isInletClosed()
      Check if inlet is closed.
      Returns:
      true if inlet boundary condition is CLOSED
    • setCflNumber

      public void setCflNumber(double cfl)
      Set CFL number for time stepping.
      Parameters:
      cfl - CFL number (0 < cfl < 1)
    • setTimeIntegrationMethod

      public void setTimeIntegrationMethod(TimeIntegrator.Method method)
      Set the time integration method.

      Use TimeIntegrator.Method.IMEX_PRESSURE_CORRECTION for long pipelines where the acoustic CFL constraint is prohibitively small. The IMEX method solves the pressure wave equation implicitly, allowing time steps 10-100x larger than explicit schemes.

      Parameters:
      method - integration method (RK4, EULER, IMEX_PRESSURE_CORRECTION, etc.)
    • getTimeIntegrationMethod

      public TimeIntegrator.Method getTimeIntegrationMethod()
      Get the current time integration method.
      Returns:
      current integration method
    • setMaxSimulationTime

      public void setMaxSimulationTime(double time)
      Set maximum simulation time for transient calculations.
      Parameters:
      time - Maximum simulation time in seconds
    • getMaxSimulationTime

      public double getMaxSimulationTime()
      Get maximum simulation time.
      Returns:
      Maximum simulation time in seconds
    • setIncludeEnergyEquation

      public void setIncludeEnergyEquation(boolean include)
      Enable/disable energy equation.
      Parameters:
      include - true to include energy equation
    • setSurfaceTemperature

      public void setSurfaceTemperature(double temperature, String unit)
      Set surface temperature for heat transfer calculations.

      Enables heat transfer modeling. The pipe loses/gains heat to reach this temperature.

      Parameters:
      temperature - Surface temperature in the specified unit
      unit - Temperature unit ("K" or "C")
    • setHeatTransferCoefficient

      public void setHeatTransferCoefficient(double heatTransferCoefficient)
      Set heat transfer coefficient for convective heat transfer.

      Heat transfer rate: Q = h * A * (T_pipe - T_surface)
      where h = heat transfer coefficient (W/(m²·K))
      A = pipe surface area (m²)
      T_pipe = bulk fluid temperature (K)
      T_surface = surrounding surface temperature (K)

      Typical values:

      • Insulated subsea pipe: 5-15 W/(m²·K)
      • Uninsulated subsea pipe: 20-30 W/(m²·K)
      • Exposed/above-ground pipe: 50-100 W/(m²·K)
      Specified by:
      setHeatTransferCoefficient in interface PipeLineInterface
      Overrides:
      setHeatTransferCoefficient in class Pipeline
      Parameters:
      heatTransferCoefficient - Heat transfer coefficient in W/(m²·K)
    • getSurfaceTemperature

      public double getSurfaceTemperature()
      Get the surface temperature used for heat transfer calculations.
      Returns:
      Surface temperature in Kelvin
    • getHeatTransferCoefficient

      public double getHeatTransferCoefficient()
      Get the heat transfer coefficient.
      Specified by:
      getHeatTransferCoefficient in interface PipeLineInterface
      Overrides:
      getHeatTransferCoefficient in class Pipeline
      Returns:
      Heat transfer coefficient in W/(m²·K)
    • isHeatTransferEnabled

      public boolean isHeatTransferEnabled()
      Check if heat transfer is enabled.
      Returns:
      true if heat transfer modeling is active
    • setIncludeMassTransfer

      public void setIncludeMassTransfer(boolean include)
      Enable/disable mass transfer (flashing/condensation).
      Parameters:
      include - true to include mass transfer
    • setEnableSlugTracking

      public void setEnableSlugTracking(boolean enable)
      Enable/disable slug tracking.
      Parameters:
      enable - true to enable slug tracking
    • setEnableAdaptiveTimestepping

      public void setEnableAdaptiveTimestepping(boolean enable)
      Enable adaptive timestepping (OLGA/LedaFlow-style).

      When enabled, the solver automatically adjusts the internal sub-step size to maintain stability. Per sub-step, it: (1) recomputes the CFL-stable dt from current velocities, (2) monitors solution quality (pressure change, holdup divergence, velocity blow-up), (3) rejects bad steps and halves dt with state rollback, (4) gradually grows dt back when stable.

      This approach follows the semi-implicit OLGA paradigm: the CFL condition is evaluated from material velocities (not sound speed) when using IMEX integration, allowing large timesteps for long pipelines. The adaptive controller ensures stability across flow regime transitions, terrain slugging, valve operations, and riser-base dynamics.

      Parameters:
      enable - true to enable adaptive timestepping
    • isAdaptiveTimesteppingEnabled

      public boolean isAdaptiveTimesteppingEnabled()
      Check if adaptive timestepping is enabled.
      Returns:
      true if adaptive timestepping is enabled
    • getAdaptiveDtFactor

      public double getAdaptiveDtFactor()
      Get the current adaptive dt factor (1.0 = full CFL step, lower = reduced for stability).

      Useful for monitoring: if this stays well below 1.0, the simulation is fighting instability.

      Returns:
      current adaptive dt factor in range [0.001, 1.0]
    • setAdaptiveMaxPressure

      public void setAdaptiveMaxPressure(double maxPressureBar)
      Set the maximum pressure before adaptive dt reduction triggers.
      Parameters:
      maxPressureBar - maximum pressure in bara (default 1000)
    • setEnableWaterOilSlip

      public void setEnableWaterOilSlip(boolean enable)
      Enable water-oil velocity slip modeling.

      When enabled, uses 7-equation model with separate oil and water momentum equations, allowing water and oil phases to flow at different velocities. This is important for:

      • Uphill flow: water slips back relative to oil due to higher density
      • Downhill flow: water accelerates relative to oil
      • Stratified oil-water flow with shear at interface
      Parameters:
      enable - true to enable 7-equation model with oil-water slip
    • isWaterOilSlipEnabled

      public boolean isWaterOilSlipEnabled()
      Check if water-oil velocity slip modeling is enabled.
      Returns:
      true if 7-equation model is enabled
    • setThermodynamicUpdateInterval

      public void setThermodynamicUpdateInterval(int interval)
      Set thermodynamic update interval.
      Parameters:
      interval - Update every N time steps
    • setSteadyStateUnderRelaxation

      public void setSteadyStateUnderRelaxation(double factor)
      Set the under-relaxation factor for steady-state pressure and holdup updates.
      Parameters:
      factor - Relaxation factor in range (0, 1]. Lower is more stable but slower.
    • setSteadyStateFlashInterval

      public void setSteadyStateFlashInterval(int interval)
      Set the flash calculation interval during steady-state iterations.

      A TP-flash is performed for every section only every N iterations. Default is 5.

      Parameters:
      interval - Flash every N iterations (1 = every iteration)
    • setSteadyStateMaxWallClockTime

      public void setSteadyStateMaxWallClockTime(double seconds)
      Set the maximum wall-clock time for the steady-state solver.
      Parameters:
      seconds - Maximum time in seconds (default 30)
    • setMinimumLiquidHoldup

      public void setMinimumLiquidHoldup(double minHoldup)
      Set minimum liquid holdup for stratified flow (OLGA-style constraint).

      This parameter enforces a minimum liquid holdup in gas-dominant stratified flow, preventing unrealistically low values at high gas velocities. OLGA uses a similar approach based on the observation that a thin liquid film always remains on the pipe wall.

      Typical values:

      • 0.005 (0.5%) - Default, suitable for gas-condensate systems
      • 0.01 (1%) - Conservative estimate for wet gas
      • 0.02 (2%) - High liquid loading or wavy stratified flow
      Parameters:
      minHoldup - Base minimum liquid holdup fraction (0-1), default 0.01
    • getMinimumLiquidHoldup

      public double getMinimumLiquidHoldup()
      Get base minimum liquid holdup for stratified flow.
      Returns:
      Base minimum liquid holdup fraction (0-1)
    • setMinimumSlipFactor

      public void setMinimumSlipFactor(double slipFactor)
      Set the slip factor used for adaptive minimum holdup calculation.

      The adaptive minimum holdup is calculated as: lambdaL * minimumSlipFactor, where lambdaL is the no-slip (input) liquid fraction. This ensures physically reasonable minimum holdup for systems with varying liquid loading.

      Example: For a lean gas with 0.5% liquid loading and slipFactor=2.0:

      • adaptiveMin = 0.005 * 2.0 = 1% holdup
      • This is more reasonable than a fixed 5% minimum
      Parameters:
      slipFactor - Multiplier for no-slip holdup (1.0-5.0), default 2.0
    • getMinimumSlipFactor

      public double getMinimumSlipFactor()
      Get the slip factor used for adaptive minimum holdup calculation.
      Returns:
      Slip factor (multiplier for no-slip holdup)
    • setEnforceMinimumSlip

      public void setEnforceMinimumSlip(boolean enforce)
      Enable or disable OLGA-style minimum slip constraint.

      When enabled (default), enforces a minimum liquid holdup in gas-dominant stratified flow. This matches OLGA behavior and prevents unrealistically low holdup at high velocities.

      When disabled, holdup can approach no-slip values at high Froude numbers, similar to the original Beggs-Brill correlation behavior.

      Parameters:
      enforce - true to enforce minimum slip (OLGA-style, default), false for Beggs-Brill style
    • isEnforceMinimumSlip

      public boolean isEnforceMinimumSlip()
      Check if OLGA-style minimum slip constraint is enabled.
      Returns:
      true if minimum slip is enforced (OLGA-style)
    • setUseAdaptiveMinimumOnly

      public void setUseAdaptiveMinimumOnly(boolean useAdaptive)
      Set whether to use adaptive-only minimum holdup (no absolute floor).

      When true (default), the minimum holdup is calculated purely from flow correlations (Beggs-Brill type) scaled by the no-slip holdup, without enforcing an absolute floor. This allows the model to predict very low holdups for lean gas systems where the physical holdup may be well below 1%.

      When false, an absolute minimum (minimumLiquidHoldup, default 0.1%) is enforced in addition to the correlation-based minimum. This is more conservative but may overpredict holdup for very lean gas systems.

      Parameters:
      useAdaptive - true to use correlation-only minimum (recommended for lean gas), false to also enforce absolute floor
    • isUseAdaptiveMinimumOnly

      public boolean isUseAdaptiveMinimumOnly()
      Check if adaptive-only minimum holdup mode is enabled.
      Returns:
      true if using correlation-based minimum only (no absolute floor)
    • setOLGAModelType

      public void setOLGAModelType(TwoFluidPipe.OLGAModelType modelType)
      Set the OLGA model type for holdup and flow regime calculations.

      Available model types:

      • FULL - Full OLGA model with momentum balance for all flow regimes (most accurate)
      • SIMPLIFIED - Simplified OLGA model with empirical correlations (faster)
      • DRIFT_FLUX - Original NeqSim drift-flux model (for backward compatibility)
      Parameters:
      modelType - the OLGA model type to use
    • getOLGAModelType

      public TwoFluidPipe.OLGAModelType getOLGAModelType()
      Get the current OLGA model type.
      Returns:
      the current OLGA model type
    • setMinimumFilmThickness

      public void setMinimumFilmThickness(double thickness)
      Set minimum film thickness for annular flow model.
      Parameters:
      thickness - minimum film thickness in meters (default 0.0001 m = 0.1 mm)
    • getMinimumFilmThickness

      public double getMinimumFilmThickness()
      Get minimum film thickness for annular flow model.
      Returns:
      minimum film thickness in meters
    • setEnableAnnularFilmModel

      public void setEnableAnnularFilmModel(boolean enable)
      Enable or disable OLGA-style annular film model.
      Parameters:
      enable - true to enable annular film model
    • isEnableAnnularFilmModel

      public boolean isEnableAnnularFilmModel()
      Check if annular film model is enabled.
      Returns:
      true if annular film model is enabled
    • setEnableTerrainTracking

      public void setEnableTerrainTracking(boolean enable)
      Enable or disable full terrain tracking.

      Terrain tracking identifies low points and models liquid accumulation in valleys. Required for accurate liquid inventory prediction in undulating pipelines.

      Parameters:
      enable - true to enable terrain tracking (default true)
    • isEnableTerrainTracking

      public boolean isEnableTerrainTracking()
      Check if terrain tracking is enabled.
      Returns:
      true if terrain tracking is enabled
    • setTerrainSlugCriticalHoldup

      public void setTerrainSlugCriticalHoldup(double criticalHoldup)
      Set the critical holdup for terrain-induced slug initiation.
      Parameters:
      criticalHoldup - holdup fraction (0-1) at which terrain slug initiates (default 0.6)
    • getTerrainSlugCriticalHoldup

      public double getTerrainSlugCriticalHoldup()
      Get the critical holdup for terrain-induced slug initiation.
      Returns:
      critical holdup fraction
    • setLiquidFallbackCoefficient

      public void setLiquidFallbackCoefficient(double coefficient)
      Set the liquid fallback coefficient for uphill sections.

      Controls liquid accumulation in uphill sections. Higher values mean more liquid falls back and accumulates. OLGA default is approximately 0.3.

      Parameters:
      coefficient - fallback coefficient (0-1), default 0.3
    • getLiquidFallbackCoefficient

      public double getLiquidFallbackCoefficient()
      Get the liquid fallback coefficient.
      Returns:
      liquid fallback coefficient
    • setEnableSevereSlugModel

      public void setEnableSevereSlugModel(boolean enable)
      Enable or disable severe slugging model for risers.
      Parameters:
      enable - true to enable severe slugging detection (default true)
    • isEnableSevereSlugModel

      public boolean isEnableSevereSlugModel()
      Check if severe slugging model is enabled.
      Returns:
      true if severe slugging model is enabled
    • setUseOLGAFlowRegimeMap

      public void setUseOLGAFlowRegimeMap(boolean enable)
      Enable or disable OLGA flow regime map.

      When enabled, uses OLGA's flow regime transition criteria instead of Taitel-Dukler. OLGA's criteria include roughness effects and better inclined flow handling.

      Parameters:
      enable - true to use OLGA flow regime map (default true)
    • isUseOLGAFlowRegimeMap

      public boolean isUseOLGAFlowRegimeMap()
      Check if OLGA flow regime map is used.
      Returns:
      true if OLGA flow regime map is enabled
    • setFlowRegimeHysteresis

      public void setFlowRegimeHysteresis(double hysteresis)
      Set flow regime transition hysteresis factor.

      Prevents rapid switching between flow regimes near transition boundaries. A value of 0.1 means 10% hysteresis band.

      Parameters:
      hysteresis - hysteresis factor (0-0.5), default 0.1
    • getFlowRegimeHysteresis

      public double getFlowRegimeHysteresis()
      Get flow regime transition hysteresis factor.
      Returns:
      hysteresis factor
    • setInsulationType

      public void setInsulationType(TwoFluidPipe.InsulationType type)
      Set insulation type using predefined U-values.

      This is a convenience method that sets appropriate heat transfer coefficient based on insulation type. Automatically enables heat transfer modeling.

      Parameters:
      type - Insulation type preset
    • getInsulationTypeEnum

      public TwoFluidPipe.InsulationType getInsulationTypeEnum()
      Get the current insulation type.
      Returns:
      Current insulation type
    • getInsulationType

      public String getInsulationType()
      Get the insulation type/material.
      Specified by:
      getInsulationType in interface PipeLineInterface
      Overrides:
      getInsulationType in class Pipeline
      Returns:
      insulation type
    • setInsulationType

      public void setInsulationType(String type)
      Set the insulation type/material.
      Specified by:
      setInsulationType in interface PipeLineInterface
      Overrides:
      setInsulationType in class Pipeline
      Parameters:
      type - insulation type (e.g., "polyurethane", "mineral wool", "aerogel")
    • setHeatTransferProfile

      public void setHeatTransferProfile(double[] profile)
      Set heat transfer coefficient profile along the pipe.

      Allows different U-values at different positions (e.g., buried vs exposed sections).

      Parameters:
      profile - Array of U-values [W/(m²·K)], one per section
    • getHeatTransferProfile

      public double[] getHeatTransferProfile()
      Get the heat transfer coefficient profile.
      Returns:
      Array of U-values or null if constant
    • setSurfaceTemperatureProfile

      public void setSurfaceTemperatureProfile(double[] profile)
      Set surface temperature profile along the pipe.

      Allows different ambient temperatures at different positions (e.g., varying seabed depth).

      Parameters:
      profile - Array of surface temperatures [K], one per section
    • getSurfaceTemperatureProfile

      public double[] getSurfaceTemperatureProfile()
      Get the surface temperature profile.
      Returns:
      Array of surface temperatures or null if constant
    • setWallProperties

      public void setWallProperties(double thickness, double density, double heatCapacity)
      Set pipe wall properties for transient thermal calculations.
      Parameters:
      thickness - Wall thickness [m]
      density - Wall material density [kg/m³]
      heatCapacity - Wall specific heat capacity [J/(kg·K)]
    • getWallThickness

      public double getWallThickness()
      Get pipe wall thickness.
      Specified by:
      getWallThickness in interface PipeLineInterface
      Overrides:
      getWallThickness in class Pipeline
      Returns:
      Wall thickness [m]
    • setSoilThermalResistance

      public void setSoilThermalResistance(double resistance)
      Set soil/burial thermal resistance.

      For buried pipelines, this adds thermal resistance between pipe outer wall and ambient. The effective U-value becomes: U_eff = 1 / (1/U + R_soil)

      Parameters:
      resistance - Soil thermal resistance [m²·K/W]
    • getSoilThermalResistance

      public double getSoilThermalResistance()
      Get soil thermal resistance.
      Returns:
      Soil thermal resistance [m²·K/W]
    • getThermalCalculator

      public MultilayerThermalCalculator getThermalCalculator()
      Get or create the multi-layer thermal calculator.

      If not yet created, initializes with current pipe geometry. The calculator allows defining multiple radial thermal layers (steel wall, insulation, coatings, etc.) for accurate heat transfer calculations.

      Returns:
      MultilayerThermalCalculator instance
    • setThermalCalculator

      public void setThermalCalculator(MultilayerThermalCalculator calculator)
      Set a pre-configured thermal calculator.
      Parameters:
      calculator - Configured MultilayerThermalCalculator
    • setUseMultilayerThermalModel

      public void setUseMultilayerThermalModel(boolean enable)
      Enable multi-layer thermal model for OLGA-style radial heat transfer.

      When enabled, uses the MultilayerThermalCalculator for accurate heat transfer with proper modeling of:

      • Steel pipe wall thermal mass and conductivity
      • Insulation layers (PU foam, syntactic, aerogel, etc.)
      • Coating layers (FBE, 3LPE, etc.)
      • Concrete weight coating
      • Burial/soil effects
      Parameters:
      enable - true to use multi-layer model, false to use simple U-value
    • isUseMultilayerThermalModel

      public boolean isUseMultilayerThermalModel()
      Check if multi-layer thermal model is enabled.
      Returns:
      true if using multi-layer thermal model
    • configureSubseaThermalModel

      public void configureSubseaThermalModel(double insulationThickness, double concreteThickness, RadialThermalLayer.MaterialType insulationMaterial)
      Configure standard subsea pipe thermal model.

      Creates a typical subsea configuration with:

      1. Steel wall
      2. FBE corrosion coating
      3. Insulation (optional)
      4. Concrete weight coating (optional)
      Parameters:
      insulationThickness - Insulation thickness [m], 0 for uninsulated
      concreteThickness - Concrete coating thickness [m], 0 for none
      insulationMaterial - Type of insulation material
    • configureBuriedThermalModel

      public void configureBuriedThermalModel(double burialDepth, boolean wetSoil)
      Configure buried onshore pipe thermal model.
      Parameters:
      burialDepth - Depth of cover [m]
      wetSoil - true for wet soil, false for dry
    • calculateCooldownTime

      public double calculateCooldownTime(double targetTemperature, String unit)
      Calculate cooldown time from current state to a target temperature.

      Estimates shutdown cooldown time, useful for hydrate prevention planning.

      Parameters:
      targetTemperature - Target temperature
      unit - Temperature unit ("K" or "C")
      Returns:
      Cooldown time in hours
    • calculateHydrateCooldownTime

      public double calculateHydrateCooldownTime()
      Calculate cooldown time to hydrate formation temperature.
      Returns:
      Cooldown time in hours, or infinity if hydrate temp not set
    • getThermalSummary

      public String getThermalSummary()
      Get thermal summary including U-value and layer details.
      Returns:
      Formatted thermal summary string
    • setEnableJouleThomson

      public void setEnableJouleThomson(boolean enable)
      Enable or disable Joule-Thomson effect.

      When enabled, temperature drops due to pressure reduction are calculated. This is important for gas pipelines with significant pressure drop.

      Parameters:
      enable - true to enable J-T effect
    • isJouleThomsonEnabled

      public boolean isJouleThomsonEnabled()
      Check if Joule-Thomson effect is enabled.
      Returns:
      true if J-T effect is modeled
    • setHydrateFormationTemperature

      public void setHydrateFormationTemperature(double temperature, String unit)
      Set hydrate formation temperature for risk monitoring.
      Parameters:
      temperature - Hydrate formation temperature
      unit - Temperature unit ("K" or "C")
    • getHydrateFormationTemperature

      public double getHydrateFormationTemperature()
      Get hydrate formation temperature.
      Returns:
      Hydrate formation temperature [K], or 0 if not set
    • setWaxAppearanceTemperature

      public void setWaxAppearanceTemperature(double temperature, String unit)
      Set wax appearance temperature for risk monitoring.
      Parameters:
      temperature - Wax appearance temperature
      unit - Temperature unit ("K" or "C")
    • getWaxAppearanceTemperature

      public double getWaxAppearanceTemperature()
      Get wax appearance temperature.
      Returns:
      Wax appearance temperature [K], or 0 if not set
    • getHydrateRiskSections

      public boolean[] getHydrateRiskSections()
      Get sections with hydrate formation risk.
      Returns:
      Array of booleans, true where temperature is below hydrate formation temperature
    • getWaxRiskSections

      public boolean[] getWaxRiskSections()
      Get sections with wax deposition risk.
      Returns:
      Array of booleans, true where temperature is below wax appearance temperature
    • hasHydrateRisk

      public boolean hasHydrateRisk()
      Check if any section has hydrate risk.
      Returns:
      true if any section temperature is below hydrate formation temperature
    • hasWaxRisk

      public boolean hasWaxRisk()
      Check if any section has wax risk.
      Returns:
      true if any section temperature is below wax appearance temperature
    • getTemperatureProfile

      public double[] getTemperatureProfile(String unit)
      Get temperature profile with specified unit.
      Parameters:
      unit - Temperature unit ("K", "C", or "F")
      Returns:
      Temperature profile in the specified unit
    • getWallTemperatureProfile

      public double[] getWallTemperatureProfile()
      Get the pipe wall temperature profile.
      Returns:
      Wall temperature profile [K], or null if not calculated
    • getHydrateRiskSectionCount

      public int getHydrateRiskSectionCount()
      Get number of sections with hydrate risk.
      Returns:
      Count of sections below hydrate formation temperature
    • getFirstHydrateRiskSection

      public int getFirstHydrateRiskSection()
      Get first section index with hydrate risk.
      Returns:
      Section index where hydrate risk first occurs, or -1 if no risk
    • getDistanceToHydrateRisk

      public double getDistanceToHydrateRisk()
      Get distance to first hydrate risk location.
      Returns:
      Distance [m] from inlet to first hydrate risk, or -1 if no risk
    • getAverageLiquidHoldup

      public double getAverageLiquidHoldup()
      Get average liquid holdup in the pipe.
      Returns:
      Volume-weighted average liquid holdup (fraction 0-1)
    • getDominantFlowRegime

      public String getDominantFlowRegime()
      Get dominant flow regime in the pipe.

      Returns the most common flow regime across all sections.

      Returns:
      Name of dominant flow regime
    • getAverageSuperficialGasVelocity

      public double getAverageSuperficialGasVelocity()
      Get average superficial gas velocity in the pipe.
      Returns:
      Average superficial gas velocity [m/s]
    • getAverageSuperficialLiquidVelocity

      public double getAverageSuperficialLiquidVelocity()
      Get average superficial liquid velocity in the pipe.
      Returns:
      Average superficial liquid velocity [m/s]
    • getInletPressure

      public double getInletPressure()
      Get inlet pressure.
      Specified by:
      getInletPressure in interface TwoPortInterface
      Overrides:
      getInletPressure in class TwoPortEquipment
      Returns:
      Inlet pressure [bara]
    • getOutletPressure

      public double getOutletPressure()
      Get outlet pressure.
      Specified by:
      getOutletPressure in interface TwoPortInterface
      Overrides:
      getOutletPressure in class TwoPortEquipment
      Returns:
      Outlet pressure [bara]
    • getErosionalVelocity

      public double getErosionalVelocity(double cFactor)
      Calculate erosional velocity per API RP 14E.

      The API 14E erosional velocity is given by:

      $$V_e = \frac{C}{\sqrt{\rho_{mix}}}$$

      where:

      • $V_e$ = Erosional velocity (m/s)
      • $C$ = Empirical constant (typically 100-150 for continuous service)
      • $\rho_{mix}$ = Average mixture density (kg/m³)

      C-Factor Guidelines (API RP 14E)

      API 14E C-factor recommendations
      Service C-factor (SI)
      Continuous service 100-122
      Intermittent service 122-183
      Clean, non-corrosive service 122-152
      Corrosive service (CO2, H2S) 75-100

      Reference: API RP 14E (2007), "Recommended Practice for Design and Installation of Offshore Production Platform Piping Systems", Section 2.5.

      Parameters:
      cFactor - API 14E C-factor constant (SI units: m/s * sqrt(kg/m³))
      Returns:
      Erosional velocity in m/s
    • getErosionalVelocity

      public double getErosionalVelocity()
      Calculate erosional velocity using default C-factor of 122.

      The default C-factor of 122 (SI) corresponds to the commonly used value for continuous service in non-corrosive conditions.

      Returns:
      Erosional velocity in m/s
    • getAverageMixtureDensity

      public double getAverageMixtureDensity()
      Get average mixture density in the pipe.

      Calculates volume-weighted average density from all pipe sections.

      Returns:
      Average mixture density in kg/m³
    • getMaxMixtureVelocity

      public double getMaxMixtureVelocity()
      Get maximum mixture velocity in the pipe.

      Scans all sections to find the highest mixture velocity, which occurs where velocity is maximum.

      Returns:
      Maximum mixture velocity in m/s
    • isVelocityAboveErosionalLimit

      public boolean isVelocityAboveErosionalLimit(double cFactor)
      Check if mixture velocity exceeds erosional limit.
      Parameters:
      cFactor - API 14E C-factor constant (SI units)
      Returns:
      true if maximum velocity exceeds erosional limit
    • isVelocityAboveErosionalLimit

      public boolean isVelocityAboveErosionalLimit()
      Check if mixture velocity exceeds erosional limit using default C-factor.
      Returns:
      true if maximum velocity exceeds erosional limit (C=122)
    • getErosionalVelocityMargin

      public double getErosionalVelocityMargin(double cFactor)
      Get erosional velocity margin.

      Calculates the ratio of actual maximum velocity to erosional velocity. Values greater than 1.0 indicate erosion risk.

      Parameters:
      cFactor - API 14E C-factor constant (SI units)
      Returns:
      Velocity margin (V_max / V_erosional). Values > 1.0 indicate erosion risk.
    • getErosionRiskAssessment

      public String getErosionRiskAssessment(double cFactor)
      Get erosion risk assessment.

      Returns a summary of erosion risk based on API 14E criteria.

      Parameters:
      cFactor - API 14E C-factor constant
      Returns:
      Erosion risk assessment string
    • getFlowAnalysisSummary

      public String getFlowAnalysisSummary()
      Get flow quality analysis summary for comparison with literature data.

      Returns key dimensionless parameters used in published two-phase flow correlations.

      Returns:
      Flow analysis summary with dimensionless parameters
    • addLocalLoss

      public void addLocalLoss(double position, double kFactor)
      Add a local loss (K-factor) at a specific pipe position.

      K-factors represent minor losses from fittings, valves, and bends. The pressure drop is: ΔP = K × 0.5 × ρ × v²

      Typical K-factor values:

      Typical K-factor values for pipe fittings
      Fitting K-factor
      90° elbow (standard) 0.30
      90° elbow (long radius) 0.20
      45° elbow 0.17
      Tee (straight through) 0.20
      Tee (branch) 1.00
      Gate valve (fully open) 0.10
      Ball valve (fully open) 0.05
      Check valve (swing) 2.00
      Sudden expansion 1.00
      Sudden contraction 0.50
      Parameters:
      position - Distance from inlet (m)
      kFactor - Loss coefficient (dimensionless)
    • clearLocalLosses

      public void clearLocalLosses()
      Clear all local losses.
    • getLocalLossKFactor

      public double getLocalLossKFactor(double position)
      Get local loss K-factor at a specific position.
      Parameters:
      position - Distance from inlet (m)
      Returns:
      K-factor at that position, or 0 if none defined
    • getTotalLocalLossKFactors

      public double getTotalLocalLossKFactors()
      Get total of all local loss K-factors.
      Returns:
      Sum of all K-factors
    • setNumberOf90DegreeBends

      public void setNumberOf90DegreeBends(int count)
      Set number of 90-degree bends in the pipe.
      Parameters:
      count - Number of 90° bends
    • setNumberOf45DegreeBends

      public void setNumberOf45DegreeBends(int count)
      Set number of 45-degree bends in the pipe.
      Parameters:
      count - Number of 45° bends
    • setInletLossCoefficient

      public void setInletLossCoefficient(double kFactor)
      Set inlet loss coefficient.
      Parameters:
      kFactor - Inlet K-factor (sharp-edge ~ 0.5, bell-mouth ~ 0.05)
    • setOutletLossCoefficient

      public void setOutletLossCoefficient(double kFactor)
      Set outlet loss coefficient.
      Parameters:
      kFactor - Outlet K-factor (sudden expansion ~ 1.0)
    • setEquivalentLengthFittings

      public void setEquivalentLengthFittings(double equivalentLength)
      Set equivalent length of fittings.

      Alternative to specifying K-factors: add equivalent pipe length that produces the same friction loss as the fittings.

      Parameters:
      equivalentLength - Equivalent length in meters
    • getEquivalentLengthFittings

      public double getEquivalentLengthFittings()
      Get equivalent length of fittings.
      Returns:
      Equivalent length in meters
    • calculateLocalLossPressureDrop

      public double calculateLocalLossPressureDrop()
      Calculate total pressure drop from local losses.

      Uses the formula: ΔP = Σ(K × 0.5 × ρ_mix × v_mix²)

      Returns:
      Total pressure drop from fittings/bends in Pa
    • getTotalPressureDrop

      public double getTotalPressureDrop()
      Calculate total pressure drop including local losses.
      Returns:
      Total pressure drop (friction + gravity + local losses) in bar
    • getLocalLossSummary

      public String getLocalLossSummary()
      Get a summary of local losses.
      Returns:
      Summary string of all local losses