Class MercuryRemovalBed

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

public class MercuryRemovalBed extends TwoPortEquipment
Fixed-bed mercury removal unit operation using chemisorption (e.g. PuraSpec, MRU).

Models irreversible chemisorption of elemental mercury (Hg0) onto metal-sulphide sorbents such as CuS, FeS, or ZnS pellets commonly used in LNG pre-treatment. Unlike physical adsorption the reaction is non-regenerable: the bed is replaced when spent.

Features:

  • Irreversible Langmuir–Hinshelwood chemisorption kinetics
  • Time-dependent bed loading and mercury breakthrough tracking
  • Mass-transfer-zone (MTZ) length estimation
  • Degradation modelling for fouled/degraded column internals
  • Ergun-equation pressure drop
  • Integrated mechanical design and cost estimation
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 object for this class.
    • bedDiameter

      private double bedDiameter
      Internal diameter of the bed vessel (m).
    • bedLength

      private double bedLength
      Length/height of the packed section (m).
    • voidFraction

      private double voidFraction
      Void fraction (inter-particle porosity).
    • sorbentType

      private String sorbentType
      Name or trade-mark of the sorbent material (e.g. "PuraSpec", "MRU-CuS").
    • sorbentBulkDensity

      private double sorbentBulkDensity
      Bulk density of the sorbent (kg/m3).
    • particleDiameter

      private double particleDiameter
      Sorbent particle diameter (m).
    • maxMercuryCapacity

      private double maxMercuryCapacity
      Maximum mercury loading capacity of the sorbent (mg Hg / kg sorbent). Typical PuraSpec values are 10–25 wt% Hg; default 10 wt% = 100 000 mg/kg.
    • reactionRateConstant

      private double reactionRateConstant
      First-order rate constant for chemisorption (1/s). Relates to the linear-driving-force approximation: r = k * C_Hg * (1 - theta). Typical value for PuraSpec-type CuS sorbents: 0.3-0.8 s⁻¹.
    • activationEnergy

      private double activationEnergy
      Activation energy for the chemisorption reaction (J/mol).
    • referenceTemperature

      private double referenceTemperature
      Reference temperature for the rate constant (K).
    • degradationFactor

      private double degradationFactor
      Overall degradation factor (0–1). At 1.0 the bed is brand-new; at lower values the effective capacity and/or rate constant are reduced because of fouling, liquid carry-over, or other damage to column internals.
    • bypassFraction

      private double bypassFraction
      Fraction of bed that is bypassed due to channelling caused by degraded internals (0–1). At 0 there is no bypass. Gas that bypasses does not contact sorbent.
    • numberOfCells

      private int numberOfCells
      Number of axial cells.
    • cellLoading

      private double[] cellLoading
      Mercury loading in each cell (mg Hg / kg sorbent).
    • cellHgConcentration

      private double[] cellHgConcentration
      Gas-phase Hg concentration in each cell (microgram/Nm3).
    • transientInitialised

      private boolean transientInitialised
      Whether the transient grid has been initialised.
    • elapsedTimeHours

      private double elapsedTimeHours
      Total elapsed on-stream time (hours).
    • replacementUtilisation

      private double replacementUtilisation
      Practical sorbent utilisation at replacement (0–1). In practice operators change out sorbent when only a fraction of the theoretical capacity has been used, because the mass-transfer zone leaves the tail of the bed under-utilised and a safety margin is maintained before breakthrough. Typical values: 0.4–0.6 for single beds, 0.7–0.9 for lead–lag configurations.
    • breakthroughThreshold

      private double breakthroughThreshold
      Breakthrough threshold as fraction of inlet Hg concentration (0–1).
    • breakthroughOccurred

      private boolean breakthroughOccurred
      Whether breakthrough has been detected.
    • breakthroughTimeHours

      private double breakthroughTimeHours
      Time at which breakthrough was first detected (hours).
    • pressureDrop

      private double pressureDrop
      Pressure drop across the bed (Pa).
    • calculatePressureDrop

      private boolean calculatePressureDrop
      Whether to calculate pressure drop via Ergun equation.
    • mercuryIndex

      private int mercuryIndex
      Index of the mercury component in the thermodynamic system (-1 if not present).
    • system

      private SystemInterface system
      Working copy of the thermodynamic system.
  • Constructor Details

    • MercuryRemovalBed

      public MercuryRemovalBed(String name)
      Constructor for MercuryRemovalBed.
      Parameters:
      name - the name of the unit operation
    • MercuryRemovalBed

      public MercuryRemovalBed(String name, StreamInterface inletStream)
      Constructor for MercuryRemovalBed with inlet stream.
      Parameters:
      name - the name of the unit operation
      inletStream - the inlet gas stream
  • Method Details

    • run

      public void run(UUID id)

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

      Steady-state mode assumes the bed is not yet saturated and calculates mercury removal based on the overall NTU/efficiency for the current bed geometry and kinetics.

      Parameters:
      id - UUID
    • runTransient

      public void runTransient(double dt, UUID id)

      runTransient

      This method calculates thermodynamic and unit operations using difference equations if available and calculateSteadyState is true. Use setCalculateSteadyState to set the parameter. Sets calc identifier UUID.

      Advances the bed state by dt seconds. The bed is discretised into axial cells; each cell tracks its local mercury loading and gas-phase Hg concentration. The irreversible chemisorption kinetics consume mercury from the gas phase and accumulate it on the sorbent until the local capacity is exhausted.

      Parameters:
      dt - time-step size in seconds
      id - calculation identifier
    • initialiseTransientGrid

      public void initialiseTransientGrid()
      Initialise the axial discretisation grid with empty sorbent.
    • preloadBed

      public void preloadBed(double fractionalSaturation)
      Pre-load the bed to simulate a partially spent sorbent.
      Parameters:
      fractionalSaturation - fraction of maximum capacity already consumed (0 = fresh, 1 = spent)
    • resetBed

      public void resetBed()
      Reset the bed to a fresh (unloaded) state.
    • getLoadingProfile

      public double[] getLoadingProfile()
      Get the mercury loading profile along the bed.
      Returns:
      array of loading values (mg Hg / kg sorbent) per axial cell
    • getConcentrationProfile

      public double[] getConcentrationProfile()
      Get the gas-phase mercury concentration profile along the bed.
      Returns:
      array of concentrations (microgram/Nm3) per axial cell
    • getAverageLoading

      public double getAverageLoading()
      Get the average mercury loading across the entire bed.
      Returns:
      average loading in mg Hg / kg sorbent
    • getBedUtilisation

      public double getBedUtilisation()
      Get the bed utilisation factor (average loading / effective capacity).
      Returns:
      utilisation factor (0 to 1)
    • getMassTransferZoneLength

      public double getMassTransferZoneLength()
      Estimate the length of the mass transfer zone (MTZ).

      The MTZ is defined as the axial distance over which the normalised gas-phase Hg concentration transitions from 0.05 to 0.95 of the inlet concentration.

      Returns:
      MTZ length in metres, 0 if not applicable
    • estimateBedLifetime

      public double estimateBedLifetime()
      Estimate bed lifetime (hours) based on current inlet conditions and bed capacity.
      Returns:
      estimated lifetime in hours, or -1 if mercury is not present
    • getSorbentMass

      public double getSorbentMass()
      Get the total mass of sorbent in the bed.
      Returns:
      sorbent mass in kg
    • getBedVolume

      public double getBedVolume()
      Get the bed volume.
      Returns:
      bed volume in m3
    • getRemovalEfficiency

      public double getRemovalEfficiency()
      Get the outlet mercury removal efficiency based on the most recent calculation.
      Returns:
      removal efficiency (0 to 1), or -1 if not yet calculated
    • getMechanicalDesign

      public MercuryRemovalMechanicalDesign getMechanicalDesign()

      Get a mechanicalDesign for the equipment.

      Specified by:
      getMechanicalDesign in interface ProcessEquipmentInterface
      Overrides:
      getMechanicalDesign in class ProcessEquipmentBaseClass
      Returns:
      a MechanicalDesign object
    • findMercuryIndex

      private void findMercuryIndex(SystemInterface sys)
      Find the index of elemental mercury in the thermodynamic system.
      Parameters:
      sys - the thermodynamic system
    • effectiveRateConstant

      private double effectiveRateConstant(double temperatureK)
      Calculate the temperature-corrected effective rate constant using an Arrhenius relation.
      Parameters:
      temperatureK - temperature in Kelvin
      Returns:
      effective rate constant (1/s)
    • calcInletHgConcentration

      private double calcInletHgConcentration(SystemInterface sys)
      Calculate the inlet mercury concentration in microgram/Nm3.
      Parameters:
      sys - the thermodynamic system with mercury present
      Returns:
      inlet Hg concentration in microgram/Nm3
    • setOutletMercuryFromConcentration

      private void setOutletMercuryFromConcentration(SystemInterface sys, double outletConc, double inletConc)
      Set the outlet mercury content by scaling the inlet mole fraction.
      Parameters:
      sys - the working thermodynamic system to modify
      outletConc - outlet Hg concentration (microgram/Nm3)
      inletConc - inlet Hg concentration (microgram/Nm3)
    • calcErgunPressureDrop

      private double calcErgunPressureDrop(SystemInterface sys, double us)
      Calculate pressure drop across the packed bed using the Ergun equation.
      Parameters:
      sys - the thermodynamic system for fluid properties
      us - superficial velocity (m/s)
      Returns:
      total pressure drop (Pa)
    • toJson

      public String toJson()

      Serializes the Process Equipment along with its state to a JSON string.

      Specified by:
      toJson in interface ProcessEquipmentInterface
      Overrides:
      toJson in class TwoPortEquipment
      Returns:
      json string.
    • validateSetup

      public ValidationResult validateSetup()
      Validate the process equipment before execution.

      Checks for common setup errors:

      • Equipment has a valid name
      • Input streams connected
      • Operating parameters in valid ranges

      Validates the two-port equipment setup before execution. Checks that:

      • Equipment has a valid name
      • Inlet stream is connected
      • Outlet stream is initialized
      Specified by:
      validateSetup in interface ProcessEquipmentInterface
      Overrides:
      validateSetup in class TwoPortEquipment
      Returns:
      validation result with errors and warnings
    • getBedDiameter

      public double getBedDiameter()
      Get the bed internal diameter.
      Returns:
      bed diameter in metres
    • setBedDiameter

      public void setBedDiameter(double diameter)
      Set the bed internal diameter.
      Parameters:
      diameter - bed diameter in metres
    • getBedLength

      public double getBedLength()
      Get the bed length.
      Returns:
      bed length in metres
    • setBedLength

      public void setBedLength(double length)
      Set the bed length.
      Parameters:
      length - bed length in metres
    • getVoidFraction

      public double getVoidFraction()
      Get the void fraction.
      Returns:
      void fraction (0 to 1)
    • setVoidFraction

      public void setVoidFraction(double voidFraction)
      Set the void fraction (inter-particle porosity).
      Parameters:
      voidFraction - void fraction (0 to 1)
    • getSorbentType

      public String getSorbentType()
      Get the sorbent type name.
      Returns:
      sorbent type
    • setSorbentType

      public void setSorbentType(String sorbentType)
      Set the sorbent type name (e.g. "PuraSpec", "MRU-CuS").
      Parameters:
      sorbentType - sorbent type
    • getSorbentBulkDensity

      public double getSorbentBulkDensity()
      Get the sorbent bulk density.
      Returns:
      bulk density in kg/m3
    • setSorbentBulkDensity

      public void setSorbentBulkDensity(double density)
      Set the sorbent bulk density.
      Parameters:
      density - bulk density in kg/m3
    • getParticleDiameter

      public double getParticleDiameter()
      Get the particle diameter.
      Returns:
      particle diameter in metres
    • setParticleDiameter

      public void setParticleDiameter(double diameter)
      Set the sorbent particle diameter.
      Parameters:
      diameter - particle diameter in metres
    • getMaxMercuryCapacity

      public double getMaxMercuryCapacity()
      Get the maximum mercury loading capacity.
      Returns:
      maximum capacity in mg Hg / kg sorbent
    • setMaxMercuryCapacity

      public void setMaxMercuryCapacity(double capacity)
      Set the maximum mercury loading capacity of the sorbent.
      Parameters:
      capacity - maximum capacity in mg Hg / kg sorbent (typical PuraSpec: 100 000)
    • getReactionRateConstant

      public double getReactionRateConstant()
      Get the chemisorption reaction rate constant.
      Returns:
      rate constant in 1/s
    • setReactionRateConstant

      public void setReactionRateConstant(double k)
      Set the chemisorption reaction rate constant.
      Parameters:
      k - rate constant in 1/s
    • getReplacementUtilisation

      public double getReplacementUtilisation()
      Get the practical replacement utilisation factor.
      Returns:
      replacement utilisation (0 to 1)
    • setReplacementUtilisation

      public void setReplacementUtilisation(double utilisation)
      Set the practical replacement utilisation factor. This is the fraction of theoretical sorbent capacity that can be used before the bed must be replaced. Typical 0.4–0.6 for single beds, 0.7–0.9 for lead–lag.
      Parameters:
      utilisation - replacement utilisation factor (0 to 1)
    • getActivationEnergy

      public double getActivationEnergy()
      Get the activation energy.
      Returns:
      activation energy in J/mol
    • setActivationEnergy

      public void setActivationEnergy(double energy)
      Set the activation energy for the chemisorption reaction.
      Parameters:
      energy - activation energy in J/mol
    • getDegradationFactor

      public double getDegradationFactor()
      Get the degradation factor.
      Returns:
      degradation factor (0 to 1)
    • setDegradationFactor

      public void setDegradationFactor(double factor)
      Set the degradation factor for column internals or sorbent fouling.

      A value of 1.0 means brand-new / undegraded bed. Lower values reduce both the effective capacity and the reaction rate to simulate fouling, liquid carry-over, or damaged internals.

      Parameters:
      factor - degradation factor (0 to 1)
    • getBypassFraction

      public double getBypassFraction()
      Get the bypass fraction.
      Returns:
      bypass fraction (0 to 1)
    • setBypassFraction

      public void setBypassFraction(double fraction)
      Set the bypass fraction to model channelling due to degraded internals.
      Parameters:
      fraction - bypass fraction (0 to <1)
    • getNumberOfCells

      public int getNumberOfCells()
      Get the number of axial cells.
      Returns:
      number of cells
    • setNumberOfCells

      public void setNumberOfCells(int cells)
      Set the number of axial cells for spatial discretisation.
      Parameters:
      cells - number of cells (at least 2)
    • getPressureDrop

      public double getPressureDrop()
      Get the pressure drop across the bed.
      Returns:
      pressure drop in Pa
    • getPressureDrop

      public double getPressureDrop(String unit)
      Get the pressure drop across the bed in a specified unit.
      Parameters:
      unit - pressure unit ("Pa", "bar", "bara", "psi")
      Returns:
      pressure drop in the given unit
    • setCalculatePressureDrop

      public void setCalculatePressureDrop(boolean calculate)
      Set whether to calculate pressure drop from the Ergun equation.
      Parameters:
      calculate - true to calculate, false to skip
    • getElapsedTimeHours

      public double getElapsedTimeHours()
      Get the elapsed on-stream time in hours.
      Returns:
      elapsed time in hours
    • isBreakthroughOccurred

      public boolean isBreakthroughOccurred()
      Check if mercury breakthrough has occurred.
      Returns:
      true if breakthrough detected
    • getBreakthroughTimeHours

      public double getBreakthroughTimeHours()
      Get the breakthrough time.
      Returns:
      breakthrough time in hours, or -1 if not yet occurred
    • setBreakthroughThreshold

      public void setBreakthroughThreshold(double threshold)
      Set the breakthrough detection threshold.
      Parameters:
      threshold - outlet/inlet Hg concentration ratio (0 to 1)
    • setReferenceTemperature

      public void setReferenceTemperature(double temperature)
      Set the reference temperature for the Arrhenius rate constant.
      Parameters:
      temperature - reference temperature in Kelvin
    • getReferenceTemperature

      public double getReferenceTemperature()
      Get the reference temperature for the Arrhenius rate constant.
      Returns:
      reference temperature in Kelvin