Skip to the content.

EnergyStream carries a power rate between process equipment. Its canonical unit is watt (W), while unit-aware APIs accept W, kW, MW, hp, and BTU/hr.

Typed EnergyPort metadata separates three concepts:

Calculation mode controls process-graph ordering. An equipment port in CALCULATED mode is scheduled before a unit reading the same stream through a SPECIFICATION port, even if units were added to the process in the opposite order.

Energy-driven pump

A connected shaft-work stream makes Pump calculate its outlet pressure from available shaft power, inlet volumetric flow, and efficiency:

SystemInterface water = new SystemSrkEos(298.15, 2.0);
water.addComponent("water", 1.0);
water.setMixingRule("classic");

Stream feed = new Stream("pump feed", water);
feed.setFlowRate(100000.0, "kg/hr");
feed.run();

EnergyStream shaft = new EnergyStream("pump shaft", EnergyType.SHAFT_WORK);
shaft.setPower(100.0, "kW");

Pump pump = new Pump("energy-driven pump", feed);
pump.setIsentropicEfficiency(0.75);
pump.setEnergyStream(shaft);
pump.run();

double outletPressure = pump.getOutletStream().getPressure("bara");
EnergyPortMode mode = pump.getEnergyPort("shaftPower").getMode();

Without an externally connected energy stream, Pump keeps its existing pressure-specified behavior and publishes the calculated shaft duty through getEnergyStream().

Multi-party buses and shafts

Use EnergyBus when several producers or consumers share a heat or electrical network. Named contributions are signed: positive values inject power and negative values withdraw power.

EnergyBus grid = new EnergyBus("main electrical bus", EnergyType.ELECTRICAL);
grid.setContribution("solar", 2.0, "MW");
grid.setContribution("electrolyzer", -1.5, "MW");
double reserve = grid.getNetPower("kW");

MechanicalShaft is a shaft-work bus with convenience methods for generation and loads:

MechanicalShaft shaftTrain = new MechanicalShaft("expander-compressor shaft");
shaftTrain.setMechanicalEfficiency(0.98);
shaftTrain.setGeneratedPower("expander", 10.0e6);
shaftTrain.setConsumedPower("compressor", 8.0e6);
double sparePower = shaftTrain.getNetPower("MW");

Point-to-point EnergyStream connections reject multiple calculated producers or specification consumers during graph construction. Use EnergyBus for intentional multi-party distribution.

Coupled networks and repeated execution

When a specification consumer is connected to an EnergyBus, it reads the net power excluding its own contribution from the previous run. After calculation, supported consumers publish their actual withdrawal back to the bus. This makes repeated steady-state runs stable instead of progressively subtracting the same load.

getNetPowerExcluding(String) exposes the same balance operation for custom dispatch logic. Input and output ports convert equipment power to negative withdrawals and positive injections. A bidirectional specification port treats positive equipment duty as a bus withdrawal, which supports recovered-heat links such as condenser to heater.

The process graph orders calculated producers before specification consumers. This applies to coupled networks such as:

These connections remain stable when the flowsheet is executed repeatedly, and Java serialization preserves shared bus identity, port metadata, and named contributions.

Deterministic allocation and balancing

For a state-of-the-art multi-party network, ports publish offers or requests and the bus solves one deterministic allocation. Lower priority numbers are served first; equal-priority participants share available power proportionally.

EnergyBus allocatedGrid = new EnergyBus("allocated grid", EnergyType.ELECTRICAL);

EnergyPort generator = new EnergyPort("power", EnergyType.ELECTRICAL,
    EnergyPortDirection.OUTPUT, EnergyPortMode.CALCULATED);
generator.setOwnerName("generator");
generator.connect(allocatedGrid);
generator.setDuty(100.0, "kW");

EnergyPort essentialLoad = new EnergyPort("power", EnergyType.ELECTRICAL,
    EnergyPortDirection.INPUT, EnergyPortMode.SPECIFICATION);
essentialLoad.setOwnerName("essential load");
essentialLoad.setPriority(10);
essentialLoad.setRequestedPower(80.0, "kW");
essentialLoad.connect(allocatedGrid);

EnergyPort flexibleLoad = new EnergyPort("power", EnergyType.ELECTRICAL,
    EnergyPortDirection.INPUT, EnergyPortMode.SPECIFICATION);
flexibleLoad.setOwnerName("flexible load");
flexibleLoad.setPriority(20);
flexibleLoad.setRequestedPower(80.0, "kW");
flexibleLoad.connect(allocatedGrid);

EnergyNetworkReport allocation = allocatedGrid.solveBalance();
double essentialAllocation = essentialLoad.getPowerMagnitude("kW"); // 80 kW
double flexibleAllocation = flexibleLoad.getPowerMagnitude("kW");   // 20 kW
double unmetDemand = allocation.getUnmetDemand();                   // 60000 W

A BALANCE port can inject power during shortage and absorb power during surplus. Configure its generation and consumption limits with setBalanceLimits. BatteryStorage.enableAutomaticBalancing provides this behavior with state-of-charge, charge/discharge efficiency, power limits, ramp response, and trip handling.

When a bus is part of a graph-executed process, add an EnergyNetworkSolver to make allocation an explicit scheduling node:

EnergyNetworkSolver network = new EnergyNetworkSolver("electrical allocation", allocatedGrid);
process.add(network);

The graph schedules calculated participants before the solver and specification or balance participants after it.

Coupled process-energy convergence

A single graph-ordered run gives the correct causal sequence, but an energy-limited consumer can publish a revised request after the network has already been solved. Use CoupledProcessEnergySolver to repeat the complete process until stream pressure, temperature, mass flow, energy requests, allocations, shortages, curtailment, and losses stop changing.

CoupledProcessEnergySolver coupledSolver = new CoupledProcessEnergySolver(process);
coupledSolver.setMaximumIterations(50);
coupledSolver.setProcessTolerance(1.0e-6);
coupledSolver.setPowerTolerance(1.0e3); // 1 kW
coupledSolver.setRelaxationFactor(0.5);

CoupledProcessEnergyResult result = coupledSolver.solve();
if (!result.isConverged()) {
  throw new IllegalStateException(result.toJson());
}

The relaxation factor is applied only to SPECIFICATION requests between complete process runs. A value of one disables damping; values below one stabilize oscillating feedback such as available motor power changing compressor operation, which then changes the next compressor-power request. The result contains iteration-by-iteration process and power residuals plus immutable reports from the final energy-network solution.

Conversion equipment and rotating drives

The neqsim.process.equipment.energy package provides process units with explicit input, useful-output, and heat-loss ports:

Equipment Conversion
ElectricMotor electrical → shaft work
Generator shaft work → electricity
Gearbox shaft work → shaft work, with speed ratio
Inverter electrical → electrical, with voltage/frequency quality
Transformer electrical → electrical, with voltage ratio
PrimeMover chemical/fuel energy → shaft work

MotorDriveTrain connects an electric motor to any pump, compressor, or other unit exposing shaftPower. MotorAssistedDriveTrain connects an expander, an assist motor, and a compressor to the same MechanicalShaft. The two network solvers then dispatch electrical supply to the motor and combined shaft supply to the compressor.

Energy quality and utility levels

EnergyQuality adds voltage, frequency, temperature, pressure, and shaft-speed metadata. Ports may declare required quality, and incompatible specified qualities are rejected during connection.

UtilityEnergyBus represents typed thermal utilities:

ThermalUtilitySource and ThermalUtilityConsumer participate in the same allocation, shortage, cost, and emissions reporting as electrical and shaft networks. Heaters, coolers, condensers, reboilers, two-stream heat exchangers, multi-stream exchangers, and LNGHeatExchanger publish or consume typed heat duties.

Thermodynamic utility mass flow

Configure explicit supply and return states when the utility network must report physical circulation rather than only thermal power. Specific enthalpy is supplied in J/kg, allowing the values to come from NeqSim, vendor data, or another qualified property package.

ThermalUtilityState steamSupply =
    new ThermalUtilityState(425.0, 4.0e5, 2.8e6);
ThermalUtilityState condensateReturn =
    new ThermalUtilityState(383.0, 4.0e5, 0.6e6);

UtilityEnergyBus lpSteam = new UtilityEnergyBus(
    "LP steam", UtilityLevel.LOW_PRESSURE_STEAM,
    steamSupply, condensateReturn);

ThermalUtilitySource boiler =
    new ThermalUtilitySource("boiler", UtilityLevel.LOW_PRESSURE_STEAM);
ThermalUtilityConsumer reboiler =
    new ThermalUtilityConsumer("reboiler", UtilityLevel.LOW_PRESSURE_STEAM);
boiler.connectEnergyStream(ThermalUtilitySource.OUTPUT_PORT,
    lpSteam, EnergyPortMode.CALCULATED);
reboiler.connectEnergyStream(ThermalUtilityConsumer.INPUT_PORT,
    lpSteam, EnergyPortMode.SPECIFICATION);
boiler.setAvailablePower(2.0e6);
reboiler.setRequestedPower(1.5e6);

boiler.run();
lpSteam.solveBalance();
reboiler.run();

double servedSteamKgPerSecond = lpSteam.getServedMassFlow();
double curtailedSteamKgPerSecond = lpSteam.getCurtailedMassFlow();
double servedSteamTonPerHour = lpSteam.getMassFlowForDuty(
    lpSteam.getLastReport().getServedDemand(), "W", "ton/hr");

Heating utilities require supply enthalpy above return enthalpy. Cooling-water, chilled-water, refrigeration, and ambient-cooling utilities require return enthalpy above supply enthalpy because they absorb process heat. The solved bus exposes requested, served, offered, accepted, unmet, and curtailed mass-flow equivalents.

Dynamics and reporting

MechanicalShaft.advanceTransient(dt) integrates rotational kinetic energy from the solved net shaft power. Moment of inertia, friction loss, maximum speed, acceleration/deceleration limits, and trip coastdown are configurable.

Every solved bus returns an EnergyNetworkReport containing offered and accepted supply, requested and served demand, balancing generation/consumption, unmet demand, curtailment, conversion loss, delivery efficiency, fuel-energy rate, operating cost, and CO2-equivalent rate. Set marginal price and emission factor on producer ports with setEnergyPricePerMWh and setEmissionFactorKgPerMWh.

Equipment coverage

Equipment group Typed port Supported role
Pump, Compressor shaftPower input Calculated duty or external power specification
Expander, SteamTurbine shaftPower output Calculated shaft power
GasTurbine shaftPower and exhaustHeat outputs Calculated power/heat; shaft output can also be a fuel-sizing specification
GasTurbineUnit shaftPower output Calculated delivered shaft power at the active demand and site limit
CombinedCycleSystem electricalPower output Calculated combined-cycle generation
Heater, Cooler heatDuty bidirectional Calculated duty or legacy external duty specification
Condenser heatDuty output Calculated heat removal
Reboiler heatDuty input Calculated duty or legacy external duty specification
SolarPanel, WindTurbine, WindFarm, FuelCell electricalPower output Calculated generation
BatteryStorage electricalPower bidirectional Calculated charge/discharge or automatic balance
Electrolyzer electricalPower input Feed-calculated demand or connected power-driven specification
CO2Electrolyzer, BioFeedstockPreparation electricalPower input Calculated demand
AmmoniaSynthesisReactor reactionHeat output Calculated reaction heat
StirredTankReactor heatDuty bidirectional; agitatorPower input Calculated or specified heat duty and calculated electrical demand
HeatExchanger, MultiStreamHeatExchanger, LNGHeatExchanger heatDuty bidirectional Calculated recoverable heat
Energy converters energyInput, energyOutput, heatLoss Specified input, calculated useful output and loss

Reboiler duty reporting

A Reboiler now publishes its calculated heat duty through getEnergyStream(). The stream is typed as HEAT, and getDuty("kW") or getEnergyFlow("MW") can be used for utility summaries and downstream coupling.

Compatibility

Existing getDuty(), setDuty(double), equality, and setEnergyStream(EnergyStream) behavior remain available. Legacy equipment that encodes direction in a signed duty keeps that convention until it is migrated to typed ports. New integrations should declare an EnergyType and use named ports so type validation and graph scheduling are available.