Process Optimization in NeqSim - Overview
This document provides a high-level introduction to the process optimization capabilities in NeqSim, explaining how the different components relate to each other and when to use each one.
Table of Contents
- Quick Navigation
- Architecture Overview
- The Two Main Optimizers
- Full ProcessModel Optimization
- When to Use Which Optimizer
- Key Concepts
- Search Algorithms
- Python Usage via JPype
- Getting Started
- Complete Examples
- Related Documentation
Quick Navigation
| I want to… | Use this class | Documentation |
|---|---|---|
| Find maximum throughput for given pressures | ProcessOptimizationEngine |
Optimizer Plugin Architecture |
| Optimize arbitrary objectives with constraints | ProductionOptimizer |
Production Optimization Guide |
| Do multi-objective Pareto optimization | ProductionOptimizer.optimizePareto() |
Multi-Objective Optimization |
| Run batch parameter studies | BatchStudy |
Batch Studies |
| Generate and rank candidate flowsheets from feed/product targets | ProcessResearcher |
Process Researcher |
| Calculate flow rates for pressure boundaries | FlowRateOptimizer |
Flow Rate Optimization |
| Generate Eclipse lift curves (VFP tables) | EclipseVFPExporter |
Optimizer Plugin Architecture |
| Evaluate equipment constraints | ProcessConstraintEvaluator |
Capacity Constraint Framework |
| Integrate with external optimizers (SciPy, NLopt) | ProcessSimulationEvaluator |
External Optimizer Integration |
| Optimize full multi-area process models | ProcessModelSimulationEvaluator |
Use area-qualified ProcessAutomation addresses and installed CapacityConstraint limits |
| Ramp producers until a full facility reaches a bottleneck | ProcessModelThroughputOptimizer |
Use producer mappings, installed capacity tables, and exported case traces |
| Solve constrained NLP (equality + inequality) | SQPoptimizer |
SQP Optimizer |
| Calibrate model parameters to data | BatchParameterEstimator |
Data Reconciliation and Steady-State Detection |
| Load optimization config from YAML/JSON | ProductionOptimizationSpecLoader |
YAML Spec Format |
Getting Started
If you are new to process optimization in NeqSim, begin with:
This sequence covers base-run requirements, optimizer selection, and safe variable access through ProcessAutomation.
All Documentation Files
| Document | Purpose |
|---|---|
| This Document | High-level overview and when to use which optimizer |
| Optimization & Constraints Guide | COMPREHENSIVE: Complete guide to algorithms, constraint types, bottleneck analysis, practical examples |
| ProductionOptimizer Tutorial (Jupyter) | Interactive notebook: algorithms, single/multi-variable, Pareto, constraints |
| Python Optimization Tutorial (Jupyter) | Using SciPy/Python optimizers with NeqSim: constraints, Pareto, global opt |
| Optimizer Plugin Architecture | Equipment capacity strategies, ProcessOptimizationEngine API, VFP export |
| Production Optimization Guide | Complete examples for ProductionOptimizer with Java/Python |
| Practical Examples | Code samples for common optimization tasks |
| Process Researcher | Candidate flowsheet generation and ranking from feed/product specifications |
| Multi-Objective Optimization | Pareto fronts, weighted-sum, epsilon-constraint methods |
| Batch Studies | Parallel parameter sweeps and sensitivity analysis |
| Flow Rate Optimization | FlowRateOptimizer and lift curve tables |
| External Optimizer Integration | ProcessSimulationEvaluator and ProcessModelSimulationEvaluator for Python/SciPy integration |
| Getting Started | Step-by-step first optimization workflow for process models/systems |
| Optimizer Guide | Detailed API reference for all optimizer classes |
| SQP Optimizer | Sequential Quadratic Programming — constrained NLP with BFGS + active-set QP |
| Capacity Constraint Framework | Equipment constraints and bottleneck detection |
Architecture Overview
NeqSim provides three main levels of optimization capability:
┌─────────────────────────────────────────────────────────────────────────────┐
│ LEVEL 3: Application-Specific │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ ProductionOpt. │ │ BatchParameter │ │ EclipseVFP │ │
│ │ (max throughput) │ │ (model calibr.) │ │ (lift curves) │ │
│ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ │
└───────────┼──────────────────────────────────────────┼───────────────────────┘
│ │ │
┌───────────┼──────────────────────────────────────────┼───────────────────────┐
│ ▼ LEVEL 2: Unified Engine ▼ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ ProcessOptimizationEngine ││
│ │ • findMaximumThroughput() • evaluateAllConstraints() ││
│ │ • analyzeSensitivity() • generateLiftCurve() ││
│ │ • Search algorithms: Binary, Golden-Section, BFGS ││
│ └──────────────────────────────────┬──────────────────────────────────────┘│
└─────────────────────────────────────┼────────────────────────────────────────┘
│
┌─────────────────────────────────────┼────────────────────────────────────────┐
│ ▼ │
│ LEVEL 1: Equipment Constraint Layer │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ EquipmentCapacityStrategyRegistry (18 Built-in Strategies) ││
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ ││
│ │ │Compressor │ │ Separator │ │ Pump │ │ Reactor │ ││
│ │ │ Strategy │ │ Strategy │ │ Strategy │ │ Strategy │ + custom ││
│ │ │Pipe, Valve │ │ HX, Tank │ │ Expander │ │ PowerGen │ ││
│ │ │Mixer, Split│ │ Ejector │ │ Distill. │ │ Subsea,Well│ ││
│ │ └────────────┘ └────────────┘ └────────────┘ └────────────┘ ││
│ └─────────────────────────────────────────────────────────────────────────┘│
│ │ │
│ ┌─────────────────────────────────────────────────────────────────────────┐│
│ │ ProcessEquipmentBaseClass (Universal Constraint Storage) ││
│ │ All 144+ equipment types inherit: addCapacityConstraint(), ││
│ │ getMaxUtilization(), isCapacityExceeded(), getBottleneckConstraint() ││
│ └─────────────────────────────────────────────────────────────────────────┘│
└──────────────────────────────────────────────────────────────────────────────┘
The Two Main Optimizers
ProcessOptimizationEngine
Purpose: Find maximum throughput for given inlet/outlet pressure conditions while respecting equipment constraints.
Best for:
- Maximum throughput calculations
- Pressure-constrained optimization
- Lift curve generation
- Equipment bottleneck analysis
- Integration with ProcessSystem/ProcessModule
Key Features:
- Works directly with
ProcessSystemorProcessModule - Uses equipment capacity strategy plugins
- Supports multiple search algorithms (Binary, Golden-Section, BFGS)
- Auto-detects feed and outlet streams
- Generates sensitivity analysis
// ProcessOptimizationEngine - throughput-focused
ProcessOptimizationEngine engine = new ProcessOptimizationEngine(process);
// Find max throughput at given pressures
OptimizationResult result = engine.findMaximumThroughput(
50.0, // inlet pressure (bara)
10.0, // outlet pressure (bara)
1000.0, // min flow rate
100000.0 // max flow rate
);
System.out.println("Max flow: " + result.getOptimalValue() + " kg/hr");
System.out.println("Bottleneck: " + result.getBottleneck());
ProductionOptimizer
Purpose: General-purpose optimization with arbitrary objective functions, multiple decision variables, and user-defined constraints.
Best for:
- Custom objective functions (not just throughput)
- Multi-variable optimization
- Multi-objective Pareto optimization
- User-defined constraints
- Scenario evaluation and parallelization
Key Features:
- Arbitrary objective functions via lambdas/interfaces
- Multiple decision variables (
ManipulatedVariable) - Multiple search algorithms (Binary, Golden-Section, Nelder-Mead, PSO)
- Pareto multi-objective optimization
- Parallel scenario evaluation
- Works with any
ProcessSystem
// ProductionOptimizer - general-purpose
ProductionOptimizer optimizer = new ProductionOptimizer();
// Configure optimization
OptimizationConfig config = new OptimizationConfig(50000.0, 200000.0)
.tolerance(100.0)
.searchMode(SearchMode.GOLDEN_SECTION_SCORE)
.maxIterations(30);
// Define objectives
List<OptimizationObjective> objectives = Arrays.asList(
new OptimizationObjective("throughput",
proc -> proc.getUnit("outlet").getFlowRate("kg/hr"),
1.0, ObjectiveType.MAXIMIZE)
);
// Run optimization
OptimizationResult result = optimizer.optimize(process, feed, config, objectives, null);
System.out.println("Optimal rate: " + result.getOptimalRate() + " kg/hr");
When to Use Which Optimizer
| Scenario | Recommended | Why |
|---|---|---|
| “What’s the max flow at P_in=50, P_out=10?” | ProcessOptimizationEngine |
Designed exactly for this |
| “Find bottleneck equipment” | ProcessOptimizationEngine |
Has constraint evaluation built-in |
| “Generate Eclipse VFP tables” | ProcessOptimizationEngine |
Has EclipseVFPExporter integration |
| “Minimize operating cost” | ProductionOptimizer |
Custom objective function support |
| “Optimize pressure AND flow rate together” | ProductionOptimizer |
Multi-variable support |
| “Trade off throughput vs power consumption” | ProductionOptimizer.optimizePareto() |
Pareto multi-objective |
| “Increase several producers until the full facility reaches a bottleneck” | ProcessModelThroughputOptimizer |
Maps producers, loads installed capacities, and records the active bottleneck per case |
| “Evaluate 100 scenarios in parallel” | ProductionOptimizer |
Has parallel evaluation |
| “Calibrate model to match field data” | BatchParameterEstimator |
Levenberg-Marquardt for data fitting |
Full ProcessModel Optimization
Use ProcessModelThroughputOptimizer for large fixed-equipment studies such as increasing one or more producer feed rates until a separator, compressor, valve, heat exchanger, or export train reaches its installed capacity. It is the ergonomic layer for the common full-facility throughput-to-bottleneck task.
Use ProcessModelSimulationEvaluator directly when you need a lower-level black-box bridge to SciPy, NLopt, SQP, Pyomo, or another external optimizer.
The evaluator is deliberately a black-box bridge. It keeps the full plant model intact, lets external optimizers pass a vector of decision variables, runs ProcessModel.run(), and returns objective values, constraint margins, feasibility, and the active bottleneck.
| Requirement | Pattern |
|---|---|
| Producer controls | Use addProducer(...) with area-qualified addresses such as wells::feed.flowRate |
| Scenario-level multipliers | Use addProducerMultiplier(...) for variables not exposed by automation |
| Objective | Use setObjective(...), typically export gas, export oil, total sales rate, or power-normalized production |
| Installed equipment limits | Attach CapacityConstraint objects or load a CSV table with loadInstalledCapacities(...) |
| Search | Use findMaximumThroughput(lower, upper, tolerance) for scalar producer-ramp studies |
| Bottleneck reporting | Read getBestFeasibleCase(), getFirstInfeasibleCase(), and the case table rows |
The typical workflow is:
- Build each process area as a separate
ProcessSystemand compose them in aProcessModel. - Add installed capacity constraints to equipment whose sizes are fixed.
- Register producer feed rates or scenario multipliers as throughput controls.
- Register the objective, for example export gas flow, oil export rate, or total sales flow.
- Run
findMaximumThroughput(...)to bracket the first infeasible case and binary-search the maximum feasible multiplier. - Export the case table with
ProcessModelThroughputResult.exportToCSV(...)or serialize it withtoJson(). - Inspect the best feasible case, first infeasible case, and active bottleneck metadata for the recommended operating point.
The high-level API pattern below is covered by the focused unit test ProcessModelThroughputOptimizerTest.
ProcessModelThroughputOptimizer optimizer = new ProcessModelThroughputOptimizer(model);
optimizer.addProducer("feed", "wells::feed.flowRate", 1.0, 2.0, "kg/hr");
optimizer.setObjective("exportGas", new ToDoubleFunction<ProcessModel>() {
@Override
public double applyAsDouble(ProcessModel processModel) {
return processModel.getVariableValue("separation::separator.gasOutStream.flowRate", "kg/hr");
}
}, "kg/hr");
optimizer.loadInstalledCapacities("installed_capacity.csv");
ProcessModelThroughputResult result = optimizer.findMaximumThroughput(1.0, 2.0, 0.01);
ThroughputCaseRow best = result.getBestFeasibleCase();
ThroughputCaseRow firstLimit = result.getFirstInfeasibleCase();
result.exportToCSV("throughput_trace.csv");
Active bottleneck rows preserve limit provenance, evidence-quality confidence, the inclusive
scalar validity range, and whether the snapshotted current load is inside that range. Check
hasConfidence() and hasValidityRange() before reading numeric metadata. JSON uses null
for unset values; CSV retains explicit presence flags and blank unset-value cells. These fields are
diagnostics only and do not change feasibility or throughput search.
The installed-capacity table uses one row per equipment limit:
area,equipment,constraint,currentValueAddress,designValue,maxValue,unit,severity,enabled
separation,separator,installedGasCapacity,wells::feed.flowRate,15000,16500,kg/hr,HARD,true
For custom optimizers, use the underlying ProcessModelSimulationEvaluator. The API pattern below is covered by the focused unit test ProcessModelSimulationEvaluatorTest.
ProcessModelSimulationEvaluator evaluator = new ProcessModelSimulationEvaluator(model);
evaluator.addParameter("wells::feed.flowRate", 5000.0, 20000.0, "kg/hr");
evaluator.addObjective("exportGas", new ToDoubleFunction<ProcessModel>() {
@Override
public double applyAsDouble(ProcessModel processModel) {
return processModel.getVariableValue("separation::separator.gasOutStream.flowRate", "kg/hr");
}
}, ProcessModelSimulationEvaluator.ObjectiveDefinition.Direction.MAXIMIZE);
evaluator.addConstraintUpperBound("feedLimit", new ToDoubleFunction<ProcessModel>() {
@Override
public double applyAsDouble(ProcessModel processModel) {
return processModel.getVariableValue("wells::feed.flowRate", "kg/hr");
}
}, 15000.0);
evaluator.addEquipmentCapacityConstraints();
ProcessModelSimulationEvaluator.EvaluationResult result = evaluator.evaluate(new double[] {12000.0});
ProcessModelSimulationEvaluator.BottleneckStatus bottleneck = result.getActiveBottleneck();
List<ProcessModelSimulationEvaluator.BottleneckStatus> ranked =
result.getRankedCapacityConstraints();
Each successful evaluate(...) call retains every enabled model-level limit as an immutable,
descending-utilization snapshot in its EvaluationResult. The snapshot remains unchanged after
later evaluations, so a case history can reveal an emerging compressor, separator, pipeline,
utility, or export bottleneck before it becomes the leading constraint. ThroughputCaseRow
preserves the same list for every case generated by ProcessModelThroughputOptimizer; its JSON
representation includes rankedCapacityConstraints with engineering values and evidence metadata.
Use getEvidenceApplicability() to distinguish
WITHIN_VALIDITY_RANGE, OUTSIDE_VALIDITY_RANGE, and NOT_ASSESSED results. The engineering
order remains utilization-only: confidence is retained as evidence quality and is never converted
to a safety probability, feasibility adjustment, or ranking weight. Equal-utilization limits retain
model registration order, including the declared order of built-in strategy-generated limits, and
each dynamic limit supplier is sampled once per ranking call.
Enabled limits with undefined (NaN) utilization remain visible at the end for diagnosis.
Call rankCapacityConstraints(model) directly only when a ranking is needed outside an evaluator
run; it returns the same snapshot shape without adding a process simulation.
ProcessModelSimulationEvaluator complements rather than replaces the other optimizers. Use ProcessOptimizationEngine for compact throughput cases on one process, ProductionOptimizer for existing single-system objective workflows, and ProcessModelSimulationEvaluator when the optimization boundary is the full plant model.
Relationship Diagram
┌──────────────────────────────────────────────────────────────────────────────┐
│ USER CODE │
└─────────┬─────────────────────┬────────────────────────┬─────────────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────┐ ┌────────────────────┐ ┌─────────────────────────────┐
│ProcessOptimization │ │ ProductionOptimizer│ │ BatchParameterEstimator │
│Engine │ │ │ │ (model calibration) │
│ │ │• Custom objectives │ │ │
│• findMaxThroughput()│ │• Multi-variable │ │• Levenberg-Marquardt │
│• evaluateConstraint │ │• Pareto multi-obj │ │• Parameter fitting │
│• generateLiftCurve()│ │• Parallel eval │ │• Uncertainty quantification │
└──────────┬──────────┘ └─────────┬──────────┘ └──────────────────────────────┘
│ │
│ ┌─────────────────┘
│ │
▼ ▼
┌──────────────────────────────────────────┐
│ ProcessSystem │
│ (contains equipment, streams, recycles) │
│ │
│ process.run() → converged state │
│ process.getUnit("name") → equipment │
└────────────────┬─────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ Equipment Capacity Strategy Registry │
│ │
│ CompressorCapacityStrategy │
│ SeparatorCapacityStrategy │
│ PumpCapacityStrategy │
│ ... (extensible plugin system) │
└────────────────┬─────────────────────────┘
│
▼
┌──────────────────────────────────────────┐
│ CapacityConstraint │
│ │
│ • name, unit, type │
│ • designValue, maxValue │
│ • getUtilization() → 0.0 to 1.0+ │
│ • severity (HARD/SOFT) │
└──────────────────────────────────────────┘
Key Concepts
Equipment Capacity Constraints
Equipment constraints define operating limits. Each equipment type has a strategy that extracts constraints:
| Equipment | Typical Constraints |
|---|---|
| Compressor | Surge margin, max power, operating envelope, speed limits |
| Separator | Liquid level, residence time, gas/liquid capacity |
| Pump | NPSH margin, max power, flow limits |
| Pipe | Erosional velocity, pressure drop |
| Valve | Cv capacity, choke conditions |
⚠️ Important: Most equipment constraints are disabled by default for backward compatibility. The optimizer automatically falls back to traditional capacity methods (
getCapacityMax()/getCapacityDuty()) when no enabled constraints exist. To use multi-constraint capacity analysis, you must explicitly enable constraints:separator.useEquinorConstraints(); // Enable Equinor TR3500 constraints // OR separator.enableConstraints(); // Enable all constraintsSee Capacity Constraint Framework - Constraints Disabled by Default for details.
Utilization Ratio
The utilization ratio is the key metric:
\[\text{utilization} = \frac{\text{actual value}}{\text{design limit}}\]0.0= not used1.0= at design limit> 1.0= exceeds limit (constraint violation)
Bottleneck Detection
The bottleneck is the equipment with the highest utilization ratio:
String bottleneck = engine.findBottleneckEquipment();
// Returns equipment name with highest utilization
Search Algorithms
Both optimizers support multiple search algorithms:
| Algorithm | Best For | Convergence | Notes |
|---|---|---|---|
| Binary Search | Monotonic problems | Fast | Assumes feasibility is monotonic |
| Golden Section | Single variable, non-monotonic | Moderate | Robust, doesn’t require derivatives |
| Nelder-Mead | Multi-variable (2-10 vars) | Moderate | No gradients needed |
| PSO (Particle Swarm) | Global search, many local optima | Slow | Good for non-convex problems |
| Gradient Descent | Smooth multi-variable (5-20+) | Fast | New (Jan 2026) - Finite-difference gradients |
| BFGS | Smooth functions | Fast | Requires gradient approximation |
For full multi-area ProcessModel studies, ProcessModelSimulationEvaluator keeps forward
differences as the low-cost default and also exposes FiniteDifferenceMethod.CENTRAL. Both methods
strictly honor parameter bounds and divide by the actual applied perturbation. Central differences
use a symmetric stencil at interior points and a one-sided fallback at an active bound. Verify
step-size stability before interpreting a local derivative as debottlenecking sensitivity or
shadow-value evidence. estimateSensitivitiesWithQuality(...) automates one step-halving check,
returns the fine-step objective gradient and constraint-margin Jacobian, and records the actual
stencil, applied steps, convergence, hard-constraint feasibility, and evaluation errors for every
perturbation. Callers select the acceptable relative-disagreement tolerance and must still check
nearby points and active equipment/control regimes. Its immutable parameter, selected-objective,
and constraint snapshots bind every derivative column and row to names, addresses, units,
directions or types, bounds, hard/soft semantics, capacity origin, and the sampled base values and
margins. This avoids joining archived matrices back to mutable evaluator definitions. The
snapshots preserve raw units; normalize only with declared engineering scales before comparing
unlike constraints.
ProcessOptimizationEngine Algorithms
engine.setSearchAlgorithm(SearchAlgorithm.GOLDEN_SECTION);
engine.setSearchAlgorithm(SearchAlgorithm.BFGS);
engine.setSearchAlgorithm(SearchAlgorithm.GRADIENT_ACCELERATED);
ProductionOptimizer Algorithms
config.searchMode(SearchMode.BINARY_FEASIBILITY);
config.searchMode(SearchMode.GOLDEN_SECTION_SCORE);
config.searchMode(SearchMode.NELDER_MEAD_SCORE);
config.searchMode(SearchMode.PARTICLE_SWARM_SCORE);
config.searchMode(SearchMode.GRADIENT_DESCENT_SCORE); // New (Jan 2026)
January 2026 Update: ProductionOptimizer now includes
GRADIENT_DESCENT_SCOREalgorithm, configuration validation, stagnation detection, warm start, bounded LRU cache, and infeasibility diagnostics. See Production Optimization Guide for details.
Python Usage via JPype
Both optimizers work seamlessly from Python using neqsim-python:
ProcessOptimizationEngine from Python
from neqsim.neqsimpython import jneqsim
# Get classes
ProcessOptimizationEngine = jneqsim.process.util.optimizer.ProcessOptimizationEngine
SearchAlgorithm = ProcessOptimizationEngine.SearchAlgorithm
# Create and configure
engine = ProcessOptimizationEngine(process)
engine.setSearchAlgorithm(SearchAlgorithm.GOLDEN_SECTION)
# Find max throughput
result = engine.findMaximumThroughput(50.0, 10.0, 1000.0, 100000.0)
print(f"Max flow: {result.getOptimalValue():.0f} kg/hr")
print(f"Bottleneck: {result.getBottleneck()}")
ProductionOptimizer from Python
from neqsim.neqsimpython import jneqsim
from jpype import JImplements, JOverride
# Get classes
ProductionOptimizer = jneqsim.process.util.optimizer.ProductionOptimizer
OptimizationConfig = ProductionOptimizer.OptimizationConfig
OptimizationObjective = ProductionOptimizer.OptimizationObjective
SearchMode = ProductionOptimizer.SearchMode
# Define objective function as Java interface
@JImplements("java.util.function.ToDoubleFunction")
class ThroughputObjective:
@JOverride
def applyAsDouble(self, proc):
return proc.getUnit("outlet").getFlowRate("kg/hr")
# Configure and run
optimizer = ProductionOptimizer()
config = OptimizationConfig(50000.0, 200000.0) \
.tolerance(100.0) \
.searchMode(SearchMode.GOLDEN_SECTION_SCORE)
objectives = [
OptimizationObjective("throughput", ThroughputObjective(), 1.0)
]
result = optimizer.optimize(process, feed, config, objectives, None)
print(f"Optimal rate: {result.getOptimalRate():.0f} kg/hr")
Complete Examples
Example 1: Find Maximum Compressor Throughput
import neqsim.process.util.optimizer.ProcessOptimizationEngine;
import neqsim.process.processmodel.ProcessSystem;
import neqsim.thermo.system.SystemSrkEos;
// Create gas system
SystemInterface gas = new SystemSrkEos(288.15, 50.0);
gas.addComponent("methane", 0.9);
gas.addComponent("ethane", 0.1);
gas.setMixingRule("classic");
// Build process
Stream feed = new Stream("feed", gas);
feed.setFlowRate(50000, "kg/hr");
feed.setPressure(50.0, "bara");
Compressor compressor = new Compressor("comp", feed);
compressor.setOutletPressure(100.0);
ProcessSystem process = new ProcessSystem();
process.add(feed);
process.add(compressor);
process.run();
// Find maximum throughput
ProcessOptimizationEngine engine = new ProcessOptimizationEngine(process);
engine.setFeedStreamName("feed");
engine.setSearchAlgorithm(SearchAlgorithm.GOLDEN_SECTION);
OptimizationResult result = engine.findMaximumThroughput(
50.0, // inlet pressure
100.0, // outlet pressure
10000.0, // min flow
200000.0 // max flow
);
System.out.println("Maximum throughput: " + result.getOptimalValue() + " kg/hr");
System.out.println("Limited by: " + result.getBottleneck());
Example 2: Multi-Objective Pareto Optimization
import neqsim.process.util.optimizer.ProductionOptimizer;
import neqsim.process.util.optimizer.ProductionOptimizer.*;
ProductionOptimizer optimizer = new ProductionOptimizer();
// Define competing objectives
List<OptimizationObjective> objectives = Arrays.asList(
new OptimizationObjective("throughput",
proc -> proc.getUnit("outlet").getFlowRate("kg/hr"),
1.0, ObjectiveType.MAXIMIZE),
new OptimizationObjective("power",
proc -> ((Compressor) proc.getUnit("comp")).getPower("kW"),
1.0, ObjectiveType.MINIMIZE)
);
// Configure Pareto optimization
OptimizationConfig config = new OptimizationConfig(50000.0, 200000.0)
.paretoGridSize(20) // 20 weight combinations
.tolerance(100.0);
// Generate Pareto front
ParetoResult pareto = optimizer.optimizePareto(process, feed, config, objectives);
System.out.println("Pareto front has " + pareto.getPoints().size() + " solutions");
for (ParetoPoint point : pareto.getPoints()) {
System.out.printf("Flow: %.0f kg/hr, Power: %.0f kW%n",
point.getObjectives().get("throughput"),
point.getObjectives().get("power"));
}
YAML Specification Files
The ProductionOptimizationSpecLoader class allows loading optimization scenarios from YAML or JSON files, enabling configuration-driven optimization workflows.
YAML Format
scenarios:
- name: "MaxThroughput"
process: "myProcess" # Key in processes map
feedStream: "wellFeed" # Key in feeds map
lowerBound: 50000.0
upperBound: 200000.0
rateUnit: "kg/hr"
tolerance: 100.0
maxIterations: 30
searchMode: "GOLDEN_SECTION_SCORE"
utilizationMarginFraction: 0.05
objectives:
- name: "throughput"
weight: 1.0
type: "MAXIMIZE"
metric: "throughputMetric" # Key in metrics map
constraints:
- name: "maxPower"
metric: "powerMetric"
limit: 5000.0
direction: "LESS_THAN"
severity: "HARD"
description: "Compressor power limit"
Loading YAML Specs in Java
import neqsim.process.util.optimizer.ProductionOptimizationSpecLoader;
// Create registries mapping spec keys to objects
Map<String, ProcessSystem> processes = new HashMap<>();
processes.put("myProcess", process);
Map<String, StreamInterface> feeds = new HashMap<>();
feeds.put("wellFeed", feed);
Map<String, ToDoubleFunction<ProcessSystem>> metrics = new HashMap<>();
metrics.put("throughputMetric", p -> p.getUnit("outlet").getFlowRate("kg/hr"));
metrics.put("powerMetric", p -> ((Compressor) p.getUnit("comp")).getPower("kW"));
// Load scenarios from YAML
List<ScenarioRequest> scenarios = ProductionOptimizationSpecLoader.load(
Paths.get("optimization.yaml"), processes, feeds, metrics);
// Run each scenario
ProductionOptimizer optimizer = new ProductionOptimizer();
for (ScenarioRequest scenario : scenarios) {
OptimizationResult result = optimizer.optimizeScenario(scenario);
System.out.println(scenario.getName() + ": " + result.getOptimalRate());
}
Class Summary
| Class | Purpose | Key Method | Documentation |
|---|---|---|---|
ProcessOptimizationEngine |
Throughput-focused optimization | findMaximumThroughput() |
Plugin Architecture |
ProductionOptimizer |
General-purpose optimization | optimize(), optimizePareto() |
Production Guide |
FlowRateOptimizer |
Flow rate for pressure boundaries | findMaxFlowRate() |
Flow Rate Optimization |
MultiObjectiveOptimizer |
Pareto front generation | optimize() |
Multi-Objective |
BatchStudy |
Parallel parameter sweeps | run() |
Batch Studies |
ProcessConstraintEvaluator |
Constraint evaluation | evaluate() |
Capacity Framework |
ProcessSimulationEvaluator |
External optimizer interface | evaluate() |
External Integration |
ProcessModelSimulationEvaluator |
External optimizer interface for multi-area ProcessModel studies |
evaluate() |
External Integration |
ProcessModelThroughputOptimizer |
Full-model throughput-to-bottleneck study helper | findMaximumThroughput() |
External Integration |
InstalledCapacityTableLoader |
Attach fixed equipment limits from CSV | load() |
Capacity Framework |
EclipseVFPExporter |
Eclipse VFP tables | exportVFPPROD() |
Plugin Architecture |
LiftCurveGenerator |
Lift curve tables | generateLiftCurve() |
Flow Rate Optimization |
BatchParameterEstimator |
Model calibration | solve() |
Data Reconciliation and Steady-State Detection |
ProductionOptimizationSpecLoader |
YAML/JSON config loading | load() |
YAML Format |
Decision Guide
Choose based on your use case:
- Max throughput at pressures →
ProcessOptimizationEngine - Custom objectives/multi-variable →
ProductionOptimizer - Full
ProcessModelwith several process areas and producer ramping →ProcessModelThroughputOptimizer - Full
ProcessModelcustom external optimization →ProcessModelSimulationEvaluator - Model calibration →
BatchParameterEstimator