| name | neqsim-reaction-engineering |
| description | Reaction engineering patterns for NeqSim. USE WHEN: modeling chemical reactors (equilibrium, kinetic, CSTR, PFR), setting up reaction systems, analyzing conversion/selectivity, or designing reactor networks. Covers GibbsReactor (equilibrium), PlugFlowReactor (kinetic PFR), StirredTankReactor (CSTR), KineticReaction setup, and CatalystBed configuration. |
| last_verified | 2026-07-04 |
Reaction Engineering Patterns
Guide for chemical reactor modeling in NeqSim using the reactor equipment classes.
Reactor Type Selection
| Reactor Type | NeqSim Class | When to Use |
|---|
| Equilibrium | GibbsReactor | High-T reactions approaching equilibrium (reforming, combustion, water-gas shift) |
| Plug Flow (PFR) | PlugFlowReactor | Tubular reactors with axial kinetics, catalytic fixed beds |
| Stirred Tank (CSTR) | StirredTankReactor | Perfectly mixed, steady-state with kinetics |
| Stoichiometric | StoichiometricReaction | Known fixed conversion, simple mass balance |
| CO2-specific equilibrium | GibbsReactorCO2 | CO2 capture reactions with optimized convergence |
| Fermenter | Fermenter | Bio-reactions, enzymatic processes |
Equilibrium Reactor (GibbsReactor)
Best for high-temperature reactions where equilibrium is reached.
Setup Pattern
import neqsim.process.equipment.reactor.GibbsReactor;
import neqsim.process.equipment.stream.Stream;
import neqsim.thermo.system.SystemSrkEos;
SystemInterface fluid = new SystemSrkEos(273.15 + 800.0, 30.0);
fluid.addComponent("methane", 1.0);
fluid.addComponent("water", 3.0);
fluid.addComponent("hydrogen", 0.0001);
fluid.addComponent("CO", 0.0001);
fluid.addComponent("CO2", 0.0001);
fluid.setMixingRule("classic");
Stream feed = new Stream("feed", fluid);
feed.setFlowRate(1000.0, "kg/hr");
GibbsReactor reactor = new GibbsReactor("SMR Reactor", feed);
reactor.setEnergyMode(GibbsReactor.EnergyMode.ISOTHERMAL);
reactor.setMaxIterations(5000);
reactor.setConvergenceTolerance(1e-8);
reactor.addInertComponent("nitrogen");
reactor.run();
if (reactor.hasConverged()) {
Stream (Stream) reactor.getOutletStream();
reactor.getComponentConversion();
reactor.getMassBalanceError();
}
Adiabatic Mode
reactor.setEnergyMode(GibbsReactor.EnergyMode.ADIABATIC);
reactor.run();
double outletTemp = reactor.getOutletStream().getTemperature() - 273.15;
double heatOfReaction = reactor.getEnthalpyOfReactions();
Kinetic PFR (PlugFlowReactor)
For reactions with known kinetics and axial profiles.
Define Reactions
import neqsim.process.equipment.reactor.KineticReaction;
import neqsim.process.equipment.reactor.CatalystBed;
import neqsim.process.equipment.reactor.PlugFlowReactor;
KineticReaction smr = new KineticReaction("Steam Methane Reforming");
smr.addReactant("methane", 1, 1.0);
smr.addReactant("water", 1, 0.5);
smr.addProduct("CO", 1);
smr.addProduct("hydrogen", 3);
smr.setPreExponentialFactor(1.17e15);
smr.setActivationEnergy(240100.0);
smr.setHeatOfReaction(206000.0);
smr.setReactionType(KineticReaction.ReactionType.POWER_LAW);
Configure Catalyst
CatalystBed catalyst = new CatalystBed();
catalyst.setParticleDiameter(3.0, "mm");
catalyst.setVoidFraction(0.40);
catalyst.setBulkDensity(800.0);
catalyst.setCatalystDensity(2100.0);
catalyst.setTortuosity(3.5);
catalyst.setSpecificSurfaceArea(50.0);
Build and Run PFR
PlugFlowReactor pfr = new PlugFlowReactor("PFR-1", feedStream);
pfr.addReaction(smr);
pfr.setCatalystBed(catalyst);
pfr.setLength(5.0, "m");
pfr.setDiameter(0.5, "m");
pfr.setNumberOfIncrements(200);
pfr.setIntegrationMethod(PlugFlowReactor.IntegrationMethod.RK4);
pfr.setEnergyMode(PlugFlowReactor.EnergyMode.ADIABATIC);
pfr.run();
double[] positions = pfr.getAxialPositions();
double[] temperatures = pfr.getTemperatureProfile();
double[] conversions = pfr.getConversionProfile("methane");
double[] pressures = pfr.getPressureProfile();
Cooled PFR with External Heat Exchange
pfr.setEnergyMode(PlugFlowReactor.EnergyMode.COOLANT);
pfr.setCoolantTemperature(273.15 + 300.0);
pfr.setOverallHeatTransferCoefficient(150.0);
CSTR (StirredTankReactor)
For perfectly mixed continuous reactors.
import neqsim.process.equipment.reactor.StirredTankReactor;
StirredTankReactor cstr = new StirredTankReactor("CSTR-1", feedStream);
cstr.addReaction(reaction);
cstr.setVolume(10.0);
cstr.run();
double outletConcentration = cstr.getOutletStream()
.getFluid().getComponent("product").getx();
Stoichiometric Reactor
For known conversions without kinetics.
import neqsim.process.equipment.reactor.StoichiometricReaction;
StoichiometricReaction reactor = new StoichiometricReaction("fixed-conv", feed);
reactor.run();
Process Integration with Reactors
ProcessSystem process = new ProcessSystem();
Stream feed = new Stream("feed", fluid);
feed.setFlowRate(5000.0, "kg/hr");
process.add(feed);
Heater preheater = new Heater("preheat", feed);
preheater.setOutTemperature(273.15 + 800.0);
process.add(preheater);
GibbsReactor reactor = new GibbsReactor("reactor", preheater.getOutletStream());
reactor.setEnergyMode(GibbsReactor.EnergyMode.ISOTHERMAL);
process.add(reactor);
Cooler cooler = new Cooler("cool", reactor.getOutletStream());
cooler.setOutTemperature(273.15 + 40.0);
process.add(cooler);
Separator sep = new Separator("flash", cooler.getOutletStream());
process.add(sep);
process.run();
Key Analysis Metrics
| Metric | How to Calculate |
|---|
| Conversion | reactor.getComponentConversion("methane") |
| Mass balance error | reactor.getMassBalanceError() |
| Heat of reaction | reactor.getEnthalpyOfReactions() |
| Outlet temperature | reactor.getOutletStream().getTemperature() - 273.15 |
| Convergence | reactor.hasConverged() |
Common Pitfalls
- Products must be in feed: For GibbsReactor, add trace amounts (1e-4) of expected products
- Missing inerts: Always mark inert components with
addInertComponent()
- Convergence: Increase
setMaxIterations() and decrease setConvergenceTolerance() for difficult systems
- Damping: Use
setDampingComposition(0.01) for oscillating systems
- Energy mode: Choose ISOTHERMAL vs ADIABATIC based on the physical reactor — wrong choice gives wrong results
- Unit consistency: Activation energy in J/mol, heat of reaction in J/mol
Bioprocessing Reactors
NeqSim includes specialized bioreactors beyond the generic StirredTankReactor/Fermenter.
AnaerobicDigester
Substrate-specific biogas production from organic waste. Not a flash-based reactor — uses empirical biogas yield models.
AnaerobicDigester digester = new AnaerobicDigester("AD-1", feedStream);
digester.setSubstrateType(AnaerobicDigester.SubstrateType.FOOD_WASTE);
digester.setDigesterTemperature(37.0, "C");
digester.setFeedRate(10000.0, 0.25);
digester.setVesselVolume(6000.0);
digester.run();
FermentationReactor
Extends Fermenter with kinetic models and operation modes.
FermentationReactor reactor = new FermentationReactor("FR-1", sugarFeed);
reactor.setKineticModel(FermentationReactor.KineticModel.MONOD);
reactor.setOperationMode(FermentationReactor.OperationMode.CONTINUOUS);
reactor.setSubstrateConcentration(100.0);
reactor.setBiomassConcentration(1.0);
reactor.setMaxSpecificGrowthRate(0.30);
reactor.setMonodConstant(1.0);
reactor.setYieldBiomass(0.10);
reactor.setYieldProduct(0.45);
reactor.setResidenceTime(10.0, "hr");
reactor.run();
Map<String, Object> results = reactor.getResults();
BiogasUpgrader
Splits biogas into biomethane + offgas using technology-specific split factors.
BiogasUpgrader upgrader = new BiogasUpgrader("BGU-1", biogasStream);
upgrader.setTechnology(BiogasUpgrader.UpgradingTechnology.MEMBRANE);
upgrader.run();
Pre-built Biorefinery Modules
| Module | Purpose | Key Methods |
|---|
BiogasToGridModule | AD → upgrading → compression → grid | setGridPressureBara(), setGridTemperatureC(), getResults() |
GasificationSynthesisModule | Biomass → syngas → FT liquids | setBiomass(BiomassCharacterization, kgPerHr) |
WasteToEnergyCHPModule | AD → gas engine CHP | setElectricalEfficiency(), getElectricalPowerKW(), getHeatOutputKW() |
SustainabilityMetrics
Utility class for CO₂-equivalent tracking and LCA:
SustainabilityMetrics metrics = new SustainabilityMetrics();
metrics.setBiogasProductionNm3PerYear(3_000_000.0);
metrics.setMethaneContentFraction(0.60);
metrics.setMethaneSlipPercent(1.5);
metrics.setElectricityProductionMWhPerYear(8000.0);
metrics.setHeatProductionMWhPerYear(10000.0);
metrics.setParasiticElectricityMWhPerYear(800.0);
metrics.setFossilReferenceEmissionFactor(0.450);
metrics.setFossilHeatEmissionFactor(0.250);
metrics.calculate();
Uncontrolled and self-sustaining reactions
Two distinct escalation questions sit outside the reactor classes above, and the
choice between them depends on whether heat loss is spatially resolved:
| Question | Model | Class |
|---|
| A charged batch reacts adiabatically — how hot does it get, and how long until maximum rate? | Lumped adiabatic (MTSR, dT_ad, TMR_ad) | neqsim.process.safety.reaction.RunawayReactionAnalyzer |
| A material generates heat throughout its volume and conducts it to a boundary — will it self-ignite, at what size and after how long? | Frank-Kamenetskii / Semenov criticality | neqsim.process.safety.selfheating |
RunawayReactionAnalyzer assumes a well-stirred mass with no spatial
conduction, so it has no concept of a critical thickness or a critical ambient
temperature. Do not use it to assess spontaneous ignition of a combustible liquid
absorbed into porous insulation (a lagging fire) — see
neqsim-self-heating-ignition.
Note also that KineticReaction and GibbsReactor are complementary but not
interchangeable for ignition questions: equilibrium will report complete oxidation
of any hydrocarbon at ambient temperature, which says nothing about whether the
reaction proceeds at a measurable rate. Ignition is always a kinetic question.