NeqSim Design Framework
The Design Framework provides an integrated workflow for automated equipment sizing, process template-based design, and production optimization. This document describes the key components and usage patterns.
Compatibility
The typed process-design additions retain the legacy public source entry points, so callers can migrate incrementally. They are not a promise of identical behavior: validation-only optimizer runs no longer report false convergence, configured mechanical-design objects are preserved, invalid or ambiguous engineering inputs fail earlier, and corrected standard editions/applicability can change selection results. Java object deserialization across NeqSim versions is not part of this compatibility contract.
See Migrate process design to typed standard kernels for the complete compatibility boundary and staged migration path.
Related Documentation
| Document | Description |
|---|---|
| PRODUCTION_OPTIMIZATION_GUIDE.md | Production optimization examples |
| CAPACITY_CONSTRAINT_FRAMEWORK.md | Multi-constraint equipment framework |
| process_design_guide.md | Complete process design workflow |
| mechanical_design.md | Mechanical design integration |
Overview
The design framework consists of several integrated components:
| Component | Purpose |
|---|---|
AutoSizeable |
Interface for equipment that can auto-size based on flow |
DesignSpecification |
Builder class for equipment configuration |
ProcessTemplate |
Interface for reusable process templates |
ProcessBasis |
Design basis with feed conditions and constraints |
EquipmentConstraintRegistry |
Registry of default constraint templates |
DesignOptimizer |
Integrated design-to-optimization workflow |
DesignResult |
Container for optimization results |
EquipmentDesignKernel |
Readiness-gated, standard-specific calculation adapter |
Standard-specific equipment calculations are registered explicitly. The current registry exposes screening kernels for API 617 compressor-casing checks, API 610 pump checks, API 521 relief-scenario evaluation, API 526 standard-orifice selection, and API 12J separator-performance checks. Unsupported editions, inapplicable equipment types, and incomplete inputs return blocked results. All remain preliminary engineering screens and do not claim certification or construction readiness.
The executable StandardDesignKernelVerificationSuite.evaluateRegression() runs every registered
kernel against deterministic numeric baselines. It includes SI/customary equivalence at the API 526
orifice boundary and metre/micrometre equivalence for API 12J. Inspect
report.areAllBenchmarksPassed() for regression health and report.getFailedBenchmarkIds() for
diagnosis. The records are deliberately classified as REGRESSION_BASELINE; therefore
report.isPassed() remains false until separately controlled, independently reviewed evidence is
provided for the exact method versions.
EquipmentDesignKernelRegistry.getRegisteredStandards() provides an immutable, deterministic
registry snapshot for API and serialization regression checks. A registered kernel must identify the
same standard as its lookup key, support the catalogued default edition, expose a unique
method@version, use a maturity above CATALOGUED, and remain serializable.
Quick Start
Basic Auto-Sizing Example
// Create a fluid and feed stream
SystemInterface fluid = new SystemSrkEos(298.15, 80.0);
fluid.addComponent("methane", 0.9);
fluid.addComponent("ethane", 0.07);
fluid.addComponent("propane", 0.03);
fluid.setMixingRule("classic");
Stream feed = new Stream("Feed", fluid);
feed.setFlowRate(20000.0, "kg/hr");
feed.setTemperature(30.0, "C");
feed.setPressure(80.0, "bara");
// Create separator and auto-size it
Separator sep = new Separator("HP-Sep", feed);
sep.setDesignGasLoadFactor(0.08); // K-factor
sep.autoSize(1.2); // 20% safety factor
// Get sizing report
System.out.println(sep.getSizingReport());
Using Design Specifications
// Create design spec with fluent builder
DesignSpecification spec = DesignSpecification.forSeparator("HP-Separator")
.setKFactor(0.08)
.setDiameter(2.5, "m")
.setLength(7.5, "m")
.setMaterial("316L")
.setStandard("ASME-VIII")
.setSafetyFactor(1.25);
// Apply to equipment
spec.applyTo(separator);
Using Process Templates
// Define design basis
ProcessBasis basis = ProcessBasis.builder()
.setFeedFluid(myOilGasFluid)
.setFeedFlowRate(50000.0, "kg/hr")
.setFeedPressure(85.0, "bara")
.setFeedTemperature(50.0, "C")
.addStagePressure(1, 80.0, "bara") // HP
.addStagePressure(2, 20.0, "bara") // MP
.addStagePressure(3, 2.0, "bara") // LP
.setCompanyStandard("Equinor", "TR2000")
.build();
// Create process from template
ProcessTemplate template = new ThreeStageSeparationTemplate();
ProcessSystem process = template.create(basis);
process.run();
Integrated Design and Optimization
// Full workflow: template → auto-size → optimize
DesignOptimizer optimizer = DesignOptimizer.fromTemplate(template, basis)
.autoSizeEquipment(1.2)
.applyDefaultConstraints()
.configureFeedRateOptimization("Feed", 25000.0, 80000.0, "kg/hr")
.setObjective(DesignOptimizer.ObjectiveType.MAXIMIZE_PRODUCTION);
DesignResult result = optimizer.optimize();
if (result.getExecutionStatus() == DesignResult.ExecutionStatus.OPTIMIZED) {
logger.info(result.getSummary());
}
Component Details
AutoSizeable Interface
Equipment that implements AutoSizeable can automatically calculate their dimensions based on flow conditions.
Implemented by:
Separator- Sizes based on gas load factor (K-factor) and liquid residence timeThreePhaseSeparator- Inherits from Separator with three-phase handlingGasScrubber- Inherits from Separator, defaults to vertical orientationThrottlingValve- Sizes based on Cv calculation using IEC 60534PipeBeggsAndBrills- Sizes based on target velocity criteriaHeater- Sizes based on duty requirements with mechanical designCooler- Inherits from HeaterHeatExchanger- Sizes based on duty, UA value, and LMTD with two-stream supportManifold- Sizes based on velocity limits, FIV analysis, and erosional velocity
Methods:
void autoSize(double safetyFactor); // Size with specified margin
void autoSize(); // Size with default 20% margin
void autoSize(String company, String tr); // Size per company standard
boolean isAutoSized(); // Check if auto-sized
String getSizingReport(); // Get text report
String getSizingReportJson(); // Get JSON report
DesignSpecification
Builder pattern class for standardized equipment configuration.
Factory Methods:
forSeparator(name)- Separator configurationforValve(name)- Valve configurationforPipeline(name)- Pipeline configurationforHeater(name)- Heater configurationforCompressor(name)- Compressor configuration
Common Settings:
DesignSpecification spec = DesignSpecification.forSeparator("HP-Sep")
.setMaterial("316L") // Material grade
.setStandard("ASME-VIII") // Design standard
.setTRDocument("TR2000") // Technical requirement
.setSafetyFactor(1.25) // Design margin
.setCompanyStandard("Equinor"); // Company name
Equipment-Specific:
// Separator
spec.setKFactor(0.08);
spec.setDiameter(2.5, "m");
spec.setLength(7.5, "m");
// Valve
spec.setCv(150.0);
spec.setMaxValveOpening(90.0);
// Pipeline
spec.setMaxVelocity(15.0, "m/s");
spec.setMaxPressureDrop(5.0, "bar");
// Heater
spec.setMaxDuty(5.0, "MW");
// Compressor
spec.setMaxSpeed(12000.0);
spec.setMinSurgeMargin(10.0);
ProcessBasis
Contains design basis information including feed conditions, stage pressures, and company standards.
ProcessBasis basis = ProcessBasis.builder()
// Feed conditions
.setFeedFluid(fluid)
.setFeedFlowRate(50000.0, "kg/hr")
.setFeedPressure(85.0, "bara")
.setFeedTemperature(50.0, "C")
// Stage pressures
.addStagePressure(1, 80.0, "bara")
.addStagePressure(2, 20.0, "bara")
.addStagePressure(3, 2.0, "bara")
// Company standards
.setCompanyStandard("Equinor", "TR2000")
.setSafetyFactor(1.15)
// Ambient conditions
.setAmbientTemperature(15.0, "C")
.build();
EquipmentConstraintRegistry
Singleton registry of default constraint templates by equipment type.
EquipmentConstraintRegistry registry = EquipmentConstraintRegistry.getInstance();
// Get templates for equipment type
List<ConstraintTemplate> sepConstraints = registry.getConstraintTemplates("Separator");
// Available templates by type:
// Separator: gasLoadFactor, liquidResidenceTime
// Compressor: surgeLine, stonewallLine, maxSpeed, maxPower
// Valve: maxOpening, maxCv
// Pipeline: maxVelocity, maxPressureDrop, fivLOF
// Heater: maxDuty, maxOutletTemperature
ProcessTemplate Interface
Interface for creating reusable process configurations.
Available Templates:
ThreeStageSeparationTemplate- HP/MP/LP separation train
Methods:
ProcessSystem create(ProcessBasis basis); // Create process
boolean isApplicable(SystemInterface fluid); // Check applicability
String[] getRequiredEquipmentTypes(); // Equipment types used
String[] getExpectedOutputs(); // Output stream descriptions
String getName(); // Template name
String getDescription(); // Template description
DesignOptimizer
Integrated workflow manager for design and optimization.
// Create from existing ProcessSystem
DesignOptimizer optimizer = DesignOptimizer.forProcess(myProcess);
// Create from ProcessModule (multi-system modular processes)
DesignOptimizer optimizer = DesignOptimizer.forProcess(myModule);
// Or create from template
DesignOptimizer optimizer = DesignOptimizer.fromTemplate(template, basis);
// Configure workflow
optimizer
.autoSizeEquipment(1.2) // Auto-size all AutoSizeable equipment
.applyDefaultConstraints() // Apply registry constraints
.configureFeedRateOptimization("Feed", 25000.0, 80000.0, "kg/hr")
.setObjective(ObjectiveType.MAXIMIZE_PRODUCTION);
// Run
DesignResult result = optimizer.validate(); // Just validate
DesignResult result = optimizer.optimize(); // Bounded search only when explicitly configured
ProcessModule Support:
- Use
forProcess(ProcessModule)for modular process structures - Check mode with
optimizer.isModuleMode() - Access the module with
optimizer.getModule() - Baseline validation, constraint reporting, and auto-sizing cover all child
ProcessSystemobjects - Bounded search through
DesignOptimizercurrently requires oneProcessSystem; use the whole-plantProductionOptimizer/ProcessModelOptimizationViewAPIs for multi-system optimization
Objective Types:
MAXIMIZE_PRODUCTION- Maximize total hydrocarbon productionMAXIMIZE_OIL- Maximize oil productionMAXIMIZE_GAS- Maximize gas productionMINIMIZE_ENERGY- Minimize energy consumptionCUSTOM- Custom objective function
Optimization is fail-closed. Without configureFeedRateOptimization(...), optimize() runs only the
baseline, optional auto-sizing, and validation; the result status is VALIDATED or AUTO_SIZED,
isConverged() is false, and no optimized flow is reported. Oil and gas objectives additionally
require setProductStream(...). A custom objective requires setCustomObjective(...).
DesignResult
Container for design and optimization results.
DesignResult result = optimizer.optimize();
// First distinguish validation/sizing from a real bounded search
if (result.getExecutionStatus() == DesignResult.ExecutionStatus.OPTIMIZED) {
// isConverged() means the configured interval search can reach its decision-variable tolerance
boolean toleranceReached = result.isConverged();
// Get metrics
int iterations = result.getIterations();
double objective = result.getObjectiveValue();
// Get optimized values
double gasFlow = result.getOptimizedFlowRate("Export Gas");
// Get equipment sizes
Map<String, Double> sizes = result.getEquipmentSizes("HP-Separator");
double diameter = sizes.get("diameter");
// Check constraints
boolean violated = result.hasViolations();
List<String> warnings = result.getWarnings();
// Get summary report
String summary = result.getSummary();
}
Best Practices
1. Always Set Design Basis First
// Create comprehensive design basis
ProcessBasis basis = ProcessBasis.builder()
.setFeedFluid(fluid)
.setFeedFlowRate(rate, "kg/hr")
.setFeedPressure(pressure, "bara")
.setFeedTemperature(temp, "C")
.setSafetyFactor(1.2)
.build();
2. Use Templates for Standard Configurations
// Use pre-built templates for common configurations
ProcessTemplate template = new ThreeStageSeparationTemplate();
if (template.isApplicable(myFluid)) {
ProcessSystem process = template.create(basis);
}
3. Apply Company Standards
// Company-specific standards are used for sizing
separator.autoSize("Equinor", "TR2000");
4. Always Validate Before Optimization
// Validate first to catch configuration issues
DesignResult validation = optimizer.validate();
if (!validation.hasViolations()) {
DesignResult result = optimizer.optimize();
}
5. Review Sizing Reports
// Check auto-sizing results
System.out.println(separator.getSizingReport());
System.out.println(valve.getSizingReportJson());
Integration with Mechanical Design System
The AutoSizeable interface connects to NeqSim’s comprehensive mechanical design system, which includes design standards, material databases, and company-specific technical requirements.
Architecture Overview
┌─────────────────────────────────────────────────────────────────┐
│ AutoSizeable Interface │
│ autoSize(company, trDocument) ─────────────────────────────────┤
└───────────────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ MechanicalDesign │
│ - setCompanySpecificDesignStandards(company) │
│ - readDesignSpecifications() ← loads from database │
│ - calcDesign() ← applies standards │
└───────────────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Design Standards (designstandards/) │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ SeparatorDesign │ │ PipelineDesign │ │
│ │ Standard │ │ Standard │ │
│ │ - getGasLoadFactor │ │ - getDesignFactor │ │
│ │ - getFg │ │ - getUsageFactor │ │
│ └────────────────────┘ └────────────────────┘ │
└───────────────────────────┬─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Database Tables (src/main/resources/designdata/) │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ TechnicalRequirements_Process.csv │ │
│ │ - Equipment-specific parameters by Company │ │
│ │ - NORSOK, ASME, DNV, API standard references │ │
│ │ - TR document mappings (TR1414, TR2000, etc.) │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ MaterialPipeProperties.csv, MaterialPlateProperties.csv │ │
│ │ - Material grades (SA-516, X65, 316L, etc.) │ │
│ │ - SMYS, SMTS, density values │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Using Company-Specific Standards
When you call autoSize(company, trDocument), the system:
- Sets company on MechanicalDesign - Triggers database lookup
- Loads design parameters - K-factors, design factors, safety margins from TR documents
- Applies standards - Uses NORSOK, ASME, DNV values per company specification
// Size separator using Equinor's NORSOK-based standards
Separator sep = new Separator("HP-Sep", feed);
sep.autoSize("Equinor", "NORSOK-P-001");
// The system automatically:
// 1. Queries TechnicalRequirements_Process for "Separator" + "Equinor"
// 2. Loads GasLoadFactor = 0.12-0.15 per NORSOK P-001
// 3. Applies to sizing calculation
Database Tables for Design Standards
TechnicalRequirements_Process.csv contains equipment-specific parameters:
| EQUIPMENTTYPE | SPECIFICATION | VALUE | Company | DOCUMENTID |
|---|---|---|---|---|
| Separator | GasLoadFactor | 0.12-0.15 | Equinor | NORSOK-P-001 |
| Pipeline | designFactor | 0.72 | Equinor | NORSOK-L-001 |
| Gas scrubber | GasLoadFactor | 0.11 | StatoilTR | TR1414 |
| Compressor | SurgeMargin | 10% | Equinor | NORSOK-P-002 |
| Pump | DriverPowerMargin | 1.15 | Equinor | API-610 |
| Pump | NPSHMargin | 0.6 | Equinor | API-610 |
| Manifold | HeaderVelocityLimit | 15.0 | Equinor | API-RP-14E |
| Manifold | LOFThreshold | 0.5 | Equinor | EI-GL-017 |
Standards Tables (in designdata/standards/ subdirectory):
| File | Standards Covered |
|---|---|
api_standards.csv |
API-610 (pumps), API-674/675 (reciprocating/metering), API-682 (seals), API-RP-17A (subsea), API-RP-14E (erosional velocity) |
asme_standards.csv |
ASME B73 (pumps), ASME B31.3 (piping/manifolds), ASME B16.5 (flanges), ASME-PTC-8.2 (pump tests) |
dnv_iso_en_standards.csv |
ISO-13709 (pumps), ISO-21049 (seals), ISO-13628 (subsea manifolds), DNV-RP-A203 (subsea pumps) |
norsok_standards.csv |
NORSOK-L-002 (piping), NORSOK-P-001/P-002 (process/pumps), NORSOK-U-001 (subsea) |
Example query flow:
// When Separator.autoSize("Equinor", "NORSOK-P-001") is called:
SELECT SPECIFICATION, MAXVALUE, MINVALUE
FROM TechnicalRequirements_Process
WHERE EQUIPMENTTYPE='Separator' AND Company='Equinor'
// Returns: GasLoadFactor = 0.12-0.15, LiquidRetentionTime = 2-5 min, etc.
Extending the Design Database
To add new company standards or equipment types:
- Add rows to TechnicalRequirements_Process.csv:
"ID","EQUIPMENTTYPE","SPECIFICATION","MINVALUE","MAXVALUE","UNIT","Company","DOCUMENTID","DESCRIPTION" 100,"Separator","GasLoadFactor",0.10,0.12,"m/s","Shell","DEP-31.22.05.11","Shell K-factor" - Create or update DesignStandard subclass if custom logic is needed:
public class ShellSeparatorDesignStandard extends SeparatorDesignStandard { // Shell-specific sizing rules }
Material Properties Database
MaterialPipeProperties.csv and MaterialPlateProperties.csv contain:
- Material grades (API 5L X65, SA-516-70, etc.)
- Mechanical properties (SMYS, SMTS, density)
- Temperature derating factors
Used for wall thickness calculations:
// Pipeline wall thickness per ASME B31.8
double t = (P * D) / (2 * S * F * E * T)
// where S = SMYS from MaterialPipeProperties
// F = design factor from TechnicalRequirements_Process
Integration with Existing Code
The design framework integrates with existing NeqSim capabilities:
With ProductionOptimizer
// DesignOptimizer can work with ProductionOptimizer
DesignOptimizer designOpt = DesignOptimizer.forProcess(process)
.autoSizeEquipment()
.applyDefaultConstraints()
.configureFeedRateOptimization("Feed", 25000.0, 80000.0, "kg/hr")
.setObjective(ObjectiveType.MAXIMIZE_PRODUCTION);
// The underlying ProductionOptimizer handles the mathematical optimization
DesignResult result = designOpt.optimize();
With CapacityConstrainedEquipment
// Auto-sized equipment maintains capacity constraints
separator.autoSize(1.2);
separator.addCapacityConstraint(new CapacityConstraint.Builder()
.name("K-factor")
.type("gasLoadFactor")
.maxValue(0.08)
.build());
With Mechanical Design
// Auto-sizing uses mechanical design calculations
valve.autoSize(1.2); // Uses IEC 60534 via MechanicalDesign
double cv = valve.getMechanicalDesign().getValveCvMax();
// Company-specific sizing
separator.autoSize("Equinor", "NORSOK-P-001");
// → Loads K-factor from TechnicalRequirements_Process
// → Applies NORSOK design rules via SeparatorDesignStandard
Full Example with Standards
// Create separator with company standards
Separator sep = new Separator("HP-Sep", feed);
// Method 1: Direct auto-size with company standard
sep.autoSize("Equinor", "NORSOK-P-001");
// Method 2: Manual configuration then auto-size
sep.getMechanicalDesign().setCompanySpecificDesignStandards("Equinor");
sep.getMechanicalDesign().readDesignSpecifications();
sep.autoSize(1.15); // Use 15% margin per company policy
// Get full mechanical design report
sep.getMechanicalDesign().displayResults();
Future Enhancements
Planned improvements include:
- Additional process templates (compression trains, fractionation)
- More equipment types implementing AutoSizeable
- Enhanced company-specific standards from database
- Export to design tools (PFD generation, data sheets)
- Machine learning-based sizing recommendations
AutoSizing, Mechanical Design, and Optimization Integration
This section explains how AutoSizing, Mechanical Design, and Production Optimization work together to create a complete equipment sizing and process optimization workflow.
The Complete Workflow
┌─────────────────────────────────────────────────────────────────────────────┐
│ 1. EQUIPMENT CREATION │
│ Equipment is created with basic process specifications │
│ (flow rate, inlet/outlet conditions) │
└────────────────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 2. AUTO-SIZING (autoSize) │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ • Calculates physical dimensions (diameter, length, impeller size) │ │
│ │ • Generates compressor curves (for Compressor) │ │
│ │ • Sets operational modes (solveSpeed=true for compressors) │ │
│ │ • Uses company standards from database (TR documents) │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ MECHANICAL DESIGN (calcDesign) │ │
│ │ • Wall thickness, material selection, weight estimation │ │
│ │ • Driver power sizing, stage calculations │ │
│ │ • Cost estimation, bill of materials │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 3. CAPACITY CONSTRAINTS ARE SET │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Each equipment has constraints based on mechanical design: │ │
│ │ │ │
│ │ Separator: gasLoadFactor, liquidResidenceTime │ │
│ │ Compressor: speed, power, surgeMargin, stonewallMargin │ │
│ │ Pump: npshMargin, power, flowRate │ │
│ │ Valve: valveOpening, cvUtilization │ │
│ │ Pipeline: velocity, pressureDrop, FIV_LOF, FIV_FRMS │ │
│ │ Heater: duty, outletTemperature │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└────────────────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 4. PRODUCTION OPTIMIZATION │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Optimizer increases feed rate until an ACTIVE CONSTRAINT is hit │ │
│ │ │ │
│ │ • Checks ALL CapacityConstrainedEquipment in the process │ │
│ │ • The equipment with highest utilization is the BOTTLENECK │ │
│ │ • The specific constraint limiting that equipment is ACTIVE │ │
│ │ • Reports optimal flow and which constraint limits production │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
Equipment That Can Be Bottlenecks
ANY equipment implementing CapacityConstrainedEquipment can be a bottleneck, not just compressors:
| Equipment Class | Constraints | When It Limits |
|---|---|---|
| Separator | gasLoadFactor, liquidResidenceTime |
High gas/liquid rates |
| Compressor | speed, power, surgeMargin, stonewallMargin |
High gas rates, high compression ratios |
| Pump | npshMargin, power, flowRate |
High liquid rates, low suction pressure |
| ThrottlingValve | valveOpening, cvUtilization |
High flow through restriction |
| Pipeline | velocity, pressureDrop, FIV_LOF, FIV_FRMS |
High velocities, long pipelines |
| Heater | duty, outletTemperature |
High heating demand |
What is an “Active Constraint”?
An active constraint is the specific limit on a piece of equipment that currently restricts the process from operating at a higher rate.
// Example: Finding the active constraint
ProcessSystem process = new ProcessSystem();
// ... add equipment ...
process.run();
// Find the bottleneck equipment
ProcessEquipmentInterface bottleneck = process.getBottleneck();
System.out.println("Bottleneck equipment: " + bottleneck.getName());
// Find the specific active constraint on that equipment
if (bottleneck instanceof CapacityConstrainedEquipment) {
CapacityConstrainedEquipment constrained = (CapacityConstrainedEquipment) bottleneck;
CapacityConstraint activeConstraint = constrained.getBottleneckConstraint();
System.out.println("Active constraint: " + activeConstraint.getName());
System.out.println("Current value: " + activeConstraint.getCurrentValue());
System.out.println("Design limit: " + activeConstraint.getDesignValue());
System.out.println("Utilization: " + activeConstraint.getUtilizationPercent() + "%");
}
Example outputs:
- “Bottleneck: HP Separator, Active constraint: gasLoadFactor at 95%”
- “Bottleneck: Export Compressor, Active constraint: power at 92%”
- “Bottleneck: Feed Valve, Active constraint: valveOpening at 88%”
- “Bottleneck: Export Pipeline, Active constraint: velocity at 97%”
How Constraints Are Set
Constraints are initialized automatically when equipment is auto-sized or when initMechanicalDesign() is called:
// Method 1: Auto-sizing sets constraints automatically
Separator sep = new Separator("HP-Sep", feed);
sep.autoSize(1.2); // Sets gasLoadFactor constraint based on design K-factor
// Method 2: Manual constraint setup
Compressor comp = new Compressor("Export Comp", gasStream);
comp.setMaximumSpeed(11000.0); // Sets HARD speed constraint
comp.initMechanicalDesign();
comp.getMechanicalDesign().setMaxDesignPower(2000.0); // kW power limit (HARD)
// Surge / stonewall margins come from the compressor performance curve
// (set via autoSize() or setCompressorChart())
// Method 3: Programmatic constraint addition
Pipeline pipe = new Pipeline("Export Line", compOutput);
pipe.addCapacityConstraint(new CapacityConstraint("velocity", "m/s", ConstraintType.DESIGN)
.setDesignValue(15.0)
.setMaxValue(20.0)
.setWarningThreshold(0.8)
.setValueSupplier(() -> pipe.getVelocity()));
Constraint Types and Optimization Behavior
| Constraint Type | During Optimization | Example |
|---|---|---|
| HARD | Cannot be exceeded - optimization stops | Compressor trip speed, vessel MAWP |
| SOFT | Can be exceeded with penalty/warning | Efficiency degradation zone |
| DESIGN | Target limit for normal operation | Design K-factor, rated flow |
// Setting constraint types
CapacityConstraint speedLimit = new CapacityConstraint("speed", "rpm", ConstraintType.HARD)
.setDesignValue(10000.0) // Normal operating speed
.setMaxValue(11000.0); // Trip point - HARD limit
CapacityConstraint surgeMargin = new CapacityConstraint("surgeMargin", "%", ConstraintType.SOFT)
.setDesignValue(10.0) // 10% margin from surge
.setMinValue(5.0); // Absolute minimum - warning
CapacityConstraint kFactor = new CapacityConstraint("gasLoadFactor", "m/s", ConstraintType.DESIGN)
.setDesignValue(0.08) // Design basis
.setWarningThreshold(0.9); // Warn at 90% utilization
Optimization with Multiple Equipment Types
The optimizer checks all constrained equipment, not just compressors:
// Create process with multiple equipment types
ProcessSystem process = new ProcessSystem();
Stream feed = new Stream("Feed", fluid);
feed.setFlowRate(10000.0, "kg/hr");
Separator sep = new Separator("Inlet Sep", feed);
sep.autoSize(1.2); // Sets gasLoadFactor constraint
ThrottlingValve valve = new ThrottlingValve("HP Valve", sep.getGasOutStream());
valve.setOutletPressure(30.0, "bara");
valve.autoSize(1.2); // Sets valveOpening constraint
Compressor comp = new Compressor("Export Comp", valve.getOutletStream());
comp.setOutletPressure(100.0);
comp.autoSize(1.2); // Sets speed, power, surge constraints
Pipeline pipe = new PipeBeggsAndBrills("Export Pipeline", comp.getOutletStream());
pipe.setLength(50000.0);
pipe.setDiameter(0.4);
// Pipeline has velocity, pressureDrop, FIV constraints
process.add(feed);
process.add(sep);
process.add(valve);
process.add(comp);
process.add(pipe);
// Run optimization - checks ALL equipment constraints
OptimizationConfig config = new OptimizationConfig(1000.0, 50000.0)
.defaultUtilizationLimit(0.95);
OptimizationResult result = new ProductionOptimizer().optimize(process, feed, config, null, null);
// The bottleneck could be ANY of: separator, valve, compressor, or pipeline
System.out.println("Bottleneck: " + result.getBottleneck().getName());
System.out.println("Bottleneck utilization: "
+ String.format("%.1f%%", result.getBottleneckUtilization() * 100));
System.out.println("Optimal rate: " + result.getOptimalRate() + " kg/hr");
Viewing All Constraints in a Process
// Get all constrained equipment
for (CapacityConstrainedEquipment equip : process.getConstrainedEquipment()) {
System.out.println("\n" + equip.getName() + ":");
for (CapacityConstraint c : equip.getCapacityConstraints().values()) {
String status = c.isViolated() ? "⚠️ EXCEEDED" :
c.isNearLimit() ? "⚡ NEAR LIMIT" : "✓ OK";
System.out.printf(" %-20s: %6.1f / %6.1f %s (%5.1f%%) %s%n",
c.getName(),
c.getCurrentValue(),
c.getDesignValue(),
c.getUnit(),
c.getUtilizationPercent(),
status);
}
}
Example output:
Inlet Sep:
gasLoadFactor : 0.07 / 0.08 m/s (87.5%) ✓ OK
liquidResidenceTime : 3.20 / 3.00 min (106.7%) ⚠️ EXCEEDED
HP Valve:
valveOpening : 72.00 / 90.00 % (80.0%) ✓ OK
cvUtilization : 45.00 / 50.00 - (90.0%) ⚡ NEAR LIMIT
Export Comp:
speed : 9500.0 /10000.0 RPM (95.0%) ⚡ NEAR LIMIT
power : 1650.0 / 2000.0 kW (82.5%) ✓ OK
surgeMargin : 12.00 / 10.00 % (83.3%) ✓ OK
Export Pipeline:
velocity : 14.50 / 15.00 m/s (96.7%) ⚡ NEAR LIMIT
pressureDrop : 4.20 / 5.00 bara (84.0%) ✓ OK
FIV_LOF : 0.35 / 1.00 - (35.0%) ✓ OK
Summary: AutoSizing → Mechanical Design → Constraints → Optimization
- AutoSizing (
autoSize()) calculates equipment dimensions from process conditions - Mechanical Design (
calcDesign()) determines detailed specifications (materials, wall thickness, etc.) - Constraints are set based on the design limits (K-factor, max speed, rated power, etc.)
- Optimization finds the maximum flow rate that respects ALL constraints across ALL equipment
- The Active Constraint is the specific limit currently preventing higher production
- The Bottleneck is the equipment where that active constraint exists