Class LoopedPipeNetwork
- All Implemented Interfaces:
Serializable, Runnable, ProcessEquipmentInterface, ProcessElementInterface, SimulationInterface, NamedInterface
This class extends the basic pipeline network concept to support looped configurations commonly found in water distribution systems, oil and gas gathering networks, and gas transmission systems. The Hardy Cross method is used to iteratively solve for flow distribution in networks with loops.
Hardy Cross Method
The Hardy Cross method is an iterative technique for solving networks with loops:
- Initial flow estimates are made for each pipe
- Independent loops are identified using DFS spanning tree algorithm
- For each loop, calculate head loss imbalance: ΔH = ∑(h·sign)
- Calculate flow correction: ΔQ = -ΔH / ∑(|dh/dQ|)
- Apply corrections to all pipes in each loop
- Repeat until convergence (ΔH < tolerance for all loops)
Network Topology
The network supports:
- Multiple source nodes (wells, compressor stations)
- Multiple sink nodes (customers, export terminals)
- Junction nodes where pipes connect
- Looped configurations for redundancy
Example Usage
// Create a simple ring main network
SystemInterface gas = new SystemSrkEos(298.15, 50.0);
gas.addComponent("methane", 0.9);
gas.addComponent("ethane", 0.1);
gas.setMixingRule("classic");
LoopedPipeNetwork network = new LoopedPipeNetwork("ring main");
network.setFluidTemplate(gas);
// Add nodes
network.addSourceNode("supply", 50.0, 1000.0); // 50 bar, 1000 kg/hr
network.addJunctionNode("A");
network.addJunctionNode("B");
network.addJunctionNode("C");
network.addSinkNode("customer1", 100.0); // 100 kg/hr demand
network.addSinkNode("customer2", 200.0);
// Connect with pipes (creates loops)
network.addPipe("supply", "A", "pipe1", 1000.0, 0.3);
network.addPipe("A", "B", "pipe2", 500.0, 0.2);
network.addPipe("B", "C", "pipe3", 500.0, 0.2);
network.addPipe("C", "A", "pipe4", 500.0, 0.2); // Creates a loop
network.addPipe("B", "customer1", "pipe5", 200.0, 0.15);
network.addPipe("C", "customer2", "pipe6", 200.0, 0.15);
// Solve using Hardy Cross
network.setSolverType(SolverType.HARDY_CROSS);
network.setTolerance(1e-6);
network.run();
// Get results
System.out.println("Converged in " + network.getIterationCount() + " iterations");
for (String pipeName : network.getPipeNames()) {
System.out.println(pipeName + ": " + network.getPipeFlowRate(pipeName) + " kg/hr");
}
- Version:
- 1.0
- Author:
- Even Solbraa
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumArtificial lift type for wells.static enumIPR model type for well inflow performance.static enumNetwork element type for generalized resistance elements.static classRepresents a node in the pipe network.static classRepresents a pipe in the network.static enumNode type in the network.static enumPipe flow model type.(package private) static classAttached reservoir info: maps a network source node to a SimpleReservoir and well within it.static enumSolver type for network analysis. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate Map<String, LoopedPipeNetwork.ReservoirAttachment> Map from source node name to reservoir attachment.private doubleprivate booleanprivate doublePressure tolerance for topside coupling convergence (bar).private final Map<String, StreamInterface> private SystemInterfaceprivate doubleprivate intprivate static final org.apache.logging.log4j.LoggerLogger for this class.private List<NetworkLoop> private doubleprivate doubleprivate doubleprivate doubleMaximum compressor power in MW.private intMaximum coupling iterations.private intprivate doubleprivate doubleMaximum separator capacity utilization (0.0 to 1.0).private doubleprivate doubleprivate final Map<String, SystemInterface> private final Map<String, LoopedPipeNetwork.NetworkNode> private final Map<String, StreamInterface> private LoopedPipeNetwork.PipeModelTypeprivate final Map<String, LoopedPipeNetwork.NetworkPipe> private doubleprivate static final longprivate LoopedPipeNetwork.SolverTypeprivate doubleprivate ProcessSystemThe topsideProcessSystemcoupled to the network outlet.private StringName of the sink node used as the topside coupling point.private doubleprivate doubleprivate doubleprivate doubleLast optimization results per well.Per-well gas price for revenue-based optimization (USD/kg).Per-well oil price for revenue-based optimization (USD/kg).Fields inherited from class ProcessEquipmentBaseClass
conditionAnalysisMessage, energyStream, hasController, isSolved, properties, reportFields inherited from class SimulationBaseClass
calcIdentifier, calculateSteadyState, timeFields inherited from class NamedBaseClass
name -
Constructor Summary
ConstructorsConstructorDescriptionLoopedPipeNetwork(String name) Create a new looped pipe network.LoopedPipeNetwork(String name, StreamInterface feedStream) Create a new looped pipe network with a single feed stream. -
Method Summary
Modifier and TypeMethodDescriptionAdd a production choke element between two nodes.addCompressor(String fromNode, String toNode, String elementName, double polytropicEfficiency) Add a compressor or booster station element between two nodes.addCompressorWithChart(String fromNode, String toNode, String elementName, Compressor compressor) Add a compressor with a performance chart (speed curves).voidaddFixedPressureSinkNode(String name, double pressureBar) Add a fixed-pressure sink node (delivery point with specified pressure).voidaddFixedPressureSinkNode(String name, double pressureBar, double elevationM) Add a fixed-pressure sink node with specified elevation.voidaddJunctionNode(String name) Add a junction node to the network.voidaddJunctionNode(String name, double elevationM) Add a junction node with specified elevation.addMultiphasePipe(String fromNode, String toNode, String elementName, double lengthM, double diameterM) Add a multiphase pipeline element using Beggs-Brill correlation.Add a pipe connecting two nodes.addPipe(String fromNode, String toNode, String pipeName, double lengthM, double diameterM, double roughnessM) Add a pipe with specified roughness.addRegulator(String fromNode, String toNode, String elementName, double setPointBar) Add a pressure regulator (PRV) element between two nodes.voidaddSinkNode(String name, double demandKgHr) Add a sink node (demand point) to the network.voidaddSinkNode(String name, double demandKgHr, double elevationM) Add a sink node with specified elevation.voidaddSourceNode(String name, double pressureBar, double flowRateKgHr) Add a source node to the network.voidaddSourceNode(String name, double pressureBar, double flowRateKgHr, double elevationM) Add a source node with specified elevation.addTubing(String bottomNode, String topNode, String elementName, double lengthM, double diameterM, double inclinationDeg) Add wellbore tubing element (vertical lift performance).addWaterInjection(String sourceNode, String reservoirNode, String elementName, double injectionRateKgHr) Add a water injection well element between two nodes.addWellIPR(String reservoirNode, String wellboreNode, String elementName, double productivityIndexSI, boolean isGas) Add a well IPR element using the productivity index model.addWellIPRFetkovich(String reservoirNode, String wellboreNode, String elementName, double cCoeff, double nExp) Add a well IPR element using the Fetkovich model for gas wells.addWellIPRVogel(String reservoirNode, String wellboreNode, String elementName, double qmaxKgS) Add a well IPR element using the Vogel model for solution-gas-drive oil wells.private voidApply conditions from connected feed streams to their corresponding source nodes.private voidapplyParameterValue(String elementName, String parameterType, double value) Apply a parameter value to a network element.voidattachReservoir(String sourceNodeName, SimpleReservoir reservoir, String wellType) Attach a SimpleReservoir to a source node (convenience: assumes well index 0).voidattachReservoir(String sourceNodeName, SimpleReservoir reservoir, String wellType, int wellIndex) Attach a SimpleReservoir to a source node in the network.private voidBFS distance computation from seed nodes through pipe connections.private voidBuild per-well allocation report after optimization.Calculate CO2/H2S corrosion rates for all pipe elements.Calculate greenhouse gas emissions for all compressor stations in the network.Calculate fuel gas consumption for all compressor elements in the network.Calculate gas quality properties at every node that has an assigned fluid composition.private doubleCalculate head loss for a network element based on its type.private doubleCalculate head loss for a production choke element.private doubleCalculate head loss for a compressor element.private doubleCalculate head loss for a standard pipe using Darcy-Weisbach equation with elevation.private doubleCalculate derivative of head loss with respect to flow rate for any element type.private doubleCalculate dh/dQ for choke element.private doubleCalculate dh/dQ for compressor element.private doubleCalculate dh/dQ for IPR element.private doubleCalculate dh/dQ for regulator (pressure reducing valve) element.private doubleCalculate head loss for a well IPR element.private doubleCalculate head loss for a multiphase pipe using simplified Beggs-Brill approach.private doubleCalculate head loss for a pressure regulator element.private doubleCalculate head loss for wellbore tubing (VLP) element.private voidCalculate overall mass balance error for the network.Calculate oil quality properties (TVP and RVP) at every node that has an assigned fluid composition.Calculate sand transport and erosion rates for all pipe elements.Calculate water balance for the entire network.Check all defined constraints and return any violations.Check erosional velocity limits per API RP 14E for all pipe elements.checkGasQualityLimits(double wobbeMin, double wobbeMax) Check if gas quality at all sink (delivery) nodes meets the specified Wobbe index bounds.checkOilQualityLimits(double tvpMaxBara, double rvpMaxBara) Check if oil quality at all sink (delivery) nodes meets the specified TVP and RVP limits.private doublecomputeBHPFromIPR(LoopedPipeNetwork.NetworkPipe iprPipe, double pResPa, double qKgs) Compute BHP from IPR model given a flow rate.private doubleCompute objective with penalty for constraint violations.private doublecomputeIPRFlowRate(LoopedPipeNetwork.NetworkPipe iprPipe, double pResPa, double bhpPa) Compute IPR flow rate at a given bottom-hole pressure.private doubleCompute the optimization objective (revenue or total flow).Create aNetworkOptimizerfor this network.private voidDetect loops in the network using DFS spanning tree algorithm.private doubleEstimate compressor shaft power from polytropic head calculation.private doubleestimateNodeTemperature(String nodeName) Estimate the node temperature in Kelvin.private doubleestimatePressureDropAtRate(LoopedPipeNetwork.NetworkPipe pipe, double qKgs) Estimate pressure drop through a network element at a given flow rate.private doubleestimateVLPRate(LoopedPipeNetwork.NetworkPipe outPipe, double bhpPa) Estimate VLP (outflow) rate at a given bottom-hole pressure.voidexportCoupledVFPTables(String filePath, double[] flowRates_kghr, double[] thps) Export coupled VFP tables to Eclipse-format files.voidexportVFPTables(String filePath, double[] flowRates, double[] thps, double[] waterCuts, double[] gors) Export VFP (Vertical Flow Performance) tables for well elements in the network.fullFieldForecast(Map<String, double[]> reservoirPressureProfiles, double[] timestepYears) Run a full-field lifecycle forecast from plateau through decline.private double[][][][][]generateBHPTable(LoopedPipeNetwork.NetworkPipe pipe, double[] flowRates, double[] thps, double[] waterCuts, double[] gors) Generate BHP table for a well element across parameter ranges.generateCoupledVFPTables(double[] flowRates_kghr, double[] thps) Generate coupled VFP tables for wells in the network.generateNetworkBackpressureCurve(String exportNodeName, double[] flowRates_kghr) Generate network back-pressure VFP table (VFPEXP).doubleGet annual CO2-equivalent emissions in tonnes/year.getAttachedReservoir(String sourceNodeName) Get the attached reservoir for a source node, or null if none.doubleGet the CO2 emission factor.Get the list of constraint violations from the lastcheckConstraints()call.Get corrosion violation messages.doubleGet emissions intensity in kgCO2eq per tonne of production.Get erosional velocity violations after solving.Get the fluid template.doubleGet the fuel gas heat rate in kJ/kWh.doubleGet the fuel gas consumption as a percentage of total network throughput.Returns all inlet streams connected to this equipment.intGet number of iterations in last solve.getLoops()Get detected loops in the network.doubleGet mass balance error from last solve in kg/s.doubleGet the maximum compressor power limit.intGet maximum iterations.doubleGet maximum residual from last iteration.doubleGet the maximum separator utilization limit.Get a summary report of the network solution including gas quality at each node.Get a node by name.doublegetNodeFlowRate(String nodeName) Get the net delivered flow rate at a node in kg/hr.getNodeFluid(String nodeName) Get the fluid composition at a specific node (after solving with compositional tracking).double[]getNodeGasQuality(String nodeName) Get gas quality properties at a specific node.double[]getNodeOilQuality(String nodeName) Get oil quality properties at a specific node.doublegetNodePressure(String nodeName) Get pressure at a node in bara.intGet number of loops in the network.Get the default outlet stream.getOutletStream(String sinkNodeName) Get the outlet stream for a named sink node.Returns all outlet streams produced by this equipment.Get a pipe by name.doublegetPipeFlowRate(String pipeName) Get flow rate for a specific pipe in kg/hr.getPipeFlowRegime(String pipeName) Get flow regime description for a specific pipe.doublegetPipeFrictionFactor(String pipeName) Get Darcy friction factor for a specific pipe.doublegetPipeHeadLoss(String pipeName) Get head loss for a specific pipe in bara.Get the pipe flow model type.Get all pipe names.doublegetPipeReynoldsNumber(String pipeName) Get Reynolds number for a specific pipe.doublegetPipeVelocity(String pipeName) Get pipe velocity in m/s.doubleGet relaxation factor.Get sand violation messages.Get a summary of the network solution.Get the solver type.getSourceNodeStream(String sourceNodeName) Get the outlet stream for a named source node (for IPR well sources where flow is computed).doubleGet convergence tolerance.Get the coupled topside model.doubleGet total CO2-equivalent emissions from all compressors in kg/hr.doubleGet the total ESP power consumption across all wells in kW.doubleGet the total fuel gas consumption rate for all compressors in the network.doubleGet the total gas lift injection rate across all wells in kg/hr.doubleGet total flow rate into all sink nodes (total network production).doubleGet total water injection rate in kg/hr.doubleGet total water production rate in kg/hr.Get the well allocation results from the last optimization.booleanCheck whether any reservoirs are attached to this network.private voidInitialize pipe flow estimates using BFS spanning tree to satisfy mass balance.private voidinitializeFreeNodePressures(List<String> freeNodeList) Initialize pressures for free (non-fixed) nodes using BFS propagation from fixed-pressure nodes.private voidInitialize AdiabaticPipe models for each pipe.private doubleinterpolateVFP(double[][] table, double[] xAxis, double[] yAxis, double x, double y) Bilinear interpolation in a 2D VFP table.booleanCheck if solution converged.booleanCheck whether the current network state is feasible given topside constraints.loadFluidFromE300(String e300FilePath) Load a fluid template from an Eclipse E300-format file.nodalAnalysis(String iprElementName, String outflowElementName, int numPoints) Perform nodal analysis for a well defined by an IPR element and an outflow (tubing/pipe/choke) element downstream of the well node.doubleoptimizeChokeOpenings(int maxIterations, double tolerance) Optimize choke openings to maximize total production from all wells.optimizeFullField(int optimMaxIter, double optimTolerance) Run full-field optimisation from reservoir to export.optimizeMultiObjective(int numPoints) Run multi-objective optimization exploring the production vs compression power trade-off.doubleoptimizeProduction(int maxIterations, double tolerance) Optimize choke openings to maximize revenue (price-weighted production).Optimize production using a formal NLP solver (BOBYQA by default).productionForecast(double[] reservoirPressures, double[] timestepYears) Run a production forecast with declining reservoir pressure over time.productionForecastCoupled(double[] timestepYears) Run a coupled lifecycle forecast with default optimisation parameters.productionForecastCoupled(double[] timestepYears, int optimMaxIter, double optimTolerance) Run a full lifecycle forecast with coupled SimpleReservoir material balance.productionForecastWithOptimization(String sourceNodeName, double[] reservoirPressures, double[] timestepYears, int optimMaxIter, double optimTolerance) Simplified production forecast with re-optimisation using a single reservoir.productionForecastWithOptimization(Map<String, double[]> reservoirPressureProfiles, double[] timestepYears, int optimMaxIter, double optimTolerance) Run production forecast with choke re-optimisation at each timestep.private voidpropagatePressure(String nodeName, SystemInterface fluid) Propagate pressure from a node to connected nodes.voidIn this method all thermodynamic and unit operations will be calculated in a steady state calculation.Run the network coupled with the topside model.private voidrunHardyCross(UUID id) Run Hardy Cross iterative solver.private voidrunNewtonRaphson(UUID id) Run Newton-Raphson Global Gradient Algorithm (Todini-Pilati, 1988).private voidrunSequential(UUID id) Run sequential solver for tree networks.runTransientCoupled(double dtSeconds, int optimMaxIter, double optimTolerance) Run a single coupled timestep: solve network, drain reservoirs, update pressures.Run all validation benchmarks and return results.sensitivityAnalysis(String elementName, String parameterType, double[] values) Run sensitivity analysis by sweeping a parameter across a range.voidsetCO2EmissionFactor(double factor) Set the CO2 emission factor for fuel gas combustion.voidsetCorrosionModel(String elementName, String model) Set the corrosion model for a pipe element.voidsetCorrosiveGas(String elementName, double co2MoleFrac, double h2sMoleFrac) Set CO2 and H2S mole fractions for a pipe element for corrosion calculation.voidsetCouplingToleranceBar(double toleranceBar) Set the coupling convergence tolerance.voidsetElementFlowLimits(String elementName, double minFlowKgHr, double maxFlowKgHr) Set flow rate limits for a network element (pipe, choke, compressor, etc.).voidConfigure an Electrical Submersible Pump (ESP) on a well element.voidsetFeedStream(String sourceNodeName, StreamInterface stream) Associate a feed stream with a named source node.voidsetFluidTemplate(SystemInterface fluid) Set the fluid template for the network.voidsetFuelGasHeatRate(double heatRateKJPerKWh) Set the fuel gas heat rate for gas-turbine driven compressors.voidsetGasLift(String elementName, double gasLiftRateKgHr) Configure gas lift on an existing well tubing or IPR element.voidsetGasPrice(double pricePerKg) Set gas price for revenue-based optimization.voidsetJetPump(String elementName, double equivalentPowerKW, double efficiency) Configure a jet pump on a well element.voidsetMaxAllowableErosionRate(double maxRateMmYr) Set the maximum allowable erosion rate for integrity management.voidsetMaxAllowableSandRate(double maxRateKgHr) Set the maximum allowable sand production rate.voidsetMaxCompressorPowerMW(double maxPowerMW) Set the maximum compressor power limit for topside coupling.voidsetMaxCouplingIterations(int maxIter) Set the maximum coupling iterations.voidsetMaxIterations(int max) Set maximum number of iterations.voidsetMaxSeparatorUtilization(double maxUtil) Set the maximum separator utilization for coupled optimisation.voidsetMethaneSlipFactor(double slipFraction) Set the methane slip factor for gas turbine/engine drivers.voidsetMinAllowableWallLife(double years) Set the minimum allowable remaining wall life.voidsetNodeFluid(String sourceNodeName, SystemInterface fluid) Set the fluid composition for a specific source node.voidsetNodePressure(String nodeName, double pressureBar) Set the pressure of an existing node.voidsetNodePressureLimits(String nodeName, double minPressureBar, double maxPressureBar) Set pressure limits for a node.voidsetOilPrice(double pricePerKg) Set oil price for revenue-based optimization.voidsetPipeEfficiency(String pipeName, double efficiency) Set pipe efficiency factor for a named pipe.voidSet the pipe flow model type.voidsetRelaxationFactor(double factor) Set relaxation factor for Hardy Cross (0 < factor <= 1).voidsetReservoirComposition(String sourceNodeName, double[] molarComposition) Set the molar composition for a specific reservoir source node.voidsetReservoirCompositionFromE300(String sourceNodeName, String e300FilePath) Set a reservoir node's fluid composition from a separate E300 file.voidsetReservoirPressure(String sourceNodeName, double pressureBar) Set the reservoir pressure for all IPR wells connected to a given source node.voidsetRodPump(String elementName, double equivalentPowerKW, double efficiency) Configure a rod pump (beam pump) on a well element.voidsetSandRate(String elementName, double sandRateKgHr) Set the sand production rate for a well element.voidSet the solver type.voidsetTolerance(double tol) Set convergence tolerance for head loss balance (Pa).voidsetTopsideModel(ProcessSystem topside, String sinkNodeName) Set the topside process model to couple with the network.voidsetWaterBreakthrough(String elementName, double breakthroughWC, double finalWC, double currentWC) Set the water breakthrough profile for a well (time-dependent water cut).voidsetWaterCut(String elementName, double waterCut) Set the water cut for a well or pipe element.voidsetWellPrice(String wellOrChokeName, double pricePerKg) Set per-well product price for revenue allocation.private double[]solveLinearSystem(double[][] matA, double[] vecB, int n) Solve a linear system Ax = b using the best available solver.toJson()Serializes the Process Equipment along with its state to a JSON string.voidUpdate compositional mixing at junction nodes.private voidUpdate node pressures based on calculated head losses.private voidCreate or update outlet streams at sink nodes with the solved network state.private voidUpdate hydraulic properties (velocity, Reynolds, friction factor) for all pipes.validate()Validate the network topology.validateVFPPoint(double[][] vfpTable, double[] flowRates_kghr, double[] thps, double actualRate, double actualTHP, double actualBHP) Validate VFP table against network solution at current operating point.Methods inherited from class ProcessEquipmentBaseClass
addCapacityConstraint, addController, copy, displayResult, equals, getAvailableMargin, getAvailableMarginPercent, getBottleneckConstraint, getCapacityConstraints, getConditionAnalysisMessage, getConstraintEvaluationReport, getController, getController, getControllers, getEffectiveCapacityFactor, getEnergyStream, getEntropyProduction, getExergyChange, getFailureMode, getMassBalance, getMassBalance, getMaxUtilization, getMaxUtilizationPercent, getMechanicalDesign, getMinimumFlow, getPressure, getPressure, getProperty, getReferenceDesignation, getReport_json, getResultTable, getSpecification, getTemperature, getTemperature, getThermoSystem, getUtilizationSummary, hashCode, initElectricalDesign, initializeDefaultConstraints, initInstrumentDesign, initMechanicalDesign, isActive, isActive, isCapacityAnalysisEnabled, isCapacityExceeded, isFailed, isHardLimitExceeded, isNearCapacityLimit, isSetEnergyStream, reportResults, restoreFromFailure, run_step, runConditionAnalysis, setCapacityAnalysisEnabled, setController, setEnergyStream, setEnergyStream, setFailureMode, setFlowValveController, setMinimumFlow, setPressure, setReferenceDesignation, setRegulatorOutSignal, setSpecification, setTemperature, simulateDegradedOperation, simulateTrip, solved, toJsonMethods inherited from class SimulationBaseClass
getCalculateSteadyState, getCalculationIdentifier, getTime, increaseTime, isRunInSteps, setCalculateSteadyState, setCalculationIdentifier, setRunInSteps, setTimeMethods inherited from class NamedBaseClass
getName, getTagNumber, setName, setTagNumberMethods inherited from class Object
clone, finalize, getClass, notify, notifyAll, toString, wait, wait, waitMethods inherited from interface NamedInterface
getName, getTagName, getTagNumber, setName, setTagName, setTagNumberMethods inherited from interface ProcessEquipmentInterface
getCapacityDuty, getCapacityMax, getElectricalDesign, getEquipmentState, getExergyChange, getExergyDestruction, getExergyDestruction, getFluid, getInstrumentDesign, getOperatingEnvelopeViolation, getOutletFlowRate, getOutletPressure, getOutletTemperature, getReferenceDesignationString, getRestCapacity, getSimulationValidationErrors, isSimulationValid, isWithinOperatingEnvelope, needRecalculation, validateSetupMethods inherited from interface SimulationInterface
getCalculateSteadyState, getCalculationIdentifier, getTime, increaseTime, isRunInSteps, run, run_step, runTransient, runTransient, setCalculateSteadyState, setCalculationIdentifier, setRunInSteps, setTime
-
Field Details
-
serialVersionUID
private static final long serialVersionUID- See Also:
-
logger
private static final org.apache.logging.log4j.Logger loggerLogger for this class. -
nodes
-
pipes
-
pipeNames
-
solverType
-
pipeModelType
-
tolerance
private double tolerance -
maxIterations
private int maxIterations -
relaxationFactor
private double relaxationFactor -
loops
-
iterationCount
private int iterationCount -
maxResidual
private double maxResidual -
converged
private boolean converged -
fluidTemplate
-
massBalanceError
private double massBalanceError -
feedStreams
-
outletStreams
-
nodeFluidMap
-
erosionalViolations
-
nodeGasQuality
-
nodeOilQuality
-
nodePressureLimits
-
elementFlowLimits
-
constraintViolations
-
fuelGasHeatRate
private double fuelGasHeatRate -
totalFuelGasRate
private double totalFuelGasRate -
nodeWaterBalance
-
totalWaterProduction
private double totalWaterProduction -
totalWaterInjection
private double totalWaterInjection -
pipeSandResults
-
sandViolations
-
maxAllowableSandRate
private double maxAllowableSandRate -
maxAllowableErosionRate
private double maxAllowableErosionRate -
pipeCorrosionResults
-
corrosionViolations
-
minAllowableWallLife
private double minAllowableWallLife -
emissionsResults
-
co2EmissionFactor
private double co2EmissionFactor -
totalCO2Emissions
private double totalCO2Emissions -
methaneSlipFactor
private double methaneSlipFactor -
wellOilPrices
-
wellGasPrices
-
wellAllocationResults
-
topsideModel
The topsideProcessSystemcoupled to the network outlet. -
topsideSinkNodeName
Name of the sink node used as the topside coupling point. -
maxSeparatorUtilization
private double maxSeparatorUtilizationMaximum separator capacity utilization (0.0 to 1.0). Default 0.90. -
maxCompressorPowerMW
private double maxCompressorPowerMWMaximum compressor power in MW. Default 999 (unlimited). -
couplingToleranceBar
private double couplingToleranceBarPressure tolerance for topside coupling convergence (bar). Default 0.5. -
maxCouplingIterations
private int maxCouplingIterationsMaximum coupling iterations. Default 20. -
attachedReservoirs
Map from source node name to reservoir attachment.
-
-
Constructor Details
-
LoopedPipeNetwork
Create a new looped pipe network.- Parameters:
name- network name
-
LoopedPipeNetwork
Create a new looped pipe network with a single feed stream.The feed stream's fluid is used as the network fluid template. The stream is associated with the first source node added to the network. Call
setFeedStream(String, StreamInterface)to explicitly bind a stream to a named source node.- Parameters:
name- network namefeedStream- inlet stream providing fluid composition, temperature and pressure
-
-
Method Details
-
setFeedStream
Associate a feed stream with a named source node.When
run(UUID)is called, the stream's pressure and flow rate are read and applied to the named source node. If the fluid template has not been set, it is derived from the first feed stream.- Parameters:
sourceNodeName- name of an existing source nodestream- the feed stream
-
getOutletStream
Get the outlet stream for a named sink node.The returned stream contains the solved pressure, temperature, flow rate, and fluid composition at the sink node. It is updated each time
run(UUID)completes and can be connected to downstream process equipment.- Parameters:
sinkNodeName- name of a sink node- Returns:
- outlet stream, or null if the node does not exist or has not been solved
-
getOutletStream
Get the default outlet stream.Returns the outlet stream of the first sink node in the network. This provides a convenient single-outlet accessor for networks with one delivery point.
- Returns:
- outlet stream of the first sink node, or null if no sinks exist
-
getSourceNodeStream
Get the outlet stream for a named source node (for IPR well sources where flow is computed).- Parameters:
sourceNodeName- name of a source node- Returns:
- outlet stream at the source node, or null if not yet solved
-
getInletStreams
Returns all inlet streams connected to this equipment. Subclasses override to report their specific inlets. Used by graph builders, DEXPI export, and auto-instrumentation to discover topology withoutinstanceofchecks.- Returns:
- unmodifiable list of inlet streams (empty by default)
-
getOutletStreams
Returns all outlet streams produced by this equipment. Subclasses override to report their specific outlets. Used by graph builders, DEXPI export, and auto-instrumentation to discover topology withoutinstanceofchecks.- Returns:
- unmodifiable list of outlet streams (empty by default)
-
setFluidTemplate
Set the fluid template for the network.- Parameters:
fluid- the fluid system to use as template
-
getFluidTemplate
-
setPipeModelType
Set the pipe flow model type.- Parameters:
type- pipe model type (DARCY_WEISBACH or BEGGS_BRILL)
-
getPipeModelType
Get the pipe flow model type.- Returns:
- pipe model type
-
addSourceNode
Add a source node to the network.- Parameters:
name- node namepressureBar- fixed pressure in baraflowRateKgHr- supply flow rate in kg/hr (optional, for validation)
-
addSourceNode
Add a source node with specified elevation.- Parameters:
name- node namepressureBar- fixed pressure in baraflowRateKgHr- supply flow rate in kg/hrelevationM- node elevation in meters
-
addSinkNode
Add a sink node (demand point) to the network.- Parameters:
name- node namedemandKgHr- demand flow rate in kg/hr
-
addSinkNode
Add a sink node with specified elevation.- Parameters:
name- node namedemandKgHr- demand flow rate in kg/hrelevationM- node elevation in meters
-
addFixedPressureSinkNode
Add a fixed-pressure sink node (delivery point with specified pressure).In this mode the solver determines the flow rate that the network can deliver to this node given the upstream source pressures and network resistances. This is the "pressure-pressure" operating mode, analogous to PIPESIM's fixed-pressure deliverability calculation.
- Parameters:
name- node namepressureBar- delivery pressure in bara
-
addFixedPressureSinkNode
Add a fixed-pressure sink node with specified elevation.- Parameters:
name- node namepressureBar- delivery pressure in baraelevationM- node elevation in meters
-
addJunctionNode
Add a junction node to the network.- Parameters:
name- node name
-
addJunctionNode
Add a junction node with specified elevation.- Parameters:
name- node nameelevationM- node elevation in meters
-
addPipe
public LoopedPipeNetwork.NetworkPipe addPipe(String fromNode, String toNode, String pipeName, double lengthM, double diameterM) Add a pipe connecting two nodes.- Parameters:
fromNode- source node nametoNode- target node namepipeName- pipe namelengthM- pipe length in metersdiameterM- pipe inner diameter in meters- Returns:
- the created pipe
-
addPipe
public LoopedPipeNetwork.NetworkPipe addPipe(String fromNode, String toNode, String pipeName, double lengthM, double diameterM, double roughnessM) Add a pipe with specified roughness.- Parameters:
fromNode- source node nametoNode- target node namepipeName- pipe namelengthM- pipe length in metersdiameterM- pipe inner diameter in metersroughnessM- pipe roughness in meters- Returns:
- the created pipe
-
addWellIPR
public LoopedPipeNetwork.NetworkPipe addWellIPR(String reservoirNode, String wellboreNode, String elementName, double productivityIndexSI, boolean isGas) Add a well IPR element using the productivity index model.Creates a network element from reservoir node to wellbore node representing the inflow performance relationship. For gas wells, uses P^2 drawdown: q = PI * (Pr^2 - Pwf^2). For oil wells, uses linear drawdown: q = PI * (Pr - Pwf).
- Parameters:
reservoirNode- name of reservoir (source) node (must be fixed-pressure)wellboreNode- name of wellbore/bottomhole nodeelementName- element nameproductivityIndexSI- productivity index in kg/s/Pa (oil) or kg/s/Pa^2 (gas)isGas- true for gas wells (P^2 formulation)- Returns:
- the created element
-
addWellIPRVogel
public LoopedPipeNetwork.NetworkPipe addWellIPRVogel(String reservoirNode, String wellboreNode, String elementName, double qmaxKgS) Add a well IPR element using the Vogel model for solution-gas-drive oil wells.- Parameters:
reservoirNode- name of reservoir (source) nodewellboreNode- name of wellbore nodeelementName- element nameqmaxKgS- absolute open flow in kg/s- Returns:
- the created element
-
addWellIPRFetkovich
public LoopedPipeNetwork.NetworkPipe addWellIPRFetkovich(String reservoirNode, String wellboreNode, String elementName, double cCoeff, double nExp) Add a well IPR element using the Fetkovich model for gas wells.- Parameters:
reservoirNode- name of reservoir (source) nodewellboreNode- name of wellbore nodeelementName- element namecCoeff- Fetkovich coefficient C in kg/s/Pa^(2n)nExp- Fetkovich exponent n (0.5-1.0)- Returns:
- the created element
-
addChoke
public LoopedPipeNetwork.NetworkPipe addChoke(String fromNode, String toNode, String elementName, double kv, double openingPercent) Add a production choke element between two nodes.The choke uses a simplified valve equation: Q = Kv * (opening/100) * sqrt(dP * rho). For critical (choked) flow, the pressure drop is limited by the critical pressure ratio.
- Parameters:
fromNode- upstream node nametoNode- downstream node nameelementName- element namekv- valve flow coefficient in m3/hr per sqrt(bar)openingPercent- valve opening (0-100%)- Returns:
- the created element
-
addTubing
public LoopedPipeNetwork.NetworkPipe addTubing(String bottomNode, String topNode, String elementName, double lengthM, double diameterM, double inclinationDeg) Add wellbore tubing element (vertical lift performance).Models multiphase flow through wellbore tubing. Pressure drop includes hydrostatic head, wall friction, and flow acceleration. Uses a simplified Beggs-Brill-like approach with gravity and friction components.
- Parameters:
bottomNode- bottomhole node name (higher pressure)topNode- wellhead node name (lower pressure)elementName- element namelengthM- tubing measured depth in metersdiameterM- tubing inner diameter in metersinclinationDeg- inclination from horizontal (90 = vertical)- Returns:
- the created element
-
addMultiphasePipe
public LoopedPipeNetwork.NetworkPipe addMultiphasePipe(String fromNode, String toNode, String elementName, double lengthM, double diameterM) Add a multiphase pipeline element using Beggs-Brill correlation.Uses NeqSim's PipeBeggsAndBrills internally for accurate multiphase pressure-drop calculation. This element type is suitable for subsea flowlines and production pipelines carrying gas-oil or gas-oil-water mixtures.
- Parameters:
fromNode- upstream node nametoNode- downstream node nameelementName- element namelengthM- pipe length in metersdiameterM- pipe inner diameter in meters- Returns:
- the created element
-
addCompressor
public LoopedPipeNetwork.NetworkPipe addCompressor(String fromNode, String toNode, String elementName, double polytropicEfficiency) Add a compressor or booster station element between two nodes.The compressor adds energy to the flow (negative head loss). Head rise is calculated from polytropic efficiency and compression ratio, or from a performance chart if provided. Wraps NeqSim's
Compressorclass internally.- Parameters:
fromNode- suction (upstream) node nametoNode- discharge (downstream) node nameelementName- element namepolytropicEfficiency- polytropic efficiency (0-1, typically 0.70-0.85)- Returns:
- the created element
-
addCompressorWithChart
public LoopedPipeNetwork.NetworkPipe addCompressorWithChart(String fromNode, String toNode, String elementName, Compressor compressor) Add a compressor with a performance chart (speed curves).When a chart is provided, the head-flow relationship follows the compressor curve at the specified speed. The solver iterates to find the operating point on the curve.
- Parameters:
fromNode- suction node nametoNode- discharge node nameelementName- element namecompressor- pre-configured NeqSimCompressorwith chart- Returns:
- the created element
-
addRegulator
public LoopedPipeNetwork.NetworkPipe addRegulator(String fromNode, String toNode, String elementName, double setPointBar) Add a pressure regulator (PRV) element between two nodes.The regulator maintains a fixed downstream pressure set-point. If upstream pressure is above the set-point, the regulator throttles to deliver exactly the set-point downstream. If upstream pressure falls below the set-point, the regulator is fully open (acts as a pipe).
- Parameters:
fromNode- upstream node nametoNode- downstream node nameelementName- element namesetPointBar- downstream pressure set-point in bara- Returns:
- the created element
-
setGasLift
Configure gas lift on an existing well tubing or IPR element.Gas lift reduces the hydrostatic head in the tubing by injecting gas, effectively reducing the pressure drop from bottomhole to wellhead. The model applies a head-loss reduction factor based on the injection rate.
- Parameters:
elementName- name of the well element (IPR or tubing)gasLiftRateKgHr- gas lift injection rate in kg/hr
-
setESP
Configure an Electrical Submersible Pump (ESP) on a well element.The ESP adds a negative head-loss (pressure boost) to the tubing element, calculated as: dP = espPower * efficiency / volumetricFlowRate. This enables production from wells that cannot flow naturally.
- Parameters:
elementName- name of the well element (IPR or tubing)ratedPowerKW- ESP rated power in kWefficiency- pump efficiency (0-1, typically 0.3-0.7)
-
setJetPump
Configure a jet pump on a well element.The jet pump uses high-pressure power fluid to create a pressure boost via a venturi effect. Modeled similarly to ESP with an equivalent power and efficiency.
- Parameters:
elementName- name of the well elementequivalentPowerKW- equivalent hydraulic power in kWefficiency- nozzle-throat efficiency (typically 0.2-0.4)
-
setRodPump
Configure a rod pump (beam pump) on a well element.The rod pump provides artificial lift for low-rate wells. Modeled as an equivalent pressure boost based on pump displacement and stroke rate.
- Parameters:
elementName- name of the well elementequivalentPowerKW- equivalent mechanical power in kWefficiency- pump efficiency (typically 0.4-0.6)
-
getTotalGasLiftRate
public double getTotalGasLiftRate()Get the total gas lift injection rate across all wells in kg/hr.- Returns:
- total gas lift rate in kg/hr
-
getTotalESPPower
public double getTotalESPPower()Get the total ESP power consumption across all wells in kW.- Returns:
- total ESP power in kW
-
setWaterCut
Set the water cut for a well or pipe element.Water cut is the volume fraction of water in the total liquid production. This enables produced water tracking through the network for water treatment sizing and disposal planning.
- Parameters:
elementName- name of the elementwaterCut- water cut fraction (0-1)
-
addWaterInjection
public LoopedPipeNetwork.NetworkPipe addWaterInjection(String sourceNode, String reservoirNode, String elementName, double injectionRateKgHr) Add a water injection well element between two nodes.Water injection wells provide pressure support to reservoirs. The injection rate creates a negative flow (into the reservoir) and increases reservoir pressure.
- Parameters:
sourceNode- water supply nodereservoirNode- reservoir nodeelementName- element nameinjectionRateKgHr- injection rate in kg/hr- Returns:
- the created element
-
calculateWaterBalance
Calculate water balance for the entire network.Tracks water production at each node based on water cuts and flow rates. Also tracks water injection rates. Returns per-node water balance: [0] = water production (kg/hr), [1] = water injection (kg/hr), [2] = net water (kg/hr).
- Returns:
- map of node name to water balance array
-
getTotalWaterProduction
public double getTotalWaterProduction()Get total water production rate in kg/hr.- Returns:
- total water production
-
getTotalWaterInjection
public double getTotalWaterInjection()Get total water injection rate in kg/hr.- Returns:
- total water injection
-
setWaterBreakthrough
public void setWaterBreakthrough(String elementName, double breakthroughWC, double finalWC, double currentWC) Set the water breakthrough profile for a well (time-dependent water cut).Models water breakthrough as a function of cumulative production. When the cumulative production from a well exceeds the breakthrough threshold, the water cut ramps up linearly to the final water cut.
- Parameters:
elementName- well element namebreakthroughWC- water cut at breakthrough (typically 0.05-0.10)finalWC- ultimate water cut (typically 0.80-0.95)currentWC- current water cut
-
setSandRate
Set the sand production rate for a well element.- Parameters:
elementName- well element namesandRateKgHr- sand production rate in kg/hr
-
setMaxAllowableSandRate
public void setMaxAllowableSandRate(double maxRateKgHr) Set the maximum allowable sand production rate.- Parameters:
maxRateKgHr- maximum sand rate in kg/hr (0 = no limit)
-
setMaxAllowableErosionRate
public void setMaxAllowableErosionRate(double maxRateMmYr) Set the maximum allowable erosion rate for integrity management.- Parameters:
maxRateMmYr- maximum erosion rate in mm/yr (default 5.0)
-
calculateSandTransport
Calculate sand transport and erosion rates for all pipe elements.Sand erosion rate is calculated using the DNV RP O501 simplified model: E = K * F(alpha) * v^n * d_p / (rho_t * A) where K is material constant, F(alpha) is impact angle function, v is velocity, d_p is particle size, rho_t is target material density, A is pipe cross-section area. For the simplified API approach: E_rate = C_sand * rho_sand * V^2 / (rho_pipe * t_wall)
- Returns:
- map of pipe name to sand results: [0]=sandConc_kgm3, [1]=erosionRate_mmyr, [2]=depositionRate_kgmyr, [3]=sandVelocity_ms
-
getSandViolations
-
setCorrosiveGas
Set CO2 and H2S mole fractions for a pipe element for corrosion calculation.- Parameters:
elementName- pipe element nameco2MoleFrac- CO2 mole fraction in gas phase (0-1)h2sMoleFrac- H2S mole fraction in gas phase (0-1)
-
setCorrosionModel
-
setMinAllowableWallLife
public void setMinAllowableWallLife(double years) Set the minimum allowable remaining wall life.- Parameters:
years- minimum years before wall thickness falls below minimum
-
calculateCorrosion
Calculate CO2/H2S corrosion rates for all pipe elements.Supports two corrosion models:
- de Waard-Milliams (1975/1991): log10(Vcorr) = 5.8 - 1710/T + 0.67*log10(pCO2) where T is temperature in K and pCO2 is CO2 partial pressure in bar.
- NORSOK M-506 (2005): Vcorr = K_t * f(T) * (fCO2)^0.62 * (S/19)^0.146 + f(Vwall) which includes temperature, CO2 fugacity, shear stress, and pH effects.
- Returns:
- map of pipe name to corrosion results: [0]=corrosionRate_mmyr, [1]=co2PartialPressure_bar, [2]=h2sPartialPressure_bar, [3]=remainingLife_yr
-
getCorrosionViolations
-
setCO2EmissionFactor
public void setCO2EmissionFactor(double factor) Set the CO2 emission factor for fuel gas combustion.- Parameters:
factor- emission factor in kgCO2 per kg fuel gas (default 2.75 for natural gas)
-
getCO2EmissionFactor
public double getCO2EmissionFactor()Get the CO2 emission factor.- Returns:
- kgCO2 per kg fuel gas
-
setMethaneSlipFactor
public void setMethaneSlipFactor(double slipFraction) Set the methane slip factor for gas turbine/engine drivers.- Parameters:
slipFraction- fraction of unburned methane (0-1, default 0.02 = 2%)
-
calculateEmissions
Calculate greenhouse gas emissions for all compressor stations in the network.Emissions are calculated from fuel gas consumption (from compressor power and heat rate). Results include: CO2 from combustion, methane slip (unburned CH4), and CO2-equivalent (using GWP=28 for CH4 per IPCC AR5). Per-compressor breakdown is returned.
- Returns:
- map of compressor element name to emissions array: [0]=CO2_kghr, [1]=CH4_slip_kghr, [2]=CO2eq_kghr, [3]=power_kW, [4]=fuelGas_kghr
-
getTotalCO2Emissions
public double getTotalCO2Emissions()Get total CO2-equivalent emissions from all compressors in kg/hr.- Returns:
- total CO2eq emissions in kg/hr
-
getAnnualCO2EmissionsTonnes
public double getAnnualCO2EmissionsTonnes()Get annual CO2-equivalent emissions in tonnes/year.- Returns:
- annual CO2eq in tonnes/yr
-
getEmissionsIntensity
public double getEmissionsIntensity()Get emissions intensity in kgCO2eq per tonne of production.- Returns:
- emissions intensity (kgCO2eq/tonne product)
-
setNodeFluid
Set the fluid composition for a specific source node.Enables compositional tracking where different wells/sources have different fluid compositions. At junction nodes, fluids are mixed weighted by mass flow from each incoming pipe. This provides accurate gas quality (heating value, Wobbe index) and phase behavior at each node.
- Parameters:
sourceNodeName- name of the source nodefluid- the fluid composition at this source
-
getNodeFluid
Get the fluid composition at a specific node (after solving with compositional tracking).- Parameters:
nodeName- node name- Returns:
- fluid at this node, or the template fluid if compositional tracking is not used
-
getErosionalVelocityViolations
Get erosional velocity violations after solving.Returns a list of pipe names where the actual velocity exceeds the API RP 14E erosional velocity limit:
V_erosional = C / sqrt(rho_mixture)where C is typically 100-150.- Returns:
- list of violation descriptions (empty if no violations)
-
setPipeEfficiency
Set pipe efficiency factor for a named pipe.The efficiency factor accounts for pipe aging, internal fouling, wax deposition, or scale build-up. A factor of 1.0 means new pipe; 0.85 means 15% degradation. The friction loss is multiplied by
1/efficiency.- Parameters:
pipeName- pipe nameefficiency- efficiency factor (0.5-1.0, typically 0.85-1.0)
-
getNode
Get a node by name.- Parameters:
name- node name- Returns:
- the node
-
getPipe
Get a pipe by name.- Parameters:
name- pipe name- Returns:
- the pipe
-
getMassBalanceError
public double getMassBalanceError()Get mass balance error from last solve in kg/s.- Returns:
- mass balance error
-
setSolverType
Set the solver type.- Parameters:
type- solver type
-
getSolverType
-
setTolerance
public void setTolerance(double tol) Set convergence tolerance for head loss balance (Pa).- Parameters:
tol- tolerance in Pa
-
getTolerance
public double getTolerance()Get convergence tolerance.- Returns:
- tolerance in Pa
-
setMaxIterations
public void setMaxIterations(int max) Set maximum number of iterations.- Parameters:
max- maximum iterations
-
getMaxIterations
public int getMaxIterations()Get maximum iterations.- Returns:
- max iterations
-
setRelaxationFactor
public void setRelaxationFactor(double factor) Set relaxation factor for Hardy Cross (0 < factor <= 1).- Parameters:
factor- relaxation factor
-
getRelaxationFactor
public double getRelaxationFactor()Get relaxation factor.- Returns:
- relaxation factor
-
getIterationCount
public int getIterationCount()Get number of iterations in last solve.- Returns:
- iteration count
-
getMaxResidual
public double getMaxResidual()Get maximum residual from last iteration.- Returns:
- max residual in Pa
-
isConverged
public boolean isConverged()Check if solution converged.- Returns:
- true if converged
-
getLoops
-
getNumberOfLoops
public int getNumberOfLoops()Get number of loops in the network.- Returns:
- number of loops
-
getPipeNames
-
getPipeFlowRate
Get flow rate for a specific pipe in kg/hr.- Parameters:
pipeName- pipe name- Returns:
- flow rate in kg/hr
-
getNodePressure
Get pressure at a node in bara.- Parameters:
nodeName- node name- Returns:
- pressure in bara
-
getNodeFlowRate
Get the net delivered flow rate at a node in kg/hr.Computes the net inflow to the node: sum of incoming pipe flows minus outgoing. For a source node this is negative (supply). For a sink node this is the delivered flow rate. Useful in pressure-pressure mode where the delivered flow is not specified but computed by the solver.
- Parameters:
nodeName- node name- Returns:
- net delivered flow in kg/hr (positive = net inflow to node)
-
initializeFlowEstimates
private void initializeFlowEstimates()Initialize pipe flow estimates using BFS spanning tree to satisfy mass balance.Builds a spanning tree from source nodes using BFS. Tree-edge flows are set to satisfy mass balance at every node (required for Hardy Cross). Non-tree edges (loop closers) are initialized to zero — the loop solver will correct them.
-
calculateHeadLoss
Calculate head loss for a network element based on its type.Dispatches to the appropriate head loss model depending on the element type: Darcy-Weisbach pipe, well IPR, production choke, tubing VLP, or multiphase pipe.
- Parameters:
pipe- the network elementfluid- fluid properties- Returns:
- head loss in Pa (positive = pressure drop from-to direction)
-
calculateHeadLossDarcyWeisbach
private double calculateHeadLossDarcyWeisbach(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate head loss for a standard pipe using Darcy-Weisbach equation with elevation.- Parameters:
pipe- the pipefluid- fluid properties- Returns:
- head loss in Pa
-
calculateHeadLossIPR
Calculate head loss for a well IPR element.Models the reservoir-to-wellbore pressure relationship. For a given flow rate Q:
- PI model (oil): dP = Q / PI
- PI model (gas): Pr^2 - Pwf^2 = Q / PI, so dP = Pr - sqrt(Pr^2 - Q/PI)
- Vogel: q/qmax = 1 - 0.2*(Pwf/Pr) - 0.8*(Pwf/Pr)^2
- Fetkovich: q = C * (Pr^2 - Pwf^2)^n
- Parameters:
pipe- the IPR elementfluid- fluid properties (not used directly, IPR is empirical)- Returns:
- head loss in Pa
-
calculateHeadLossChoke
Calculate head loss for a production choke element.Uses a simplified valve equation: Q = Kv * (opening/100) * sqrt(dP * rho / SG_ref). Inverting: dP = (Q / (Kv_eff))^2 / rho where Kv_eff = Kv * (opening/100) converted to SI.
For critical (choked) flow, the effective dP is limited by the critical pressure ratio.
- Parameters:
pipe- the choke elementfluid- fluid properties- Returns:
- head loss in Pa
-
calculateHeadLossTubing
Calculate head loss for wellbore tubing (VLP) element.Simplified multiphase vertical lift model with gravity and friction components: dP = dP_gravity + dP_friction = rho * g * L * sin(theta) + f * (L/D) * (rho * v^2 / 2)
- Parameters:
pipe- the tubing elementfluid- fluid properties- Returns:
- head loss in Pa (positive = pressure drop bottom-to-top)
-
calculateHeadLossMultiphase
private double calculateHeadLossMultiphase(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate head loss for a multiphase pipe using simplified Beggs-Brill approach.When the fluid template has multiple phases, this uses a mixture density and viscosity for the pressure drop calculation. For single-phase conditions, it degenerates to Darcy-Weisbach. Elevation is incorporated via sin(angle) where angle is calculated from pipe-level elevation difference.
- Parameters:
pipe- the multiphase pipe elementfluid- fluid properties- Returns:
- head loss in Pa
-
calculateHeadLossCompressor
private double calculateHeadLossCompressor(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate head loss for a compressor element.Compressors add energy to the flow, so they produce a negative head loss (pressure rise). The pressure rise is computed from the polytropic efficiency and compression ratio, or from a performance chart if available.
- Parameters:
pipe- the compressor elementfluid- fluid properties- Returns:
- head loss in Pa (negative = pressure rise)
-
calculateHeadLossRegulator
private double calculateHeadLossRegulator(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate head loss for a pressure regulator element.The regulator maintains a fixed downstream pressure set-point. When upstream pressure exceeds the set-point, the regulator throttles: ΔP = P_upstream - P_setpoint. When upstream is below the set-point, the regulator is fully open (minimal resistance).
- Parameters:
pipe- the regulator elementfluid- fluid properties (used for velocity calculation only)- Returns:
- head loss in Pa
-
calculateHeadLossDerivative
private double calculateHeadLossDerivative(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate derivative of head loss with respect to flow rate for any element type.- Parameters:
pipe- the network elementfluid- fluid properties- Returns:
- dh/dQ in Pa/(kg/s)
-
calculateHeadLossDerivativeIPR
Calculate dh/dQ for IPR element.- Parameters:
pipe- the IPR element- Returns:
- dh/dQ in Pa/(kg/s)
-
calculateHeadLossDerivativeChoke
private double calculateHeadLossDerivativeChoke(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate dh/dQ for choke element.- Parameters:
pipe- the choke elementfluid- fluid properties- Returns:
- dh/dQ in Pa/(kg/s)
-
calculateHeadLossDerivativeCompressor
private double calculateHeadLossDerivativeCompressor(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate dh/dQ for compressor element.For a compressor (which produces a pressure rise), the head loss is negative. The derivative reflects how the pressure rise changes with flow. At high flow, head decreases per the compressor curve. A first-order approximation uses 2|h|/Q.
- Parameters:
pipe- the compressor elementfluid- fluid properties- Returns:
- dh/dQ in Pa/(kg/s) — typically negative (head rise decreases with more flow)
-
calculateHeadLossDerivativeRegulator
private double calculateHeadLossDerivativeRegulator(LoopedPipeNetwork.NetworkPipe pipe, SystemInterface fluid) Calculate dh/dQ for regulator (pressure reducing valve) element.A regulator maintains a set-point downstream pressure. When it is active (upstream pressure above set-point), the pressure drop is nearly independent of flow, so the derivative is small.
- Parameters:
pipe- the regulator elementfluid- fluid properties- Returns:
- dh/dQ in Pa/(kg/s)
-
detectLoops
private void detectLoops()Detect loops in the network using DFS spanning tree algorithm. -
runHardyCross
Run Hardy Cross iterative solver.- Parameters:
id- calculation identifier
-
runSequential
Run sequential solver for tree networks.- Parameters:
id- calculation identifier
-
initializePipeModels
private void initializePipeModels()Initialize AdiabaticPipe models for each pipe. -
updateNodePressures
Update node pressures based on calculated head losses.- Parameters:
fluid- fluid for calculations
-
propagatePressure
Propagate pressure from a node to connected nodes.- Parameters:
nodeName- starting node namefluid- fluid for calculations
-
run
Description copied from interface:SimulationInterfaceIn this method all thermodynamic and unit operations will be calculated in a steady state calculation.
- Parameters:
id- UUID
-
updatePipeHydraulicProperties
private void updatePipeHydraulicProperties()Update hydraulic properties (velocity, Reynolds, friction factor) for all pipes. -
updateCompositionalMixing
public void updateCompositionalMixing()Update compositional mixing at junction nodes.When different source nodes have different fluid compositions (set via
setNodeFluid(String, SystemInterface)), this method traces flows through the network and calculates mass-weighted mixed compositions at junction nodes. The resulting mixed fluid at each node is stored in thenodeFluidMap.Call this after the network has converged to determine gas quality (heating value, Wobbe index) at each delivery point.
-
checkErosionalVelocity
Check erosional velocity limits per API RP 14E for all pipe elements.The erosional velocity is calculated as:
V_e = C / sqrt(rho_mixture)
where C is the empirical constant (default 125 for continuous service, 100-150 typical range) and rho_mixture is the mixture density in kg/m3. Pipes where the actual velocity exceeds the erosional velocity are flagged as violations.
- Returns:
- list of violation descriptions (empty if all pipes are within limits)
-
calculateGasQuality
Calculate gas quality properties at every node that has an assigned fluid composition.Uses NeqSim's
Standard_ISO6976implementation to compute ISO 6976 properties at each node: superior (gross) calorific value, inferior (net) calorific value, Wobbe index, and relative density. CallupdateCompositionalMixing()first to propagate compositions through the network.Results are stored per node and accessible via
getNodeGasQuality(String). The returned array contains: [0] = Superior Wobbe Index (MJ/Sm3), [1] = Superior Calorific Value (kJ/Sm3), [2] = Inferior Calorific Value (kJ/Sm3), [3] = Relative Density.- Returns:
- map of node name to gas quality array [Wobbe, HHV, LHV, relDens]
-
getNodeGasQuality
Get gas quality properties at a specific node.Returns null if gas quality has not been calculated or the node has no assigned fluid. Call
calculateGasQuality()first.- Parameters:
nodeName- name of the node- Returns:
- array of [Wobbe (MJ/Sm3), HHV (kJ/Sm3), LHV (kJ/Sm3), RelDens], or null
-
checkGasQualityLimits
Check if gas quality at all sink (delivery) nodes meets the specified Wobbe index bounds.Typical H-gas Wobbe bounds: 46.44-52.81 MJ/Sm3 (EN 16726). Call
calculateGasQuality()first.- Parameters:
wobbeMin- minimum acceptable Wobbe index in MJ/Sm3wobbeMax- maximum acceptable Wobbe index in MJ/Sm3- Returns:
- list of violation descriptions (empty if all sinks are within spec)
-
calculateOilQuality
Calculate oil quality properties (TVP and RVP) at every node that has an assigned fluid composition.True Vapor Pressure (TVP) is the bubble-point pressure at the node's actual flowing temperature. Reid Vapor Pressure (RVP) is calculated per ASTM D6377 at the standard reference temperature of 37.8 deg C (100 deg F). Both are key oil quality metrics for pipeline transport, storage tank design, and emissions control.
Results are stored per node and accessible via
getNodeOilQuality(String). The returned array contains: [0] = TVP (bara), [1] = RVP (bara), [2] = VPCR4 (bara).- Returns:
- map of node name to oil quality array [TVP_bara, RVP_bara, VPCR4_bara]
-
estimateNodeTemperature
Estimate the node temperature in Kelvin.For source nodes, uses the inlet fluid temperature. For other nodes, uses 15 deg C as a default. This can be overridden with per-node temperature data if available.
- Parameters:
nodeName- the node name- Returns:
- temperature in Kelvin
-
getNodeOilQuality
Get oil quality properties at a specific node.Returns null if oil quality has not been calculated or the node has no assigned fluid. Call
calculateOilQuality()first.- Parameters:
nodeName- name of the node- Returns:
- array of [TVP (bara), RVP (bara), VPCR4 (bara)], or null
-
checkOilQualityLimits
Check if oil quality at all sink (delivery) nodes meets the specified TVP and RVP limits.TVP limits are typically driven by storage tank design pressure and emission regulations. RVP limits depend on crude classification and regional regulations (e.g., EPA, ASTM D4953). Typical pipeline crude specifications: TVP max 1.0 bara (atmospheric storage), RVP max 0.69 bara (10 psi) for light crude. Call
calculateOilQuality()first.- Parameters:
tvpMaxBara- maximum acceptable TVP in bara at deliveryrvpMaxBara- maximum acceptable RVP in bara at delivery- Returns:
- list of violation descriptions (empty if all sinks are within spec)
-
nodalAnalysis
public Map<String,double[]> nodalAnalysis(String iprElementName, String outflowElementName, int numPoints) Perform nodal analysis for a well defined by an IPR element and an outflow (tubing/pipe/choke) element downstream of the well node.Sweeps bottom-hole pressure from near-zero to reservoir pressure, computing the IPR flow rate and the VLP (vertical lift performance) flow rate at each point. The operating point is the intersection where IPR rate equals VLP rate. This is standard well deliverability analysis per Beggs (Production Optimization) and Brown & Lea.
The returned map contains:
- "bhp" - array of bottom-hole pressures in bara (sweep points)
- "iprRate" - array of IPR flow rates in kg/hr at each BHP
- "vlpRate" - array of VLP flow rates in kg/hr at each BHP (backpressure-derived)
- "operatingBHP" - single value, operating BHP in bara
- "operatingRate" - single value, operating rate in kg/hr
- Parameters:
iprElementName- name of the WELL_IPR elementoutflowElementName- name of the downstream element (pipe, choke, or tubing)numPoints- number of sweep points (default 20 if <= 0)- Returns:
- map with nodal analysis arrays, or empty map if elements not found
-
computeIPRFlowRate
private double computeIPRFlowRate(LoopedPipeNetwork.NetworkPipe iprPipe, double pResPa, double bhpPa) Compute IPR flow rate at a given bottom-hole pressure.- Parameters:
iprPipe- the IPR elementpResPa- reservoir pressure in PabhpPa- bottom-hole pressure in Pa- Returns:
- flow rate in kg/s (positive)
-
estimateVLPRate
Estimate VLP (outflow) rate at a given bottom-hole pressure.For a pipe/choke downstream of the well, this estimates the flow rate that the outflow system can deliver given the available driving pressure (BHP minus downstream network pressure).
- Parameters:
outPipe- the outflow elementbhpPa- available bottom-hole pressure in Pa- Returns:
- flow rate in kg/s (positive)
-
setNodePressureLimits
Set pressure limits for a node.After solving the network, call
checkConstraints()to verify pressures at all constrained nodes are within bounds. This enables safety envelope checking for minimum arrival pressure, maximum allowable working pressure, hydrate formation limits, etc.- Parameters:
nodeName- name of the nodeminPressureBar- minimum acceptable pressure in baramaxPressureBar- maximum acceptable pressure in bara
-
setElementFlowLimits
Set flow rate limits for a network element (pipe, choke, compressor, etc.).Limits are checked after the network is solved. This enables enforcement of choke rate limits, compressor minimum/maximum flow, pipeline capacity limits, etc.
- Parameters:
elementName- name of the elementminFlowKgHr- minimum acceptable flow rate in kg/hr (use 0 for no minimum)maxFlowKgHr- maximum acceptable flow rate in kg/hr
-
checkConstraints
Check all defined constraints and return any violations.Verifies:
- Node pressures within min/max bounds (set via
setNodePressureLimits(String, double, double)) - Element flow rates within min/max bounds (set via
setElementFlowLimits(String, double, double))
- Returns:
- list of constraint violation descriptions (empty if all constraints satisfied)
- Node pressures within min/max bounds (set via
-
getConstraintViolations
Get the list of constraint violations from the lastcheckConstraints()call.- Returns:
- list of violation descriptions
-
setFuelGasHeatRate
public void setFuelGasHeatRate(double heatRateKJPerKWh) Set the fuel gas heat rate for gas-turbine driven compressors.The heat rate defines how much fuel energy is consumed per unit of mechanical work. Typical values: 9,000-12,000 kJ/kWh for industrial gas turbines, 3,600 kJ/kWh for electric drives (ideal).
- Parameters:
heatRateKJPerKWh- fuel gas heat rate in kJ/kWh
-
getFuelGasHeatRate
public double getFuelGasHeatRate()Get the fuel gas heat rate in kJ/kWh.- Returns:
- heat rate
-
calculateFuelGasConsumption
Calculate fuel gas consumption for all compressor elements in the network.For each compressor element, computes fuel gas rate from shaft power and driver heat rate:
fuelRate_kgs = (power_kW * heatRate_kJperkWh) / (LHV_kJperkg * 3600)
where LHV is the lower heating value of the gas at the compressor suction node. If gas quality has been calculated via
calculateGasQuality(), the LHV from ISO 6976 is used. Otherwise a default of 47,000 kJ/kg (typical natural gas) is assumed.The total fuel gas rate is the sum across all compressors and can be accessed via
getTotalFuelGasRate().- Returns:
- map of compressor element name to fuel gas rate in kg/hr
-
estimateCompressorPower
Estimate compressor shaft power from polytropic head calculation.- Parameters:
compPipe- the compressor element- Returns:
- estimated power in kW
-
getTotalFuelGasRate
public double getTotalFuelGasRate()Get the total fuel gas consumption rate for all compressors in the network.Call
calculateFuelGasConsumption()first to populate this value.- Returns:
- total fuel gas rate in kg/hr
-
getFuelGasPercentage
public double getFuelGasPercentage()Get the fuel gas consumption as a percentage of total network throughput.This is the "self-consumption" ratio: how much of the transported gas is consumed as compressor fuel. Typical values: 1-3% for gas transmission, 0% for electric drives.
- Returns:
- fuel gas percentage of total sink flow (0-100)
-
optimizeChokeOpenings
public double optimizeChokeOpenings(int maxIterations, double tolerance) Optimize choke openings to maximize total production from all wells.Uses a gradient-based optimization approach: for each choke element, perturb the opening slightly, re-solve the network, and compute the sensitivity of total production to the choke opening. Then adjust openings in the direction of increasing total production.
The optimization respects constraints: choke openings between 0-100%, and downstream pressure/erosional limits.
- Parameters:
maxIterations- maximum number of optimization iterationstolerance- convergence tolerance for relative change in total production- Returns:
- total optimized production in kg/s
-
getTotalSinkFlow
public double getTotalSinkFlow()Get total flow rate into all sink nodes (total network production).- Returns:
- total sink inflow in kg/s (positive value)
-
exportVFPTables
public void exportVFPTables(String filePath, double[] flowRates, double[] thps, double[] waterCuts, double[] gors) Export VFP (Vertical Flow Performance) tables for well elements in the network.Generates Eclipse E300-compatible VFPPROD/VFPINJ tables using the
EclipseVFPExporter. For each well (IPR + tubing) element pair, this method creates a VFP table covering the specified flow rate, THP, and parameter ranges.- Parameters:
filePath- the file path to write VFP tables toflowRates- array of flow rates (Sm3/d) for VFP tablethps- array of tubing head pressures (bara) for VFP tablewaterCuts- array of water cuts (fraction) for VFP tablegors- array of gas-oil ratios (Sm3/Sm3) for VFP table
-
generateBHPTable
private double[][][][][] generateBHPTable(LoopedPipeNetwork.NetworkPipe pipe, double[] flowRates, double[] thps, double[] waterCuts, double[] gors) Generate BHP table for a well element across parameter ranges.- Parameters:
pipe- the well element (IPR or tubing)flowRates- flow rates to evaluate (Sm3/d)thps- tubing head pressures (bara)waterCuts- water cut values (fraction)gors- GOR values (Sm3/Sm3)- Returns:
- 5D BHP table: [flow][thp][wc][gor][alq]
-
setOilPrice
public void setOilPrice(double pricePerKg) Set oil price for revenue-based optimization.- Parameters:
pricePerKg- oil price in USD/kg (e.g., 0.50 for ~$80/bbl crude)
-
setGasPrice
public void setGasPrice(double pricePerKg) Set gas price for revenue-based optimization.- Parameters:
pricePerKg- gas price in USD/kg
-
setWellPrice
Set per-well product price for revenue allocation.- Parameters:
wellOrChokeName- name of the well IPR or choke elementpricePerKg- product price in USD/kg
-
optimizeProduction
public double optimizeProduction(int maxIterations, double tolerance) Optimize choke openings to maximize revenue (price-weighted production).Uses adaptive gradient ascent with Armijo backtracking line search. Supports revenue-based objective (price x rate) and respects constraint limits set via
setNodePressureLimits(String, double, double)andsetElementFlowLimits(String, double, double).- Parameters:
maxIterations- maximum number of optimization iterationstolerance- convergence tolerance for relative revenue change- Returns:
- optimized total revenue in USD/hr (or total flow in kg/hr if no prices set)
-
computeObjective
private double computeObjective()Compute the optimization objective (revenue or total flow).- Returns:
- objective value
-
computeConstrainedObjective
private double computeConstrainedObjective()Compute objective with penalty for constraint violations.- Returns:
- penalized objective
-
buildWellAllocationReport
private void buildWellAllocationReport()Build per-well allocation report after optimization. -
getWellAllocationResults
-
sensitivityAnalysis
public Map<String,double[]> sensitivityAnalysis(String elementName, String parameterType, double[] values) Run sensitivity analysis by sweeping a parameter across a range.Supported parameter types: "reservoir_pressure", "well_pi", "choke_opening", "sink_pressure", "pipe_diameter".
- Parameters:
elementName- name of the element to sweepparameterType- type of parameter to varyvalues- array of parameter values to evaluate- Returns:
- map with keys "paramValues", "totalFlow_kghr", "sinkPressures_bara" containing results
-
applyParameterValue
-
productionForecast
Run a production forecast with declining reservoir pressure over time.At each timestep, reservoir pressures are updated for all well IPR elements and the network is re-solved. Returns time-series of production rates, pressures, and cumulative production.
- Parameters:
reservoirPressures- array of reservoir pressures (bara) at each timesteptimestepYears- array of time values (years) corresponding to each pressure- Returns:
- map with keys "time_years", "rate_kghr", "cumulative_kg", "avg_pressure_bara"
-
generateCoupledVFPTables
Generate coupled VFP tables for wells in the network.Unlike the basic
exportVFPTables(String, double[], double[], double[], double[]), this method runs the full well system (IPR + tubing/flowline) at each (Q, THP) point. The THP is applied as the boundary condition at the wellhead node and the coupled system is solved to determine BHP. This produces accurate VFP tables suitable for reservoir simulation coupling.- Parameters:
flowRates_kghr- array of flow rates (kg/hr) for VFP tablethps- array of tubing head pressures (bara) for VFP table- Returns:
- map from well name to 2D BHP table [flowRate][THP] in bara
-
computeBHPFromIPR
Compute BHP from IPR model given a flow rate.- Parameters:
iprPipe- the IPR elementpResPa- reservoir pressure in PaqKgs- flow rate in kg/s- Returns:
- bottom-hole pressure in Pa
-
estimatePressureDropAtRate
Estimate pressure drop through a network element at a given flow rate.- Parameters:
pipe- the network elementqKgs- flow rate in kg/s- Returns:
- pressure drop in Pa (positive)
-
exportCoupledVFPTables
Export coupled VFP tables to Eclipse-format files.Generates accurate VFPPROD tables by running the full well system at each operating point. Each well gets its own VFP table file.
- Parameters:
filePath- base file path for VFP filesflowRates_kghr- flow rates in kg/hrthps- tubing head pressures in bara
-
generateNetworkBackpressureCurve
public Map<String,double[]> generateNetworkBackpressureCurve(String exportNodeName, double[] flowRates_kghr) Generate network back-pressure VFP table (VFPEXP).For each delivery rate at the network export boundary, this method determines the required inlet pressure. This enables reservoir-to-facility coupled simulation by providing the facility back-pressure curve for the reservoir simulator.
- Parameters:
exportNodeName- name of the export/delivery sink nodeflowRates_kghr- array of flow rates (kg/hr) to evaluate- Returns:
- map with "flowRate_kghr" and "requiredPressure_bara" arrays
-
validateVFPPoint
public Map<String,Double> validateVFPPoint(double[][] vfpTable, double[] flowRates_kghr, double[] thps, double actualRate, double actualTHP, double actualBHP) Validate VFP table against network solution at current operating point.Runs the network and compares the actual BHP/rate/THP against the VFP table interpolated values. Reports discrepancy as a percentage error.
- Parameters:
vfpTable- 2D BHP table [flowRate][THP] from generateCoupledVFPTablesflowRates_kghr- flow rate axis values in kg/hrthps- THP axis values in baraactualRate- actual rate in kg/hractualTHP- actual THP in baraactualBHP- actual BHP in bara- Returns:
- map with "vfpBHP_bara", "actualBHP_bara", "error_pct"
-
interpolateVFP
private double interpolateVFP(double[][] table, double[] xAxis, double[] yAxis, double x, double y) Bilinear interpolation in a 2D VFP table.- Parameters:
table- BHP table [flowRate][THP]xAxis- flow rate axisyAxis- THP axisx- query flow ratey- query THP- Returns:
- interpolated BHP
-
getNetworkReport
Get a summary report of the network solution including gas quality at each node.This method provides a comprehensive report with node pressures, pipe flows, element types, erosional velocity checks, and compositional data at each node. Useful for verifying network convergence and identifying potential issues.
- Returns:
- formatted report string
-
initializeFreeNodePressures
Initialize pressures for free (non-fixed) nodes using BFS propagation from fixed-pressure nodes. This produces a reasonable pressure gradient across the network, especially important for production networks where junctions sit between high-pressure sources and low-pressure sinks.- Parameters:
freeNodeList- names of free nodes needing pressure initialization
-
bfsDistances
-
runNewtonRaphson
Run Newton-Raphson Global Gradient Algorithm (Todini-Pilati, 1988).Solves the system of nodal mass balance equations + pipe head loss equations simultaneously using a Newton-Raphson scheme. This is the algorithm used by EPANET and PIPESIM Network.
The method solves: [A11 A12] [dQ] = [f1] where A11 = diag(dh/dQ), A12 = incidence matrix, [A21 0 ] [dH] = [f2] A21 = A12^T, f1 = head residuals, f2 = flow residuals
- Parameters:
id- calculation identifier
-
solveLinearSystem
private double[] solveLinearSystem(double[][] matA, double[] vecB, int n) Solve a linear system Ax = b using the best available solver.Delegates to
NetworkLinearSolver.solve(double[][], double[], int)which automatically selects sparse CSC LU (for n > 30), dense EJML LU, or Gaussian elimination with partial pivoting as a fallback.- Parameters:
matA- coefficient matrix (n x n)vecB- right-hand side vector (n)n- system size- Returns:
- solution vector x
-
calculateMassBalanceError
private void calculateMassBalanceError()Calculate overall mass balance error for the network. -
applyFeedStreams
private void applyFeedStreams()Apply conditions from connected feed streams to their corresponding source nodes.For each registered feed stream, updates the source node's pressure and supply flow rate from the stream's current state. Also updates the fluid template from the first feed stream if not already set.
-
updateOutletStreams
private void updateOutletStreams()Create or update outlet streams at sink nodes with the solved network state.For each sink node, creates a
Streamcontaining the fluid at the solved pressure, temperature, and flow rate. These streams can be connected to downstream process equipment in aProcessSystem. -
validate
-
getPipeVelocity
Get pipe velocity in m/s.- Parameters:
pipeName- pipe name- Returns:
- velocity in m/s (after solving)
-
getPipeHeadLoss
Get head loss for a specific pipe in bara.- Parameters:
pipeName- pipe name- Returns:
- head loss in bara
-
getPipeReynoldsNumber
Get Reynolds number for a specific pipe.- Parameters:
pipeName- pipe name- Returns:
- Reynolds number (dimensionless, after solving)
-
getPipeFrictionFactor
Get Darcy friction factor for a specific pipe.- Parameters:
pipeName- pipe name- Returns:
- friction factor (dimensionless, after solving)
-
getPipeFlowRegime
-
getSolutionSummary
-
toJson
Description copied from class:ProcessEquipmentBaseClassSerializes the Process Equipment along with its state to a JSON string.
- Specified by:
toJsonin interfaceProcessEquipmentInterface- Overrides:
toJsonin classProcessEquipmentBaseClass- Returns:
- json string.
-
setNodePressure
Set the pressure of an existing node.Convenience method to update a node's pressure without recreating it. For source nodes this changes the reservoir pressure. For sink nodes this changes the delivery pressure (back- pressure). Throws
IllegalArgumentExceptionif the node does not exist.- Parameters:
nodeName- name of the existing nodepressureBar- new pressure in bara
-
setReservoirPressure
Set the reservoir pressure for all IPR wells connected to a given source node.Updates both the source node pressure and the reservoir-pressure parameter on each connected IPR element. This is the correct API when modelling reservoir depletion.
- Parameters:
sourceNodeName- name of the reservoir source nodepressureBar- new reservoir pressure in bara
-
setTopsideModel
Set the topside process model to couple with the network.When a topside model is set, calling
runCoupled()will iterate between the network solver and the topside separator/compressor model until the arrival pressure converges. The topside model should be aProcessSystemcontaining at minimum an inlet separator.- Parameters:
topside- the topsideProcessSystemsinkNodeName- the network sink node to couple (the arrival point)
-
getTopsideModel
Get the coupled topside model.- Returns:
- the topside
ProcessSystem, or null if not set
-
setMaxSeparatorUtilization
public void setMaxSeparatorUtilization(double maxUtil) Set the maximum separator utilization for coupled optimisation.- Parameters:
maxUtil- maximum utilization (0.0 to 1.0), e.g. 0.90 for 90%
-
getMaxSeparatorUtilization
public double getMaxSeparatorUtilization()Get the maximum separator utilization limit.- Returns:
- max utilization (0.0 to 1.0)
-
setMaxCompressorPowerMW
public void setMaxCompressorPowerMW(double maxPowerMW) Set the maximum compressor power limit for topside coupling.- Parameters:
maxPowerMW- power limit in MW
-
getMaxCompressorPowerMW
public double getMaxCompressorPowerMW()Get the maximum compressor power limit.- Returns:
- power limit in MW
-
setCouplingToleranceBar
public void setCouplingToleranceBar(double toleranceBar) Set the coupling convergence tolerance.- Parameters:
toleranceBar- pressure tolerance in bar
-
setMaxCouplingIterations
public void setMaxCouplingIterations(int maxIter) Set the maximum coupling iterations.- Parameters:
maxIter- maximum iterations
-
runCoupled
Run the network coupled with the topside model.Solves the integrated network + topside system by iterating: (1) solve the network to get outlet flow, (2) feed the outlet stream to the topside model, (3) run the topside model, (4) evaluate topside constraints (separator utilisation, compressor power), and (5) iterate. The convergence criterion is that the network arrives at a feasible operating point where all topside constraints are satisfied.
If no topside model is set, this method simply calls
SimulationInterface.run().- Returns:
- a map with coupling results: arrivalPressure_bara, totalFlow_kghr, separatorUtilization, compressorPower_MW, converged, iterations
-
isTopsideFeasible
public boolean isTopsideFeasible()Check whether the current network state is feasible given topside constraints.- Returns:
- true if separator utilization and compressor power are within limits
-
productionForecastWithOptimization
public Map<String,double[]> productionForecastWithOptimization(Map<String, double[]> reservoirPressureProfiles, double[] timestepYears, int optimMaxIter, double optimTolerance) Run production forecast with choke re-optimisation at each timestep.This extends
productionForecast(double[], double[])by callingoptimizeProduction(int, double)at each timestep. This models how operators manage declining fields: as reservoir pressure drops, chokes are re-adjusted to maximise production or revenue. If a topside model is set, topside constraints are enforced at each timestep.- Parameters:
reservoirPressureProfiles- map from source-node name to pressure profiles (bara). Each array must have the same length as timestepYears.timestepYears- array of timestep years (e.g., 0, 1, 2, ... 20)optimMaxIter- max iterations for choke optimisation at each timestepoptimTolerance- convergence tolerance for optimisation- Returns:
- map with time-series results: time_years, rate_kghr, cumulative_kg, revenue_usd_hr, separator_util_pct, compressor_power_MW, plus per-reservoir pressures
-
productionForecastWithOptimization
public Map<String,double[]> productionForecastWithOptimization(String sourceNodeName, double[] reservoirPressures, double[] timestepYears, int optimMaxIter, double optimTolerance) Simplified production forecast with re-optimisation using a single reservoir.Convenience overload for networks with a single reservoir source node. Delegates to
productionForecastWithOptimization(Map, double[], int, double).- Parameters:
sourceNodeName- name of the reservoir source nodereservoirPressures- pressure profile (bara) at each timesteptimestepYears- array of timestep yearsoptimMaxIter- max iterations for optimisationoptimTolerance- convergence tolerance- Returns:
- time-series results map
-
loadFluidFromE300
Load a fluid template from an Eclipse E300-format file.Reads the E300 file using
EclipseFluidReadWrite.read(String, String)and sets it as the network's fluid template. The EOS type (SRK, PR, PR-LK) is determined automatically from the file. After loading, specific reservoir compositions can be set usingsetReservoirCompositionFromE300(String, String).- Parameters:
e300FilePath- path to the E300 file- Returns:
- the loaded
SystemInterfacefor further inspection
-
setReservoirCompositionFromE300
Set a reservoir node's fluid composition from a separate E300 file.Uses the same component characterisation (EOS, Tc, Pc, omega, BIPs) as the template fluid but applies a different molar composition read from the ZI section of the specified E300 file. This enables multi-reservoir networks where different reservoirs have different compositions but share the same fluid characterisation.
- Parameters:
sourceNodeName- name of the reservoir source nodee300FilePath- path to the E300 file with ZI section for this reservoir
-
setReservoirComposition
Set the molar composition for a specific reservoir source node.The composition array must have the same length and order as the fluid template's components. The template's EOS, BIPs, and component properties are preserved. Only the mole fractions change.
- Parameters:
sourceNodeName- name of the reservoir source nodemolarComposition- mole fractions (same component order as template)
-
optimizeFullField
Run full-field optimisation from reservoir to export.Combines network flow optimisation with topside equipment constraints to find the maximum revenue operating point. This is the highest-level optimisation call: it optimises choke settings, evaluates topside feasibility, and optionally sweeps arrival pressure to find the best overall operating point.
- Parameters:
optimMaxIter- max iterations for choke optimisationoptimTolerance- tolerance for optimisation convergence- Returns:
- map with results: arrivalPressure_bara, totalFlow_kghr, revenue_usd_hr, separatorUtilization, compressorPower_MW, chokeSettings (per-well)
-
fullFieldForecast
public Map<String,double[]> fullFieldForecast(Map<String, double[]> reservoirPressureProfiles, double[] timestepYears) Run a full-field lifecycle forecast from plateau through decline.Performs a complete field lifecycle simulation: at each year, updates reservoir pressures, re-optimises choke settings, runs the topside model, and records all KPIs. This is the highest-level forecast for field development planning.
- Parameters:
reservoirPressureProfiles- map from source-node name to pressure arrays (bara)timestepYears- array of years- Returns:
- comprehensive forecast results per timestep
-
attachReservoir
public void attachReservoir(String sourceNodeName, SimpleReservoir reservoir, String wellType, int wellIndex) Attach a SimpleReservoir to a source node in the network.When a reservoir is attached, the network can run coupled transient simulations where production drains the reservoir (via TV-flash material balance) and the reservoir pressure drops naturally. This replaces the need for manually-supplied pressure profiles.
The reservoir must already have the appropriate producer well added (via
addGasProduceroraddOilProducer).- Parameters:
sourceNodeName- name of the reservoir source node in the networkreservoir- the SimpleReservoir instancewellType- type of producer well: "gas" or "oil"wellIndex- index of the well in the reservoir's producer list (0-based)
-
attachReservoir
Attach a SimpleReservoir to a source node (convenience: assumes well index 0).- Parameters:
sourceNodeName- name of the reservoir source nodereservoir- the SimpleReservoir instancewellType- "gas" or "oil"
-
getAttachedReservoir
Get the attached reservoir for a source node, or null if none.- Parameters:
sourceNodeName- source node name- Returns:
- the SimpleReservoir, or null
-
hasAttachedReservoirs
public boolean hasAttachedReservoirs()Check whether any reservoirs are attached to this network.- Returns:
- true if at least one reservoir is attached
-
runTransientCoupled
public Map<String,Object> runTransientCoupled(double dtSeconds, int optimMaxIter, double optimTolerance) Run a single coupled timestep: solve network, drain reservoirs, update pressures.This is the core coupled simulation step:
- Optimise choke settings to maximise production at current reservoir pressures
- For each attached reservoir, set the well stream flow rate to match the network flow
- Call
reservoir.runTransient(dt)to deplete moles and TV-flash at fixed volume - Read the new reservoir pressure and update the network source node + IPR elements
- Parameters:
dtSeconds- timestep duration in secondsoptimMaxIter- max iterations for choke optimisation (0 to skip optimisation)optimTolerance- convergence tolerance for optimisation- Returns:
- map with post-step state: reservoir pressures, total flow, GIP/OIP
-
productionForecastCoupled
public Map<String,double[]> productionForecastCoupled(double[] timestepYears, int optimMaxIter, double optimTolerance) Run a full lifecycle forecast with coupled SimpleReservoir material balance.Unlike
productionForecastWithOptimization(Map, double[], int, double)which requires externally-supplied pressure profiles, this method computes reservoir pressure decline naturally through the thermodynamic TV-flash material balance in SimpleReservoir. Each timestep:- Network solves flow rates at current reservoir pressure
- Production flow rates update the reservoir well streams
- Reservoir runs TV-flash at fixed volume, computing new pressure and composition
- New pressure feeds back to network for next timestep
Reservoirs must be attached via
attachReservoir(String, SimpleReservoir, String, int)before calling this method.- Parameters:
timestepYears- array of timestep years (e.g., 0, 1, 2, ... 20)optimMaxIter- max iterations for choke optimisation at each timestepoptimTolerance- convergence tolerance for optimisation- Returns:
- map with time-series: time_years, rate_kghr, cumulative_kg, revenue_usd_hr, separator_util_pct, compressor_power_MW, plus per-reservoir pressures and GIP/OIP
-
productionForecastCoupled
-
createOptimizer
Create aNetworkOptimizerfor this network.The returned optimizer provides access to BOBYQA and CMA-ES derivative-free optimization algorithms and multi-objective Pareto front exploration. Use it for formal production optimization as an alternative to the simpler gradient-based
optimizeChokeOpenings(int, double)andoptimizeProduction(int, double).- Returns:
- a new optimizer bound to this network
-
optimizeProductionNLP
Optimize production using a formal NLP solver (BOBYQA by default).Convenience method that creates a
NetworkOptimizer, runs BOBYQA to maximize total production, and returns the optimized result. For more control (algorithm selection, objective type, max evaluations), usecreateOptimizer()directly.- Returns:
- optimization result
-
optimizeMultiObjective
Run multi-objective optimization exploring the production vs compression power trade-off.Sweeps Pareto front weights and returns all non-dominated solutions. Each point represents a different balance between maximizing production and minimizing compressor fuel/power.
- Parameters:
numPoints- number of Pareto front points to evaluate (5–20 typical)- Returns:
- list of Pareto-optimal results
-
runValidationBenchmarks
Run all validation benchmarks and return results.Provides quantitative verification against analytical solutions (Darcy-Weisbach, parallel pipe flow split), mass balance checks, solver cross-verification (Hardy Cross vs Newton-Raphson), pressure monotonicity, and sparse vs dense solver agreement.
- Returns:
- list of benchmark results
- See Also:
-