Skip to the content.

Pipeline Network Optimization

NeqSim’s LoopedPipeNetwork provides a comprehensive pipeline network solver with formal optimization, sparse linear algebra, and analytical validation benchmarks.

Overview

Feature Class Description
NLP Optimizer NetworkOptimizer BOBYQA and CMA-ES choke allocation
Multi-Objective NetworkOptimizer Weighted-sum Pareto front exploration
Sparse Solver NetworkLinearSolver Auto-selects Gaussian, Dense EJML, or Sparse CSC
Multiphase Caching LoopedPipeNetwork Reuses Beggs-Brill models across iterations
Benchmarks NetworkValidationBenchmarks 6 analytical/published verification cases

NLP Choke Optimization

The NetworkOptimizer replaces gradient-finite-difference with formal bound-constrained optimization from Apache Commons Math:

Java Example

LoopedPipeNetwork network = new LoopedPipeNetwork("MyNetwork");
network.setFluidTemplate(gas);
network.setSolverType(LoopedPipeNetwork.SolverType.NEWTON_RAPHSON);
network.setMaxIterations(200);
network.setTolerance(100.0);

// Build network with wells, chokes, and export
network.addSourceNode("res1", 200.0, 0.0);
network.addJunctionNode("wh1");
network.addJunctionNode("manifold");
network.addFixedPressureSinkNode("export", 50.0);

network.addWellIPR("res1", "wh1", "ipr1", 5e-6, false);
network.addChoke("wh1", "manifold", "choke1", 50.0, 80.0);
network.addPipe("manifold", "export", "export_pipe", 20000.0, 0.3, 0.00005);

// Create and configure optimizer
NetworkOptimizer optimizer = network.createOptimizer();
optimizer.setAlgorithm(NetworkOptimizer.Algorithm.BOBYQA);
optimizer.setObjectiveType(NetworkOptimizer.ObjectiveType.MAX_PRODUCTION);
optimizer.setMaxEvaluations(300);

// Run optimization
NetworkOptimizer.OptimizationResult result = optimizer.optimize();
System.out.println("Production: " + result.totalProductionKgHr + " kg/hr");
System.out.println("Converged: " + result.converged);

Objective Types

Type Description
MAX_PRODUCTION Maximize total mass flow at all sinks
MAX_REVENUE Maximize price-weighted production
MIN_COMPRESSOR_POWER Minimize total compressor power
MAX_SPECIFIC_PRODUCTION Maximize production per unit power

Convenience Methods

// Quick single-objective optimization
NetworkOptimizer.OptimizationResult result = network.optimizeProductionNLP();

// Multi-objective Pareto front (11 points)
List<NetworkOptimizer.OptimizationResult> pareto = network.optimizeMultiObjective(11);

Multi-Objective Pareto Optimization

The multi-objective method sweeps a weight parameter $w$ from 0 to 1:

\[f(x) = w \cdot \text{production}(x) - (1 - w) \cdot \text{power}(x)\]

Each Pareto point represents a different production-vs-power tradeoff. Results include paretoWeight, totalProductionKgHr, and totalCompressorPowerKW.

Sparse Matrix Solver

NetworkLinearSolver automatically selects the optimal solver for the Newton-Raphson Schur complement system:

System Size Solver Reason
n ≤ 30 Gaussian elimination Backward compatible, fastest for small systems
30 < n ≤ 100 Dense EJML LU Better numerical stability
n > 100 Sparse CSC LU Exploits sparsity for large networks

All three solvers are also available directly:

double[] x = NetworkLinearSolver.solve(matA, vecB, n);      // Auto-select
double[] x = NetworkLinearSolver.solveGaussian(matA, vecB, n); // Force Gaussian
double[] x = NetworkLinearSolver.solveDense(matA, vecB, n);    // Force Dense EJML
double[] x = NetworkLinearSolver.solveSparse(matA, vecB, n);   // Force Sparse EJML

Multiphase Stream Caching

The multiphase head loss calculation now caches PipeBeggsAndBrills models on each NetworkPipe, avoiding re-creation of Stream and solver objects on every iteration. This is transparent — no API changes required.

Validation Benchmarks

Six analytical/published benchmark cases verify solver accuracy:

# Benchmark Verification
1 Single Pipe (Darcy-Weisbach) Swamee-Jain analytical pressure drop
2 Two Parallel Pipes Known flow split ratio $(D_1/D_2)^{5/2}$
3 Triangle Loop Mass balance conservation at all nodes
4 HC vs NR Cross-Verification Both solvers converge to same solution
5 Pressure Monotonicity Pressure decreases along flow direction
6 Sparse vs Dense Agreement All three solvers produce identical results

Running Benchmarks

List<NetworkValidationBenchmarks.BenchmarkResult> results =
    NetworkValidationBenchmarks.runAllBenchmarks();

for (NetworkValidationBenchmarks.BenchmarkResult r : results) {
    System.out.println(r.getSummary());
}

Or via the static convenience method on LoopedPipeNetwork:

List<NetworkValidationBenchmarks.BenchmarkResult> results =
    LoopedPipeNetwork.runValidationBenchmarks();

for (NetworkValidationBenchmarks.BenchmarkResult r : results) {
    System.out.println(r.getSummary());
}

Python Example

from neqsim import jneqsim

LoopedPipeNetwork = jneqsim.process.equipment.network.LoopedPipeNetwork
NetworkOptimizer = jneqsim.process.equipment.network.NetworkOptimizer
SystemSrkEos = jneqsim.thermo.system.SystemSrkEos

gas = SystemSrkEos(298.15, 50.0)
gas.addComponent("methane", 0.85)
gas.addComponent("ethane", 0.10)
gas.addComponent("propane", 0.05)
gas.createDatabase(True)
gas.setMixingRule("classic")
gas.init(0)
gas.init(1)

network = LoopedPipeNetwork("GatheringNetwork")
network.setFluidTemplate(gas)
network.setSolverType(LoopedPipeNetwork.SolverType.NEWTON_RAPHSON)
network.setMaxIterations(200)
network.setTolerance(100.0)

# Build network...
network.run()

# Optimize
optimizer = network.createOptimizer()
optimizer.setAlgorithm(NetworkOptimizer.Algorithm.BOBYQA)
optimizer.setMaxEvaluations(300)
result = optimizer.optimize()
print(f"Production: {result.totalProductionKgHr:.0f} kg/hr")