Enhanced Separator Entrainment Modeling
Physics-based, inlet-to-outlet separator performance calculation using open-literature correlations. This is an optional enhancement to the standard NeqSim separator that computes entrainment from first principles rather than user-specified fractions.
Package: neqsim.process.equipment.separator.entrainment
Table of Contents
- Overview
- Architecture
- Quick Start
- Calculation Chain (7 Stages)
- Separator Internals Database
- Vendor-Certified Efficiency Curves
- Droplet Size Distributions
- Grade Efficiency Curves
- Calibration Framework
- Using the Enhanced Mode
- JSON Output
- Mechanical Design Integration
- Dynamic Simulation Integration
- Correlations and References
- Class Reference
Overview
Traditional NeqSim separators use user-specified entrainment fractions via setEntrainment().
The enhanced model instead derives entrainment from physical properties automatically:
| Aspect | Standard Model | Enhanced Model |
|---|---|---|
| Entrainment source | User-specified fractions | Computed from DSD + vessel geometry |
| Flow regime | Not considered | Mandhane (horizontal), Taitel-Dukler (vertical) |
| Inlet device | Not modeled | 7 device types with momentum limits |
| Gravity section | Not modeled | Schiller-Naumann drag, cut diameter |
| Mist eliminator | Not modeled | Grade efficiency curve (wire mesh, vane, cyclone) |
| Liquid-liquid | Not modeled | Stokes settling with oil pad geometry |
| K-factor | External | Computed, with flooding detection |
The enhanced model is enabled by a single flag and runs alongside the thermodynamic
flash in the existing Separator and ThreePhaseSeparator classes.
Architecture
Inlet Pipe Separator Vessel
┌──────────┐ ┌─────────────────────────────────────────┐
│ Flow │ │ Inlet Gravity Mist │
│ Regime │───>│ Device Section Eliminator │──> Gas Out
│ + DSD │ │ (bulk (settling) (grade eff.) │
│ Predict │ │ sep.) │
└──────────┘ │ │
│ Liquid-Liquid Section (3-phase only) │
│ (oil/water settling, coalescence) │──> Liquid Out(s)
└─────────────────────────────────────────┘
Key classes:
| Class | Purpose |
|---|---|
SeparatorPerformanceCalculator |
Main orchestrator — routes through all stages |
MultiphaseFlowRegime |
Predicts inlet flow regime, generates DSD |
InletDeviceModel |
Models inlet device bulk separation + DSD transformation |
SeparatorGeometryCalculator |
Vessel geometry for H/V vessels, K-factor |
DropletSizeDistribution |
Rosin-Rammler and log-normal DSD models |
DropletSettlingCalculator |
Schiller-Naumann terminal velocity |
GradeEfficiencyCurve |
S-curve grade efficiency for mist eliminators |
SeparatorInternalsDatabase |
CSV-backed database of internals specifications |
Quick Start
Java — Two-Phase Separator with Enhanced Entrainment
import neqsim.process.equipment.separator.Separator;
import neqsim.process.equipment.separator.entrainment.*;
import neqsim.process.equipment.stream.Stream;
import neqsim.thermo.system.SystemSrkEos;
// Create fluid
SystemSrkEos fluid = new SystemSrkEos(273.15 + 30.0, 70.0);
fluid.addComponent("methane", 0.85);
fluid.addComponent("ethane", 0.10);
fluid.addComponent("n-heptane", 0.05);
fluid.setMixingRule("classic");
Stream feed = new Stream("Feed", fluid);
feed.setFlowRate(50000.0, "kg/hr");
feed.run();
// Create separator with enhanced entrainment
Separator separator = new Separator("HP Sep", feed);
separator.setInternalDiameter(2.0);
separator.setSeparatorLength(6.0);
// Enable enhanced mode
separator.setEnhancedEntrainmentCalculation(true);
separator.setInletDeviceType(InletDeviceModel.InletDeviceType.INLET_VANE);
separator.setInletPipeDiameter(0.254); // 10-inch pipe
// Configure mist eliminator
separator.getPerformanceCalculator()
.setMistEliminatorCurve(GradeEfficiencyCurve.wireMeshDefault());
separator.run();
// Results
System.out.println("Inlet flow regime: " + separator.getInletFlowRegime());
System.out.println("K-factor: " + separator.getKFactor());
System.out.println("K-factor utilization: " + separator.getKFactorUtilization());
System.out.println("Mist eliminator flooded: " + separator.isMistEliminatorFlooded());
System.out.println("Overall gas-liquid efficiency: "
+ separator.getPerformanceCalculator().getOverallGasLiquidEfficiency());
Python — Enhanced Separator
from neqsim import jneqsim
import jpype
# Classes
SystemSrkEos = jneqsim.thermo.system.SystemSrkEos
Stream = jneqsim.process.equipment.stream.Stream
Separator = jneqsim.process.equipment.separator.Separator
ProcessSystem = jneqsim.process.processmodel.ProcessSystem
InletDeviceModel = jneqsim.process.equipment.separator.entrainment.InletDeviceModel
GradeEfficiencyCurve = jneqsim.process.equipment.separator.entrainment.GradeEfficiencyCurve
# Fluid
fluid = SystemSrkEos(273.15 + 30.0, 70.0)
fluid.addComponent("methane", 0.85)
fluid.addComponent("ethane", 0.10)
fluid.addComponent("n-heptane", 0.05)
fluid.setMixingRule("classic")
feed = Stream("Feed", fluid)
feed.setFlowRate(50000.0, "kg/hr")
# Separator with enhanced mode
sep = Separator("HP Sep", feed)
sep.setInternalDiameter(2.0)
sep.setSeparatorLength(6.0)
sep.setEnhancedEntrainmentCalculation(True)
sep.setInletDeviceType(InletDeviceModel.InletDeviceType.INLET_VANE)
sep.setInletPipeDiameter(0.254)
sep.getPerformanceCalculator().setMistEliminatorCurve(
GradeEfficiencyCurve.wireMeshDefault())
process = ProcessSystem()
process.add(feed)
process.add(sep)
process.run()
print(f"Inlet flow regime: {sep.getInletFlowRegime()}")
print(f"K-factor: {sep.getKFactor():.4f} m/s")
print(f"K-factor utilization: {sep.getKFactorUtilization():.1%}")
print(f"Overall efficiency: "
f"{sep.getPerformanceCalculator().getOverallGasLiquidEfficiency():.2%}")
Calculation Chain (7 Stages)
When setEnhancedEntrainmentCalculation(true) is called, the SeparatorPerformanceCalculator
executes a 7-stage pipeline. Each stage feeds the next.
Stage 1: Inlet Flow Regime Prediction
Class: MultiphaseFlowRegime
Predicts the multiphase flow regime in the inlet pipe using dimensionless superficial velocity maps:
- Horizontal pipes: Mandhane, Gregory, and Aziz (1974) flow pattern map
- Vertical pipes: Taitel, Dukler, and Barnea (1980) flow pattern transitions
Flow regimes (enum FlowRegime):
| Regime | Description | Typical Gas Velocity |
|---|---|---|
STRATIFIED_SMOOTH |
Separated layers, calm interface | Low vsg, low vsl |
STRATIFIED_WAVY |
Separated layers, wavy interface | Moderate vsg, low vsl |
SLUG |
Alternating liquid slugs and gas pockets | Moderate vsg, moderate vsl |
PLUG |
Elongated gas bubbles in liquid | Low vsg, moderate vsl |
ANNULAR |
Liquid film on wall, gas core | High vsg |
ANNULAR_MIST |
Annular with entrained droplets | Very high vsg |
DISPERSED_BUBBLE |
Small gas bubbles in liquid | Low vsg, high vsl |
CHURN |
Chaotic vertical oscillating flow | Moderate-high vsg (vertical) |
BUBBLE |
Discrete bubbles rising in liquid | Low vsg (vertical) |
API pattern (setter → predict → getter):
MultiphaseFlowRegime calc = new MultiphaseFlowRegime();
calc.setGasDensity(50.0); // kg/m3
calc.setLiquidDensity(800.0); // kg/m3
calc.setGasViscosity(1.0e-5); // Pa.s
calc.setLiquidViscosity(1.0e-3); // Pa.s
calc.setSurfaceTension(0.025); // N/m
calc.setPipeDiameter(0.254); // m
calc.setGasSuperficialVelocity(15.0); // m/s
calc.setLiquidSuperficialVelocity(0.1); // m/s
calc.setPipeOrientation("horizontal"); // or "vertical"
calc.predict();
MultiphaseFlowRegime.FlowRegime regime = calc.getPredictedRegime();
DropletSizeDistribution dsd = calc.getGeneratedDSD();
double entrainedFraction = calc.calcEntrainedLiquidFraction();
The flow regime determines which DSD correlation is used in Stage 2.
Stage 2: Inlet Droplet Size Distribution
The DSD is generated automatically based on the predicted flow regime:
| Flow Regime | DSD Correlation | Reference |
|---|---|---|
| Annular / Annular-Mist | Azzopardi (1997) — Sauter mean diameter from Weber number and Reynolds number | Azzopardi, B.J. (1997) |
| Stratified / Stratified-Wavy | Ishii-Grolmes (1975) — entrainment onset and droplet generation from interfacial shear | Ishii and Grolmes (1975) |
| Slug / Plug / Churn | Hinze (1955) — maximum stable droplet from turbulent breakup | Hinze (1955) |
| Bubble / Dispersed Bubble | Hinze (1955) — applied for gas bubble breakup in liquid | Hinze (1955) |
The entrained liquid fraction is computed using the Oliemans, Pots, and Trompe (1986) correlation.
Alternatively, specify the DSD directly:
// Rosin-Rammler distribution
DropletSizeDistribution dsd = DropletSizeDistribution.rosinRammler(100e-6, 2.6);
// Log-normal distribution
DropletSizeDistribution dsd = DropletSizeDistribution.logNormal(80e-6, 0.8);
// Set on calculator
separator.getPerformanceCalculator().setGasLiquidDSD(dsd);
Stage 3: Inlet Device Modeling
Class: InletDeviceModel
Models the inlet device that distributes the feed into the vessel. The inlet device provides partial bulk separation of liquid from gas before the gravity section.
Device types (enum InletDeviceType):
| Device Type | Typical Bulk Efficiency | Max Momentum [Pa] | Pressure Drop Coeff. | Typical Application |
|---|---|---|---|---|
NONE |
0% | — | 0 | Simple pipe entry |
DEFLECTOR_PLATE |
50-65% | 1500-2000 | 0.5-0.6 | Low-cost basic service |
HALF_PIPE |
65-75% | 3000-3500 | 0.8-1.0 | Moderate liquid load |
INLET_VANE |
75-85% | 5000-7000 | 1.5-2.0 | Standard gas-liquid separators |
INLET_CYCLONE |
85-95% | 8000-10000 | 3.0-5.0 | High-performance scrubbers |
SCHOEPENTOETER |
80-90% | 7000-9000 | 2.0-3.0 | Large diameter vessels |
IMPINGEMENT_PLATE |
55-70% | 2000-3000 | 0.8-1.2 | Slug catcher service |
Key physics:
- Momentum flux $\rho_m v_n^2$ where $\rho_m$ is mixture density and $v_n$ is nozzle velocity
- When momentum exceeds the device’s maximum limit (Bothamley, 2013), efficiency degrades
- The DSD is transformed downstream — large droplets are removed, remaining DSD shifts to smaller sizes
InletDeviceModel model = new InletDeviceModel(
InletDeviceModel.InletDeviceType.INLET_VANE);
model.setInletNozzleDiameter(0.254); // 10-inch
model.calculate(inletDSD, gasDensity, liquidDensity,
gasVolumeFlow, liquidVolumeFlow, surfaceTension);
double bulkEff = model.getBulkSeparationEfficiency();
double momentum = model.getMomentumFlux(); // Pa
double pressureDrop = model.getPressureDrop(); // Pa
DropletSizeDistribution remainingDSD = model.getDownstreamDSD();
Stage 4: Vessel Geometry
Class: SeparatorGeometryCalculator
Computes exact vessel cross-sectional areas, gas/liquid heights, and residence times for both horizontal and vertical vessels.
Horizontal vessel geometry:
The gas and liquid cross-sectional areas are computed from the exact circular segment formula:
\[A_{liquid} = \frac{D^2}{4} \left[ \cos^{-1}\left(1 - \frac{2h}{D}\right) - \left(1 - \frac{2h}{D}\right)\sqrt{\frac{4h}{D} - \frac{4h^2}{D^2}} \right]\]where $h$ is the liquid height and $D$ is the internal diameter.
Vertical vessel geometry:
\[A_{gas} = \frac{\pi D^2}{4}, \quad L_{gas} = L_{TT} \cdot (1 - f_{liquid})\]The full cross-section is available for gas flow; the gas residence time depends on the effective gas height above the liquid level.
K-factor (Souders-Brown):
\[K = v_g \sqrt{\frac{\rho_g}{\rho_l - \rho_g}}\]This static method is used to check flooding conditions:
double kFactor = SeparatorGeometryCalculator.calcKFactor(
gasVelocity, gasDensity, liquidDensity);
API:
SeparatorGeometryCalculator geom = new SeparatorGeometryCalculator();
geom.setOrientation("horizontal"); // or "vertical"
geom.setInternalDiameter(2.0); // m
geom.setTangentToTangentLength(6.0); // m
geom.setNormalLiquidLevel(0.5); // fraction of diameter
geom.calculate(gasVolumeFlow, liquidVolumeFlow);
double gasArea = geom.getGasArea(); // m2
double liquidArea = geom.getLiquidArea(); // m2
double settlingHeight = geom.getEffectiveGasSettlingHeight(); // m
double gasResTime = geom.getGasResidenceTime(); // s
double liqResTime = geom.getLiquidResidenceTime(); // s
// Three-phase
geom.calculateThreePhase(gasVolumeFlow, oilVolumeFlow,
waterVolumeFlow, oilLevelFraction);
double oilPad = geom.getOilPadThickness(); // m
double waterLayer = geom.getWaterLayerHeight(); // m
Stage 5: Gravity Settling Section
Class: DropletSettlingCalculator
Computes the terminal velocity of each droplet size class using the Schiller-Naumann drag correlation, which smoothly transitions from Stokes flow to Newton’s law:
\[C_D = \frac{24}{Re}\left(1 + 0.15 Re^{0.687}\right), \quad Re < 1000\] \[v_t = \sqrt{\frac{4 g d_p |\Delta\rho|}{3 C_D \rho_c}}\]The gravity cut diameter is the smallest droplet that can settle across the effective settling height within the available residence time:
\[d_{cut} = d_p \text{ where } v_t(d_p) = \frac{H_{settle}}{t_{residence}}\]Droplets smaller than $d_{cut}$ pass through the gravity section; larger droplets are captured.
// Single droplet terminal velocity
double vt = DropletSettlingCalculator.calcTerminalVelocity(
dropletDiameter, // m
continuousDensity, // kg/m3 (gas for liquid droplets)
dispersedDensity, // kg/m3 (liquid for liquid droplets)
continuousViscosity); // Pa.s
Stage 6: Mist Eliminator
Class: GradeEfficiencyCurve
Models separation internals using an S-shaped grade efficiency curve defined by $d_{50}$ (50% collection efficiency diameter) and maximum achievable efficiency:
\[\eta(d_p) = \eta_{max} \cdot \left[1 - \exp\left(-0.693 \left(\frac{d_p}{d_{50}}\right)^n\right)\right]\]where $n$ is the sharpness parameter (typically 2-4).
Pre-configured internals types:
| Factory Method | $d_{50}$ | Max $\eta$ | Application |
|---|---|---|---|
wireMeshDefault() |
5 $\mu$m | 99.8% | Standard demisting pad |
vanePackDefault() |
15 $\mu$m | 99.0% | Higher capacity, coarser cut |
axialCycloneDefault() |
3 $\mu$m | 99.8% | Highest efficiency |
platePack(d50, maxEff) |
Custom | Custom | Liquid-liquid coalescence |
Overall efficiency integrates the grade efficiency over the DSD:
\[\eta_{overall} = \int_0^{\infty} \eta(d_p) \cdot f(d_p) \, dd_p\]GradeEfficiencyCurve curve = GradeEfficiencyCurve.wireMeshDefault();
// Single-size efficiency
double eta100um = curve.getEfficiency(100e-6); // ~99.8% for wire mesh
// Overall efficiency against a DSD
double etaOverall = curve.calcOverallEfficiency(dsd);
Flooding detection: If the K-factor exceeds the internals’ maximum K-factor (from the database), the mist eliminator is flagged as flooded and its efficiency is degraded.
Stage 7: Liquid-Liquid Separation (Three-Phase)
For ThreePhaseSeparator, the enhanced model also computes:
- Oil-in-water settling — water droplets rising through the oil pad
- Water-in-oil settling — oil droplets settling through the water layer
- Gas bubble carry-under — gas rising through the liquid phase
The liquid-liquid residence time uses the actual vessel geometry to determine the available settling time. Stokes settling velocity is used with the interfacial tension between oil and water phases.
Separator Internals Database
Class: SeparatorInternalsDatabase
A CSV-backed database of separator internals specifications, loaded as a
singleton from src/main/resources/designdata/:
- SeparatorInternals.csv — 70+ records covering wire mesh (19 variants incl. Monel, Hastelloy, PTFE, Duplex), vane pack (12 variants), axial cyclone (10 variants), plate pack (13 variants), and gravity (10 variants)
- SeparatorInletDevices.csv — 31 records covering all inlet device types (elbow inlets, distributors, vanes, cyclones, deflector plates, schoepentoeter, impingement plates)
- SeparatorVendorCurves.csv — 25 vendor-certified grade efficiency curves from factory acceptance tests (FAT), covering wire mesh, vane pack, axial cyclone, and plate pack; includes atmospheric and high-pressure (50 bar) test data
Internals Records
Each record in SeparatorInternals.csv contains:
| Field | Description | Example |
|---|---|---|
internalsType |
Category | WIRE_MESH, VANE_PACK, AXIAL_CYCLONE, PLATE_PACK, GRAVITY |
subType |
Variant | Standard Knitted, Double Pocket, High Efficiency Tube |
manufacturer |
Manufacturer | Generic (extensible to vendor-specific) |
d50_um |
50% collection diameter [$\mu$m] | 3.0 to 500.0 |
sharpness |
Grade efficiency curve sharpness | 1.5 to 4.0 |
maxEfficiency |
Maximum achievable efficiency | 0.90 to 0.999 |
maxKFactor |
Maximum K-factor before flooding [m/s] | 0.04 to 0.30 |
minKFactor |
Minimum recommended K-factor [m/s] | 0.01 to 0.05 |
pressureDrop_mbar |
Typical pressure drop [mbar] | 0.1 to 10.0 |
designStandard |
Applicable standard | API 12J, NORSOK P-100 |
material |
Construction material | SS316L, Monel, Hastelloy C-276, PTFE, Titanium Gr2, Duplex 2205 |
maxTemperature_C |
Maximum operating temperature [C] | 150 to 800 |
minThickness_mm |
Minimum pad/element thickness [mm] | 50 to 300 |
weight_kg_m2 |
Installed weight per unit area [kg/m²] | 10 to 120 |
reference |
Published reference | Brunazzi and Paglianti (1998), El-Dessouky et al. (2000), York (2003) |
Inlet Device Records
Each record in SeparatorInletDevices.csv contains:
| Field | Description | Example |
|---|---|---|
deviceType |
Category | DEFLECTOR_PLATE, INLET_VANE, INLET_CYCLONE, etc. |
subType |
Variant | Flat Baffle, Multi-Tube, Standard |
minMomentum_Pa |
Minimum recommended momentum [Pa] | 0 to 1000 |
maxMomentum_Pa |
Maximum recommended momentum [Pa] | 500 to 10000 |
typicalBulkEfficiency |
Typical bulk liquid separation efficiency | 0.0 to 0.95 |
dsdMultiplier |
DSD transformation factor (downstream/upstream d50) | 0.45 to 1.0 |
pressureDropCoeff |
Pressure loss coefficient | 0.0 to 5.0 |
reference |
Published reference | Bothamley (2013) |
Querying the Database
SeparatorInternalsDatabase db = SeparatorInternalsDatabase.getInstance();
// Find all wire mesh types
List<SeparatorInternalsDatabase.InternalsRecord> meshes = db.findByType("WIRE_MESH");
for (SeparatorInternalsDatabase.InternalsRecord rec : meshes) {
System.out.printf("%-30s d50=%5.1f um maxK=%.3f m/s maxEff=%.3f%n",
rec.subType, rec.d50_um, rec.maxKFactor, rec.maxEfficiency);
}
// Find specific variant
SeparatorInternalsDatabase.InternalsRecord hiEff =
db.findByTypeAndSubType("WIRE_MESH", "High Efficiency");
// Convert to grade efficiency curve for calculations
GradeEfficiencyCurve curve = hiEff.toGradeEfficiencyCurve();
// Find inlet devices
List<SeparatorInternalsDatabase.InletDeviceRecord> vanes =
db.findInletDeviceByType("INLET_VANE");
// Export full catalog as JSON
String json = db.toCatalogJson();
Extending the Database
Add rows to the CSV files to include vendor-specific or custom internals.
The database reloads automatically on next getInstance() call after JVM restart.
Fields are public for direct access — no getters needed.
Vendor-Certified Efficiency Curves
The database includes 25 vendor-certified grade efficiency curves from factory
acceptance tests (FAT), stored in SeparatorVendorCurves.csv. Each curve contains
12 measured (droplet diameter, efficiency) points obtained from standardized testing
(EN 13544, ISO 29042, or vendor in-house methods).
Vendor Curve Records
| Field | Description | Example |
|---|---|---|
curveId |
Unique identifier | VC001, VC015 |
internalsType |
WIRE_MESH, VANE_PACK, AXIAL_CYCLONE, PLATE_PACK | WIRE_MESH |
vendorName |
Vendor name | VendorA, VendorB |
productFamily |
Product model designation | WM-StdKnit-150, VP-DP-Standard |
testStandard |
Test method | EN 13544 / ISO 29042 |
testFluid |
Gas-liquid pair used | Air-Water, N2-Exxsol |
testPressure_bar |
Test pressure [bar] | 1.0, 50.0 |
testTemperature_C |
Test temperature [°C] | 20, 25 |
diameterPoints_um |
Measured droplet diameters [µm] | 1;2;3;5;8;10;15;20;30;50;80;100 |
efficiencyPoints |
Measured collection efficiencies [0-1] | 0.05;0.12;0.25;0.50;… |
maxKFactor |
Maximum K-factor at test conditions [m/s] | 0.107 |
testDate |
Factory acceptance test date | 2022-03-15 |
certificateRef |
Certificate or report reference | FAT-2022-001 |
Coverage
| Internals Type | Number of Curves | Includes HP (50 bar) |
|---|---|---|
| WIRE_MESH | 8 | Yes (2 curves) |
| VANE_PACK | 6 | Yes (1 curve) |
| AXIAL_CYCLONE | 6 | Yes (1 curve) |
| PLATE_PACK | 3 | No |
| Total | 25 |
Querying Vendor Curves
SeparatorInternalsDatabase db = SeparatorInternalsDatabase.getInstance();
// All vendor curves
List<SeparatorInternalsDatabase.VendorCurveRecord> all = db.getAllVendorCurves();
// Find by internals type
List<SeparatorInternalsDatabase.VendorCurveRecord> meshCurves =
db.findVendorCurvesByType("WIRE_MESH");
// Find by vendor
List<SeparatorInternalsDatabase.VendorCurveRecord> vendorACurves =
db.findVendorCurvesByVendor("VendorA");
// Find specific curve by ID
SeparatorInternalsDatabase.VendorCurveRecord curve = db.findVendorCurveById("VC001");
System.out.println("Product: " + curve.productFamily);
System.out.println("Test pressure: " + curve.testPressure_bar + " bar");
System.out.println("Points: " + curve.diameterPoints_um.length);
// Convert to GradeEfficiencyCurve for calculations
GradeEfficiencyCurve gec = curve.toGradeEfficiencyCurve();
double eta10 = gec.getEfficiency(10e-6); // Efficiency at 10 µm
// Find by type AND vendor
List<SeparatorInternalsDatabase.VendorCurveRecord> vendorBMesh =
db.findVendorCurvesByTypeAndVendor("WIRE_MESH", "VendorB");
Using Vendor Curves in Simulation
// Use a specific vendor curve instead of the generic defaults
SeparatorInternalsDatabase db = SeparatorInternalsDatabase.getInstance();
SeparatorInternalsDatabase.VendorCurveRecord vc =
db.findVendorCurveById("VC001");
separator.getPerformanceCalculator()
.setMistEliminatorCurve(vc.toGradeEfficiencyCurve());
Python API
db = SeparatorInternalsDatabase.getInstance()
# Browse vendor curves
for vc in db.getAllVendorCurves():
print(f"{vc.curveId:6s} {vc.internalsType:15s} {vc.vendorName:10s} "
f"{vc.productFamily:25s} P={vc.testPressure_bar:.0f} bar")
# Get a specific curve and use it
curve = db.findVendorCurveById("VC001")
gec = curve.toGradeEfficiencyCurve()
print(f"Efficiency at 10 um: {gec.getEfficiency(10e-6):.3f}")
Droplet Size Distributions
Class: DropletSizeDistribution
Two statistical models are supported:
Rosin-Rammler Distribution
\[F(d) = 1 - \exp\left[-\left(\frac{d}{d_0}\right)^n\right]\]where $d_0$ is the characteristic diameter (63.2% cumulative) and $n$ is the spread parameter (typically 2.0-4.0 for separator applications).
// d0 = 100 um, spread = 2.6
DropletSizeDistribution dsd = DropletSizeDistribution.rosinRammler(100e-6, 2.6);
Log-Normal Distribution
\[f(d) = \frac{1}{d \sigma \sqrt{2\pi}} \exp\left[-\frac{(\ln d - \ln d_{50})^2}{2\sigma^2}\right]\]// d50 = 80 um, geometric standard deviation = 0.8
DropletSizeDistribution dsd = DropletSizeDistribution.logNormal(80e-6, 0.8);
Key Properties
double d50 = dsd.getD50(); // Median diameter [m]
double d32 = dsd.getSauterMeanDiameter(); // Volume-to-surface mean [m]
// Discrete classes for numerical integration (20 bins)
double[][] classes = dsd.getDiscreteClasses();
// Each row: [d_lower, d_mid, volume_fraction]
Grade Efficiency Curves
Class: GradeEfficiencyCurve
The S-shaped collection efficiency function characterizes any separation device (mist eliminator, coalescer, gravity section):
// Pre-configured types
GradeEfficiencyCurve wireMesh = GradeEfficiencyCurve.wireMeshDefault();
GradeEfficiencyCurve vanePack = GradeEfficiencyCurve.vanePackDefault();
GradeEfficiencyCurve cyclone = GradeEfficiencyCurve.axialCycloneDefault();
// Custom curve
GradeEfficiencyCurve custom = GradeEfficiencyCurve.platePack(20e-6, 0.98);
// From database record
SeparatorInternalsDatabase db = SeparatorInternalsDatabase.getInstance();
GradeEfficiencyCurve fromDB = db.findByTypeAndSubType("VANE_PACK", "Double Pocket")
.toGradeEfficiencyCurve();
// Query efficiency
double eta = wireMesh.getEfficiency(10e-6); // Efficiency at 10 um
double overall = wireMesh.calcOverallEfficiency(dsd); // Integrated over DSD
Calibration Framework
The enhanced model includes a structured calibration system for matching model predictions to plant or laboratory measurements. Three independent calibration multipliers adjust three categories of entrainment:
| Multiplier | Affects | Default |
|---|---|---|
liquidInGasCalibrationFactor |
Oil-in-gas, water-in-gas | 1.0 |
gasCarryUnderCalibrationFactor |
Gas-in-oil, gas-in-water | 1.0 |
liquidLiquidCalibrationFactor |
Oil-in-water, water-in-oil | 1.0 |
Manual Calibration
Set factors directly:
SeparatorPerformanceCalculator perf = separator.getPerformanceCalculator();
perf.setLiquidInGasCalibrationFactor(1.5); // 50% more carryover than model
perf.setGasCarryUnderCalibrationFactor(0.8); // 20% less gas carry-under
perf.setLiquidLiquidCalibrationFactor(2.0); // double liq-liq cross-contamination
Auto-Calibration from a Single Measurement
Fit factors to one set of measured fractions:
SeparatorPerformanceCalculator.CalibrationSummary summary =
perf.calibrateFromMeasuredFractions(
1.5e-3, // measured oil-in-gas fraction
0.0, // measured water-in-gas (0 if not measured)
8.0e-3, // measured gas-in-oil
0.0, // measured gas-in-water
2.0e-2, // measured oil-in-water
0.0, // measured water-in-oil
1e-12); // model floor (avoid divide-by-zero)
System.out.println("New liquid-in-gas factor: " + summary.newLiquidInGasFactor);
System.out.println("New gas carry-under factor: " + summary.newGasCarryUnderFactor);
System.out.println("New liquid-liquid factor: " + summary.newLiquidLiquidFactor);
Grouped-Measurement Convenience
When plant data is reported as grouped categories (not individual fractions):
SeparatorPerformanceCalculator.CalibrationSummary summary =
perf.calibrateFromGroupedMeasurements(
1.5e-3, // measured grouped liquid-in-gas
8.0e-3, // measured grouped gas carry-under
2.0e-2, // measured grouped liquid-liquid
1e-12); // model floor
Batch Calibration from CSV Case Library
Fit calibration factors across multiple operating points from a CSV file:
// Load calibration cases from CSV
List<SeparatorPerformanceCalculator.CalibrationCase> cases =
SeparatorPerformanceCalculator.loadCalibrationCasesFromCsv(
"src/main/resources/designdata/SeparatorCalibrationCasesTemplate.csv");
// Fit (finds median ratio across all cases)
SeparatorPerformanceCalculator.BatchCalibrationSummary fit =
perf.calibrateFromCaseLibrary(cases, 1e-12);
System.out.println("Cases: " + fit.nCases);
System.out.println("Before MAPE: " + fit.beforeMAPE);
System.out.println("After MAPE: " + fit.afterMAPE);
JSON Calibration Report
Generate a comprehensive report with per-case residuals:
String report = perf.buildBatchCalibrationReportJson(cases, fit);
System.out.println(report); // JSON with calibrationFactors, caseResults, summary
// Or save to file
perf.saveBatchCalibrationReportJson("calibration_report.json", cases, fit);
Using the Enhanced Mode
Java API
The enhanced mode is activated on a Separator or ThreePhaseSeparator via
convenience methods that delegate to the internal SeparatorPerformanceCalculator:
Separator sep = new Separator("V-100", feed);
sep.setInternalDiameter(2.0);
sep.setSeparatorLength(6.0);
// ── Enable enhanced mode ──
sep.setEnhancedEntrainmentCalculation(true);
// ── Configure inlet device ──
sep.setInletDeviceType(InletDeviceModel.InletDeviceType.INLET_VANE);
sep.setInletPipeDiameter(0.254); // 10-inch feed pipe
sep.setGasLiquidSurfaceTension(0.025); // N/m (optional override)
// ── Configure mist eliminator ──
sep.getPerformanceCalculator()
.setMistEliminatorCurve(GradeEfficiencyCurve.wireMeshDefault());
// ── Run ──
sep.run();
// ── Results ──
// Flow regime at inlet
MultiphaseFlowRegime.FlowRegime regime = sep.getInletFlowRegime();
// Souders-Brown K-factor and utilization (% of max K before flooding)
double kFactor = sep.getKFactor();
double kUtil = sep.getKFactorUtilization();
// Flooding check
boolean flooded = sep.isMistEliminatorFlooded();
// Detailed performance from calculator
SeparatorPerformanceCalculator perf = sep.getPerformanceCalculator();
double gravityEff = perf.getGravitySectionEfficiency();
double meEff = perf.getMistEliminatorEfficiency();
double overallEff = perf.getOverallGasLiquidEfficiency();
double dCut = perf.getGravityCutDiameter();
// Entrainment fractions (fed back into Separator outlet compositions)
double oilInGas = perf.getOilInGasFraction();
double waterInGas = perf.getWaterInGasFraction();
double gasInOil = perf.getGasInOilFraction();
// Full JSON report
String json = perf.toJson();
// Optional: one-point grouped calibration from measured field data
// (liquid-in-gas, gas carry-under, liquid-liquid)
perf.calibrateFromGroupedMeasurements(
1.5e-3, // measured grouped liquid-in-gas
8.0e-3, // measured grouped gas carry-under
2.0e-2, // measured grouped liquid-liquid cross-contamination
1e-12); // model floor
// Optional: batch calibration from a field-case library CSV
List<SeparatorPerformanceCalculator.CalibrationCase> cases =
SeparatorPerformanceCalculator.loadCalibrationCasesFromCsv(
"src/main/resources/designdata/SeparatorCalibrationCasesTemplate.csv");
SeparatorPerformanceCalculator.BatchCalibrationSummary fit =
perf.calibrateFromCaseLibrary(cases, 1e-12);
Advanced: Direct Calculator Usage
For standalone calculations without a Separator equipment object:
SeparatorPerformanceCalculator calc = new SeparatorPerformanceCalculator();
// Set inlet DSD (manual or from flow regime prediction)
calc.setGasLiquidDSD(DropletSizeDistribution.rosinRammler(100e-6, 2.6));
// Set mist eliminator
calc.setMistEliminatorCurve(GradeEfficiencyCurve.vanePackDefault());
// Enable enhanced mode
calc.setUseEnhancedCalculation(true);
calc.setInletPipeDiameter(0.254);
calc.setSurfaceTension(0.025);
calc.setInletDeviceModel(
new InletDeviceModel(InletDeviceModel.InletDeviceType.INLET_VANE));
// Run: gas density, oil density, water density,
// gas viscosity, oil viscosity, water viscosity,
// gas velocity, separator diameter, separator length,
// orientation, liquid level fraction
calc.calculate(
50.0, 800.0, 0.0, // densities (0 = no water)
1.5e-5, 3.0e-3, 0.0, // viscosities
3.0, 2.0, 6.0, // velocity, diameter, length
"horizontal", 0.5); // orientation, liquid level
// Get results
double overallEff = calc.getOverallGasLiquidEfficiency();
double kFactor = calc.getKFactor();
Python API
from neqsim import jneqsim
# Import entrainment classes
InletDeviceModel = jneqsim.process.equipment.separator.entrainment.InletDeviceModel
GradeEfficiencyCurve = jneqsim.process.equipment.separator.entrainment.GradeEfficiencyCurve
DropletSizeDistribution = jneqsim.process.equipment.separator.entrainment.DropletSizeDistribution
SeparatorInternalsDatabase = jneqsim.process.equipment.separator.entrainment.SeparatorInternalsDatabase
MultiphaseFlowRegime = jneqsim.process.equipment.separator.entrainment.MultiphaseFlowRegime
# Query internals database
db = SeparatorInternalsDatabase.getInstance()
all_internals = list(db.getAllInternals())
for rec in all_internals:
print(f"{rec.internalsType:15s} {rec.subType:25s} "
f"d50={rec.d50_um:6.1f} um maxK={rec.maxKFactor:.3f} m/s")
# Create custom DSD
dsd = DropletSizeDistribution.rosinRammler(100e-6, 2.6)
print(f"D50 = {dsd.getD50() * 1e6:.1f} um")
print(f"D32 = {dsd.getSauterMeanDiameter() * 1e6:.1f} um")
# Predict flow regime
regime_calc = MultiphaseFlowRegime()
regime_calc.setGasDensity(50.0)
regime_calc.setLiquidDensity(800.0)
regime_calc.setGasViscosity(1.0e-5)
regime_calc.setLiquidViscosity(1.0e-3)
regime_calc.setSurfaceTension(0.025)
regime_calc.setPipeDiameter(0.254)
regime_calc.setGasSuperficialVelocity(15.0)
regime_calc.setLiquidSuperficialVelocity(0.1)
regime_calc.setPipeOrientation("horizontal")
regime_calc.predict()
print(f"Flow regime: {regime_calc.getPredictedRegime()}")
JSON Output
The toJson() method on SeparatorPerformanceCalculator produces a comprehensive
JSON report. When enhanced mode is active, it includes additional sections:
{
"gasLiquidDSD": {
"type": "ROSIN_RAMMLER",
"characteristicDiameter_m": 1.0e-4,
"spreadParameter": 2.6,
"d50_m": 8.3e-5,
"sauterMeanDiameter_m": 7.1e-5
},
"gravitySectionEfficiency": 0.72,
"gravityCutDiameter_m": 4.5e-5,
"mistEliminatorEfficiency": 0.998,
"overallGasLiquidEfficiency": 0.9994,
"oilInGasFraction": 6.0e-4,
"waterInGasFraction": 0.0,
"gasInOilFraction": 0.002,
"enhancedResults": {
"inletFlowRegime": "ANNULAR",
"kFactor_m_s": 0.068,
"kFactorUtilization": 0.63,
"mistEliminatorFlooded": false,
"inletDeviceBulkEfficiency": 0.82,
"inletDeviceMomentumFlux_Pa": 3200,
"inletDevicePressureDrop_Pa": 450,
"gasResidenceTime_s": 8.5,
"liquidResidenceTime_s": 120.0,
"gasSettlingHeight_m": 0.95,
"postInletDeviceDSD": {
"type": "ROSIN_RAMMLER",
"characteristicDiameter_m": 5.5e-5,
"spreadParameter": 2.6
}
}
}
Mechanical Design Integration
When detailed entrainment calculation is enabled, the SeparatorMechanicalDesign class
automatically pulls performance results from the SeparatorPerformanceCalculator into
the mechanical design output. This means calcDesign() and toJson() include
entrainment fractions, efficiency metrics, calibration factors, and the full performance
calculator JSON — all in a single design report.
How It Works
- Enable detailed entrainment on the separator:
separator.setDetailedEntrainmentCalculation(true) - Run the separator:
separator.run()— this executes the performance calculator - Call
calcDesign()on the mechanical design — at the end, it callspopulateEntrainmentResults()which copies all performance data from the calculator into the design object - Call
toJson()— the response includes both vessel sizing data AND entrainment performance
Fields Added to Mechanical Design JSON
| Field | Type | Description |
|---|---|---|
detailedEntrainmentUsed |
boolean | Whether detailed entrainment was active |
oilInGasFraction |
double | Oil-in-gas carryover (volume basis, 0-1) |
waterInGasFraction |
double | Water-in-gas carryover (volume basis, 0-1) |
gasInOilFraction |
double | Gas carry-under into oil (volume basis, 0-1) |
gasInWaterFraction |
double | Gas carry-under into water (volume basis, 0-1) |
oilInWaterFraction |
double | Oil-in-water (volume basis, 0-1) |
waterInOilFraction |
double | Water-in-oil (volume basis, 0-1) |
overallGasLiquidEfficiency |
double | Combined gravity + ME efficiency (0-1) |
mistEliminatorEfficiency |
double | Mist eliminator efficiency alone (0-1) |
kFactorUtilization |
double | Actual K / design K (0-1) |
mistEliminatorFlooded |
boolean | True if K-factor exceeds ME capacity |
liquidInGasCalibrationFactor |
double | Calibration multiplier (1.0 = uncalibrated) |
gasCarryUnderCalibrationFactor |
double | Calibration multiplier (1.0 = uncalibrated) |
liquidLiquidCalibrationFactor |
double | Calibration multiplier (1.0 = uncalibrated) |
entrainmentDetailJson |
String | Full SeparatorPerformanceCalculator.toJson() output |
Java Example
Separator separator = new Separator("HP Sep", feedStream);
separator.setDetailedEntrainmentCalculation(true);
separator.run();
SeparatorMechanicalDesign design =
(SeparatorMechanicalDesign) separator.getMechanicalDesign();
design.calcDesign();
// Entrainment data is now part of the mechanical design
double efficiency = design.getOverallGasLiquidEfficiency();
double oilCarryover = design.getOilInGasFraction();
boolean flooded = design.isMistEliminatorFlooded();
// Full JSON includes vessel sizing + entrainment performance
String json = design.toJson();
Python Example
from neqsim import jneqsim
import json
Separator = jneqsim.process.equipment.separator.Separator
sep = Separator("HP Sep", feed_stream)
sep.setDetailedEntrainmentCalculation(True)
sep.run()
design = sep.getMechanicalDesign()
design.calcDesign()
print(f"Efficiency: {design.getOverallGasLiquidEfficiency():.2%}")
print(f"Oil in gas: {design.getOilInGasFraction():.4f}")
print(f"ME flooded: {design.isMistEliminatorFlooded()}")
# Full JSON report
report = json.loads(str(design.toJson()))
Calibration Factors in Design Reports
When the performance calculator has been calibrated (via calibrateFromMeasuredFractions()
or batch CSV calibration), the calibration factors are carried through to the mechanical
design JSON. This provides full traceability from measured plant data to the design report.
// Calibrate, then generate design
SeparatorPerformanceCalculator perf = separator.getPerformanceCalculator();
perf.calibrateFromMeasuredFractions(measuredOilInGas, measuredGasInOil, measuredOilInWater);
// Re-run separator with calibrated calculator
separator.run();
// Design now includes calibration factors
design.calcDesign();
assert design.getLiquidInGasCalibrationFactor() != 1.0; // calibrated
Dynamic Simulation Integration
The enhanced entrainment model is fully integrated with NeqSim’s transient (dynamic)
simulation via runTransient(). When enabled, the separator recalculates entrainment
fractions at every timestep using live vessel conditions, then applies those fractions to
outlet stream compositions—without disturbing the vessel mass/energy balance.
How It Works
During each runTransient(dt, id) call the following sequence executes:
- VU flash — The standard volume-energy (VU) flash solves for the new vessel state given inlet/outlet mass flows and energy balance.
- Performance calculator update — If enhanced entrainment is enabled, the calculator
reads physical properties directly from the post-flash vessel state (
thermoSystem), estimates gas velocity from the previous-timestep outlet stream, and runs the full 7-stage calculation chain. - Clone and redistribute — The vessel inventory is cloned (never modified), and
addPhaseFractionToPhase()is applied to the clone to model imperfect separation. Outlet stream compositions are set from the modified clone. - Vessel inventory preserved — The original
thermoSystem(mass balance state) is untouched. Entrainment only affects what leaves the vessel, not what is stored in it.
This design ensures that the dynamic mass balance remains conserved while outlet quality responds to changing conditions in real time.
Enabling Entrainment in Dynamic Mode
Java API
// Create separator
Separator separator = new Separator("V-100", feed);
separator.setOrientation("horizontal");
separator.setSeparatorLength(5.0);
separator.setInternalDiameter(1.5);
separator.setLiquidLevel(0.5);
// Enable enhanced entrainment (auto-generates DSD from flow regime)
separator.setEnhancedEntrainmentCalculation(true);
// Switch to transient mode
separator.setCalculateSteadyState(false);
// Initial steady-state run
separator.run();
// Transient loop
UUID id = UUID.randomUUID();
double dt = 1.0; // seconds
for (int step = 0; step < 3600; step++) {
separator.runTransient(dt, id);
// Read current entrainment fractions (updated each timestep)
SeparatorPerformanceCalculator perf = separator.getPerformanceCalculator();
double oilInGas = perf.getOilInGasFraction();
double gasInOil = perf.getGasInOilFraction();
}
Python API
from neqsim import jneqsim
import java.util.UUID as UUID
Separator = jneqsim.process.equipment.separator.Separator
separator = Separator("V-100", feed)
separator.setOrientation("horizontal")
separator.setSeparatorLength(5.0)
separator.setInternalDiameter(1.5)
separator.setLiquidLevel(0.5)
separator.setEnhancedEntrainmentCalculation(True)
separator.setCalculateSteadyState(False)
separator.run()
sim_id = UUID.randomUUID()
dt = 1.0
for step in range(3600):
separator.runTransient(dt, sim_id)
level = separator.getLiquidLevel()
perf = separator.getPerformanceCalculator()
oil_in_gas = perf.getOilInGasFraction()
Three-Phase Separator
ThreePhaseSeparator follows the same pattern but tracks all six entrainment paths:
| Path | From Phase | To Phase |
|---|---|---|
| Oil-in-gas | Oil | Gas |
| Water-in-gas | Aqueous | Gas |
| Gas-in-oil | Gas | Oil |
| Gas-in-water | Gas | Aqueous |
| Oil-in-water | Oil | Aqueous |
| Water-in-oil | Aqueous | Oil |
ThreePhaseSeparator sep3 = new ThreePhaseSeparator("V-200", feed);
sep3.setEnhancedEntrainmentCalculation(true);
sep3.setCalculateSteadyState(false);
sep3.run();
UUID id = UUID.randomUUID();
for (int step = 0; step < 3600; step++) {
sep3.runTransient(1.0, id);
// Gas, oil, and water outlets all have entrainment-corrected compositions
}
Key Design Notes
| Aspect | Detail |
|---|---|
| Gas velocity source | Estimated from gas outlet stream flow rate (previous timestep), not from vessel inventory |
| Liquid level | Read from liquidLevel field, which is updated each timestep by the VU flash |
| Oil volume fraction | Computed from vessel phase volumes (moles × molar volume) |
| Vessel inventory | Never modified by entrainment—only outlet compositions change |
| Backward compatible | Entrainment only activates when setEnhancedEntrainmentCalculation(true) is called; default behavior unchanged |
| Standard vs enhanced | The enhanced path auto-generates DSD from flow regime prediction; the standard path requires explicit DSD setup |
| Manual fractions | setEntrainment() fractions are also applied during runTransient() (no calculator needed) |
Monitoring Entrainment Over Time
Track entrainment fractions across timesteps to observe how they respond to feed disturbances, pressure changes, or liquid level swings:
List<Double> oilInGasHistory = new ArrayList<>();
List<Double> gasVelocityHistory = new ArrayList<>();
for (int step = 0; step < totalSteps; step++) {
separator.runTransient(dt, id);
SeparatorPerformanceCalculator perf = separator.getPerformanceCalculator();
oilInGasHistory.add(perf.getOilInGasFraction());
// Also track gas velocity to correlate with entrainment
// gasVelocityHistory.add(perf.getGasVelocity()); // if exposed
}
In Python with matplotlib:
import matplotlib.pyplot as plt
times, oil_in_gas_vals, levels = [], [], []
for step in range(total_steps):
separator.runTransient(dt, sim_id)
times.append(step * dt)
oil_in_gas_vals.append(separator.getPerformanceCalculator().getOilInGasFraction())
levels.append(separator.getLiquidLevel())
fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
ax1.plot(times, oil_in_gas_vals)
ax1.set_ylabel("Oil-in-Gas Fraction")
ax2.plot(times, levels)
ax2.set_ylabel("Liquid Level (m)")
ax2.set_xlabel("Time (s)")
plt.tight_layout()
plt.show()
Correlations and References
| Correlation | Application | Reference |
|---|---|---|
| Mandhane-Gregory-Aziz flow map | Horizontal flow regime prediction | Mandhane, J.M., Gregory, G.A., Aziz, K. (1974). A flow pattern map for gas-liquid flow in horizontal pipes. Int. J. Multiphase Flow, 1(4), 537-553. |
| Taitel-Dukler-Barnea | Vertical flow regime transitions | Taitel, Y., Dukler, A.E. (1976); Barnea, D. (1987). A unified model for predicting flow-pattern transitions. Int. J. Multiphase Flow, 13(1), 1-12. |
| Azzopardi d32 | Annular flow Sauter mean diameter | Azzopardi, B.J. (1997). Drops in annular two-phase flow. Int. J. Multiphase Flow, 23, 1-53. |
| Ishii-Grolmes | Stratified flow entrainment onset | Ishii, M., Grolmes, M.A. (1975). Inception criteria for droplet entrainment in two-phase concurrent film flow. AIChE J., 21(2), 308-318. |
| Hinze | Turbulent droplet breakup | Hinze, J.O. (1955). Fundamentals of the hydrodynamic mechanism of splitting in dispersion processes. AIChE J., 1(3), 289-295. |
| Oliemans et al. | Entrained liquid fraction | Oliemans, R.V.A., Pots, B.F.M., Trompe, N. (1986). Modelling of annular dispersed two-phase flow in vertical pipes. Int. J. Multiphase Flow, 12(5), 711-732. |
| Schiller-Naumann | Drag coefficient correlation | Schiller, L., Naumann, A. (1933). Uber die grundlegenden Berechnungen bei der Schwerkraftaufbereitung. Z. Ver. Dtsch. Ing., 77, 318-320. |
| Souders-Brown | K-factor for mist eliminator flooding | Souders, M., Brown, G.G. (1934). Design of fractionating columns. Ind. Eng. Chem., 26(1), 98-103. |
| Bothamley | Inlet device momentum limits | Bothamley, M. (2013). Gas/Liquid Separators: Quantifying Separation Performance. Oil Gas Facilities, 2(4), 21-29. |
| Brunazzi-Paglianti | Wire mesh demister performance | Brunazzi, E., Paglianti, A. (1998). Design of wire mesh mist eliminators. AIChE J., 44(3), 505-512. |
| Csanady | Turbulent diffusion cut-diameter correction | Csanady, G.T. (1963). Turbulent diffusion of heavy particles in the atmosphere. J. Atmos. Sci., 20(3), 201-208. |
| Koenders et al. | Turbulence intensity from K-factor load | Koenders, M.A. et al. (2015). Gas-liquid separation: prediction of liquid carryover from gravity settlers. SPE J., 20(4), 810-822. |
| API 12J | Compliance thresholds (K, cut diameter, HRT) | API Specification 12J (2014). Specification for Oil and Gas Separators. American Petroleum Institute. |
| Fabian et al. / GPSA | Partial flooding efficiency degradation | Fabian, P. et al. (1993). Demisting applications. Chem. Eng. Progress, 89(10), 58-63; GPSA Engineering Data Book (14th ed.), Ch. 7. |
| Hinze | Liquid-liquid droplet breakup (oil-water DSD) | Hinze, J.O. (1955). Fundamentals of the hydrodynamic mechanism of splitting in dispersion processes. AIChE J., 1(3), 289-295. |
Class Reference
SeparatorPerformanceCalculator
Main orchestrator. Call calculate() with fluid properties and vessel geometry.
| Method | Description |
|---|---|
calculate(...) |
Run standard or enhanced calculation |
setUseEnhancedCalculation(boolean) |
Switch between standard and enhanced |
setGasLiquidDSD(DropletSizeDistribution) |
Set inlet DSD (overrides flow regime prediction) |
setMistEliminatorCurve(GradeEfficiencyCurve) |
Set mist eliminator grade efficiency |
setInletDeviceModel(InletDeviceModel) |
Set inlet device |
setFlowRegimeCalculator(MultiphaseFlowRegime) |
Set flow regime predictor |
setGeometryCalculator(SeparatorGeometryCalculator) |
Set vessel geometry |
setInletPipeDiameter(double) |
Feed pipe diameter [m] |
setSurfaceTension(double) |
Gas-liquid interfacial tension [N/m] |
setOilWaterInterfacialTension(double) |
Oil-water interfacial tension [N/m] |
setLiquidInGasCalibrationFactor(double) |
Calibration multiplier for liquid-in-gas fractions |
setGasCarryUnderCalibrationFactor(double) |
Calibration multiplier for gas carry-under fractions |
setLiquidLiquidCalibrationFactor(double) |
Calibration multiplier for liquid-liquid fractions |
calibrateFromMeasuredFractions(...) |
Auto-calibrate from measured entrainment fractions |
calibrateFromGroupedMeasurements(...) |
Auto-calibrate from grouped measurement categories |
static loadCalibrationCasesFromCsv(String) |
Load calibration cases from CSV file |
calibrateFromCaseLibrary(List, double) |
Batch fit factors across multiple cases |
buildBatchCalibrationReportJson(List, BatchCalibrationSummary) |
JSON calibration report |
saveBatchCalibrationReportJson(String, List, BatchCalibrationSummary) |
Save report to file |
setOilVolumeFraction(double) |
Oil fraction in liquid for 3-phase geometry [0-1] — auto-set from EOS when running via Separator |
setApplyTurbulenceCorrection(boolean) |
Enable/disable Csanady turbulence correction (default: true) |
getApiComplianceResult() |
API 12J compliance result after calculate() |
static generateLiquidLiquidDSD(sigma, rhoCont, vNozzle, dNozzle) |
Hinze-based oil-water DSD from inlet conditions |
getOverallGasLiquidEfficiency() |
Combined gravity + mist eliminator efficiency |
getGravitySectionEfficiency() |
Gravity section efficiency alone |
getMistEliminatorEfficiency() |
Mist eliminator efficiency alone |
getGravityCutDiameter() |
Smallest droplet removed by gravity [m] |
getKFactor() |
Souders-Brown K-factor [m/s] |
getKFactorUtilization() |
K-factor as fraction of max allowed |
isMistEliminatorFlooded() |
True if K exceeds internals max K |
getInletFlowRegime() |
Predicted flow regime |
getPostInletDeviceDSD() |
DSD after inlet device separation |
toJson() |
Full results as JSON string |
MultiphaseFlowRegime
| Method | Description |
|---|---|
setGasDensity(double) |
Gas density [kg/m3] |
setLiquidDensity(double) |
Liquid density [kg/m3] |
setGasViscosity(double) |
Gas dynamic viscosity [Pa.s] |
setLiquidViscosity(double) |
Liquid dynamic viscosity [Pa.s] |
setSurfaceTension(double) |
Gas-liquid surface tension [N/m] |
setPipeDiameter(double) |
Pipe inner diameter [m] |
setGasSuperficialVelocity(double) |
Gas superficial velocity [m/s] |
setLiquidSuperficialVelocity(double) |
Liquid superficial velocity [m/s] |
setPipeOrientation(String) |
“horizontal” or “vertical” |
predict() |
Run prediction (no arguments) |
getPredictedRegime() |
Get result FlowRegime enum |
getGeneratedDSD() |
Get auto-generated DSD |
calcEntrainedLiquidFraction() |
Oliemans et al. correlation |
InletDeviceModel
| Method | Description |
|---|---|
InletDeviceModel(InletDeviceType) |
Constructor with device type |
setInletNozzleDiameter(double) |
Nozzle diameter [m] |
calculate(DSD, gasDens, liqDens, gasFlow, liqFlow, sigma) |
Run calculation |
getBulkSeparationEfficiency() |
Fraction of liquid removed at inlet |
getDownstreamDSD() |
DSD after inlet device |
getNozzleVelocity() |
Mixture velocity at nozzle [m/s] |
getMomentumFlux() |
Inlet momentum $\rho v^2$ [Pa] |
getPressureDrop() |
Device pressure drop [Pa] |
SeparatorGeometryCalculator
| Method | Description |
|---|---|
setOrientation(String) |
“horizontal” or “vertical” |
setInternalDiameter(double) |
Vessel ID [m] |
setTangentToTangentLength(double) |
Vessel length [m] |
setNormalLiquidLevel(double) |
Liquid level as fraction of diameter |
calculate(gasFlow, liqFlow) |
Two-phase geometry |
calculateThreePhase(gasFlow, oilFlow, waterFlow, oilFrac) |
Three-phase |
getGasArea() / getLiquidArea() |
Cross-sectional areas [m2] |
getEffectiveGasSettlingHeight() |
Gas settling height [m] |
getEffectiveLiquidSettlingHeight() |
Liquid settling height [m] |
getGasResidenceTime() / getLiquidResidenceTime() |
Residence times [s] |
getOilPadThickness() / getWaterLayerHeight() |
Three-phase heights [m] |
static calcKFactor(vGas, rhoGas, rhoLiq) |
Souders-Brown K [m/s] |
DropletSizeDistribution
| Method | Description |
|---|---|
static rosinRammler(d0, n) |
Create Rosin-Rammler DSD |
static logNormal(d50, sigma) |
Create log-normal DSD |
getD50() |
Median diameter [m] |
getSauterMeanDiameter() |
Volume-surface mean d32 [m] |
getDiscreteClasses() |
20-bin discretization |
getCumulativeFraction(d) |
CDF at diameter d |
DropletSettlingCalculator
| Method | Description |
|---|---|
static calcTerminalVelocity(d, rhoCont, rhoDisp, muCont) |
Terminal velocity [m/s] |
static calcDragCoefficient(Re) |
Schiller-Naumann drag |
static calcTurbulenceCorrectedCutDiameter(dCut, vGas, H, kFactor, kDesign, rhoGas, rhoLiq, muGas) |
Csanady (1963) turbulence-corrected effective cut diameter [m] |
static checkApi12JCompliance(dCut, kFactor, hasME, liquidHRT, orientation, isThreePhase) |
API 12J compliance check returning ApiComplianceResult |
GradeEfficiencyCurve
| Method | Description |
|---|---|
static wireMeshDefault() |
Standard wire mesh pad |
static vanePackDefault() |
Standard vane pack |
static axialCycloneDefault() |
Standard axial cyclone |
static platePack(d50, maxEff) |
Custom plate pack |
getEfficiency(d) |
Grade efficiency at diameter d |
calcOverallEfficiency(DSD) |
Integrated efficiency over DSD |
SeparatorInternalsDatabase
| Method | Description |
|---|---|
static getInstance() |
Singleton accessor |
findByType(String) |
Find internals by type |
findByTypeAndSubType(String, String) |
Find specific variant |
findInletDeviceByType(String) |
Find inlet devices by type |
getAllInternals() |
All internals records (70+) |
getAllInletDevices() |
All inlet device records (31) |
getAllVendorCurves() |
All vendor curve records (25) |
findVendorCurvesByType(String) |
Find vendor curves by internals type |
findVendorCurvesByVendor(String) |
Find vendor curves by vendor name |
findVendorCurveById(String) |
Find a specific vendor curve by ID |
findVendorCurvesByTypeAndVendor(String, String) |
Find curves by type and vendor |
toCatalogJson() |
Full catalog as JSON (internals + inlet devices + vendor curves) |
Related Documentation
- Separator Equipment — Base separator documentation, entrainment specification, design constraints
- Dynamic Simulation Guide — Transient simulation, time stepping, control systems
- Capacity Constraint Framework — K-value and performance constraints system
- Dynamic Entrainment Notebook — Transient separator simulation with enhanced entrainment
- Vendor Curves & Calibration Notebook — Internals database, vendor curves, calibration
- Steady-State Entrainment Notebook — Physics-based entrainment modeling