Class Hydrocyclone

All Implemented Interfaces:
Serializable, Runnable, AutoSizeable, CapacityConstrainedEquipment, ProcessEquipmentInterface, SeparatorInterface, StateVectorProvider, ProcessElementInterface, SimulationInterface, NamedInterface

public class Hydrocyclone extends Separator
De-oiling hydrocyclone for produced water treatment.

Models a multi-liner de-oiling hydrocyclone package used on offshore platforms for primary produced water treatment. The implementation is based on the equilibrium-orbit theory (Bradley 1965, Svarovsky 1984) combined with the Stokes-law centrifugal settling model. It covers:

  • Physics-based d50 prediction from fluid properties and liner geometry
  • Rosin-Rammler grade efficiency curve integrated over a log-normal droplet size distribution
  • Multi-liner sizing with standard liner diameters (35, 45, 60 mm)
  • PDR (Pressure Drop Ratio) model for reject stream control
  • Turndown behaviour with min/max flow per liner and efficiency degradation
  • OSPAR/NCS compliance checking against 30 mg/L monthly weighted average
  • Capacity utilization using the Separator constraint framework

Governing Equations

The cut size d50 for a cylindrical cyclone is derived from the centrifugal-Stokes balance:

d50 = sqrt(C * mu * Q / (deltaRho * D^2))

which simplifies for a standard deoiling liner to a correlation with flow, viscosity, and density difference. The grade efficiency for droplet diameter d is:

eta(d) = 1 - exp(-0.693 * (d / d50)^n)

where n is the sharpness-of-cut index (typically 2-4, default 3). The overall efficiency is obtained by integrating eta(d) over the droplet size distribution.

Design Standards

Applicable standards for hydrocyclone design
StandardScope
NORSOK P-001Process design, produced water treatment
OLF 052 (NOROG)Produced water management NCS
OSPAR Rec 2001/130 mg/L OIW discharge limit

Typical Operating Ranges

Operating ranges for oil-water hydrocyclones
ParameterRangeUnit
d50 cut size8-15microns
Reject ratio (PDR-controlled)1-3% of feed
Pressure drop (inlet to overflow)1-3bar
Differential pressure (inlet-overflow)2-6bar
Turndown ratio2.5:1 to 4:1-
PDR1.4-2.0-
Oil removal (bulk)90-98%
Version:
2.0
Author:
ESOL
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      See Also:
    • OSPAR_OIW_LIMIT_MGL

      public static final double OSPAR_OIW_LIMIT_MGL
      OSPAR / NCS monthly average OIW discharge limit (mg/L).
      See Also:
    • MIN_DESIGN_DP_BAR

      public static final double MIN_DESIGN_DP_BAR
      Minimum recommended differential pressure for oil hydrocyclone (bar).
      See Also:
    • STANDARD_LINER_SIZES_MM

      public static final double[] STANDARD_LINER_SIZES_MM
      Standard liner cone diameters in mm.
    • linerDiameterMm

      private double linerDiameterMm
      Liner cone diameter (mm). Default 35 mm is most common for oil-water.
    • linerEffectiveLengthM

      private double linerEffectiveLengthM
      Effective separation length of one liner (m). Derived from liner diameter.
    • numberOfLiners

      private int numberOfLiners
      Number of active liners.
    • numberOfSpareLiners

      private int numberOfSpareLiners
      Number of spare (blanked-off) liners.
    • linersPerVessel

      private int linersPerVessel
      Liners per vessel (pressure housing). Typical 4-12.
    • d50Microns

      private double d50Microns
      d50 cut size in microns (user-set or calculated).
    • d50UserSet

      private boolean d50UserSet
      Whether d50 was explicitly set by user (vs calculated from conditions).
    • sharpnessIndex

      private double sharpnessIndex
      Rosin-Rammler sharpness index n. Typical 2-4.
    • rejectRatio

      private double rejectRatio
      Reject ratio - fraction of feed going to reject (oil-rich) outlet.
    • pressureDrop

      private double pressureDrop
      Pressure drop across cyclone, inlet to clean water overflow (bar).
    • pdr

      private double pdr
      Pressure Drop Ratio: PDR = (P_in - P_reject) / (P_in - P_overflow).
    • oilRemovalEfficiency

      private double oilRemovalEfficiency
      Overall oil removal efficiency (0-1). Calculated or user-set.
    • efficiencyUserSet

      private boolean efficiencyUserSet
      Whether efficiency was explicitly set by user (vs calculated).
    • designFlowPerLinerM3h

      private double designFlowPerLinerM3h
      Design flow per liner (m3/h). Set from liner diameter lookup.
    • minFlowPerLinerM3h

      private double minFlowPerLinerM3h
      Minimum flow per liner (m3/h). Below this, centrifugal force is too low.
    • maxFlowPerLinerM3h

      private double maxFlowPerLinerM3h
      Maximum flow per liner (m3/h). Above this, droplet re-entrainment occurs.
    • inletOilMgL

      private double inletOilMgL
      Inlet oil concentration (mg/L).
    • outletOilMgL

      private double outletOilMgL
      Outlet oil concentration (mg/L). Calculated.
    • dv50Microns

      private double dv50Microns
      Median droplet diameter (volume-weighted) in microns.
    • gsd

      private double gsd
      Geometric standard deviation of droplet size distribution.
    • waterViscosityPas

      private double waterViscosityPas
      Water dynamic viscosity (Pa.s). Default 20 degC.
    • oilDensityKgm3

      private double oilDensityKgm3
      Oil density (kg/m3).
    • waterDensityKgm3

      private double waterDensityKgm3
      Water density (kg/m3).
    • feedFlowM3h

      private double feedFlowM3h
      Calculated feed flow rate (m3/h).
    • flowPerLinerM3h

      private double flowPerLinerM3h
      Calculated flow per liner (m3/h).
    • capacityUtilization

      private double capacityUtilization
      Calculated capacity utilization (0-1+).
    • calculatedD50

      private double calculatedD50
      Calculated d50 from Stokes model.
    • calculatedEfficiency

      private double calculatedEfficiency
      Calculated overall efficiency from DSD integration.
    • numberOfVessels

      private int numberOfVessels
      Number of vessels (calculated from liners).
    • hydrocycloneMechanicalDesign

      private HydrocycloneMechanicalDesign hydrocycloneMechanicalDesign
      Hydrocyclone-specific mechanical design instance.
  • Constructor Details

    • Hydrocyclone

      public Hydrocyclone(String name)
      Creates a hydrocyclone with default parameters.
      Parameters:
      name - equipment name/tag
    • Hydrocyclone

      public Hydrocyclone(String name, StreamInterface inletStream)
      Creates a hydrocyclone with an inlet stream.
      Parameters:
      name - equipment name/tag
      inletStream - produced water stream containing dispersed oil
  • Method Details

    • initLinerDefaults

      private void initLinerDefaults()
      Sets liner geometry defaults based on current liner diameter.
    • getMechanicalDesign

      public HydrocycloneMechanicalDesign getMechanicalDesign()

      Get a mechanicalDesign for the equipment.

      Specified by:
      getMechanicalDesign in interface ProcessEquipmentInterface
      Overrides:
      getMechanicalDesign in class Separator
      Returns:
      a MechanicalDesign object
    • initMechanicalDesign

      public void initMechanicalDesign()

      Initialize a initMechanicalDesign for the equipment.

      Specified by:
      initMechanicalDesign in interface ProcessEquipmentInterface
      Overrides:
      initMechanicalDesign in class Separator
    • setLinerDiameterMm

      public void setLinerDiameterMm(double diameterMm)
      Sets the liner cone diameter from standard sizes: 35, 45, or 60 mm.

      The liner diameter determines the design, minimum, and maximum flow per liner. Smaller liners (35 mm) give finer cut sizes and are preferred for deoiling. Larger liners (60 mm) handle higher flow per liner and are used where coarser separation is acceptable.

      Parameters:
      diameterMm - liner cone diameter in mm (35, 45, or 60)
    • getLinerDiameterMm

      public double getLinerDiameterMm()
      Gets the liner cone diameter.
      Returns:
      diameter in mm
    • updateLinerCapacityFromDiameter

      private void updateLinerCapacityFromDiameter()
      Updates flow-per-liner capacity based on liner diameter.

      Flow capacity scales approximately with D^2 (cross-sectional area). The reference is a 35 mm liner at 5 m3/h design flow. These values are based on typical vendor data for deoiling hydrocyclones (Vortoil, CDS Natco).

    • setNumberOfLiners

      public void setNumberOfLiners(int liners)
      Sets the number of active liners.
      Parameters:
      liners - number of active liners
    • getNumberOfLiners

      public int getNumberOfLiners()
      Gets the number of active liners.
      Returns:
      number of active liners
    • setNumberOfSpareLiners

      public void setNumberOfSpareLiners(int spares)
      Sets the number of spare (blanked-off) liners for turndown/redundancy.
      Parameters:
      spares - number of spare liners
    • getNumberOfSpareLiners

      public int getNumberOfSpareLiners()
      Gets the number of spare liners.
      Returns:
      spare liners
    • setLinersPerVessel

      public void setLinersPerVessel(int linersPerVessel)
      Sets the number of liners per vessel (pressure housing).
      Parameters:
      linersPerVessel - liners per vessel (typically 4-12)
    • getLinersPerVessel

      public int getLinersPerVessel()
      Gets the number of liners per vessel.
      Returns:
      liners per vessel
    • setD50Microns

      public void setD50Microns(double d50)
      Sets the d50 cut size. When set explicitly, the Stokes calculation is bypassed.
      Parameters:
      d50 - cut size in microns
    • getD50Microns

      public double getD50Microns()
      Gets the d50 cut size (user-set or calculated).
      Returns:
      d50 in microns
    • setSharpnessIndex

      public void setSharpnessIndex(double n)
      Sets the Rosin-Rammler sharpness index.
      Parameters:
      n - sharpness index (typical 2-4)
    • getSharpnessIndex

      public double getSharpnessIndex()
      Gets the sharpness index.
      Returns:
      sharpness index
    • setRejectRatio

      public void setRejectRatio(double ratio)
      Sets the reject ratio (fraction of feed going to oil-rich reject stream).
      Parameters:
      ratio - reject/feed ratio (0.005-0.10 typical)
    • getRejectRatio

      public double getRejectRatio()
      Gets the reject ratio.
      Returns:
      reject ratio
    • setPressureDrop

      public void setPressureDrop(double dp)
      Sets the pressure drop from inlet to clean water overflow.
      Overrides:
      setPressureDrop in class Separator
      Parameters:
      dp - pressure drop in bar
    • getPressureDropBar

      public double getPressureDropBar()
      Gets the pressure drop (inlet to overflow).
      Returns:
      pressure drop in bar
    • setPressureDropBar

      public void setPressureDropBar(double dp)
      Sets pressure drop in bar. Alias for setPressureDrop kept for backward compatibility.
      Parameters:
      dp - pressure drop in bar
    • setPDR

      public void setPDR(double pdr)
      Sets the Pressure Drop Ratio. PDR = (P_inlet - P_reject) / (P_inlet - P_overflow).

      PDR controls the reject split. Higher PDR drives more flow to reject, increasing oil removal but also water loss. Typical 1.4-2.0.

      Parameters:
      pdr - pressure drop ratio (typically 1.4-2.0)
    • getPDR

      public double getPDR()
      Gets the Pressure Drop Ratio.
      Returns:
      PDR
    • setOilRemovalEfficiency

      public void setOilRemovalEfficiency(double efficiency)
      Sets the overall oil removal efficiency directly. When set, the DSD integration is bypassed.
      Parameters:
      efficiency - efficiency (0.0-1.0)
    • getOilRemovalEfficiency

      public double getOilRemovalEfficiency()
      Gets the oil removal efficiency (user-set or calculated).
      Returns:
      efficiency (0.0-1.0)
    • setInletOilConcentration

      public void setInletOilConcentration(double oilMgL)
      Sets the inlet oil-in-water concentration.
      Parameters:
      oilMgL - oil concentration in mg/L
    • getInletOilConcentration

      public double getInletOilConcentration()
      Gets the inlet oil concentration.
      Returns:
      oil concentration in mg/L
    • setDv50Microns

      public void setDv50Microns(double dv50)
      Sets the volume-weighted median droplet diameter of the inlet DSD.

      Typical values for produced water after a separator are 20-50 microns. Lower values (10-20) indicate heavy/viscous oil or shear from choke valves.

      Parameters:
      dv50 - volume median diameter in microns
    • getDv50Microns

      public double getDv50Microns()
      Gets the volume median droplet diameter.
      Returns:
      dv50 in microns
    • setGeometricStdDev

      public void setGeometricStdDev(double gsd)
      Sets the geometric standard deviation of the log-normal DSD.

      Typical values 2.0-3.5. Larger GSD means a wider DSD with more fine droplets.

      Parameters:
      gsd - geometric standard deviation
    • getGeometricStdDev

      public double getGeometricStdDev()
      Gets the geometric standard deviation.
      Returns:
      GSD
    • setWaterViscosity

      public void setWaterViscosity(double viscosityPas)
      Sets the water dynamic viscosity.
      Parameters:
      viscosityPas - viscosity in Pa.s (0.001 = water at 20 degC)
    • setOilDensity

      public void setOilDensity(double densityKgm3)
      Sets the oil density.
      Parameters:
      densityKgm3 - oil density in kg/m3
    • setWaterDensity

      public void setWaterDensity(double densityKgm3)
      Sets the water density.
      Parameters:
      densityKgm3 - water density in kg/m3
    • calcNumberOfLiners

      public int calcNumberOfLiners(double totalFlowM3h)
      Calculates the required number of liners for a given total water flow rate.

      Uses the design flow per liner and rounds up to the nearest integer.

      Parameters:
      totalFlowM3h - total water flow rate in m3/h
      Returns:
      required number of active liners
    • autoSize

      public void autoSize()
      Auto-sizes the hydrocyclone for the current inlet stream flow rate.

      Determines the number of liners, vessels, and updates capacity utilization. Should be called after the inlet stream has been configured and run.

      Specified by:
      autoSize in interface AutoSizeable
      Overrides:
      autoSize in class Separator
    • calcNumberOfVessels

      public int calcNumberOfVessels()
      Calculates the number of vessels needed.
      Returns:
      number of vessels
    • getNumberOfVessels

      public int getNumberOfVessels()
      Gets the number of vessels (pressure housings).
      Returns:
      number of vessels
    • getMaxDesignCapacityM3h

      public double getMaxDesignCapacityM3h()
      Gets the total package capacity at design flow.
      Returns:
      maximum design capacity in m3/h
    • getMinOperatingFlowM3h

      public double getMinOperatingFlowM3h()
      Gets the minimum operatable flow rate (all liners at minimum flow).
      Returns:
      minimum total flow in m3/h
    • getMaxOperatingFlowM3h

      public double getMaxOperatingFlowM3h()
      Gets the maximum operatable flow rate (all liners at maximum flow).
      Returns:
      maximum total flow in m3/h
    • getTurndownRatio

      public double getTurndownRatio()
      Gets the turndown ratio based on liner operating range.
      Returns:
      turndown ratio (max/min for a single liner)
    • getDesignFlowPerLinerM3h

      public double getDesignFlowPerLinerM3h()
      Gets the design flow per liner.
      Returns:
      design flow in m3/h
    • getMinFlowPerLinerM3h

      public double getMinFlowPerLinerM3h()
      Gets the minimum flow per liner.
      Returns:
      minimum flow in m3/h
    • getMaxFlowPerLinerM3h

      public double getMaxFlowPerLinerM3h()
      Gets the maximum flow per liner.
      Returns:
      maximum flow in m3/h
    • getFlowPerLinerM3h

      public double getFlowPerLinerM3h()
      Gets the current flow per liner (after run or auto-size).
      Returns:
      current flow per liner in m3/h
    • calcD50FromConditions

      public double calcD50FromConditions()
      Calculates the d50 cut size from the centrifugal Stokes settling model.

      The cut size depends on the flow rate per liner, water viscosity, density difference between oil and water, and liner geometry. The simplified correlation is calibrated so that a 35 mm liner at 5 m3/h with water at 20 degC and deltaRho 175 kg/m3 gives d50 of approximately 12 microns.

      Returns:
      calculated d50 in microns
    • getEfficiencyForDropletSize

      public double getEfficiencyForDropletSize(double dropletSizeMicrons)
      Calculates removal efficiency for a specific droplet diameter using the Rosin-Rammler model.
      Parameters:
      dropletSizeMicrons - droplet diameter in microns
      Returns:
      removal efficiency (0.0-1.0)
    • calcEfficiencyFromDSD

      public double calcEfficiencyFromDSD()
      Integrates the grade efficiency curve over a log-normal droplet size distribution to calculate the overall separation efficiency.

      Uses 50-point numerical quadrature over the log-normal distribution from 0.5 micron to 5x the median diameter.

      Returns:
      overall efficiency (0.0-1.0) weighted by volume
    • calcRejectRatioFromPDR

      public double calcRejectRatioFromPDR()
      Estimates the reject ratio from the Pressure Drop Ratio.

      The reject ratio is approximately RR = 0.01 * PDR^1.5 for standard deoiling hydrocyclones. Gives RR approximately 1.5% at PDR 1.4 and approximately 2.5% at PDR 2.0.

      Returns:
      estimated reject ratio
    • getPDREfficiencyFactor

      public double getPDREfficiencyFactor()
      Estimates the efficiency correction factor based on PDR.

      Efficiency is optimum at PDR around 1.8. Below 1.3, short-circuiting degrades performance. Above 2.5, excessive water loss without much efficiency gain.

      Returns:
      PDR correction factor (multiply with base efficiency)
    • isDifferentialPressureAdequate

      public boolean isDifferentialPressureAdequate()
      Checks whether the available differential pressure meets the minimum design requirement.
      Returns:
      true if pressure drop meets minimum (2 bar)
    • isOSPARCompliant

      public boolean isOSPARCompliant()
      Checks if the hydrocyclone meets OSPAR 30 mg/L discharge limit.
      Returns:
      true if outlet OIW is at or below 30 mg/L
    • isWithinOperatingRange

      public boolean isWithinOperatingRange()
      Checks if each liner is operating within its valid flow range.
      Returns:
      true if within turndown/turnup limits
    • calcRequiredInletPressure

      public double calcRequiredInletPressure(double waterOutletPressureBar, double rejectValveDPBar, double rejectLineDPBar, double heightDifferenceDPBar)
      Calculates the required inlet pressure given downstream back-pressures.
      Parameters:
      waterOutletPressureBar - water outlet back-pressure (bar)
      rejectValveDPBar - pressure drop across reject control valve (bar)
      rejectLineDPBar - pressure drop in reject piping (bar)
      heightDifferenceDPBar - static head difference to reject destination (bar)
      Returns:
      required inlet pressure (bar)
    • estimateEfficiencyFromConditions

      public double estimateEfficiencyFromConditions(double availableDPBar, double waterTemperatureC)
      Estimates oil removal efficiency based on available differential pressure and water temperature.

      Higher dP improves efficiency. Lower temperature (higher viscosity) reduces efficiency. Base efficiency is at 20 degC and 5 bar dP.

      Parameters:
      availableDPBar - available differential pressure (bar)
      waterTemperatureC - water temperature (degrees Celsius)
      Returns:
      estimated oil removal efficiency (0.0-1.0)
    • getHydrocycloneCapacityUtilization

      public double getHydrocycloneCapacityUtilization()
      Gets the capacity utilization as the ratio of actual flow per liner to design flow.

      Values below 0.4 indicate under-utilisation (poor separation). Values above 1.5 indicate significant overload (droplet re-entrainment). Optimum is 0.7-1.2.

      Returns:
      capacity utilization (0.0 = empty, 1.0 = design flow)
    • isOverloaded

      public boolean isOverloaded()
      Checks if the hydrocyclone package is overloaded (flow per liner exceeds maximum).
      Overrides:
      isOverloaded in class Separator
      Returns:
      true if overloaded
    • run

      public void run(UUID id)

      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 Separator
      Parameters:
      id - UUID
    • extractFluidProperties

      private void extractFluidProperties()
      Extracts fluid properties from the inlet stream for d50 and efficiency calculations.
    • calcFeedFlow

      private void calcFeedFlow()
      Calculates the total feed flow rate from the inlet stream.
    • getOutletOilMgL

      public double getOutletOilMgL()
      Gets the outlet oil-in-water concentration.
      Returns:
      OIW in mg/L
    • getFeedFlowM3h

      public double getFeedFlowM3h()
      Gets the feed flow rate.
      Returns:
      feed flow in m3/h
    • getCalculatedD50

      public double getCalculatedD50()
      Gets the calculated d50 (from Stokes model).
      Returns:
      calculated d50 in microns
    • getCalculatedEfficiency

      public double getCalculatedEfficiency()
      Gets the calculated efficiency from DSD integration.
      Returns:
      calculated efficiency (0.0-1.0)
    • getRemovedOilKgPerHour

      public double getRemovedOilKgPerHour()
      Gets the oil mass removed per hour.
      Returns:
      removed oil in kg/h
    • getRejectFlowM3h

      public double getRejectFlowM3h()
      Gets the reject stream flow rate.
      Returns:
      reject flow in m3/h
    • getOverflowFlowM3h

      public double getOverflowFlowM3h()
      Gets the clean water (overflow) flow rate.
      Returns:
      overflow flow in m3/h
    • getDesignValidationSummary

      public String getDesignValidationSummary()
      Gets a comprehensive design and sizing summary.
      Returns:
      human-readable design report
    • getSizingResults

      public Map<String,Object> getSizingResults()
      Returns a map of sizing results for programmatic access.
      Returns:
      map of sizing parameter names to values