Skip to the content.

Thermodynamics Recipes

Copy-paste solutions for common thermodynamic tasks.

Table of Contents


Creating Fluids

Create Natural Gas

from neqsim import jneqsim

# Create at 25°C (298.15 K) and 50 bara
fluid = jneqsim.thermo.system.SystemSrkEos(273.15 + 25, 50.0)
fluid.addComponent("nitrogen", 0.02)
fluid.addComponent("CO2", 0.01)
fluid.addComponent("methane", 0.85)
fluid.addComponent("ethane", 0.06)
fluid.addComponent("propane", 0.03)
fluid.addComponent("n-butane", 0.02)
fluid.addComponent("n-pentane", 0.01)
fluid.setMixingRule("classic")

Gotcha: Always call setMixingRule() after adding all components!

Create Oil with Plus Fraction

from neqsim import jneqsim

fluid = jneqsim.thermo.system.SystemPrEos(273.15 + 60, 200.0)
fluid.addComponent("nitrogen", 0.5)
fluid.addComponent("CO2", 2.0)
fluid.addComponent("methane", 45.0)
fluid.addComponent("ethane", 8.0)
fluid.addComponent("propane", 5.0)
fluid.addComponent("n-butane", 3.0)
fluid.addComponent("n-pentane", 2.0)
fluid.addComponent("n-hexane", 2.0)

# Add C7+ as pseudo-component
fluid.addTBPfraction("C7+", 32.5, 0.220, 0.82)  # mole%, MW, SG

fluid.setMixingRule("classic")
fluid.setMultiPhaseCheck(True)

Create CO₂-Rich Fluid (CPA)

from neqsim import jneqsim

# Use CPA for CO2 with water
fluid = jneqsim.thermo.system.SystemSrkCPAstatoil(273.15 + 25, 100.0)
fluid.addComponent("CO2", 0.95)
fluid.addComponent("methane", 0.03)
fluid.addComponent("water", 0.02)
fluid.setMixingRule(10)  # CPA mixing rule

Flash Calculations

Run TP Flash

from neqsim import jneqsim

# After creating fluid...
ops = jneqsim.thermodynamicoperations.ThermodynamicOperations(fluid)
ops.TPflash()

# IMPORTANT: Initialize properties after flash
fluid.initProperties()

print(f"Phases: {fluid.getNumberOfPhases()}")

Run PH Flash (Given Pressure and Enthalpy)

# First, get enthalpy at known conditions
fluid.initProperties()
H_initial = fluid.getEnthalpy("J")

# Change pressure, calculate new T
new_pressure = 30.0  # bara
ops.PHflash(new_pressure * 1e5, H_initial)  # P in Pa!

print(f"New temperature: {fluid.getTemperature() - 273.15:.2f} °C")

Run PS Flash (Isentropic)

# Get entropy at initial conditions
fluid.initProperties()
S_initial = fluid.getEntropy("J/K")

# Isentropic expansion
new_pressure = 20.0  # bara
ops.PSflash(new_pressure * 1e5, S_initial)

print(f"New temperature: {fluid.getTemperature() - 273.15:.2f} °C")

Reading Properties

Get Density (Correctly!)

# WRONG - Returns EoS density WITHOUT Peneloux correction
density_wrong = fluid.getDensity()

# CORRECT - Returns density WITH Peneloux volume correction
density_correct = fluid.getDensity("kg/m3")

print(f"Without correction: {density_wrong:.2f} kg/m³")
print(f"With correction: {density_correct:.2f} kg/m³")

Gotcha: Always pass a unit string to getDensity() to get the corrected value!

Get All Common Properties

# Make sure to initialize first
fluid.initProperties()

# Bulk properties
print(f"Temperature: {fluid.getTemperature() - 273.15:.2f} °C")
print(f"Pressure: {fluid.getPressure():.2f} bara")
print(f"Density: {fluid.getDensity('kg/m3'):.2f} kg/m³")
print(f"Molar mass: {fluid.getMolarMass('kg/mol') * 1000:.2f} g/mol")
print(f"Z-factor: {fluid.getZ():.4f}")
print(f"Enthalpy: {fluid.getEnthalpy('kJ/kg'):.2f} kJ/kg")
print(f"Entropy: {fluid.getEntropy('J/kgK'):.2f} J/kgK")
print(f"Cp: {fluid.getCp('kJ/kgK'):.4f} kJ/kgK")
print(f"Cv: {fluid.getCv('kJ/kgK'):.4f} kJ/kgK")
print(f"Speed of sound: {fluid.getSoundSpeed('m/s'):.2f} m/s")

# Transport properties
print(f"Viscosity: {fluid.getViscosity('cP'):.4f} cP")
print(f"Thermal cond: {fluid.getThermalConductivity('W/mK'):.4f} W/mK")

Get Phase-Specific Properties

# Check available phases
if fluid.hasPhaseType("gas"):
    gas = fluid.getPhase("gas")
    print(f"Gas density: {gas.getDensity('kg/m3'):.2f} kg/m³")
    print(f"Gas viscosity: {gas.getViscosity('cP'):.4f} cP")
    print(f"Gas fraction: {gas.getBeta():.4f} (mole)")

if fluid.hasPhaseType("oil"):
    oil = fluid.getPhase("oil")
    print(f"Oil density: {oil.getDensity('kg/m3'):.2f} kg/m³")
    print(f"Oil viscosity: {oil.getViscosity('cP'):.4f} cP")

Get Component Properties

for i in range(fluid.getNumberOfComponents()):
    comp = fluid.getComponent(i)
    name = str(comp.getComponentName())
    z = comp.getz()  # Overall mole fraction
    
    print(f"{name}: z={z:.4f}, Tc={comp.getTC():.1f} K, Pc={comp.getPC():.1f} bara")

Phase Envelopes

Calculate Phase Envelope

from neqsim import jneqsim
import matplotlib.pyplot as plt

# Create fluid
fluid = jneqsim.thermo.system.SystemSrkEos(273.15 + 25, 50.0)
fluid.addComponent("methane", 0.80)
fluid.addComponent("ethane", 0.10)
fluid.addComponent("propane", 0.05)
fluid.addComponent("n-butane", 0.05)
fluid.setMixingRule("classic")

# Calculate envelope
ops = jneqsim.thermodynamicoperations.ThermodynamicOperations(fluid)
ops.calcPTphaseEnvelope()

# Extract points
dew_T = [t - 273.15 for t in list(ops.get("dewT"))]
dew_P = list(ops.get("dewP"))
bub_T = [t - 273.15 for t in list(ops.get("bubT"))]
bub_P = list(ops.get("bubP"))

# Plot
plt.figure(figsize=(10, 6))
plt.plot(dew_T, dew_P, 'b-', label='Dew line', linewidth=2)
plt.plot(bub_T, bub_P, 'r-', label='Bubble line', linewidth=2)
plt.xlabel('Temperature (°C)')
plt.ylabel('Pressure (bara)')
plt.title('Phase Envelope')
plt.legend()
plt.grid(True)
plt.show()

Get Cricondenbar and Cricondentherm

ops.calcPTphaseEnvelope()

cricondenbar_P = ops.get("cricondenbar")[1]  # Pressure
cricondenbar_T = ops.get("cricondenbar")[0] - 273.15  # Temperature in °C

cricondentherm_P = ops.get("cricondentherm")[1]
cricondentherm_T = ops.get("cricondentherm")[0] - 273.15

print(f"Cricondenbar: {cricondenbar_P:.2f} bara at {cricondenbar_T:.2f} °C")
print(f"Cricondentherm: {cricondentherm_T:.2f} °C at {cricondentherm_P:.2f} bara")

Which EoS Should I Use?

Fluid Type Recommended EoS NeqSim Class
Dry gas SRK or PR SystemSrkEos, SystemPrEos
Gas condensate PR with Peneloux SystemPrEos
Black oil PR or SRK SystemPrEos, SystemSrkEos
Heavy oil PR or CPA SystemPrEos, SystemSrkCPAstatoil
CO₂ systems CPA SystemSrkCPAstatoil
CO₂ + water CPA or Electrolyte-CPA SystemSrkCPAstatoil
Natural gas (custody) GERG-2008 SystemGERG2008
LNG GERG-2008 or PR SystemGERG2008, SystemPrEos
Aqueous systems CPA SystemSrkCPAstatoil
Electrolytes Electrolyte-CPA See electrolyte guide

Quick Selection Code

from neqsim import jneqsim

# For dry gas / gas condensate
fluid = jneqsim.thermo.system.SystemSrkEos(T, P)

# For black oil
fluid = jneqsim.thermo.system.SystemPrEos(T, P)

# For CO2/water systems
fluid = jneqsim.thermo.system.SystemSrkCPAstatoil(T, P)

# For custody transfer (natural gas)
fluid = jneqsim.thermo.system.SystemGERG2008(T, P)

Export and Import

Export to JSON

# Full fluid state as JSON
json_str = fluid.toJson()
print(json_str)

# Component-specific JSON
comp_json = fluid.getComponent(0).toJson()

Export to Python Dictionary

import json

# Parse JSON to dict
data = json.loads(fluid.toJson())
print(f"Temperature: {data['temperature']['value']} {data['temperature']['unit']}")

Clone a Fluid

# Create a copy (independent of original)
fluid_copy = fluid.clone()

# Modify copy without affecting original
fluid_copy.setTemperature(300.0)

See Also