Skip to the content.

Heat Integration and Pinch Analysis

NeqSim provides a classical pinch analysis engine (Linnhoff method) for determining minimum heating and cooling utility requirements for a set of process streams.

Classes

Class Package Purpose
PinchAnalysis process.equipment.heatexchanger.heatintegration Main analysis engine: temperature intervals, heat cascade, utility targets, composite curves
HeatStream process.equipment.heatexchanger.heatintegration Data model for a hot or cold process stream with supply/target temperatures and heat capacity flow rate

Quick Start

import neqsim.process.equipment.heatexchanger.heatintegration.PinchAnalysis;

// Create analysis with minimum approach temperature (deltaT_min)
PinchAnalysis pinch = new PinchAnalysis(10.0); // 10 C

// Add hot streams (need cooling): name, supplyTemp_C, targetTemp_C, MCp_kW/K
pinch.addHotStream("H1", 180, 80, 30);   // 180 to 80 C, MCp = 30 kW/K
pinch.addHotStream("H2", 150, 50, 15);   // 150 to 50 C, MCp = 15 kW/K

// Add cold streams (need heating)
pinch.addColdStream("C1", 30, 140, 20);  // 30 to 140 C, MCp = 20 kW/K
pinch.addColdStream("C2", 60, 120, 25);  // 60 to 120 C, MCp = 25 kW/K

// Run the analysis
pinch.run();

// Read results
double Qh = pinch.getMinimumHeatingUtility();  // kW
double Qc = pinch.getMinimumCoolingUtility();   // kW
double Tpinch = pinch.getPinchTemperatureC();   // hot-side pinch in C
double maxRecovery = pinch.getMaximumHeatRecovery(); // kW

Python (Jupyter) Usage

from neqsim import jneqsim

PinchAnalysis = jneqsim.process.equipment.heatexchanger.heatintegration.PinchAnalysis

pinch = PinchAnalysis(10.0)
pinch.addHotStream("H1", 180.0, 80.0, 30.0)
pinch.addHotStream("H2", 150.0, 50.0, 15.0)
pinch.addColdStream("C1", 30.0, 140.0, 20.0)
pinch.addColdStream("C2", 60.0, 120.0, 25.0)
pinch.run()

print(f"Min hot utility:  {pinch.getMinimumHeatingUtility():.1f} kW")
print(f"Min cold utility: {pinch.getMinimumCoolingUtility():.1f} kW")
print(f"Pinch temperature: {pinch.getPinchTemperatureC():.1f} C")
print(f"Max heat recovery: {pinch.getMaximumHeatRecovery():.1f} kW")

Algorithm

The implementation follows the classical Linnhoff & Flower (1978) temperature interval method:

  1. Shifted temperatures — Hot streams are shifted down by half the minimum approach temperature; cold streams are shifted up by half
  2. Temperature intervals — All shifted temperatures define intervals where stream populations are constant
  3. Heat balance per interval — Net heat available = (sum MCp_hot - sum MCp_cold) * dT
  4. Heat cascade — Cumulative heat surplus/deficit cascaded from highest to lowest temperature
  5. Feasible cascade — Hot utility added at the top to make all cascade values non-negative
  6. Results — The added hot utility is the minimum heating requirement; the residual at the bottom is the minimum cooling requirement; the pinch is where the cascade equals zero

Composite Curves

After running the analysis, composite curve data is accessible for plotting:

Map<String, double[]> hotCurve = pinch.getHotCompositeCurve();
Map<String, double[]> coldCurve = pinch.getColdCompositeCurve();
Map<String, double[]> grandCurve = pinch.getGrandCompositeCurve();

// Each map contains "Q_kW" (cumulative enthalpy) and "T_K" (temperature in Kelvin)
double[] hotQ = hotCurve.get("Q_kW");
double[] hotT = hotCurve.get("T_K");

In Python with matplotlib:

import matplotlib.pyplot as plt

hot_curve = pinch.getHotCompositeCurve()
cold_curve = pinch.getColdCompositeCurve()

hot_Q = list(hot_curve.get("Q_kW"))
hot_T = [t - 273.15 for t in hot_curve.get("T_K")]
cold_Q = list(cold_curve.get("Q_kW"))
cold_T = [t - 273.15 for t in cold_curve.get("T_K")]

plt.figure(figsize=(8, 6))
plt.plot(hot_Q, hot_T, 'r-o', label='Hot Composite')
plt.plot(cold_Q, cold_T, 'b-o', label='Cold Composite')
plt.xlabel('Cumulative Enthalpy (kW)')
plt.ylabel('Temperature (C)')
plt.title('Composite Curves')
plt.legend()
plt.grid(True)
plt.show()

JSON Output

The toJson() method returns a comprehensive JSON report:

String json = pinch.toJson();

The JSON includes minimum utilities, pinch temperatures, maximum heat recovery, stream data (names, types, temperatures, MCp, duties), and the minimum approach temperature.

HeatStream

The HeatStream class represents a single process stream for pinch analysis:

import neqsim.process.equipment.heatexchanger.heatintegration.HeatStream;

// Constructor: name, supplyTemp_C, targetTemp_C, MCp_kW/K
HeatStream h1 = new HeatStream("H1", 200, 100, 15);

// Auto-classified based on temperature direction
h1.getType();               // StreamType.HOT (supply > target)
h1.getEnthalpyChange();     // 1500.0 kW (MCp * |dT|)
h1.getSupplyTemperatureC(); // 200.0 C
h1.getTargetTemperatureC(); // 100.0 C
h1.getHeatCapacityFlowRate(); // 15.0 kW/K

Streams can be added directly to the analysis:

pinch.addStream(h1); // auto-routes to hot or cold list based on type

Integration with NeqSim Process Equipment

PinchAnalysis can extract stream data directly from NeqSim process equipment, eliminating the need to manually specify temperatures and MCp values.

The fromProcessSystem factory method scans all unit operations in a ProcessSystem and automatically extracts heat streams from Heaters, Coolers, HeatExchangers, and MultiStreamHeatExchanger2 (including LNGHeatExchanger):

ProcessSystem process = new ProcessSystem();
// ... add equipment, run process ...
process.run();

PinchAnalysis pinch = PinchAnalysis.fromProcessSystem(process, 10.0);
pinch.run();

double Qh = pinch.getMinimumHeatingUtility();
double Qc = pinch.getMinimumCoolingUtility();

In Python:

PinchAnalysis = jneqsim.process.equipment.heatexchanger.heatintegration.PinchAnalysis

pinch = PinchAnalysis.fromProcessSystem(process, 10.0)
pinch.run()
print(f"Min hot utility: {pinch.getMinimumHeatingUtility():.1f} kW")

From a two-stream HeatExchanger

HeatExchanger hx = new HeatExchanger("HX-100", hotStream, coldStream);
// ... run the HX ...

PinchAnalysis pinch = new PinchAnalysis(10.0);
pinch.addStreamsFromHeatExchanger(hx);
// Adds "HX-100 hot-side" and "HX-100 cold-side" automatically

From a MultiStreamHeatExchanger2 or LNGHeatExchanger

MultiStreamHeatExchanger2 mshe = new MultiStreamHeatExchanger2("LNG-HX");
// ... configure and run ...

PinchAnalysis pinch = new PinchAnalysis(10.0);
pinch.addStreamsFromHeatExchanger(mshe);
// Iterates through all internal streams

From individual process streams

For fine-grained control, add individual NeqSim streams with a specified outlet temperature:

PinchAnalysis pinch = new PinchAnalysis(10.0);
pinch.addProcessStream("Feed cooler", feedStream, 40.0);
// Extracts inlet temperature, computes MCp from enthalpy difference

Equipment type mapping

Equipment Method used Streams extracted
Cooler Heater/Cooler path 1 hot stream (process-side cooling)
Heater Heater/Cooler path 1 cold stream (process-side heating)
HeatExchanger addStreamsFromHeatExchanger(HeatExchanger) 1 hot + 1 cold (both sides)
MultiStreamHeatExchanger2 addStreamsFromHeatExchanger(MSHE2) N streams (all internal streams)
LNGHeatExchanger Same as MSHE2 (extends it) N streams (all internal streams)