Skip to the content.

This guide documents the viscosity calculation methods available in NeqSim for gas, liquid, and multiphase systems.

Table of Contents


Overview

Viscosity describes a fluid’s resistance to flow. NeqSim provides several viscosity models suitable for different applications:

Units:

Setting a viscosity model:

fluid.initPhysicalProperties();
fluid.getPhase("gas").getPhysicalProperties().setViscosityModel("friction theory");
fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("LBC");
fluid.getPhase("gas").initPhysicalProperties();
fluid.getPhase("oil").initPhysicalProperties();

Select the model after the flash and initial property calculation, then reinitialize each changed phase as shown. Model keys are case-sensitive. Unlike conductivity selection, an unsupported viscosity key leaves the current model unchanged; verify the selected key in tests rather than assuming a fallback.


Available Models

Letsou-Stiel saturated-liquid estimator

Letsou-Stiel is an opt-in pure-liquid estimator when fitted viscosity data are unavailable. It uses critical temperature, critical pressure, molar mass and acentric factor. It implements the polynomial representation of the Letsou-Stiel tables in the ChemSep book, equations 10.158–10.161, also documented by COCO/TEA. This is an estimation alternative, not a replacement for a fluid-specific reference correlation.

The supported reduced-temperature interval is $0.76 \leq T/T_c \leq 0.98$. The result estimates saturated-liquid viscosity; selecting it on a compressed-liquid phase does not add a pressure correction. The implementation refuses mixtures, gas/solid phases, nonfinite or nonpositive required inputs, and temperatures outside that interval. Selection validates the current state before replacing the previous model. Establish the liquid phase with a flash before selecting it. Later out-of-range state changes are rejected by the model; the existing physical-property initialization handler may log such an exception, so callers must keep subsequent states inside the supported interval.

Class: LetsouStielViscosity. Its static calculateViscosity API takes temperature and critical temperature in K, molar mass in kg/mol, critical pressure in bara, and returns Pa s. The inherited liquid-model getPureComponentViscosity(0) interface retains mPa s. No database coefficients or fitted binary interactions are required. No mixture mixing rule or automatic fallback is claimed.

SystemInterface fluid = new SystemSrkEos(500.0, 40.0);
fluid.addComponent("benzene", 1.0);
fluid.setMixingRule("classic");
new ThermodynamicOperations(fluid).TPflash();
fluid.initProperties();
fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("Letsou-Stiel");
fluid.getPhase("oil").initPhysicalProperties();
double saturatedLiquidEstimatePas = fluid.getPhase("oil").getViscosity("kg/msec");

LetsouStielViscosityTest executes this example and the independent ethanol example (400 K, 46.07 g/mol, 516.25 K, 6.383 MPa, acentric factor 0.6371), which gives 0.0002036150875308 Pa s. That is a correlation implementation check, not an experimental accuracy claim for ethanol or associating liquids. See the method audit.

The Viscosity liquid mixture method uses tabulated gijvisc interactions from the inter component-pair table in its Grunberg-Nissan mixing expression. Pairs without tabulated data use zero interaction. Ions and TBP fractions are excluded from this pair lookup; their presence does not suppress later valid component pairs. These parameters affect the liquid mixture method, not the separate LBCViscosityMethod implementation described below.

LBC (Lohrenz-Bray-Clark)

The Lohrenz-Bray-Clark (1964) method is widely used in reservoir simulation. It combines a dilute gas correlation with a dense fluid polynomial correction.

Class: LBCViscosityMethod

Equation: \(\eta = \eta^* + \frac{(\eta_r - 0.0001)^4}{\xi}\)

where:

The dense fluid contribution uses a polynomial: \(\eta_r = a_0 + a_1\rho_r + a_2\rho_r^2 + a_3\rho_r^3 + a_4\rho_r^4\)

Default parameters: {0.10230, 0.023364, 0.058533, -0.040758, 0.0093324}

Applicable phases: Gas, Oil

Best for:

Usage:

fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("LBC");
fluid.getPhase("oil").initPhysicalProperties();

Friction Theory

The Quiñones-Cisneros and Firoozabadi (2000) friction theory relates viscosity to the repulsive and attractive pressure contributions from the equation of state.

Class: FrictionTheoryViscosityMethod

Equation: \(\eta = \eta_0 + \kappa_a P_a + \kappa_{aa} P_a^2 + \kappa_r P_r + \kappa_{rr} P_r^2\)

where:

Applicable phases: Gas, Oil (any EoS-based phase)

Best for:

Automatic EoS detection: The method automatically selects SRK or PR constants based on the phase type.

Implementation notes in NeqSim (2026 update):

Usage:

fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("friction theory");
fluid.getPhase("oil").initPhysicalProperties();

Custom constants (advanced use):

FrictionTheoryViscosityMethod viscModel =
    (FrictionTheoryViscosityMethod) fluid.getPhase("oil")
        .getPhysicalProperties().getViscosityModel();

// Values must come from an independently validated parameter set.
viscModel.setFrictionTheoryConstants(kapac, kaprc, kaprrc, kapa, kapr, kaprr);

Here kapac, kaprc, kaprrc, and kaprr are scalar double values; kapa and kapr are double[][] matrices. This API replaces the model’s complete parameter set and is not a general fitting shortcut.


PFCT (Pedersen)

The Pedersen Friction Corresponding States Theory uses methane as a reference fluid with shape factors for mixture calculations.

The model can be selected with either "PFCT" or "CSP". The "CSP" alias is intended for PVT workflows and external reports that label the Pedersen/PFCT viscosity model as CSP viscosity.

Classes:

Equation: \(\eta_{mix} = \eta_{ref} \cdot \frac{f_\eta \cdot \alpha_{mix}}{\alpha_0}\)

where:

Applicable phases: Gas, Oil

Best for:

Usage:

// Standard Pedersen
fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("PFCT");
fluid.getPhase("oil").initPhysicalProperties();

Use "CSP" as an equivalent alias for "PFCT", or select "PFCT-Heavy-Oil" for characterized heavy fractions. Reinitialize the phase after any selection.

PFCT, PFCT-Mod86 and PFCT-Heavy-Oil clones keep independent mutable methane reference fluids. This includes the default gas/oil transport models on cloned process streams, so parallel branches can evaluate viscosity at different temperatures and pressures without overwriting a sibling reference state. Model parameters and correction factors are retained. Configure fluids and mixing parameters before launching parallel calculations; do not mutate a stream that another calculation is using.


Polynomial Correlation

Uses component-specific polynomial coefficients from the database.

Class: Viscosity (liquid), GasViscosity (gas)

Equation: \(\ln(\eta) = A + \frac{B}{T} + C\ln(T) + DT\)

where A, B, C, D are component-specific parameters from COMP database.

Database columns: LIQVISC1, LIQVISC2, LIQVISC3, LIQVISC4

Applicable phases: Primarily liquid

Best for:

Usage:

fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("polynom");
fluid.getPhase("oil").initPhysicalProperties();

Reference Fluid Methods

Specialized high-accuracy methods for specific fluids:

Methane (Reference)

Class: MethaneViscosityMethod

CO₂

Class: CO2ViscosityMethod

The earlier implementation omitted the linear-in-density contribution and failed all six finite-density check values in Laesecke and Muzny (2017), Table 6, with an error up to 6.8%. CO2ViscosityReferenceValuesTest now checks all nine Table 6 values to their printed rounding precision. CO2ViscosityMethodTest also checks seven Table 8 pressure-temperature recommendations through the existing Span–Wagner phase/property path with a 0.1% tolerance. This is a bounded implementation and EOS integration check, not a universal experimental-accuracy statement.

Both stateless APIs use the existing MCP runCapability invocation route. The ordinary CO2Model key and the existing pure-CO₂ Span–Wagner defaults use the corrected background model. PFCT mixtures are unaffected. See the method audit for parameter provenance, remaining critical-enhancement work, and computation-cost evidence.

Hydrogen

Classes: MuznyViscosityMethod, MuznyModViscosityMethod

The implemented case-sensitive keys and their constraints are:

Key Intended fluid
MethaneModel Pure methane
CO2Model Pure CO₂
Muzny, Muzny_mod Pure hydrogen
KTA, KTA_mod Pure helium
Salt Water Aqueous water/brine phase

For example, select and recalculate a pure-hydrogen gas phase with:

fluid.getPhase("gas").getPhysicalProperties().setViscosityModel("Muzny");
fluid.getPhase("gas").initPhysicalProperties();

Model Selection Guide

Application Recommended Model Notes
Reservoir simulation LBC Tunable, industry standard
Wide P-T range Friction Theory Good near critical
Heavy oils PFCT-Heavy-Oil Extended for high MW
Characterized crudes PFCT Works with pseudo-components
General gas processing Friction theory or PFCT Validate against representative data
Pure CO₂ CO2Model Reference background correlation; critical enhancement excluded
Pure H₂ Muzny Reference accuracy
Pure helium KTA Reference-fluid correlation
Aqueous systems Salt Water Water/brine correlation

Tuning Parameters

LBC viscosity-only critical volumes

LBCViscosityMethod.getCriticalVolumes() returns the effective per-component volumes used by the correlation, in cm³/mol and phase component order. setCriticalVolumes(double[]) accepts a positive finite value for every component. It configures the viscosity correlation independently of each component’s thermodynamic critical volume. Passing null clears the override and restores the legacy estimation route, including the existing Whitson-based TBP estimate. The input and output arrays are defensive copies, and overrides remain independent after model cloning or compatible-version native serialization. Changing the component slate requires a new array; stale counts fail explicitly.

This optional contract supports VCRITVIS E300 delivery and JSON viscosityModel.criticalVolumesCm3PerMol reload without silently re-estimating the transport parameter. Configure the same effective volumes and LBC coefficients on every phase that may become active. The guarded PVT delivery rejects phase-specific settings that one E300 component block cannot represent. The enabled LbcFluidRoundTripTest checks these APIs and actual petroleum-oil viscosity over pressure states.

LBC Parameter Tuning

The LBC method is commonly tuned to match laboratory viscosity data:

fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("LBC");

// Set all 5 parameters
double[] params = {0.1023, 0.023364, 0.058533, -0.040758, 0.0093324};
fluid.getPhase("oil").getPhysicalProperties().setLbcParameters(params);

// Or tune individual parameters
fluid.getPhase("oil").getPhysicalProperties().setLbcParameter(0, 0.105);
fluid.getPhase("oil").initPhysicalProperties();

Tuning procedure:

  1. Measure viscosity at multiple P-T conditions
  2. Run flash and calculate properties
  3. Adjust parameters to minimize error
  4. Validate at other conditions

CSP PFCT Parameter Tuning

The PFCT/CSP viscosity model exposes four dimensionless CSP correction factors. All factors default to 1.0, preserving the historical NeqSim calculation unless a user supplies tuned values. External PVT tools may report fitted vectors such as 0.6232, 1.1507, 1.0000, 1.0000; these can be supplied directly as the four-value CSP viscosity parameter vector.

Index Regression parameter Corrected PFCT term
0 VISCOSITY_CSP_1 Critical-temperature scaling exponent
1 VISCOSITY_CSP_2 Critical-pressure scaling exponent
2 VISCOSITY_CSP_3 Molar-mass scaling exponent
3 VISCOSITY_CSP_4 Alpha/molecular-weight correction exponent

Use PhysicalProperties.setCspViscosityParameters(double[]) to set all four parameters, setCspViscosityParameter(int, double) to tune one parameter, and getCspViscosityParameters() to read the active values. The longer setCspViscosityCorrectionFactors and getCspViscosityCorrectionFactors names are equivalent aliases.

For automated fitting, add viscosity measurements to PVTRegression with addViscosityData(...), then register RegressionParameter.VISCOSITY_CSP_1 through VISCOSITY_CSP_4 individually or call addCspViscosityRegressionParameters() to fit all four together. Viscosity observations are expected in Pa s and can target gas, oil, liquid, aqueous, or water phases.


Usage Examples

Basic Viscosity Calculation

import neqsim.thermo.system.SystemSrkEos;
import neqsim.thermo.system.SystemInterface;
import neqsim.thermodynamicoperations.ThermodynamicOperations;

// Create and flash fluid
SystemInterface fluid = new SystemSrkEos(298.15, 4.0);
fluid.addComponent("n-heptane", 0.5);
fluid.addComponent("nC10", 0.5);
fluid.setMixingRule("classic");

ThermodynamicOperations ops = new ThermodynamicOperations(fluid);
ops.TPflash();

// Initialize physical properties
fluid.initPhysicalProperties();
fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("LBC");
fluid.getPhase("oil").initPhysicalProperties();

// Get viscosity
double oilVisc = fluid.getPhase("oil").getViscosity("cP");
if (!(oilVisc > 0.0) || !Double.isFinite(oilVisc)) {
    throw new IllegalStateException("Expected positive finite oil viscosity");
}

Comparing Viscosity Models

String[] models = {"LBC", "friction theory", "PFCT"};
double[] viscositiesCp = new double[models.length];

for (int i = 0; i < models.length; i++) {
    SystemInterface fluid = new SystemSrkEos(298.15, 4.0);
    fluid.addComponent("n-heptane", 0.5);
    fluid.addComponent("nC10", 0.5);
    fluid.setMixingRule("classic");
    ThermodynamicOperations ops = new ThermodynamicOperations(fluid);
    ops.TPflash();
    fluid.initPhysicalProperties();

    fluid.getPhase("oil").getPhysicalProperties().setViscosityModel(models[i]);
    fluid.getPhase("oil").initPhysicalProperties();
    viscositiesCp[i] = fluid.getPhase("oil").getViscosity("cP");
}

Viscosity vs Temperature

SystemInterface baseFluid = new SystemSrkEos(300.0, 20.0);
baseFluid.addComponent("nC10", 1.0);
baseFluid.setMixingRule("classic");

double[] temps = {300, 320, 340, 360, 380, 400};  // K
double[] viscositiesCp = new double[temps.length];

for (int i = 0; i < temps.length; i++) {
    SystemInterface fluid = baseFluid.clone();
    fluid.setTemperature(temps[i], "K");

    ThermodynamicOperations ops = new ThermodynamicOperations(fluid);
    ops.TPflash();
    fluid.initPhysicalProperties();
    fluid.getPhase("oil").getPhysicalProperties().setViscosityModel("LBC");
    fluid.getPhase("oil").initPhysicalProperties();
    viscositiesCp[i] = fluid.getPhase("oil").getViscosity("cP");
}

Mathematical Details

Dilute Gas Viscosity (Chapman-Enskog)

For dilute gases, viscosity is calculated from kinetic theory:

\[\eta_0 = \frac{5}{16} \frac{\sqrt{\pi m k_B T}}{\pi \sigma^2 \Omega^{(2,2)*}}\]

where:

Mixing Rules

Mixing behavior is model-specific. Common forms include logarithmic molar weighting:

\[\eta_{mix} = \exp\left(\sum_i x_i \ln \eta_i\right)\]

or the more rigorous:

\[\eta_{mix} = \frac{\sum_i x_i \sqrt{M_i} \eta_i}{\sum_i x_i \sqrt{M_i}}\]

References

  1. Lohrenz, J., Bray, B.G., Clark, C.R. (1964). Calculating Viscosities of Reservoir Fluids from Their Compositions. JPT.
  2. Quiñones-Cisneros, S.E., Firoozabadi, A. (2000). One Parameter Friction Theory. AIChE J.
  3. Pedersen, K.S., et al. (1987). Viscosity of Crude Oils. Chem. Eng. Sci.
  4. Chung, T.H., et al. (1988). Generalized Multiparameter Correlation for Nonpolar and Polar Fluid Transport Properties. I&EC Res.