Documentation for recycle handling in NeqSim process simulation.
Table of Contents
Overview
Location: neqsim.process.equipment.util
Classes:
| Class | Description |
|——-|————-|
| Recycle | Main recycle handler |
| RecycleController | Advanced recycle control |
| AccelerationMethod | Convergence acceleration |
| BroydenAccelerator | Broyden’s method acceleration |
Recycles handle iterative loops in process flowsheets where a downstream stream feeds back into an upstream unit. Common examples:
- Solvent recycle in absorption
- Reactor recycle for conversion
- Distillation reflux
- Heat integration loops
Recycle Class
Basic Usage
import neqsim.process.equipment.util.Recycle;
// Create recycle
Recycle recycle = new Recycle("Solvent Recycle");
// Add the stream coming from downstream
recycle.addStream(returnStream);
// Set where the recycle feeds into
recycle.setOutletStream(feedMixer);
// Add to process
process.add(recycle);
process.run();
How Recycles Work
- Initial Estimate: Process runs with assumed recycle composition
- Calculate Downstream: Equipment processes the estimate
- Update Recycle: New recycle stream values are calculated
- Iterate: Repeat until convergence
Steady-to-Dynamic Handoff
Use the same Recycle object for the converged steady state and the following
transient. In steady state, ProcessSystem iterates the tear stream with the
configured direct-substitution, Wegstein, or Broyden method. In transient mode,
the previously accepted recycle outlet is consumed upstream before the current
recycle inlet is published for the next flowsheet evaluation. This ordered
dependency break avoids introducing a separate transient recycle class.
process.run();
if (!recycle.solved()) {
throw new IllegalStateException("Initial recycle did not converge");
}
recycle.setCalculateSteadyState(false);
process.runTransient(0.25, UUID.randomUUID());
The transient update temporarily uses direct substitution and restores the configured steady-state acceleration method afterward. It does not iterate the recycle loop to steady convergence inside each physical timestep and does not add independent material inventory. Equipment such as separators, piping, and volumes owns the differential state.
ProcessSystem detects Recycle and RecycleFlowCoordinator units and falls
back to insertion-order sequential transient execution when required, even if
parallel transient execution is enabled. A pressure-driven anti-surge topology
can use RecycleFlowCoordinator to reconcile a valve-requested recycle flow
with its discharge splitter while preserving mass balance.
Configuration
Tolerance
// Set convergence tolerance
recycle.setTolerance(1e-6);
// Separate tolerances for flow and composition
recycle.setFlowTolerance(1e-4);
recycle.setCompositionTolerance(1e-6);
recycle.setTemperatureTolerance(0.1); // K
recycle.setPressureTolerance(0.01); // bar
setFlowTolerance() retains its legacy units: kg/s below 1 kg/s loop
flow and percent at or above 1 kg/s. For example, the default 0.01 permits
0.01 kg/s change on a 0.02 kg/s loop, which is 50% of that loop flow. Choose a
smaller flow tolerance for small loops.
getAbsoluteFlowChange() always reports kg/hr. setAbsoluteFlowTolerance()
adds an OR acceptance criterion: it can relax the legacy criterion, but it
cannot make a loose legacy tolerance stricter. Tighten setFlowTolerance()
first when an absolute limit should govern convergence.
Maximum Iterations
// Limit iterations
recycle.setMaximumIterations(50);
Damping
Damping helps prevent oscillation:
// Set damping factor (0-1, lower = more damping)
recycle.setDampingFactor(0.5); // 50% of new value, 50% of old
Acceleration Methods
For faster convergence, acceleration methods can be used:
Wegstein Acceleration
import neqsim.process.equipment.util.AccelerationMethod;
recycle.setAccelerationMethod(AccelerationMethod.WEGSTEIN);
Broyden Acceleration
import neqsim.process.equipment.util.BroydenAccelerator;
BroydenAccelerator accelerator = new BroydenAccelerator();
recycle.setAccelerationMethod(accelerator);
The accelerator solves the fixed-point residual g(x) - x with a damped
inverse-Jacobian step. It uses direct substitution for its first two calls;
the first Broyden step is taken on the third call. Monitor convergence on a
representative process before using this option for a difficult recycle.
A Recycle requires a configured tear outlet before run(); wire an existing
stream using setOutletStream(stream). If missing, run() reports the recycle
name and the required configuration. Before wiring, getOutletStream() returns
null so process modules can inspect the connection without running the recycle.
Composition acceleration and diagnostics
Per-recycle Wegstein and Broyden acceleration operates on overall component mole fractions. Temperature, pressure and total molar flow use the current return stream values. The accelerated composition updates component inventories and is TP-flashed before publication; the gas and liquid phases retain distinct equilibrium compositions. Negative proposals are clipped and normalized; an invalid proposal or failed flash falls back to the unaccelerated return.
The composition convergence residual compares overall mole fractions before acceleration. This prevents a damped or clipped step from reporting a false converged state. A changed component list resets the acceleration history.
getCompositionWegsteinQFactors() returns one factor per component.
getWegsteinQFactors() preserves the 3 + n layout, with three reserved zeros
for the unaccelerated T/P/flow entries followed by the composition factors.
Factors describe the proposal before clipping and normalization. The per-recycle
Broyden matrix contains only the n composition coordinates. See the
acceleration guide
for coordinate definitions and compatibility guidance.
Direct Substitution
Simple successive substitution (default):
recycle.setAccelerationMethod("direct");
Usage Examples
Simple Solvent Recycle
ProcessSystem process = new ProcessSystem();
// Feed stream
Stream feed = new Stream("Feed", feedFluid);
process.add(feed);
// Mixer for feed and recycle
Mixer mixer = new Mixer("Feed Mixer");
mixer.addStream(feed);
process.add(mixer);
// Process unit (e.g., absorber)
Absorber absorber = new Absorber("TEG Contactor", mixer.getOutletStream());
process.add(absorber);
// Regeneration
Heater regenerator = new Heater("TEG Regenerator", absorber.getLiquidOutStream());
regenerator.setOutTemperature(200.0, "C");
process.add(regenerator);
// Cooler
Cooler cooler = new Cooler("TEG Cooler", regenerator.getOutletStream());
cooler.setOutTemperature(40.0, "C");
process.add(cooler);
// Recycle lean solvent back to mixer
Recycle solventRecycle = new Recycle("TEG Recycle");
solventRecycle.addStream(cooler.getOutletStream());
solventRecycle.setOutletStream(mixer);
solventRecycle.setTolerance(1e-5);
process.add(solventRecycle);
// Connect mixer to absorber with recycle
mixer.addStream(solventRecycle.getOutletStream());
// Run
process.run();
// Check convergence
if (solventRecycle.isConverged()) {
System.out.println("Recycle converged in " +
solventRecycle.getIterations() + " iterations");
}
Reactor Recycle
// Fresh feed
Stream freshFeed = new Stream("Fresh Feed", freshFeedFluid);
process.add(freshFeed);
// Mix fresh feed with recycle
Mixer reactorFeed = new Mixer("Reactor Feed");
reactorFeed.addStream(freshFeed);
process.add(reactorFeed);
// Reactor
GibbsReactor reactor = new GibbsReactor("Synthesis Reactor");
reactor.setInletStream(reactorFeed.getOutletStream());
process.add(reactor);
// Separator
Separator productSep = new Separator("Product Separator", reactor.getOutletStream());
process.add(productSep);
// Recycle unreacted gas
Recycle gasRecycle = new Recycle("Unreacted Gas Recycle");
gasRecycle.addStream(productSep.getGasOutStream());
gasRecycle.setOutletStream(reactorFeed);
gasRecycle.setTolerance(1e-5);
gasRecycle.setDampingFactor(0.7);
process.add(gasRecycle);
reactorFeed.addStream(gasRecycle.getOutletStream());
process.run();
Nested Recycles
For processes with multiple recycle loops:
// Outer recycle (converges first)
Recycle outerRecycle = new Recycle("Outer Recycle");
outerRecycle.addStream(outerStream);
outerRecycle.setOutletStream(outerMixer);
outerRecycle.setPriority(1); // Lower priority converges first
process.add(outerRecycle);
// Inner recycle (converges second)
Recycle innerRecycle = new Recycle("Inner Recycle");
innerRecycle.addStream(innerStream);
innerRecycle.setOutletStream(innerMixer);
innerRecycle.setPriority(2); // Higher priority
process.add(innerRecycle);
Convergence Monitoring
Check Status
// Check if converged
boolean converged = recycle.isConverged();
// Get number of iterations
int iterations = recycle.getIterations();
// Get current error
double error = recycle.getError();
System.out.println("Recycle status:");
System.out.println(" Converged: " + converged);
System.out.println(" Iterations: " + iterations);
System.out.println(" Error: " + error);
Convergence History
// Get convergence history for debugging
double[] errorHistory = recycle.getErrorHistory();
for (int i = 0; i < errorHistory.length; i++) {
System.out.println("Iteration " + i + ": error = " + errorHistory[i]);
}
Troubleshooting
Slow Convergence
- Reduce damping factor
- Use acceleration method
- Check for conflicting specifications
- Improve initial estimate
// Try Wegstein acceleration
recycle.setAccelerationMethod(AccelerationMethod.WEGSTEIN);
recycle.setDampingFactor(0.8);
Oscillation
- Increase damping
- Reduce step size
- Check for multiple solutions
// Heavy damping for oscillating systems
recycle.setDampingFactor(0.3);
recycle.setMaximumIterations(100);
Non-Convergence
- Check physical feasibility
- Verify mass balance closure
- Start with simpler configuration
- Check stream specifications
// Debug mode
recycle.setVerbose(true);
process.run();
Best Practices
- Tear Stream Selection: Choose streams with least impact on downstream
- Good Initial Estimate: Provide reasonable starting values
- Appropriate Tolerance: Balance accuracy vs. computation time
- Monitor Convergence: Check iteration count and error trends
- Sequential Solution: For nested loops, converge inner loops first
Related Documentation
- Adjusters - Variable adjustment
- Calculators - Custom calculations
- Process System - Process execution