Skip to content

Electrolyte NRTL

DWSIM Plus

Available with a DWSIM Plus (Patreon) subscription.

Electrolyte NRTL (Chen and Evans) activity-coefficient package for aqueous electrolyte solutions, with the speciation solved by a chemical-equilibrium solver over the equilibrium reactions of the flowsheet.

DWSIM.Extensions.PropertyPackages.Electrolytes.PropertyPackages.ElectrolyteNRTLPropertyPackage
Assembly DWSIM.Extensions.PropertyPackages.Electrolytes.dll · Object ← PropertyPackage ← ElectrolyteBasePropertyPackage ← BaseElectrolytePropertyPackage ← ElectrolyteNRTLPropertyPackage
Name in the flowsheet Electrolyte NRTL (Aqueous Electrolytes) · FluentAPI PropertyPackages.Plus.ElectrolyteNRTL

Scope

The package describes aqueous electrolyte solutions: brines and process waters, cooling-water and corrosion chemistry, salt crystallization, and acid-gas waters where the dissociation reactions are part of the flowsheet. Water is the only solvent. Ions are compounds of their own (Sodium (ion), Chloride (ion), Hydron, Hydroxide, ...) from the electrolyte compound database, and a salt that can precipitate is a compound as well (Sodium Chloride). The same compounds and the same speciation are used by the Extended UNIQUAC package; the two differ in the activity model.

The activity coefficients follow Chen and Evans: a long-range Pitzer-Debye-Hückel term for the electrostatic forces between ions and a short-range NRTL local-composition term, with local electroneutrality and like-ion repulsion. Ions take the unsymmetric (infinite dilution) reference and water the symmetric one; the stream reports the ion activity coefficients on the molality scale. The mean ionic activity coefficient is ln γ± = (ν+ ln γc + ν- ln γa)/(ν+ + ν-).

Speciation. A flash solves the chemical equilibrium of the liquid together with the phase split: the equilibrium reactions of the flowsheet (water self-ionization, acid and base dissociations, ion pairs, salt dissolution), Henry's law for the dissolved gases and Raoult's law for water. Without reactions the ions stay as fed. The option GenerateSolubilityReactions adds a dissolution equilibrium for every salt in the compound list that no reaction covers, with K from the Gibbs energies of formation of the salt and its ions. The pH is the one of the speciation, -log10 of the hydrogen ion activity.

Parameters. Each salt carries two water-electrolyte parameters, τw,ca and τca,w, with the temperature dependence τ(T) = Δg + Δh (1/T - 1/Tref) + Δcp ((Tref - T)/T + ln(T/Tref)), Tref = 298.15 K. The shipped enrtl_parameters.json holds 137 pairs: 45 from the Chen and Evans fit (NaCl, KCl, LiCl, HCl, NaBr, KBr, NaI, NaOH, KOH, NaNO3, KNO3, NH4Cl, Na2SO4, K2SO4, CaCl2, MgCl2, BaCl2, MgSO4, CaSO4, H2SO4 and other 1-1, 1-2, 2-1 and 3-1 salts) and 92 fitted to the Kim and Frederick single-salt Pitzer parameters (transition-metal halides, perchlorates, nitrates, sulfates). The scalar parameters are α = 0.2, the dielectric constant 78.54 and density 997 kg/m3 of water at 25 °C, and the closest-approach parameter ρ = 14.9. A salt without a τ pair gets τ = 0, so only the long-range term acts on it; when the companion pitzer_parameters.json (107 salts) has the salt, the package writes its Pitzer parameters to the log. Parameters can be edited or replaced in the package editor.

Transport properties. The liquid viscosity is the viscosity of the ion-free solvent (water and the molecular solutes) times the Jones-Dole correction, 1 + A√I + Σ Bici + D c2, with ion B-coefficients from Marcus and Jenkins and c the salt concentration; the thermal conductivity is that of the ion-free solvent times the Riedel ion-additive correction 1 - Σ αici. At 25 °C, 1 mol/kg NaCl gives 0.979 mPa·s (0.974 measured) and 0.604 W/(m·K).

Colligative properties. The osmotic coefficient and the freezing point come from the water activity of the package's own model, aw = xwγw; the freezing point depression is ΔT = -R Tf2/ΔHfus ln aw. For 1 mol/kg NaCl the osmotic coefficient is 0.933 (0.936 in Robinson and Stokes) and the freezing point -3.48 °C.

Accuracy. For the Chen and Evans salts the package reproduces the published correlations; for the Kim and Frederick salts the fit to the Robinson and Stokes data has χ2 < 10-2 from 5 to 95 % of the saturation molality, with the largest deviations at high molality for strongly ion-paired salts (FeCl3, ZnBr2, ZnI2).

Limitations

  • Recommended for 0 to 200 °C, ionic strength up to 6 mol/kg for the fitted salts, and 1 to 500 bar (no pressure parameters).
  • Water is the only solvent: other neutral compounds (dissolved gases, amines, alcohols) take part as solutes with no interaction parameters (τ = 0).
  • The vapor is ideal unless VaporPhaseFugacityCalculationMode is set to Peng-Robinson, which is advisable above about 30 bar or for a vapor rich in CO2, N2 or methane.
  • The pH comes from the activity of the hydrogen ion, Hydron (H+) or Hydronium (H3O+).

Example

This code runs on every build of this site, and the output below is what it printed.

fs = (Flowsheet.Create("ENRTLExample")
      .WithCompounds("Water", "Sodium (ion)", "Chloride (ion)", "Hydron", "Hydroxide")
      .WithPropertyPackage(PropertyPackages.Plus.ElectrolyteNRTL))

# The package takes its chemical equilibria from the reactions of the flowsheet. The
# self-ionization of water sets the pH: log10 Kw = -4470.99/T + 6.0875 - 0.01706 T
kw = Dictionary[String, Double]()
kw["Water"] = -1.0
kw["Hydron"] = 1.0
kw["Hydroxide"] = 1.0
fs.ReactionSet("Water").Add(fs.DefineEquilibriumReaction(
    "Kw", kw, "Water", "Liquid", "Activity", "", "2.302585*(-4470.99/T + 6.0875 - 0.01706*T)"))

# 1 mol of NaCl (as its ions) per kg of water, and 0.01 mol of HCl per kg of water
brine = (fs.AddMaterialStream("Brine").At(Q.Celsius(25.0), Q.Bar(1.01325))
         .SetCompoundMolarFlow("Water", 1.0 / 0.018015)
         .SetCompoundMolarFlow("Sodium (ion)", 1.0)
         .SetCompoundMolarFlow("Chloride (ion)", 1.0))
acid = (fs.AddMaterialStream("Acid").At(Q.Celsius(25.0), Q.Bar(1.01325))
        .SetCompoundMolarFlow("Water", 1.0 / 0.018015)
        .SetCompoundMolarFlow("Hydron", 0.01)
        .SetCompoundMolarFlow("Chloride (ion)", 0.01))

fs.Solve()

liq = brine.Object.Phases[3]
# ions on the molality scale, water on the mole-fraction scale
g = {name: liq.Compounds[name].ActivityCoeff for name in ("Water", "Sodium (ion)", "Chloride (ion)")}
gamma_pm = math.sqrt(g["Sodium (ion)"] * g["Chloride (ion)"])
a_w = g["Water"] * liq.Compounds["Water"].MoleFraction
phi = -math.log(a_w) / (2 * 1.0 * 0.018015)          # osmotic coefficient, 2 ions at 1 mol/kg
print(f"NaCl mean activity coefficient = {gamma_pm:.3f}")
print(f"Water activity                 = {a_w:.4f} (osmotic coefficient {phi:.3f})")
print(f"Brine density                  = {liq.Properties.density:.1f} kg/m3")
print(f"Brine pH                       = {liq.Properties.pH:.2f}")
print(f"pH of the acid                 = {acid.Object.Phases[3].Properties.pH:.2f}")

Output

NaCl mean activity coefficient = 0.643
Water activity                 = 0.9669 (osmotic coefficient 0.933)
Brine density                  = 1035.4 kg/m3
Brine pH                       = 7.00
pH of the acid                 = 2.04

DWSIM 10.2.11.0, generated 2026-10-08.

Property methods

How the package calculates each property, as it reports it in PropertyMethodsInfo (the property package editor shows the same list).

Property Method
Vapor fugacity Ideal / Peng-Robinson EOS
Liquid fugacity eNRTL Activity Coefficient + Henry's Law / Vapor Pressure
Vapor enthalpy, entropy, Cp/Cv Ideal Gas / Lee-Kesler
Liquid enthalpy, entropy, Cp/Cv Ideal Gas - Vaporization Enthalpy; the eNRTL excess enthalpy is added when IncludeExcessEnthalpy is on
Vapor density Ideal Gas / Peng-Robinson EOS
Liquid density Water density correlation plus the molar volumes of the ions (with an ionic-strength term), from the electrolyte database; molecular solutes as pure liquids
Vapor viscosity Experimental / Lucas / Jossi-Stiel-Thodos
Liquid viscosity Experimental / Letsou-Stiel
Vapor thermal conductivity Experimental / Ely-Hanley
Liquid thermal conductivity Experimental / Latini
Surface tension Experimental / Brock-Bird
Solid density Experimental Data / User-Defined
Solid enthalpy, entropy, Cp/Cv Experimental Solid Cp / From Liquid Phase Enthalpy + Enthalpy of Fusion

Default flash algorithm: Nested_Loops_VLE.

Configuration saved with the flowsheet

The package writes its settings to the simulation file (SaveData) and reads them back on load (LoadData). The elements below are the ones this package adds to those of every property package, as written for the example.

Element Content in the example What it holds
ElectrolyteFlash_ReactionSetID DefaultSet Reaction set of the electrolyte flash of the base package; this package's flash takes every equilibrium reaction of the flowsheet and does not read it
ElectrolyteFlash_Tolerance 1E-07 Tolerance of the same base flash, not used by this package
ElectrolyteFlash_MaximumIterations 200 Iteration limit of the same base flash, not used by this package
IncludeExcessEnthalpy false Adds the excess enthalpy and entropy of the activity model to the liquid (off by default; the numerical temperature derivative slows PH and PS flashes)
GenerateSolubilityReactions false Gives every salt of the compound list that no flowsheet reaction covers a dissolution equilibrium with its ions, with K from the Gibbs energies of formation (off by default)
UseReactiveKvalues false When on, the rigorous column takes its K-values from the speciation (off by default; much slower than the generic activity route)
UseCustomParameters false Whether the parameter set in CustomParametersJson replaces the shipped database
CustomParametersJson empty The custom parameter set (τ pairs and their temperature coefficients) as JSON, empty when the shipped database is used
ModelAlpha 0.2 Non-randomness parameter α (default 0.2)
ModelDielectricConstant 78.54 Dielectric constant of the solvent at 25 °C (default 78.54); the model follows the temperature dependence of water from it
ModelSolventDensity 997 Solvent density at 25 °C in kg/m3 (default 997.0)
ModelDHClosestApproach 14.9 Closest-approach parameter ρ of the Pitzer-Debye-Hückel term (default 14.9)
Settings common to every property package, as saved for the example
Element Value
Type 94 characters
ComponentName Electrolyte NRTL (Aqueous Electrolytes)
ComponentDescription Electrolyte NRTL model
Tag Electrolyte NRTL (Aqueous Electrolytes)
UseHenryConstants true
AutoEstimateMissingNRTLUNIQUACParameters true
UseImmiscibleListForLiquid2InitialEstimates true
SingleCompoundCheckThreshold 0.99999
OverrideKvalFugCoeff false
OverrideEnthalpyCalculation false
OverrideEntropyCalculation false
LiquidDensityCalculationMode_Subcritical Rackett_and_ExpData
LiquidDensityCalculationMode_Supercritical Rackett_and_ExpData
LiquidDensity_CorrectExpDataForPressure true
LiquidDensity_UsePenelouxVolumeTranslation true
LiquidViscosityCalculationMode_Subcritical ExpData
LiquidViscosityCalculationMode_Supercritical Letsou_Stiel
LiquidViscosity_CorrectExpDataForPressure true
LiquidViscosity_MixingRule MoleAverage
VaporPhaseFugacityCalculationMode Ideal
SolidPhaseFugacityCalculationMethod FromLiquidFugacity
SolidPhaseFugacity_UseIdealLiquidPhaseFugacity false
SolidPhaseEnthalpy_UsesCp false
EnthalpyEntropyCpCvCalculationMode LeeKesler
LiquidEnthalpyEntropyCpCvCalculationMode_EOS EOS
LiquidFugacity_UsePoyntingCorrectionFactor true
ActivityCoefficientModels_IgnoreMissingInteractionParameters false
IgnoreVaporFractionLimit false
IgnoreSalinityLimit false
CalculateAdditionalMaterialStreamProperties true
FlashCalculationApproach NestedLoops
DisplayMissingCompoundPropertiesWarning false
ForcedSolids []
PropertyOverrides {}
FlashSettings 36 Setting entries

Learn more

API members

Public members declared by this class. Inherited members are documented on the base classes.

Constructors

ElectrolyteNRTLPropertyPackage()
public ElectrolyteNRTLPropertyPackage()
Public Sub New()

ElectrolyteNRTLPropertyPackage(bool)
Parameter Type Description
comode Boolean
public ElectrolyteNRTLPropertyPackage(bool comode)
Public Sub New(comode As Boolean)

Properties

CustomParametersJson: JSON-serialized ENRTLDatabaseRoot with custom parameters.

JSON-serialized ENRTLDatabaseRoot with custom parameters.

public string CustomParametersJson { get; set; }
Public Property CustomParametersJson As String

ImplementsCrossPlatformEditor
public override bool ImplementsCrossPlatformEditor { get; }
Public Overrides ReadOnly Property ImplementsCrossPlatformEditor As Boolean

LegacyTauDefault: When true, unknown (i,j) ion pairs in the eNRTL short-range term receive a default τ = 2.0 (legacy behavior of the...

When true, unknown (i,j) ion pairs in the eNRTL short-range term receive a default τ = 2.0 (legacy behavior of the original implementation). When false (default), they receive τ = 0, which collapses the SR contribution of that pair to ideality — much safer when running with ions that have no measured parameters in enrtl_parameters.json. A one-time warning is logged for each missing pair regardless.

public bool LegacyTauDefault { get; set; }
Public Property LegacyTauDefault As Boolean

ModelAlpha: Default non-randomness parameter α (ion–water: 0.2).

Default non-randomness parameter α (ion–water: 0.2).

public double ModelAlpha { get; set; }
Public Property ModelAlpha As Double

ModelDHClosestApproach: Pitzer–Debye–Hückel closest-approach parameter ρ, dimensionless (default 14.9).

Pitzer–Debye–Hückel closest-approach parameter ρ, dimensionless (default 14.9).

public double ModelDHClosestApproach { get; set; }
Public Property ModelDHClosestApproach As Double

ModelDielectricConstant: Solvent dielectric constant at 25 °C (water: 78.54).

Solvent dielectric constant at 25 °C (water: 78.54). The model follows water's ε(T) from it, see ElectrolyteNRTL.WaterProperties.

public double ModelDielectricConstant { get; set; }
Public Property ModelDielectricConstant As Double

ModelSolventDensity: Solvent density at 25 °C in kg/m³ (water: 997.0).

Solvent density at 25 °C in kg/m³ (water: 997.0). The model follows water's ρ(T) from it.

public double ModelSolventDensity { get; set; }
Public Property ModelSolventDensity As Double

UseCustomParameters: Whether custom parameters are in effect.

Whether custom parameters are in effect.

public bool UseCustomParameters { get; set; }
Public Property UseCustomParameters As Boolean

Methods

CalculateChemicalEquilibria(double, double): Monta e resolve o sistema de equilíbrio químico eNRTL para a corrente atual.

Monta e resolve o sistema de equilíbrio químico eNRTL para a corrente atual. O trabalho pesado (parsing do banco JSON, resolução de nomes, varredura de reações) é feito uma única vez em BuildEquilibriumCache, chamado automaticamente por RunPostMaterialStreamSetRoutine. Por chamada, apenas operações T-dependentes são executadas: · db.GetTauAtT(salt, T) — aritmética A + B/T · dwRxn.EvaluateK(T, this) — retorna K; convertido para log₁₀(K)

Parameter Type Description
T Double Temperatura [K].
P Double Pressão [Pa].
public override EquilibriumResult CalculateChemicalEquilibria(double T, double P)
Public Overrides Function CalculateChemicalEquilibria(T As Double, P As Double) As EquilibriumResult

CalculateChemicalEquilibria(double, double, double[]): Sobrecarga de CalculateChemicalEquilibria que aceita a composição molar da mistura explicitamente, sem modificar a...

Sobrecarga de CalculateChemicalEquilibria que aceita a composição molar da mistura explicitamente, sem modificar a corrente. O vetor x deve ter o mesmo comprimento e a mesma ordem que _equilSpecies, preenchido por BuildEquilibriumCache() ao final de RunPostMaterialStreamSetRoutine. Essa ordem coincide com a de CurrentMaterialStream.Phases[0].Compounds.Values no momento em que a rotina foi chamada. O fator de escala de molalidade (base 1 kg de solvente) é recompensado a partir de x, de modo que a chamada é completamente independente da composição armazenada na corrente.

Parameter Type Description
T Double Temperatura [K].
P Double Pressão [Pa].
x Double[] Frações molares na ordem de _equilSpecies. Comprimento deve ser igual a _equilSpecies.Count.
public override EquilibriumResult CalculateChemicalEquilibria(double T, double P, double[] x)
Public Overrides Function CalculateChemicalEquilibria(T As Double, P As Double, x As Double()) As EquilibriumResult

Clone()
public override PropertyPackage Clone()
Public Overrides Function Clone() As PropertyPackage

ConvertIonsToSaltsInPlace(double[], double): Converts a solid-phase amount vector (indexed by RET_VNAMES) from ionic species to their parent salts using...

Converts a solid-phase amount vector (indexed by RET_VNAMES) from ionic species to their parent salts using precipitation reactions, least soluble first. Amounts in, amounts out, on the same basis and without renormalising: each salt formed takes its ions away, so every element is kept. Called by DryStateSolids. Default implementation is a no-op; overridden by each PP that has access to the resolved precipitation reactions.

Parameter Type Description
vs Double[]
T Double
public override void ConvertIonsToSaltsInPlace(double[] vs, double T)
Public Overrides Sub ConvertIonsToSaltsInPlace(vs As Double(), T As Double)

DisplayEditingForm()
public override void DisplayEditingForm()
Public Overrides Sub DisplayEditingForm()

DW_CalcFugCoeff(Array, double, double, State): Calculates fugacity coefficients for the specified composition at the specified conditions.

Calculates fugacity coefficients for the specified composition at the specified conditions.

Parameter Type Description
Vx Array Vector of doubles containing the molar composition of the mixture.
T Double Temperature in K
P Double Pressure in Pa
st State Mixture state (Liquid or Vapor)
public override double[] DW_CalcFugCoeff(Array Vx, double T, double P, State st)
Public Overrides Function DW_CalcFugCoeff(Vx As Array, T As Double, P As Double, st As State) As Double()

GetEditingForm(): Returns the binary interaction parameter editor of this package.

Returns the binary interaction parameter editor of this package.

public override object GetEditingForm()
Public Overrides Function GetEditingForm() As Object

LoadData(List<XElement>): Reads back what SaveParameterData writes.

Reads back what SaveParameterData writes. A file saved before these elements existed leaves the values at their defaults (built-in database).

Parameter Type Description
data List<XElement>
public override bool LoadData(List<XElement> data)
Public Overrides Function LoadData(data As List(Of XElement)) As Boolean

PopulateCrossPlatformEditor(object): The Avalonia editor; see AvaloniaPackageEditors.

The Avalonia editor; see AvaloniaPackageEditors.

Parameter Type Description
container Object
public override void PopulateCrossPlatformEditor(object container)
Public Overrides Sub PopulateCrossPlatformEditor(container As Object)

ReturnInstance(string)
Parameter Type Description
typename String
public override object ReturnInstance(string typename)
Public Overrides Function ReturnInstance(typename As String) As Object

RunPostMaterialStreamSetRoutine()
public override void RunPostMaterialStreamSetRoutine()
Public Overrides Sub RunPostMaterialStreamSetRoutine()

SaveData(): Writes IncludeExcessEnthalpy, GenerateSolubilityReactions and UseReactiveKvalues after the data the base package...

Writes IncludeExcessEnthalpy, GenerateSolubilityReactions and UseReactiveKvalues after the data the base package saves, so the three options travel with the flowsheet file and with Clone.

public override List<XElement> SaveData()
Public Overrides Function SaveData() As List(Of XElement)

Fields

ClassId
public const string ClassId = "1449faa2-67c0-4a07-bb52-86684bbc137b"
Public Const ClassId As String = "1449faa2-67c0-4a07-bb52-86684bbc137b"