Skip to the content.

Documentation for power generation equipment in NeqSim, including gas turbines, steam turbines, HRSG, combined-cycle systems, fuel cells, wind turbines, and solar panels.

Table of Contents


Overview

Location: neqsim.process.equipment.powergeneration

The power generation package provides equipment models for converting chemical and renewable energy sources into electrical power:

Equipment Energy Source Output
GasTurbine Fuel gas combustion Electricity + heat
SteamTurbine High-pressure steam Electricity
HRSG Gas turbine exhaust Steam
CombinedCycleSystem Fuel gas (GT + HRSG + ST) Electricity (high efficiency)
FuelCell Hydrogen + oxygen Electricity + water
WindTurbine Wind Electricity
SolarPanel Solar radiation Electricity
BatteryStorage Stored electricity Electricity

Gas Turbine

The GasTurbine class models a simple cycle gas turbine with integrated air compression, combustion, and expansion.

Class Hierarchy

TwoPortEquipment
└── GasTurbine

Constructor

import neqsim.process.equipment.powergeneration.GasTurbine;
import neqsim.process.equipment.stream.Stream;

// Basic constructor
GasTurbine turbine = new GasTurbine("GT-101");

// Constructor with fuel stream
GasTurbine turbine = new GasTurbine("GT-101", fuelGasStream);

Key Properties

Property Description Unit
combustionPressure Combustor pressure bara
airGasRatio Air to fuel ratio -
excessAirFactor Combustion-air excess over stoichiometric O₂ (setExcessAirFactor) -
power Net electrical power output W
heat Heat output W
compressorPower Air compressor power W
expanderPower Expander power W

Example Usage

import neqsim.process.equipment.powergeneration.GasTurbine;
import neqsim.process.equipment.stream.Stream;
import neqsim.thermo.system.SystemSrkEos;

// Create fuel gas
SystemInterface fuelGas = new SystemSrkEos(288.15, 25.0);
fuelGas.addComponent("methane", 0.90);
fuelGas.addComponent("ethane", 0.05);
fuelGas.addComponent("propane", 0.03);
fuelGas.addComponent("nitrogen", 0.02);
fuelGas.setMixingRule("classic");

Stream fuelStream = new Stream("Fuel Gas", fuelGas);
fuelStream.setFlowRate(1000.0, "kg/hr");

// Create gas turbine
GasTurbine turbine = new GasTurbine("Power Turbine", fuelStream);
turbine.combustionpressure = 2.5;   // bara (public field) - simplified low-pressure cycle
turbine.setExcessAirFactor(2.5);    // sizes combustion air so O2 is not depleted

// Run simulation
turbine.run();

// Results
System.out.println("Net power: " + turbine.getPower() / 1e6 + " MW");
System.out.println("Heat output: " + turbine.getHeat() / 1e6 + " MW");
System.out.println("Ideal air/fuel ratio: " + turbine.calcIdealAirFuelRatio());

The detailed cycle sizes combustion air using the stoichiometric oxygen demand and excessAirFactor (default 2.5). It obtains the fuel lower heating value from ISO 6976 on a molar basis (kJ/mol), using the 0 C combustion reference to match the EOS sensible-enthalpy reference, then multiplies by mol/s and 1000 to obtain W. This avoids mixing volumetric calorific values with molar flows or inconsistent standard-volume references. Combustion changes the product composition before solving its enthalpy; a heat-capacity temperature estimate initializes that solve, and an unconverged combustion energy balance raises an exception.

getPower() is positive net shaft output: recovered expander work minus air compressor work. getHeat() estimates positive heat recoverable by cooling the exhaust to 288.15 K. getOutletStream() contains the hot combustion exhaust leaving the expander so a downstream HRSG can recover that energy. The detailed cycle balances inlet sensible enthalpy plus fuel heat against shaft output and hot exhaust enthalpy; do not add recoverable heat again to that balance. It is a simplified complete-combustion model without dissociation, combustor pressure loss or blade cooling. The optional specified-efficiency and power-demand modes retain their separate fuel-sizing convention and are not detailed-cycle performance predictions.


Steam Turbine

The SteamTurbine class models isentropic expansion of high-pressure steam to produce power. Outlet conditions are computed via PS-flash (isentropic) followed by PH-flash (actual) using the specified isentropic efficiency.

Class Hierarchy

TwoPortEquipment
└── SteamTurbine

Constructor

import neqsim.process.equipment.powergeneration.SteamTurbine;

// Basic constructor
SteamTurbine st = new SteamTurbine("ST-100");

// Constructor with inlet steam stream
SteamTurbine st = new SteamTurbine("ST-100", steamStream);

Key Properties

Property Setter Default Unit
outletPressure setOutletPressure(p) / setOutletPressure(p, "bara") 1.01325 bara
isentropicEfficiency setIsentropicEfficiency(e) 0.85 0-1
numberOfStages setNumberOfStages(n) 1 -
power (result) - W

Example Usage

import neqsim.process.equipment.powergeneration.SteamTurbine;
import neqsim.process.equipment.stream.Stream;
import neqsim.thermo.system.SystemSrkEos;

// Create superheated steam
SystemInterface steam = new SystemSrkEos(273.15 + 450.0, 40.0);
steam.addComponent("water", 1.0);
steam.setMixingRule("classic");

Stream steamFeed = new Stream("HP Steam", steam);
steamFeed.setFlowRate(50000.0, "kg/hr");

// Create steam turbine
SteamTurbine turbine = new SteamTurbine("ST-100", steamFeed);
turbine.setOutletPressure(0.05, "bara");
turbine.setIsentropicEfficiency(0.88);
turbine.run();

System.out.println("Power output: " + turbine.getPower("MW") + " MW");

HRSG

The HRSG (Heat Recovery Steam Generator) class models counter-current heat exchange between hot gas turbine exhaust and a water/steam loop. It calculates the heat transferred and the steam production rate for given steam conditions.

Class Hierarchy

TwoPortEquipment
└── HRSG

Constructor

import neqsim.process.equipment.powergeneration.HRSG;

// Basic constructor
HRSG hrsg = new HRSG("HRSG-1");

// Constructor with hot gas inlet (gas turbine exhaust)
HRSG hrsg = new HRSG("HRSG-1", gasTurbineExhaust);

Key Properties

Property Setter Default Unit
steamPressure setSteamPressure(p) 40.0 bara
steamTemperature setSteamTemperature(t) / setSteamTemperature(t, "C") 400 C K
feedWaterTemperature setFeedWaterTemperature(t) / setFeedWaterTemperature(t, "C") 60 C K
approachTemperature setApproachTemperature(dT) 15.0 K
effectiveness setEffectiveness(e) 0.85 0-1

Results

Method Returns Unit
getHeatTransferred() / getHeatTransferred("MW") Heat to steam W / MW
getSteamFlowRate() / getSteamFlowRate("kg/hr") Steam production kg/s / kg/hr
getGasOutletTemperature() Gas stack temperature K

Example Usage

HRSG hrsg = new HRSG("HRSG-1", turbine.getOutletStream());
hrsg.setSteamPressure(40.0);
hrsg.setSteamTemperature(400.0, "C");
hrsg.setApproachTemperature(15.0);
hrsg.run();

System.out.println("Heat recovered: " + hrsg.getHeatTransferred("MW") + " MW");
System.out.println("Steam production: " + hrsg.getSteamFlowRate("kg/hr") + " kg/hr");

Combined Cycle System

The CombinedCycleSystem class integrates a GasTurbine, HRSG, and SteamTurbine into a single equipment unit. It models the full gas turbine combined cycle (GTCC) workflow:

  1. Fuel gas combustion in the gas turbine
  2. Exhaust heat recovery in the HRSG to produce steam
  3. Steam expansion through the steam turbine

Class Hierarchy

TwoPortEquipment
└── CombinedCycleSystem  (composes GasTurbine + HRSG + SteamTurbine)

Constructor

import neqsim.process.equipment.powergeneration.CombinedCycleSystem;

CombinedCycleSystem cc = new CombinedCycleSystem("CC-Plant");
CombinedCycleSystem cc = new CombinedCycleSystem("CC-Plant", fuelGasStream);

Key Properties

Property Setter Default Unit
combustionPressure combustionpressure (public field) 2.5 bara
steamPressure setSteamPressure(p) 40.0 bara
steamTemperature setSteamTemperature(t, "C") 400.0 C
steamTurbineEfficiency setSteamTurbineEfficiency(e) 0.85 0-1
steamCondensorPressure setSteamCondensorPressure(p) 0.05 bara
hrsgApproachTemperature setHrsgApproachTemperature(dT) 15.0 K
hrsgEffectiveness setHrsgEffectiveness(e) 0.85 0-1

Results

Method Returns Unit
getTotalPower() / getTotalPower("MW") Combined GT + ST power W / MW
getGasTurbinePower() GT contribution W
getSteamTurbinePower() ST contribution W
getOverallEfficiency() LHV thermal efficiency 0-1
getFuelEnergyInput() Fuel energy (LHV) W
toJson() Full results JSON String

Example Usage

CombinedCycleSystem cc = new CombinedCycleSystem("CC-1", fuelStream);
cc.setCombustionPressure(15.0);
cc.setSteamPressure(40.0);
cc.setSteamTemperature(400.0, "C");
cc.setSteamTurbineEfficiency(0.85);
cc.run();

System.out.println("Total power: " + cc.getTotalPower("MW") + " MW");
System.out.println("GT power: " + cc.getGasTurbinePower() / 1e6 + " MW");
System.out.println("ST power: " + cc.getSteamTurbinePower() / 1e6 + " MW");
System.out.println("Efficiency: " + cc.getOverallEfficiency() * 100 + "%");
System.out.println(cc.toJson());

Fuel Cell

Class Hierarchy

TwoPortEquipment
└── FuelCell

Constructor

import neqsim.process.equipment.powergeneration.FuelCell;

// Basic constructor
FuelCell cell = new FuelCell("FC-101");

// Constructor with fuel and oxidant streams
FuelCell cell = new FuelCell("FC-101", hydrogenStream, airStream);

Key Properties

Property Description Unit
efficiency Electrical efficiency 0-1
power Electrical power output W
heatLoss Heat loss to environment W

Example Usage

import neqsim.process.equipment.powergeneration.FuelCell;
import neqsim.process.equipment.stream.Stream;
import neqsim.thermo.system.SystemSrkEos;

// Create hydrogen fuel stream
SystemInterface h2Fluid = new SystemSrkEos(298.15, 5.0);
h2Fluid.addComponent("hydrogen", 1.0);
h2Fluid.setMixingRule("classic");

Stream hydrogenFeed = new Stream("Hydrogen", h2Fluid);
hydrogenFeed.setFlowRate(10.0, "kg/hr");

// Create air stream
SystemInterface airFluid = new SystemSrkEos(298.15, 1.01325);
airFluid.addComponent("nitrogen", 0.79);
airFluid.addComponent("oxygen", 0.21);
airFluid.setMixingRule("classic");

Stream airFeed = new Stream("Air", airFluid);
airFeed.setFlowRate(100.0, "kg/hr");

// Create fuel cell
FuelCell fuelCell = new FuelCell("SOFC", hydrogenFeed, airFeed);
fuelCell.setEfficiency(0.55);

// Run simulation
fuelCell.run();

// Results
System.out.println("Electrical power: " + fuelCell.getPower() / 1000 + " kW");
System.out.println("Heat loss: " + fuelCell.getHeatLoss() / 1000 + " kW");

Wind Turbine

The WindTurbine class models wind power generation based on wind speed and turbine characteristics.

Constructor

import neqsim.process.equipment.powergeneration.WindTurbine;

WindTurbine turbine = new WindTurbine("WT-01");
turbine.setWindSpeed(12.0);          // m/s
turbine.setRotorArea(11310.0);       // m² (e.g. pi * 60² for 120m diameter)
turbine.setPowerCoefficient(0.45);   // Betz limit max ~0.593

Key Properties

Property Description Unit
windSpeed Wind velocity m/s
rotorArea Rotor swept area
powerCoefficient Aerodynamic efficiency (Cp) 0-0.593 (Betz limit)
airDensity Air density kg/m³
power Electrical power output W

Solar Panel

The SolarPanel class models photovoltaic power generation.

Constructor

import neqsim.process.equipment.powergeneration.SolarPanel;

SolarPanel panel = new SolarPanel("PV-Array");
panel.setPanelArea(1000.0);        // m²
panel.setIrradiance(800.0);        // W/m²
panel.setEfficiency(0.20);

Key Properties

Property Description Unit
panelArea Total panel area
irradiance Solar radiation W/m²
efficiency Panel efficiency 0-1
power Electrical power output W

Battery Storage

Location: neqsim.process.equipment.battery

The BatteryStorage class models electrical energy storage systems.

Constructor

import neqsim.process.equipment.battery.BatteryStorage;

BatteryStorage battery = new BatteryStorage("BESS-01");
battery.setCapacity(3.6e11);         // Joules (= 100 MWh)
// Note: charge/discharge efficiencies are internal (default 0.95 each)

Key Properties

Property Description Unit
capacity Total energy capacity J
stateOfCharge Current energy level J
stateOfChargeFraction SOC as fraction 0-1

Operations

battery.charge(25e6, 2.0);         // charge at 25 MW for 2 hours
double delivered = battery.discharge(25e6, 1.0);  // discharge at 25 MW for 1 hour
double soc = battery.getStateOfChargeFraction();   // 0-1

Right-Sizing, Dispatch & Retrofit (gasturbine sub-package)

For late-life turndown, fleet right-sizing, dispatch with N+1 reserve, and retrofit NPV / CO₂-avoided studies, use the catalog-driven classes under neqsim.process.equipment.powergeneration.gasturbine. These complement the legacy GasTurbine class above: use the legacy class when you need full thermodynamic GT + HRSG integration; use this sub-package when the question is “which turbines, how many, and at what load over 20 years?”

Class Purpose
GasTurbineCatalog Bundled gas_turbine_catalog.csv (14 aero + industrial models: LM2500, LM2500PLUS_G4, LM6000PF/PG, RB211_6562, Trent 60, SGT-700/750, Centaur 50, Taurus 60/70, Mars 100, Titan 130/250)
GasTurbineSpec Immutable rating point (rated MW, ISO heat rate, exhaust flow/T, NOx, mass)
GasTurbinePerformanceMap Part-load + ambient correction (aero vs industrial polynomials, min-load fraction)
GasTurbineDegradation Recoverable + non-recoverable fouling vs fired hours, water-wash and overhaul reset
GasTurbineEmissions Full-carbon-balance CO₂, NOx, methane slip from fuel composition
CO2TaxSchedule Loads co2_tax_norway.csv (2020–2040 NOK/tonne, CO₂ tax + EU ETS), linear interpolation
GasTurbineUnit TwoPortEquipment — runs inside a ProcessSystem, accepts fuel Stream, aggregates Compressor shaft load via addPowerConsumer
TurbineDispatchOptimizer Picks the cheapest feasible on/off combination (brute-force ≤8 units, merit-order above) with N+1 reserve
LateLifeRetrofitStudy Year-by-year NPV / CO₂-avoided / payback for baseline vs retrofit fleet over a declining demand profile

Catalog & site-corrected available power

import neqsim.process.equipment.powergeneration.gasturbine.GasTurbineCatalog;
import neqsim.process.equipment.powergeneration.gasturbine.GasTurbineSpec;
import neqsim.process.equipment.powergeneration.gasturbine.GasTurbineUnit;

GasTurbineSpec spec = GasTurbineCatalog.get("LM2500");
GasTurbineUnit gt = new GasTurbineUnit("GT-A", fuelStream, spec);
gt.setAmbientTemperatureK(273.15 + 30.0);   // hot-day derate
gt.setDemandedPower(15.0e6);                 // 15 MW shaft
gt.run(UUID.randomUUID());
double availMW = gt.getAvailablePowerW() / 1.0e6;
double load    = gt.getLoadFraction();
double co2Tph  = gt.getCO2EmissionKgPerS() * 3.6;

Linking turbine shaft to compressor demand

Each GasTurbineUnit sums the live shaft demand from any number of Compressor objects in the same flowsheet — the dispatcher reads it on every run():

ProcessSystem plant = new ProcessSystem();
plant.add(exportCompressor);     // existing Compressor
plant.add(injectionCompressor);
GasTurbineUnit gt = new GasTurbineUnit("GT-A", fuelStream,
        GasTurbineCatalog.get("LM2500"));
gt.addPowerConsumer(exportCompressor);
gt.addPowerConsumer(injectionCompressor);
plant.add(gt);
plant.run();   // gt aggregates Compressor.getPower() automatically

Closing the loop: feeding the available-power limit back to compressors

By default the link above is one-way — the turbine reads compressor shaft power but does not constrain it. Enable setEnforcePowerLimit(true) to close the loop: on every run() the unit distributes its site-corrected getAvailablePowerW() across the attached compressors (in proportion to their current demand) and installs each share as a GasTurbineDriver performance curve on the compressor via Compressor.setDriverCurve(...). Because the per-compressor caps sum to the turbine available power, the capacity / bottleneck framework then enforces Σ compressor power ≤ turbine available power automatically.

GasTurbineUnit gt = new GasTurbineUnit("GT-A", fuelStream,
        GasTurbineCatalog.get("LM2500"));
gt.addPowerConsumer(exportCompressor);
gt.addPowerConsumer(injectionCompressor);
gt.setAmbientTemperatureK(273.15 + 30.0);   // hot-day derate shrinks the budget
gt.setEnforcePowerLimit(true);              // opt-in: cap the compressors
plant.add(gt);
plant.run();

if (gt.isOverloaded()) {
    System.out.println("Shortfall: " + gt.getPowerShortfallW() / 1e6 + " MW");
}
// Per-machine power budget actually installed on each compressor:
gt.getPowerAllocationW().forEach((name, watts) ->
        System.out.println(name + " allocated " + watts / 1e6 + " MW"));
// Each compressor now reports a finite capacity limit from its driver curve:
double capMW = exportCompressor.getCapacityMax() / 1e6;

The default (enforcePowerLimit = false) preserves the historical snapshot-only behaviour, so existing dispatch and right-sizing studies are unaffected. Turn it on when you want the turbine’s installed/derated power to act as a hard ceiling for the compression train in capacity and debottlenecking analysis.

Fleet dispatch with N+1 redundancy

import neqsim.process.equipment.powergeneration.gasturbine.TurbineDispatchOptimizer;

List<GasTurbineUnit> fleet = Arrays.asList(gt1, gt2, gt3);
TurbineDispatchOptimizer disp = new TurbineDispatchOptimizer(
        /*fuelPriceNOKPerKg*/ 4.5,
        /*co2CostNOKPerTonne*/ 1500.0);
disp.setRequireNplusOne(true);
TurbineDispatchOptimizer.DispatchResult r = disp.dispatch(fleet, 18.0e6);
if (r.feasible) {
    System.out.println(r.summary());   // running units, load, NOK/hr
}

Retrofit NPV vs baseline

import neqsim.process.equipment.powergeneration.gasturbine.CO2TaxSchedule;
import neqsim.process.equipment.powergeneration.gasturbine.LateLifeRetrofitStudy;

double[] demandMW = new double[20];
for (int i = 0; i < 20; i++) demandMW[i] = Math.max(8.0, 56.0 - i * 2.0);

LateLifeRetrofitStudy study = new LateLifeRetrofitStudy(
        baselineFleet,    // e.g. 2x LM6000PF
        retrofitFleet,    // e.g. 3x SGT-700
        demandMW,
        /*startYear*/ 2026,
        CO2TaxSchedule.loadDefault(),
        /*fuelPriceNOKPerKg*/ 4.5);
study.setRetrofitCapexMNOK(800.0);
study.setDiscountRate(0.08);
study.setAnnualOperatingHours(8000);
LateLifeRetrofitStudy.RetrofitResult res = study.run();
System.out.println("NPV (MNOK):      " + res.npvMNOK);
System.out.println("CO2 avoided (t): " + res.totalCO2AvoidedTonne);
System.out.println("Payback (yr):    " + res.simplePaybackYear);

End-to-end notebooks

The Gas Turbine & Compressor Driver Coupling notebook is a focused, runnable introduction to the three abstractions on this page: the GasTurbine Brayton-cycle thermo model (Part A), the catalog-driven GasTurbineUnit accounting wrapper that caps a compressor train (Part B), and a standalone GasTurbineDriver capacity ceiling with ambient derating (Part C).

The Gas Turbine 20-Year Right-Sizing and Retrofit notebook walks through a complete late-life study:

  1. Build a 50 MMSCFD export-compression train and link it to a GasTurbineUnit.
  2. Sweep ambient temperature × load to map site-corrected available power.
  3. Apply GasTurbineDegradation over fired hours and overhauls.
  4. Dispatch a 3-unit fleet with TurbineDispatchOptimizer against an annual load-duration curve.
  5. Run LateLifeRetrofitStudy with CO2TaxSchedule.loadDefault() to compare baseline (2 × LM6000PF) vs retrofit (3 × SGT-700) on NPV, payback, and CO₂ avoided.
  6. Layer an HRSG + steam-turbine bottoming cycle on the retrofit fleet to evaluate a combined-cycle alternative.
  7. Replace the synthetic decline with a reservoir + Beggs-Brills riser + flowline model so the compressor suction — and therefore the shaft demand — is driven by reservoir physics.

The full skill reference lives at .github/skills/neqsim-power-generation/SKILL.md.


Driver Performance Curves (driver sub-package)

A Compressor can be given a richer driver performance curve from neqsim.process.equipment.compressor.driver. Unlike the simpler enum-based CompressorDriver, the DriverCurve family models speed-dependent available power with ambient-temperature and altitude derating, and feeds that derated limit into Compressor.getCapacityMax() for capacity and bottleneck analysis.

Class Models
DriverCurve Interface (extends Serializable) — available power, torque, efficiency vs speed
DriverCurveBase Shared base: rated power/speed, ISO ambient, overspeed limit
GasTurbineDriver Ambient + altitude derating, part-load efficiency, fuel consumption
ElectricMotorDriver Constant-torque (VFD) or fixed-speed characteristics
SteamTurbineDriver Power vs steam conditions / extraction

Attaching a driver curve to a compressor

import neqsim.process.equipment.compressor.Compressor;
import neqsim.process.equipment.compressor.driver.GasTurbineDriver;

Compressor exportCompressor = new Compressor("Export", suctionStream);
exportCompressor.setOutletPressure(120.0);

// 20 MW gas-turbine driver, 35% design efficiency
GasTurbineDriver driver = new GasTurbineDriver(20000.0, 0.35); // kW, fraction
driver.setAmbientTemperature(30.0);   // hot-day derate
exportCompressor.setDriverCurve(driver);
exportCompressor.run();

// getCapacityMax() now uses the derated driver curve (highest priority)
double capMW = exportCompressor.getCapacityMax() / 1e6;
double availMW = driver.getAvailablePower(driver.getRatedSpeed()) / 1000.0; // kW->MW
boolean ok = driver.canSupplyPower(exportCompressor.getPower("kW"),
        driver.getRatedSpeed());

getCapacityMax() resolves the limit in priority order:

  1. DriverCurve (getDriverCurve()) — derated available power at the current/rated speed, if set.
  2. CompressorDriver speed-dependent max-power curve (if speed is set).
  3. Mechanical design maximum power.
  4. CompressorDriver rated power with a 10% overload margin.

This is the same curve type that GasTurbineUnit.setEnforcePowerLimit(true) installs automatically on each driven compressor (see Closing the loop), so a gas turbine’s installed/derated power becomes a hard ceiling for its compression train.


Usage Examples

Combined Heat and Power (CHP) System

import neqsim.process.processmodel.ProcessSystem;
import neqsim.process.equipment.powergeneration.GasTurbine;
import neqsim.process.equipment.powergeneration.HRSG;

ProcessSystem chpSystem = new ProcessSystem("CHP Plant");

// Create fuel gas stream
Stream fuelGas = new Stream("Fuel", fuelFluid);
fuelGas.setFlowRate(500.0, "kg/hr");
chpSystem.add(fuelGas);

// Gas turbine
GasTurbine turbine = new GasTurbine("GT", fuelGas);
turbine.combustionpressure = 12.0;
chpSystem.add(turbine);

// Heat recovery steam generator
HRSG hrsg = new HRSG("HRSG", turbine.getOutletStream());
hrsg.setSteamPressure(20.0);
hrsg.setSteamTemperature(250.0, "C");
hrsg.setApproachTemperature(15.0);
chpSystem.add(hrsg);

// Run
chpSystem.run();

// Calculate efficiency
double electricalPower = turbine.getPower();
double thermalPower = hrsg.getHeatTransferred();
double fuelInput = fuelGas.getFlowRate("kg/hr") * 50e6 / 3600;  // LHV ~ 50 MJ/kg

double electricalEff = electricalPower / fuelInput;
double totalEff = (electricalPower + thermalPower) / fuelInput;

System.out.println("Electrical efficiency: " + electricalEff * 100 + "%");
System.out.println("Total CHP efficiency: " + totalEff * 100 + "%");
System.out.println("Steam production: " + hrsg.getSteamFlowRate("kg/hr") + " kg/hr");

Combined Cycle Power Plant

import neqsim.process.equipment.powergeneration.CombinedCycleSystem;

// One-call combined cycle with internal GT + HRSG + ST
CombinedCycleSystem ccPlant = new CombinedCycleSystem("GTCC", fuelGasStream);
ccPlant.setCombustionPressure(15.0);
ccPlant.setSteamPressure(40.0);
ccPlant.setSteamTemperature(400.0, "C");
ccPlant.setSteamTurbineEfficiency(0.85);
ccPlant.run();

System.out.println("Total power: " + ccPlant.getTotalPower("MW") + " MW");
System.out.println("GT power: " + ccPlant.getGasTurbinePower() / 1e6 + " MW");
System.out.println("ST power: " + ccPlant.getSteamTurbinePower() / 1e6 + " MW");
System.out.println("Overall efficiency: " + ccPlant.getOverallEfficiency() * 100 + "%");

Hybrid Renewable System

// Solar + Wind + Battery system
SolarPanel solar = new SolarPanel("PV");
solar.setPanelArea(5000.0);
solar.setIrradiance(600.0);
solar.setEfficiency(0.18);

WindTurbine wind = new WindTurbine("Wind");
wind.setWindSpeed(8.0);
wind.setRotorArea(5027.0);  // ~80m diameter

BatteryStorage battery = new BatteryStorage("Battery");
battery.setCapacity(3.6e10);  // 10 MWh in Joules

// Calculate total renewable generation
solar.run();
wind.run();

double totalGeneration = solar.getPower() + wind.getPower();
System.out.println("Total renewable power: " + totalGeneration / 1e6 + " MW");

Capacity Constraints and Optimization

All four core power generation equipment types (GasTurbine, SteamTurbine, HRSG, CombinedCycleSystem) implement the CapacityConstrainedEquipment and AutoSizeable interfaces. This enables rated-capacity tracking, bottleneck detection, and integration with the plant-wide ProcessOptimizationEngine.

Interfaces

Interface Purpose
CapacityConstrainedEquipment Tracks operating point vs rated capacity, detects violations
AutoSizeable Sets rated capacity from current operating point with a safety factor

Setting Rated Capacity

Each equipment type has a rated capacity field that defines its design limit:

// Gas turbine — rated power
GasTurbine gt = new GasTurbine("GT-1", fuelStream);
gt.setRatedPower(30.0, "MW");  // 30 MW design rating

// Steam turbine — rated power
SteamTurbine st = new SteamTurbine("ST-1", steamStream);
st.setRatedPower(15.0, "MW");

// HRSG — design heat duty
HRSG hrsg = new HRSG("HRSG-1", gt.getOutletStream());
hrsg.setDesignHeatDuty(50.0, "MW");

// Combined cycle — rated total power
CombinedCycleSystem cc = new CombinedCycleSystem("CC-1", fuelStream);
cc.setRatedTotalPower(45.0, "MW");

Auto-Sizing

When design ratings are not known, auto-size from the current operating point:

// Run the process first to establish operating conditions
process.run();

// Auto-size with a 20% safety margin (factor = 1.2)
gt.autoSize(1.2);
st.autoSize(1.2);
hrsg.autoSize(1.2);
cc.autoSize(1.2);

// Check sizing results
System.out.println(gt.getSizingReport());
System.out.println(gt.isAutoSized());  // true

Querying Capacity

After running and setting rated capacity (manually or via auto-size), query the operating margin:

The registry’s PowerGenerationCapacityStrategy reports power and heat-duty capacities in kW. Its constraint design values and evaluateMaxCapacity(equipment) use the same equipment rating: getRatedPower("kW") for either turbine, getDesignHeatDuty("kW") for an HRSG, and getRatedTotalPower("kW") for a combined cycle. A positive equipment rating takes precedence over the strategy’s configured fallback (50,000 kW by default). Changing the equipment rating is reflected by subsequent calls to both strategy APIs. evaluateMaxCapacity reports the design rating; overload margins remain separate constraint limits. For example, a 25 MW turbine reports 25,000 kW through this strategy, while the equipment’s getCapacityMax() returns watts.

// Current operating duty vs maximum
double duty = gt.getCapacityDuty();  // current power output (W)
double max = gt.getCapacityMax();    // rated power (W)

// Utilization fraction (0-1, where 1.0 = at capacity)
double utilization = gt.getMaxUtilization();

// Check if any constraint is violated
boolean exceeded = gt.isCapacityExceeded();    // soft or hard limit
boolean hardTrip = gt.isHardLimitExceeded();   // hard limit only

// Get the most-loaded constraint
CapacityConstraint bottleneck = gt.getBottleneckConstraint();
if (bottleneck != null) {
    System.out.println(bottleneck.getName() + ": " + bottleneck.getUtilization());
}

// Iterate all constraints
for (Map.Entry<String, CapacityConstraint> entry :
        gt.getCapacityConstraints().entrySet()) {
    System.out.println(entry.getKey() + " -> " + entry.getValue().getUtilization());
}

Adding Custom Constraints

The built-in constraint (power or heat duty) covers the primary capacity limit. Add additional constraints for operational envelopes:

import neqsim.process.equipment.capacity.CapacityConstraint;

// Add an exhaust temperature limit to the gas turbine
gt.addCapacityConstraint(
    new CapacityConstraint("exhaustTemp", "C", CapacityConstraint.ConstraintType.HARD)
        .setDesignValue(550.0)
        .setMaxValue(600.0)
        .setWarningThreshold(0.90)
        .setDescription("Exhaust gas temperature limit")
        .setValueSupplier(() -> gt.getOutletStream().getTemperature("C")));

// Remove a constraint by name
gt.removeCapacityConstraint("exhaustTemp");

// Clear all constraints
gt.clearCapacityConstraints();

Integration with ProcessOptimizationEngine

The ProcessOptimizationEngine reads capacity constraints from all equipment in a ProcessSystem to find the plant-wide maximum throughput and identify bottlenecks.

Bottleneck Detection

import neqsim.process.util.optimizer.ProcessOptimizationEngine;

// Build a combined heat and power system
ProcessSystem chp = new ProcessSystem();
chp.add(fuelStream);
chp.add(gt);
chp.add(hrsg);
chp.run();

// Set rated capacities
gt.setRatedPower(30.0, "MW");
hrsg.setDesignHeatDuty(50.0, "MW");

// Evaluate constraints across the entire process
ProcessOptimizationEngine engine = new ProcessOptimizationEngine(chp);
ProcessOptimizationEngine.ConstraintReport report = engine.evaluateAllConstraints();

for (ProcessOptimizationEngine.EquipmentConstraintStatus status :
        report.getEquipmentStatuses()) {
    System.out.printf("%s %s: %.1f%% utilization%n",
        status.isWithinLimits() ? "OK" : "!!",
        status.getEquipmentName(),
        status.getMaxUtilization() * 100);
}

Maximum Throughput Optimization

Find how much fuel gas the system can handle before hitting a capacity limit:

ProcessOptimizationEngine.OptimizationResult result =
    engine.findMaximumThroughput(
        25.0,       // inlet pressure (bara)
        25.0,       // outlet pressure (bara — no compression)
        100.0,      // min fuel flow (kg/hr)
        10000.0     // max fuel flow (kg/hr)
    );

System.out.println("Max fuel rate: " + result.getOptimalFlowRate() + " kg/hr");
System.out.println("Bottleneck: " + result.getBottleneckEquipment());
System.out.println("Total power at max: " + result.getTotalPower() + " kW");

Capacity Utilization Summary

For a quick overview of all equipment headroom in the process:

Map<String, Double> utilization = chp.getCapacityUtilizationSummary();
for (Map.Entry<String, Double> entry : utilization.entrySet()) {
    System.out.printf("%-25s %.1f%%%n", entry.getKey(), entry.getValue() * 100);
}
// Example output:
// GT-1                      72.3%
// HRSG-1                    65.8%

Python (Jupyter) Example

from neqsim import jneqsim

# Create fuel gas
gas = jneqsim.thermo.system.SystemSrkEos(288.15, 25.0)
gas.addComponent("methane", 0.90)
gas.addComponent("ethane", 0.05)
gas.addComponent("propane", 0.03)
gas.addComponent("nitrogen", 0.02)
gas.setMixingRule("classic")

Stream = jneqsim.process.equipment.stream.Stream
GasTurbine = jneqsim.process.equipment.powergeneration.GasTurbine
HRSG = jneqsim.process.equipment.powergeneration.HRSG
ProcessSystem = jneqsim.process.processmodel.ProcessSystem

fuel = Stream("Fuel Gas", gas)
fuel.setFlowRate(1000.0, "kg/hr")

gt = GasTurbine("GT-1", fuel)
hrsg = HRSG("HRSG-1", gt.getOutletStream())
hrsg.setSteamPressure(40.0)

process = ProcessSystem()
process.add(fuel)
process.add(gt)
process.add(hrsg)
process.run()

# Auto-size with 20% margin
gt.autoSize(1.2)
hrsg.autoSize(1.2)

# Check utilization
print(f"GT utilization:   {gt.getMaxUtilization() * 100:.1f}%")
print(f"HRSG utilization: {hrsg.getMaxUtilization() * 100:.1f}%")
print(f"GT capacity exceeded: {gt.isCapacityExceeded()}")

# Sizing report
print(gt.getSizingReport())