Class SulfurDepositionAnalyser

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

public class SulfurDepositionAnalyser extends TwoPortEquipment
Analyser for elemental sulfur formation, deposition, and corrosion in natural gas systems.

This unit operation combines multiple analysis capabilities for understanding sulfur behaviour in gas value chains (offshore and onshore):

  • Chemical equilibrium: Uses the Gibbs reactor to compute equilibrium products from H2S and O2 reactions, including S8, SO2, SO3, and sulfuric acid formation.
  • Sulfur solubility: Calculates S8 solubility in the gas phase at given conditions and identifies precipitation (solid formation) via TP-solid flash.
  • Temperature sweep: Scans across a range of temperatures to find the onset temperature for solid sulfur deposition and maps the deposition profile.
  • Corrosion assessment: Evaluates FeS (iron sulfide) formation potential and corrosion risk from H2S and SO2 in the presence of water.

Key Reactions Modelled

Sulfur-related chemical reactions modelled by this analyser
Reaction Description
2 H2S + O2 = 2 H2O + 1/4 S8 Direct oxidation of H2S (Claus reaction)
2 H2S + 3 O2 = 2 SO2 + 2 H2O Full oxidation of H2S
3 H2S + SO2 = 4 S + 2 H2O Claus tail gas reaction
H2S + Fe = FeS + H2 Iron sulfide (corrosion) formation

Usage Example

SystemInterface gas = new SystemSrkEos(273.15 + 50, 70.0);
gas.addComponent("methane", 0.93);
gas.addComponent("H2S", 0.0001);
gas.addComponent("oxygen", 0.00001);
gas.addComponent("CO2", 0.02);
gas.addComponent("S8", 1e-8);
gas.addComponent("SO2", 0.0);
gas.addComponent("water", 0.001);
gas.setMixingRule(2);

Stream feed = new Stream("feed", gas);
feed.setFlowRate(100000, "kg/hr");
feed.run();

SulfurDepositionAnalyser analyser = new SulfurDepositionAnalyser("Sulfur Analyser", feed);
analyser.setTemperatureSweepRange(0, 200, 5); // 0-200 C in 5 C steps
analyser.run();

// Get results
String report = analyser.getResultsAsJson();
double onsetTemp = analyser.getSulfurDepositionOnsetTemperature();
double s8Solubility = analyser.getSulfurSolubilityInGas();
boolean corrosionRisk = analyser.hasCorrosionRisk();
Version:
1.0
Author:
Even Solbraa
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      Serialization version UID.
      See Also:
    • logger

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

      private static final double S8_MOLAR_MASS
      Molar mass of S8 in kg/mol.
      See Also:
    • MOL_FRAC_TO_MG_SM3

      private static final double MOL_FRAC_TO_MG_SM3
      Conversion factor from mol fraction to mg/Sm3.
      See Also:
    • tempSweepStartC

      private double tempSweepStartC
    • tempSweepEndC

      private double tempSweepEndC
    • tempSweepStepC

      private double tempSweepStepC
    • analysisPressueBara

      private double analysisPressueBara
    • runChemicalEquilibrium

      private boolean runChemicalEquilibrium
    • runSolidFlash

      private boolean runSolidFlash
    • runCorrosionAssessment

      private boolean runCorrosionAssessment
    • gibbsMaxIterations

      private int gibbsMaxIterations
    • gibbsDamping

      private double gibbsDamping
    • gibbsTolerance

      private double gibbsTolerance
    • sulfurSolubilityMolFrac

      private double sulfurSolubilityMolFrac
    • sulfurSolubilityMgSm3

      private double sulfurSolubilityMgSm3
    • sulfurDepositionOnsetTemperatureC

      private double sulfurDepositionOnsetTemperatureC
    • solidSulfurPresent

      private boolean solidSulfurPresent
    • solidSulfurFraction

      private double solidSulfurFraction
    • equilibriumComposition

      private Map<String,Double> equilibriumComposition
    • temperatureSweepResults

      private List<Map<String,Object>> temperatureSweepResults
    • corrosionAssessment

      private Map<String,Object> corrosionAssessment
    • reactionSummary

      private Map<String,Object> reactionSummary
    • kineticAnalysis

      private Map<String,Object> kineticAnalysis
    • supersaturationAnalysis

      private Map<String,Object> supersaturationAnalysis
    • gasVsLiquidSolubility

      private Map<String,Object> gasVsLiquidSolubility
    • blockageRiskAssessment

      private Map<String,Object> blockageRiskAssessment
    • catalysisAnalysis

      private Map<String,Object> catalysisAnalysis
    • pipeDiameterM

      private double pipeDiameterM
    • pipeSegmentLengthM

      private double pipeSegmentLengthM
    • flowVelocityMs

      private double flowVelocityMs
    • gasFlowRateSm3h

      private double gasFlowRateSm3h
  • Constructor Details

    • SulfurDepositionAnalyser

      public SulfurDepositionAnalyser(String name)
      Creates a new SulfurDepositionAnalyser.
      Parameters:
      name - equipment name
    • SulfurDepositionAnalyser

      public SulfurDepositionAnalyser(String name, StreamInterface stream)
      Creates a new SulfurDepositionAnalyser with an inlet stream.
      Parameters:
      name - equipment name
      stream - inlet stream
  • Method Details

    • setTemperatureSweepRange

      public void setTemperatureSweepRange(double startC, double endC, double stepC)
      Sets the temperature range for the deposition sweep analysis.
      Parameters:
      startC - start temperature in Celsius
      endC - end temperature in Celsius
      stepC - step size in Celsius
    • setAnalysisPressure

      public void setAnalysisPressure(double pressureBara)
      Sets the pressure for the analysis (default: use inlet pressure).
      Parameters:
      pressureBara - pressure in bara, or -1 to use inlet pressure
    • setRunChemicalEquilibrium

      public void setRunChemicalEquilibrium(boolean enabled)
      Enables or disables chemical equilibrium calculation.
      Parameters:
      enabled - true to run equilibrium (default: true)
    • setRunSolidFlash

      public void setRunSolidFlash(boolean enabled)
      Enables or disables solid flash calculation.
      Parameters:
      enabled - true to run solid flash (default: true)
    • setRunCorrosionAssessment

      public void setRunCorrosionAssessment(boolean enabled)
      Enables or disables corrosion assessment.
      Parameters:
      enabled - true to run corrosion assessment (default: true)
    • setGibbsMaxIterations

      public void setGibbsMaxIterations(int maxIter)
      Sets Gibbs reactor max iterations.
      Parameters:
      maxIter - maximum iterations
    • setGibbsDamping

      public void setGibbsDamping(double damping)
      Sets Gibbs reactor damping factor.
      Parameters:
      damping - damping factor (0-1)
    • setGibbsTolerance

      public void setGibbsTolerance(double tolerance)
      Sets Gibbs reactor convergence tolerance.
      Parameters:
      tolerance - convergence tolerance
    • setPipeDiameter

      public void setPipeDiameter(double diameterM)
      Sets pipe diameter for blockage risk calculations.
      Parameters:
      diameterM - pipe inner diameter in metres
    • setPipeSegmentLength

      public void setPipeSegmentLength(double lengthM)
      Sets pipe segment length for blockage risk calculations.
      Parameters:
      lengthM - pipe segment length in metres
    • setFlowVelocity

      public void setFlowVelocity(double velocityMs)
      Sets gas flow velocity for blockage risk calculations.
      Parameters:
      velocityMs - gas velocity in m/s
    • setGasFlowRate

      public void setGasFlowRate(double flowRateSm3h)
      Sets gas flow rate at standard conditions for blockage risk calculations.
      Parameters:
      flowRateSm3h - volumetric flow rate in Sm3/h
    • run

      public void run(UUID id)

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

      Parameters:
      id - UUID
    • performChemicalEquilibrium

      private void performChemicalEquilibrium(StreamInterface inlet, double pressure)
      Performs Gibbs free energy minimisation to determine equilibrium products from H2S and O2 reactions at the inlet conditions.
      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • setHydrocarbonInert

      private void setHydrocarbonInert(GibbsReactor reactor, SystemInterface sys)
      Marks hydrocarbon components as inert in the Gibbs reactor so they do not participate in reactions.
      Parameters:
      reactor - the Gibbs reactor
      sys - the thermo system
    • performSulfurSolubilityAnalysis

      private void performSulfurSolubilityAnalysis(StreamInterface inlet, double pressure)
      Analyses sulfur solubility in the gas phase and checks for solid S8 formation using TP-solid flash at inlet conditions.
      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • performTemperatureSweep

      private void performTemperatureSweep(StreamInterface inlet, double pressure)
      Sweeps temperature to find the sulfur deposition onset temperature and build a deposition profile. At each temperature, performs a TP-solid flash and records S8 in gas vs solid.
      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • performCorrosionAssessment

      private void performCorrosionAssessment(StreamInterface inlet, double pressure)
      Assesses corrosion risk from sulfur species and CO2. Evaluates:
      • FeS formation potential from H2S in presence of water
      • Sour corrosion severity based on H2S partial pressure (NACE MR0175)
      • SO2 corrosion risk and sulfuric acid formation risk
      • Direct S8 + Fe corrosion: S8 + 8Fe -> 8FeS
      • CO2 corrosion rate via de Waard-Milliams (1991) model
      • FeCO3 (siderite) scale formation tendency
      • FeS scale morphology (mackinawite / troilite / pyrrhotite)
      • Combined CO2 + H2S + S8 quantitative corrosion rate
      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • performKineticAnalysis

      private void performKineticAnalysis(StreamInterface inlet, double pressure)
      Performs kinetic analysis of sulfur-related reactions. Evaluates whether reactions are kinetically feasible at the given conditions by comparing reaction half-lives with typical process residence times.

      Literature-based rate models used:

      • H2S thermal oxidation: Ea ~ 50-65 kJ/mol (Monnery et al., 1993; Cheremisinoff, 2000). Negligible below 200 C.
      • Claus reaction (catalytic): k = A*exp(-Ea/RT), Ea ~ 30-40 kJ/mol on Al2O3 catalyst
      • FeS formation: diffusion-controlled at steel surface, rate depends on H2S partial pressure and temperature. Approximate Arrhenius with Ea ~ 20 kJ/mol (Sun & Nesic, 2009)
      • Polysulfane formation: H2S + Sx = H2(S)x+1, intermediate step in sulfur precipitation
      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • performSupersaturationAnalysis

      private void performSupersaturationAnalysis(StreamInterface inlet, double pressure)
      Analyses the supersaturation state of dissolved S8 and estimates nucleation risk using classical nucleation theory.

      The supersaturation ratio sigma = y_S8_actual / y_S8_sat determines whether precipitation will occur:

      • sigma < 1: Undersaturated. No deposition risk.
      • 1 < sigma < 1.5: Metastable zone. Nucleation unlikely without seed crystals.
      • sigma > 1.5: Labile zone. Spontaneous homogeneous nucleation expected.

      Literature: Mersmann (2001), Mullin (2001) - Crystallization. The interfacial energy of solid S8 is approx. 0.025-0.035 J/m2.

      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • performGasVsLiquidSolubilityComparison

      private void performGasVsLiquidSolubilityComparison(StreamInterface inlet, double pressure)
      Compares S8 solubility in gas phase versus liquid hydrocarbon phase.

      S8 is approximately 100-1000x more soluble in liquid hydrocarbons than in the gas phase (Roof, 1971; Roberts, 1997). This has critical implications:

      • When liquid HC condenses (crossing hydrocarbon dew point), it acts as a "sulfur sponge" - absorbing S8 from the gas phase and reducing gas-phase supersaturation.
      • Conversely, when liquid HC is flashed to gas (e.g., JT valve, separator), S8 that was dissolved in the liquid has nowhere to go - massive S8 precipitation can occur.
      • In two-phase (gas + liquid HC) flow, the liquid phase carries most of the dissolved sulfur. Pipeline liquid holdup influences where sulfur deposits.
      • Retrograde condensation near the cricondentherm temporarily provides liquid to dissolve S8, but re-vaporisation at lower pressure releases it.
      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • performBlockageRiskAssessment

      private void performBlockageRiskAssessment(StreamInterface inlet, double pressure)
      Assesses the risk of pipeline or equipment blockage from sulfur deposition. Estimates sulfur accumulation rate, time to critical restriction, and identifies pipe sections most vulnerable to plugging.

      The blockage model considers:

      • Sulfur dropout rate from supersaturated gas (kg/h per km)
      • Critical accumulation thickness to restrict flow (>5% diameter reduction)
      • Flow velocity effect on deposition vs re-entrainment
      • Susceptibility of different equipment types to blockage

      References: Pack (2005), Wilkes & McMahon (2007) - Sulfur deposition in gas pipelines.

      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • addEquipmentRisk

      private void addEquipmentRisk(List<Map<String,String>> list, String equipment, String riskLevel, String description)
      Adds an equipment risk entry to the equipment risk list.
      Parameters:
      list - the risk list to add to
      equipment - equipment name
      riskLevel - risk level string
      description - risk description
    • performCatalysisAnalysis

      private void performCatalysisAnalysis(StreamInterface inlet, double pressure)
      Evaluates catalytic pathways for elemental sulfur formation from the gas composition. Analyses homogeneous, heterogeneous, and aqueous-phase catalysis mechanisms based on inlet gas composition and conditions.

      Literature-based catalysis pathways evaluated:

      Catalytic pathways for elemental sulfur formation
      Pathway Catalyst / Mechanism Conditions Reference
      Claus reaction: 2H2S + SO2 = 3/8 S8 + 2H2O Al2O3 / TiO2 surface catalyst 200-350 C, Ea ~ 30-40 kJ/mol Monnery et al. (1993)
      Iron oxide: Fe2O3 + 3H2S = Fe2S3 + 3H2O Pipeline rust, iron sponge Ambient to 60 C, regenerable with O2 Kohl & Nielsen (1997)
      FeS surface catalysis Corrosion product on steel All pipeline T, heterogeneous Sun & Nesic (2009)
      Liquid redox: 2Fe3+ + H2S = 2Fe2+ + S + 2H+ Iron chelate (EDTA/NTA) Aqueous, pH 7-9, ambient GPSA (2004)
      Polysulfide: HS- + (n-1)S = Sn2- + H+ Alkaline aqueous phase pH > 7, water/glycol Kamyshny et al. (2007)
      COS hydrolysis: COS + H2O = CO2 + H2S Al2O3 catalyst 150-350 C, Ea ~ 35 kJ/mol George (1974)
      Activated carbon adsorption + catalysis AC surface + O2 traces Ambient, requires O2 traces Bandosz (2002)
      Parameters:
      inlet - the inlet stream
      pressure - the analysis pressure in bara
    • getComponentMolFrac

      private double getComponentMolFrac(SystemInterface sys, String name)
      Gets the mole fraction of a component from the system, returning 0 if not present.
      Parameters:
      sys - the thermodynamic system
      name - the component name
      Returns:
      mole fraction, or 0 if component not found
    • getCatalysisAnalysis

      public Map<String,Object> getCatalysisAnalysis()
      Gets the catalysis analysis results including all evaluated pathways, composition effects, and dominant mechanism assessment.
      Returns:
      map of catalysis analysis data
    • getSulfurSolubilityInGas

      public double getSulfurSolubilityInGas()
      Gets the sulfur solubility in the gas phase as mole fraction.
      Returns:
      S8 mole fraction in gas at inlet conditions
    • getSulfurSolubilityMgSm3

      public double getSulfurSolubilityMgSm3()
      Gets the sulfur solubility in the gas phase in mg/Sm3.
      Returns:
      S8 concentration in mg/Sm3 at standard conditions
    • getSulfurDepositionOnsetTemperature

      public double getSulfurDepositionOnsetTemperature()
      Gets the temperature at which solid sulfur first deposits (in Celsius). Returns NaN if no solid deposition occurs in the sweep range.
      Returns:
      onset temperature in Celsius, or NaN
    • isSolidSulfurPresent

      public boolean isSolidSulfurPresent()
      Returns true if solid sulfur is present at inlet conditions.
      Returns:
      true if solid S8 phase exists
    • getSolidSulfurFraction

      public double getSolidSulfurFraction()
      Gets the solid sulfur phase fraction at inlet conditions.
      Returns:
      solid phase mole fraction
    • hasCorrosionRisk

      public boolean hasCorrosionRisk()
      Returns true if any corrosion risk is identified.
      Returns:
      true if FeS, SO2, or H2SO4 corrosion risk exists
    • getEquilibriumComposition

      public Map<String,Double> getEquilibriumComposition()
      Gets the equilibrium composition after Gibbs reactor calculation.
      Returns:
      map of component names to mole fractions
    • getTemperatureSweepResults

      public List<Map<String,Object>> getTemperatureSweepResults()
      Gets the temperature sweep results.
      Returns:
      list of maps, each containing temperature point data
    • getCorrosionAssessment

      public Map<String,Object> getCorrosionAssessment()
      Gets the corrosion assessment results.
      Returns:
      map of corrosion assessment data
    • getReactionSummary

      public Map<String,Object> getReactionSummary()
      Gets the reaction summary from the Gibbs equilibrium calculation.
      Returns:
      map of reaction summary data
    • getKineticAnalysis

      public Map<String,Object> getKineticAnalysis()
      Gets the kinetic analysis results including reaction rates, FeS corrosion rate, root cause classification, and wall loss estimates.
      Returns:
      map of kinetic analysis data
    • getSupersaturationAnalysis

      public Map<String,Object> getSupersaturationAnalysis()
      Gets the supersaturation and nucleation analysis results.
      Returns:
      map of supersaturation data including ratio, zone, and nucleation rate
    • getGasVsLiquidSolubility

      public Map<String,Object> getGasVsLiquidSolubility()
      Gets the gas vs liquid S8 solubility comparison results.
      Returns:
      map of solubility comparison data
    • getBlockageRiskAssessment

      public Map<String,Object> getBlockageRiskAssessment()
      Gets the blockage risk assessment results.
      Returns:
      map of blockage risk data including accumulation rate and plugging time
    • getResultsAsJson

      public String getResultsAsJson()
      Returns comprehensive results as a JSON string.
      Returns:
      JSON string with all analysis results
    • printSummary

      public void printSummary()
      Prints a human-readable summary of the analysis results to the logger.
    • mapToJsonObject

      private com.google.gson.JsonObject mapToJsonObject(Map<String,Object> map)
      Converts a map to a JsonObject, handling nested Lists and Maps recursively.
      Parameters:
      map - the map to convert
      Returns:
      a JsonObject representation