Class ProcessSystem

All Implemented Interfaces:
Serializable, Runnable, SimulationInterface, NamedInterface

public class ProcessSystem extends SimulationBaseClass
Represents a process system containing unit operations.
Author:
esol
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      Serialization version UID.
      See Also:
    • logger

      static org.apache.logging.log4j.Logger logger
      Logger object for class.
    • thisThread

      transient Thread thisThread
    • measurementHistory

      private ProcessSystem.MeasurementHistory measurementHistory
    • surroundingTemperature

      private double surroundingTemperature
    • timeStepNumber

      private int timeStepNumber
    • unitOperations

      private List<ProcessEquipmentInterface> unitOperations
      List of unit operations in the process system.
    • measurementDevices

      List<MeasurementDeviceInterface> measurementDevices
    • alarmManager

      private ProcessAlarmManager alarmManager
    • recycleController

      RecycleController recycleController
    • timeStep

      private double timeStep
    • runStep

      private boolean runStep
    • equipmentCounter

      private final Map<String,Integer> equipmentCounter
    • lastAddedUnit

      private ProcessEquipmentInterface lastAddedUnit
    • initialStateSnapshot

      private transient ProcessSystem initialStateSnapshot
    • massBalanceErrorThreshold

      private double massBalanceErrorThreshold
    • minimumFlowForMassBalanceError

      private double minimumFlowForMassBalanceError
    • maxTransientIterations

      private int maxTransientIterations
    • enableMassBalanceTracking

      private boolean enableMassBalanceTracking
    • previousTotalMass

      private double previousTotalMass
    • massBalanceError

      private double massBalanceError
    • cachedGraph

      private transient ProcessGraph cachedGraph
      Cached process graph for topology analysis.
    • graphDirty

      private boolean graphDirty
      Flag indicating if the cached graph needs to be rebuilt.
    • useGraphBasedExecution

      private boolean useGraphBasedExecution
      Whether to use graph-based execution order instead of insertion order.
    • useOptimizedExecution

      private boolean useOptimizedExecution
      Whether to use optimized execution (parallel/hybrid) by default when run() is called. When true, run() delegates to runOptimized() which automatically selects the best strategy. When false, run() uses sequential execution in insertion order (legacy behavior). Default is true for optimal performance - runOptimized() automatically falls back to sequential execution for processes with multi-input equipment (mixers, heat exchangers, etc.) to preserve correct mass balance.
  • Constructor Details

    • ProcessSystem

      public ProcessSystem()

      Constructor for ProcessSystem.

    • ProcessSystem

      public ProcessSystem(String name)
      Constructor for ProcessSystem.
      Parameters:
      name - name of process
  • Method Details

    • add

      public void add(ProcessEquipmentInterface operation)

      Add to end.

      Parameters:
      operation - a ProcessEquipmentInterface object
    • add

      public void add(int position, ProcessEquipmentInterface operation)

      Add to specific position.

      Parameters:
      position - 0-based position
      operation - a ProcessEquipmentInterface object
    • add

      public void add(MeasurementDeviceInterface measurementDevice)

      Add measurementdevice.

      Parameters:
      measurementDevice - a MeasurementDeviceInterface object
    • add

      public void add(ProcessEquipmentInterface[] operations)

      Add multiple process equipment to end.

      Parameters:
      operations - an array of ProcessEquipmentInterface objects
    • replaceUnit

      public boolean replaceUnit(String name, ProcessEquipmentInterface newObject)

      Replace a unitoperation.

      Parameters:
      name - Name of the object to replace
      newObject - the object to replace it with
      Returns:
      a Boolean object
    • getUnit

      public ProcessEquipmentInterface getUnit(String name)

      Get process equipmen by name.

      Parameters:
      name - Name of
      Returns:
      a ProcessEquipmentInterface object
    • hasUnitName

      public boolean hasUnitName(String name)

      hasUnitName.

      Parameters:
      name - a String object
      Returns:
      a boolean
    • getMeasurementDevice

      public MeasurementDeviceInterface getMeasurementDevice(String name)

      Get MeasureDevice by name.

      Parameters:
      name - Name of measurement device
      Returns:
      a MeasurementDeviceInterface object
    • getUnitNumber

      public int getUnitNumber(String name)

      getUnitNumber.

      Parameters:
      name - a String object
      Returns:
      a int
    • replaceObject

      public void replaceObject(String unitName, ProcessEquipmentBaseClass operation)

      replaceObject.

      Parameters:
      unitName - a String object
      operation - a ProcessEquipmentBaseClass object
    • getAllUnitNames

      public ArrayList<String> getAllUnitNames()

      getAllUnitNames.

      Returns:
      a ArrayList object
    • getUnitOperations

      public List<ProcessEquipmentInterface> getUnitOperations()

      Gets the list of unit operations.

      Returns:
      the list of unit operations
    • validateSetup

      public ValidationResult validateSetup()
      Validates the process system setup before execution.

      This method validates:

      • The process system has at least one unit operation
      • Each unit operation passes its own validateSetup() check
      • Feed streams are defined
      • Equipment names are unique (warning)
      Returns:
      validation result with errors and warnings for all equipment
    • validateAll

      public Map<String, ValidationResult> validateAll()
      Validates all equipment in the process system and returns individual results.

      Unlike validateSetup() which returns a combined result, this method returns a map of equipment names to their individual validation results, making it easier to identify specific issues.

      Returns:
      map of equipment names to their validation results
    • isReadyToRun

      public boolean isReadyToRun()
      Checks if the process system is ready to run.

      Convenience method that returns true if validateSetup() finds no critical errors.

      Returns:
      true if process system passes validation, false otherwise
    • removeUnit

      public void removeUnit(String name)

      removeUnit.

      Parameters:
      name - a String object
    • clearAll

      public void clearAll()

      clearAll.

    • clear

      public void clear()

      clear.

    • setFluid

      public void setFluid(SystemInterface fluid1, SystemInterface fluid2, boolean addNewComponents)

      setFluid.

      Parameters:
      fluid1 - a SystemInterface object
      fluid2 - a SystemInterface object
      addNewComponents - a boolean
    • setFluid

      public void setFluid(SystemInterface fluid1, SystemInterface fluid2)

      setFluid.

      Parameters:
      fluid1 - a SystemInterface object
      fluid2 - a SystemInterface object
    • runAsTask

      public Future<?> runAsTask()
      Runs this process in a separate thread using the global NeqSim thread pool.

      This method submits the process to the shared NeqSimThreadPool and returns a Future that can be used to monitor completion, cancel the task, or retrieve any exceptions that occurred.

      Returns:
      a Future representing the pending completion of the task
      See Also:
    • runOptimized

      public void runOptimized()
      Runs the process system using the optimal execution strategy based on topology analysis.

      This method automatically selects the best execution mode:

      • For processes WITHOUT recycles: uses parallel execution for maximum speed
      • For processes WITH recycles: uses graph-based execution with optimized ordering

      This is the recommended method for most use cases as it provides the best performance without requiring manual configuration.

    • runOptimized

      public void runOptimized(UUID id)
      Runs the process system using the optimal execution strategy based on topology analysis.

      This method automatically selects the best execution mode:

      • For processes WITHOUT recycles: uses parallel execution for maximum speed
      • For processes WITH recycles: uses hybrid execution - parallel for feed-forward sections, then graph-based iteration for recycle sections
      Parameters:
      id - calculation identifier for tracking
    • hasAdjusters

      public boolean hasAdjusters()
      Checks if the process contains any Adjuster units that require iterative convergence.
      Returns:
      true if there are Adjuster units in the process
    • hasRecycles

      public boolean hasRecycles()
      Checks if the process contains any Recycle units.

      This method directly checks for Recycle units in the process, which is more reliable than graph-based cycle detection for determining if iterative execution is needed.

      Returns:
      true if there are Recycle units in the process
    • hasMultiInputEquipment

      public boolean hasMultiInputEquipment()
      Checks if the process contains any multi-input equipment.

      Multi-input equipment (Mixer, Manifold, TurboExpanderCompressor, Ejector, HeatExchanger, MultiStreamHeatExchanger) require sequential execution to ensure correct mass balance. Parallel execution can change the order in which input streams are processed, leading to incorrect results.

      Returns:
      true if there are multi-input equipment units in the process
    • runHybrid

      public void runHybrid(UUID id) throws InterruptedException
      Runs the process using hybrid execution strategy.

      This method partitions the process into:

      • Feed-forward section: Units at the beginning with no recycle dependencies - run in parallel
      • Recycle section: Units that are part of or depend on recycle loops - run with graph-based iteration
      Parameters:
      id - calculation identifier for tracking
      Throws:
      InterruptedException - if thread is interrupted during parallel execution
    • getExecutionPartitionInfo

      public String getExecutionPartitionInfo()
      Gets a description of how the process will be partitioned for execution.

      This method analyzes the process topology and returns information about:

      • Whether the process has recycle loops
      • Number of parallel execution levels
      • Maximum parallelism achievable
      • Which units are in recycle loops
      Returns:
      description of the execution partitioning
    • runParallel

      public void runParallel() throws InterruptedException
      Runs the process system using parallel execution for independent equipment.

      This method uses the process graph to identify equipment that can run in parallel (i.e., equipment with no dependencies between them). Equipment at the same "level" in the dependency graph are executed concurrently using the NeqSim thread pool.

      Note: This method does not handle recycles or adjusters - use regular SimulationInterface.run() for processes with recycle loops. This is suitable for feed-forward processes where maximum parallelism is desired.

      Throws:
      InterruptedException - if the thread is interrupted while waiting for tasks
    • runParallel

      public void runParallel(UUID id) throws InterruptedException
      Runs the process system using parallel execution for independent equipment.

      This method uses the process graph to identify equipment that can run in parallel (i.e., equipment with no dependencies between them). Equipment at the same "level" in the dependency graph are executed concurrently using the NeqSim thread pool.

      Parameters:
      id - calculation identifier for tracking
      Throws:
      InterruptedException - if the thread is interrupted while waiting for tasks
    • groupNodesBySharedInputStreams

      private List<List<ProcessNode>> groupNodesBySharedInputStreams(List<ProcessNode> nodes)
      Groups nodes by shared input streams for parallel execution safety.

      Units that share the same input stream cannot safely run in parallel because they would concurrently read from the same thermo system. This method uses Union-Find to group nodes that share any input stream, so they can be run sequentially within their group while different groups run in parallel.

      Parameters:
      nodes - list of nodes at the same execution level
      Returns:
      list of groups, where each group contains nodes that share input streams
    • getParallelPartition

      public ProcessGraph.ParallelPartition getParallelPartition()
      Gets the parallel execution partition for this process.

      This method returns information about how the process can be parallelized, including: - The number of parallel levels - Maximum parallelism (max units that can run concurrently) - Which units are at each level

      Returns:
      parallel partition result, or null if graph cannot be built
    • isParallelExecutionBeneficial

      public boolean isParallelExecutionBeneficial()
      Checks if parallel execution would be beneficial for this process.

      Parallel execution is considered beneficial when:

      • There are at least 2 units that can run in parallel (maxParallelism >= 2)
      • The process has no recycle loops (which require iterative sequential execution)
      • There are enough units to justify thread overhead (typically > 4 units)
      Returns:
      true if parallel execution is recommended
    • runOptimal

      public void runOptimal()
      Runs the process using the optimal execution strategy.

      This method automatically determines whether to use parallel or sequential execution based on the process structure. It will use parallel execution if:

      • The process has independent branches that can benefit from parallelism
      • There are no recycle loops or adjusters requiring iterative execution
      • The process is large enough to justify the thread management overhead

      For processes with recycles or adjusters, this method falls back to the standard sequential SimulationInterface.run() method which properly handles convergence iterations.

    • runOptimal

      public void runOptimal(UUID id)
      Runs the process using the optimal execution strategy with calculation ID tracking.
      Parameters:
      id - calculation identifier for tracking
      See Also:
    • runAsThread

      @Deprecated public Thread runAsThread()
      Deprecated.
      Use runAsTask() instead for better resource management. This method creates a new unmanaged thread directly.

      runAsThread.

      Returns:
      a Thread object
    • run

      public void run(UUID id)

      In this method all thermodynamic and unit operations will be calculated in a steady state calculation.

      Parameters:
      id - UUID
    • runSequential

      public void runSequential(UUID id)
      Runs the process system using sequential execution.

      This method executes units in insertion order (or topological order if useGraphBasedExecution is enabled). It handles recycle loops by iterating until convergence. This is the legacy execution mode preserved for backward compatibility.

      Parameters:
      id - calculation identifier for tracking
    • run_step

      public void run_step(UUID id)

      run_step

      In this method all thermodynamic and unit operations will be calculated in a steady state calculation. Sets calc identifier UUID. It does not solve recycles - only calculates one step
      Parameters:
      id - Calc identifier UUID to set.
    • runTransient

      public void runTransient()

      runTransient.

    • runTransient

      public void runTransient(double dt, UUID id)

      runTransient

      This method calculates thermodynamic and unit operations using difference equations if available and calculateSteadyState is true. Use setCalculateSteadyState to set the parameter. Sets calc identifier UUID.
      Parameters:
      dt - Delta time [s]
      id - Calculation identifier
    • solved

      public boolean solved()

      Returns whether or not the module has been solved.

      Returns:
      a boolean
    • getTime

      public double getTime()
      Getter for the field time.
      Specified by:
      getTime in interface SimulationInterface
      Overrides:
      getTime in class SimulationBaseClass
      Returns:
      Value of property time.
    • getTime

      public double getTime(String unit)

      Getter for the field time.

      Parameters:
      unit - a String object
      Returns:
      a double
    • calculateTotalSystemMass

      private double calculateTotalSystemMass()
      Calculate total system mass across all equipment and streams.
      Returns:
      Total mass in kg
    • setEnableMassBalanceTracking

      public void setEnableMassBalanceTracking(boolean enable)
      Enable or disable mass balance tracking during transient simulations.
      Parameters:
      enable - true to enable tracking
    • getMassBalanceError

      public double getMassBalanceError()
      Get the current mass balance error percentage.
      Returns:
      Mass balance error in percent
    • setMaxTransientIterations

      public void setMaxTransientIterations(int iterations)
      Set the maximum number of iterations within each transient time step.

      Multiple iterations help converge circular dependencies between equipment. Default is 3. Set to 1 to disable iterative convergence.

      Parameters:
      iterations - Number of iterations (must be >= 1)
    • getMaxTransientIterations

      public int getMaxTransientIterations()
      Get the maximum number of iterations within each transient time step.
      Returns:
      Number of iterations
    • size

      public int size()

      size.

      Returns:
      a int
    • view

      public void view()

      view.

    • displayResult

      public void displayResult()

      displayResult.

    • reportMeasuredValues

      public void reportMeasuredValues()

      reportMeasuredValues.

    • save

      public void save(String filePath)

      save.

      Parameters:
      filePath - a String object
    • open

      public static ProcessSystem open(String filePath)

      open.

      Parameters:
      filePath - a String object
      Returns:
      a ProcessSystem object
    • reportResults

      public String[][] reportResults()

      reportResults.

      Returns:
      an array of String objects
    • printLogFile

      public void printLogFile(String filename)

      printLogFile.

      Parameters:
      filename - a String object
    • clearHistory

      public void clearHistory()
      Clears all stored transient measurement history entries and resets the time step counter.
    • getHistorySize

      public int getHistorySize()
      Returns the number of stored transient measurement entries.
      Returns:
      number of stored history entries
    • getAlarmManager

      public ProcessAlarmManager getAlarmManager()
      Returns the alarm manager responsible for coordinating alarm evaluation.
      Returns:
      alarm manager
    • getHistorySnapshot

      public String[][] getHistorySnapshot()
      Returns a snapshot of the transient measurement history.
      Returns:
      the measurement history as a two-dimensional array
    • setHistoryCapacity

      public void setHistoryCapacity(int maxEntries)
      Sets the maximum number of entries retained in the measurement history. A value less than or equal to zero disables truncation (unbounded history).
      Parameters:
      maxEntries - maximum number of entries to keep, or non-positive for unlimited
    • getHistoryCapacity

      public int getHistoryCapacity()
      Returns the configured history capacity. A value less than or equal to zero means the history grows without bounds.
      Returns:
      configured maximum number of history entries or non-positive for unlimited
    • storeInitialState

      public void storeInitialState()
      Stores a snapshot of the current process system state that can later be restored with reset().
    • reset

      public void reset()
      Restores the process system to the stored initial state. The initial state is captured automatically the first time a transient run is executed, or manually via storeInitialState().
    • ensureInitialStateSnapshot

      private void ensureInitialStateSnapshot()
    • captureInitialState

      private void captureInitialState(boolean force)
    • applyState

      private void applyState(ProcessSystem source)
    • getTimeStep

      public double getTimeStep()

      Getter for the field timeStep.

      Returns:
      a double
    • setTimeStep

      public void setTimeStep(double timeStep)

      Setter for the field timeStep.

      Parameters:
      timeStep - a double
    • getName

      public String getName()

      Getter for the field name.

      Specified by:
      getName in interface NamedInterface
      Overrides:
      getName in class NamedBaseClass
      Returns:
      a String object
    • setName

      public void setName(String name)

      Setter for the field name.

      Specified by:
      setName in interface NamedInterface
      Overrides:
      setName in class NamedBaseClass
      Parameters:
      name - a String object
    • setRunStep

      public void setRunStep(boolean runStep)
      Setter for the field runStep.
      Parameters:
      runStep - A boolean value if run only one iteration
    • isRunStep

      public boolean isRunStep()
      Getter for the field runStep.
      Returns:
      A boolean value if run only one iteration
    • getEntropyProduction

      public double getEntropyProduction(String unit)

      getEntropyProduction.

      Parameters:
      unit - a String object
      Returns:
      a double
    • getExergyChange

      public double getExergyChange(String unit)

      getExergyChange.

      Parameters:
      unit - a String object
      Returns:
      a double
    • getPower

      public double getPower(String unit)

      getPower.

      Parameters:
      unit - a String object
      Returns:
      a double
    • getCoolerDuty

      public double getCoolerDuty(String unit)

      getCoolerDuty.

      Parameters:
      unit - a String object
      Returns:
      a double
    • getHeaterDuty

      public double getHeaterDuty(String unit)

      getHeaterDuty.

      Parameters:
      unit - a String object
      Returns:
      a double
    • getSurroundingTemperature

      public double getSurroundingTemperature()

      Getter for the field surroundingTemperature.

      Returns:
      a double
    • setSurroundingTemperature

      public void setSurroundingTemperature(double surroundingTemperature)

      Setter for the field surroundingTemperature.

      Parameters:
      surroundingTemperature - a double
    • copy

      public ProcessSystem copy()

      Create deep copy.

      Returns:
      a ProcessSystem object
    • deepCopy

      private ProcessSystem deepCopy()
    • getConditionMonitor

      public ConditionMonitor getConditionMonitor()

      getConditionMonitor.

      Returns:
      a ConditionMonitor object
    • checkMassBalance

      public Map<String, ProcessSystem.MassBalanceResult> checkMassBalance(String unit)
      Check mass balance of all unit operations in the process system.
      Parameters:
      unit - unit for mass flow rate (e.g., "kg/sec", "kg/hr", "mole/sec")
      Returns:
      a map with unit operation name as key and mass balance result as value
    • checkMassBalance

      public Map<String, ProcessSystem.MassBalanceResult> checkMassBalance()
      Check mass balance of all unit operations in the process system using kg/sec.
      Returns:
      a map with unit operation name as key and mass balance result as value in kg/sec
    • getFailedMassBalance

      public Map<String, ProcessSystem.MassBalanceResult> getFailedMassBalance(String unit, double percentThreshold)
      Get unit operations that failed mass balance check based on percentage error threshold.
      Parameters:
      unit - unit for mass flow rate (e.g., "kg/sec", "kg/hr", "mole/sec")
      percentThreshold - percentage error threshold (default: 0.1%)
      Returns:
      a map with failed unit operation names and their mass balance results
    • getFailedMassBalance

      public Map<String, ProcessSystem.MassBalanceResult> getFailedMassBalance()
      Get unit operations that failed mass balance check using kg/sec and default threshold.
      Returns:
      a map with failed unit operation names and their mass balance results
    • getFailedMassBalance

      public Map<String, ProcessSystem.MassBalanceResult> getFailedMassBalance(double percentThreshold)
      Get unit operations that failed mass balance check using specified threshold.
      Parameters:
      percentThreshold - percentage error threshold
      Returns:
      a map with failed unit operation names and their mass balance results in kg/sec
    • getMassBalanceReport

      public String getMassBalanceReport(String unit)
      Get a formatted mass balance report for this process system.
      Parameters:
      unit - unit for mass flow rate (e.g., "kg/sec", "kg/hr", "mole/sec")
      Returns:
      a formatted string report with mass balance results
    • getMassBalanceReport

      public String getMassBalanceReport()
      Get a formatted mass balance report for this process system using kg/sec.
      Returns:
      a formatted string report with mass balance results
    • getFailedMassBalanceReport

      public String getFailedMassBalanceReport(String unit, double percentThreshold)
      Get a formatted report of failed mass balance checks for this process system.
      Parameters:
      unit - unit for mass flow rate (e.g., "kg/sec", "kg/hr", "mole/sec")
      percentThreshold - percentage error threshold
      Returns:
      a formatted string report with failed unit operations
    • getFailedMassBalanceReport

      public String getFailedMassBalanceReport()
      Get a formatted report of failed mass balance checks for this process system using kg/sec and default threshold.
      Returns:
      a formatted string report with failed unit operations
    • getFailedMassBalanceReport

      public String getFailedMassBalanceReport(double percentThreshold)
      Get a formatted report of failed mass balance checks for this process system using specified threshold.
      Parameters:
      percentThreshold - percentage error threshold
      Returns:
      a formatted string report with failed unit operations in kg/sec
    • setMassBalanceErrorThreshold

      public void setMassBalanceErrorThreshold(double percentThreshold)
      Set the default mass balance error threshold for this process system.
      Parameters:
      percentThreshold - percentage error threshold (e.g., 0.1 for 0.1%)
    • getMassBalanceErrorThreshold

      public double getMassBalanceErrorThreshold()
      Get the default mass balance error threshold for this process system.
      Returns:
      percentage error threshold
    • setMinimumFlowForMassBalanceError

      public void setMinimumFlowForMassBalanceError(double minimumFlow)
      Set the minimum flow threshold for mass balance error checking. Units with inlet flow below this threshold are not considered errors.
      Parameters:
      minimumFlow - minimum flow in kg/sec (e.g., 1e-6)
    • getMinimumFlowForMassBalanceError

      public double getMinimumFlowForMassBalanceError()
      Get the minimum flow threshold for mass balance error checking.
      Returns:
      minimum flow in kg/sec
    • calculateInletFlow

      private double calculateInletFlow(ProcessEquipmentInterface unitOp, String unit)
    • calculatePercentError

      private double calculatePercentError(double massBalanceError, double inletFlow)
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
    • equals

      public boolean equals(Object obj)
      Overrides:
      equals in class Object
    • getReport_json

      public String getReport_json()

      getReport_json.

      Return results of simulation in json format
      Returns:
      a String
    • addUnit

      public <T extends ProcessEquipmentInterface> T addUnit(String name, String equipmentType)

      addUnit.

      Type Parameters:
      T - a T class
      Parameters:
      name - a String object
      equipmentType - a String object
      Returns:
      a T object
    • addUnit

      public <T extends ProcessEquipmentInterface> T addUnit(String name, EquipmentEnum equipmentEnum)

      addUnit.

      Type Parameters:
      T - a T class
      Parameters:
      name - a String object
      equipmentEnum - a EquipmentEnum object
      Returns:
      a T object
    • addUnit

      public <T extends ProcessEquipmentInterface> T addUnit(String equipmentType)

      addUnit.

      Type Parameters:
      T - a T class
      Parameters:
      equipmentType - a String object
      Returns:
      a T object
    • addUnit

      public <T extends ProcessEquipmentInterface> T addUnit(EquipmentEnum equipmentEnum)

      addUnit.

      Type Parameters:
      T - a T class
      Parameters:
      equipmentEnum - a EquipmentEnum object
      Returns:
      a T object
    • addUnit

      public <T extends ProcessEquipmentInterface> T addUnit(String name, String equipmentType, StreamInterface stream)
      Adds a new process equipment unit of the specified type and name, and sets its inlet stream.
      Type Parameters:
      T - the type of process equipment
      Parameters:
      name - the name of the equipment (if null or empty, a unique name is generated)
      equipmentType - the type of equipment to create (as a String)
      stream - the inlet stream to set for the new equipment
      Returns:
      the created and added process equipment unit
    • addUnit

      public ProcessEquipmentInterface addUnit(String name, ProcessEquipmentInterface equipment)

      addUnit.

      Parameters:
      name - a String object
      equipment - a ProcessEquipmentInterface object
      Returns:
      a ProcessEquipmentInterface object
    • addUnit

      addUnit.

      Parameters:
      equipment - a ProcessEquipmentInterface object
      Returns:
      a ProcessEquipmentInterface object
    • generateUniqueName

      private String generateUniqueName(String equipmentType)
    • autoConnect

      private void autoConnect(ProcessEquipmentInterface fromUnit, ProcessEquipmentInterface toUnit)
    • exportToGraphviz

      public void exportToGraphviz(String filename)

      exportToGraphviz.

      Parameters:
      filename - a String object
    • exportToGraphviz

      public void exportToGraphviz(String filename, ProcessSystemGraphvizExporter.GraphvizExportOptions options)
      Export the process to Graphviz with configurable stream annotations.
      Parameters:
      filename - the Graphviz output file
      options - export options controlling stream annotations and table output
    • loadProcessFromYaml

      public void loadProcessFromYaml(File yamlFile)
      Load a process from a YAML file.
      Parameters:
      yamlFile - the YAML file to load
    • getBottleneck

      public ProcessEquipmentInterface getBottleneck()

      getBottleneck.

      Returns:
      a ProcessEquipmentInterface object
    • buildGraph

      public ProcessGraph buildGraph()
      Builds an explicit graph representation of this process system.

      The graph representation enables:

      • Automatic detection of calculation order (derived from topology, not insertion order)
      • Partitioning for parallel execution
      • AI agents to reason about flowsheet structure
      • Cycle detection for recycle handling
      • Graph neural network compatible representation

      Example usage:

      ProcessSystem system = new ProcessSystem();
      // ... add units ...
      ProcessGraph graph = system.buildGraph();
      
      // Get topology-based calculation order
      List<ProcessEquipmentInterface> order = graph.getCalculationOrder();
      
      // Partition for parallel execution
      ProcessGraph.ParallelPartition partition = graph.partitionForParallelExecution();
      
      Returns:
      the process graph
      See Also:
    • invalidateGraph

      public void invalidateGraph()
      Forces a rebuild of the process graph on next access.

      Use this method when you have made structural changes to the process that the automatic detection may have missed (e.g., modifying stream connections directly).

    • setUseGraphBasedExecution

      public void setUseGraphBasedExecution(boolean useGraphBased)
      Sets whether to use graph-based execution order.

      When enabled, the run() method will execute units in topological order derived from stream connections rather than the order units were added. This can be safer when unit insertion order doesn't match the physical flow.

      Parameters:
      useGraphBased - true to use topological execution order, false to use insertion order
    • isUseGraphBasedExecution

      public boolean isUseGraphBasedExecution()
      Returns whether graph-based execution order is enabled.
      Returns:
      true if using topological execution order
    • setUseOptimizedExecution

      public void setUseOptimizedExecution(boolean useOptimized)
      Sets whether to use optimized execution (parallel/hybrid) by default when run() is called.

      When enabled (default), run() automatically selects the best execution strategy:

      • For processes WITHOUT recycles: parallel execution for maximum speed (28-57% faster)
      • For processes WITH recycles: hybrid execution - parallel for feed-forward sections, then iterative for recycle sections (28-38% faster)

      When disabled, run() uses sequential execution in insertion order (legacy behavior). This may be useful for debugging or when deterministic single-threaded execution is required.

      Parameters:
      useOptimized - true to use optimized execution (default), false for sequential execution
    • isUseOptimizedExecution

      public boolean isUseOptimizedExecution()
      Returns whether optimized execution is enabled.

      When true (default), run() delegates to runOptimized() which automatically selects the best execution strategy based on process topology.

      Returns:
      true if optimized execution is enabled
    • getTopologicalOrder

      public List<ProcessEquipmentInterface> getTopologicalOrder()
      Gets the calculation order derived from process topology.

      This method returns units in the order they should be calculated based on stream connections, not the order they were added to the ProcessSystem. This is safer than relying on insertion order, which can lead to wrong results if units are rearranged or recycles are added late.

      Returns:
      list of equipment in topology-derived calculation order
    • hasRecycleLoops

      public boolean hasRecycleLoops()
      Checks if the process has recycle loops that require iterative solving.
      Returns:
      true if the process contains cycles (recycles)
    • getParallelLevelCount

      public int getParallelLevelCount()
      Gets the number of levels for parallel execution.

      Units at the same level have no dependencies on each other and can be executed in parallel.

      Returns:
      number of parallel execution levels
    • getMaxParallelism

      public int getMaxParallelism()
      Gets the maximum parallelism (max units that can run simultaneously).
      Returns:
      maximum number of units that can execute in parallel
    • validateStructure

      public List<String> validateStructure()
      Validates the process structure and returns any issues found.

      Checks include:

      • Isolated units (no connections)
      • Duplicate edges
      • Self-loops
      • Unhandled cycles
      Returns:
      list of validation issues (empty if valid)
    • getGraphSummary

      public String getGraphSummary()
      Gets a summary of the process graph structure.
      Returns:
      summary string with node/edge counts, cycles, parallelism info
    • getRecycleBlocks

      public List<List<ProcessEquipmentInterface>> getRecycleBlocks()
      Gets the strongly connected components (SCCs) in the process graph.

      SCCs with more than one unit represent recycle loops that require iterative convergence. This method uses Tarjan's algorithm to identify these components.

      Returns:
      list of SCCs, each containing a list of equipment in that component
    • getRecycleBlockCount

      public int getRecycleBlockCount()
      Gets the number of recycle blocks (cycles) in the process.
      Returns:
      number of strongly connected components with more than one unit
    • isInRecycleLoop

      public boolean isInRecycleLoop(ProcessEquipmentInterface unit)
      Checks if a specific unit is part of a recycle loop.
      Parameters:
      unit - the unit to check
      Returns:
      true if the unit is in a recycle block
    • getRecycleBlockReport

      public String getRecycleBlockReport()
      Gets a diagnostic report of recycle blocks for debugging.
      Returns:
      formatted string describing each recycle block
    • exportState

      public ProcessSystemState exportState()
      Exports the current state of this process system for checkpointing or versioning.

      This method captures all equipment states, fluid compositions, and operating conditions into a serializable format that can be saved to disk, stored in a database, or used for model versioning in digital twin applications.

      Example usage:

      ProcessSystem system = new ProcessSystem();
      // ... configure and run ...
      ProcessSystemState state = system.exportState();
      state.saveToFile("checkpoint_v1.json");
      
      Returns:
      the current state as a serializable object
      See Also:
    • exportStateToFile

      public void exportStateToFile(String filename)
      Exports the current state to a JSON file for versioning or backup.
      Parameters:
      filename - the file path to save the state
    • loadStateFromFile

      public void loadStateFromFile(String filename)
      Loads process state from a JSON file and applies it to this system.

      Note: This method updates equipment states but does not recreate equipment. The process structure must match the saved state.

      Parameters:
      filename - the file path to load state from
    • saveToNeqsim

      public boolean saveToNeqsim(String filename)
      Saves this process system to a compressed .neqsim file using XStream serialization.

      This is the recommended format for production use, providing compact storage with full process state preservation. The file can be loaded with loadFromNeqsim(String).

      Example usage:

      ProcessSystem process = new ProcessSystem();
      // ... configure and run ...
      process.saveToNeqsim("my_model.neqsim");
      
      Parameters:
      filename - the file path to save to (recommended extension: .neqsim)
      Returns:
      true if save was successful, false otherwise
    • loadFromNeqsim

      public static ProcessSystem loadFromNeqsim(String filename)
      Loads a process system from a compressed .neqsim file.

      After loading, the process is automatically run to reinitialize calculations. This ensures the internal state is consistent.

      Example usage:

      ProcessSystem loaded = ProcessSystem.loadFromNeqsim("my_model.neqsim");
      // Process is already run and ready to use
      Stream outlet = (Stream) loaded.getUnit("outlet");
      
      Parameters:
      filename - the file path to load from
      Returns:
      the loaded ProcessSystem, or null if loading fails
    • saveAuto

      public boolean saveAuto(String filename)
      Saves the current state to a file with automatic format detection.

      File format is determined by extension:

      • .neqsim → XStream compressed XML (full serialization)
      • .json → JSON state (lightweight, Git-friendly)
      • other → Java binary serialization (legacy)
      Parameters:
      filename - the file path to save to
      Returns:
      true if save was successful
    • loadAuto

      public static ProcessSystem loadAuto(String filename)
      Loads a process system from a file with automatic format detection.

      File format is determined by extension:

      • .neqsim → XStream compressed XML
      • other → Java binary serialization (legacy)
      Parameters:
      filename - the file path to load from
      Returns:
      the loaded ProcessSystem, or null if loading fails
    • getEmissions

      public EmissionsTracker.EmissionsReport getEmissions()
      Calculates current emissions from all equipment in this process system.

      Tracks CO2-equivalent emissions from:

      • Flares (combustion emissions)
      • Furnaces and burners
      • Compressors (electricity-based, using grid emission factor)
      • Pumps (electricity-based)
      • Heaters and coolers (if fuel-fired or electric)

      Example usage:

      ProcessSystem system = new ProcessSystem();
      // ... configure and run ...
      EmissionsReport report = system.getEmissions();
      System.out.println("Total CO2e: " + report.getTotalCO2e("kg/hr") + " kg/hr");
      report.exportToCSV("emissions_report.csv");
      
      Returns:
      emissions report with breakdown by equipment and category
      See Also:
    • getEmissions

      public EmissionsTracker.EmissionsReport getEmissions(double gridEmissionFactor)
      Calculates emissions using a custom grid emission factor.

      Different regions have different electricity grid carbon intensities. Use this method to apply location-specific emission factors.

      Parameters:
      gridEmissionFactor - kg CO2 per kWh of electricity (e.g., 0.05 for Norway, 0.4 for global average)
      Returns:
      emissions report with equipment breakdown
    • getTotalCO2Emissions

      public double getTotalCO2Emissions()
      Gets total CO2-equivalent emissions from this process in kg/hr.

      This is a convenience method for quick emission checks. For detailed breakdown, use getEmissions().

      Returns:
      total CO2e emissions in kg/hr
    • createBatchStudy

      public BatchStudy.Builder createBatchStudy()
      Creates a batch study builder for running parallel parameter studies on this process.

      Batch studies allow exploring the design space by running many variations of this process in parallel. Useful for concept screening, sensitivity analysis, and optimization.

      Example usage:

      BatchStudy study =
          system.createBatchStudy().addParameter("separator1", "pressure", 30.0, 50.0, 70.0)
              .addParameter("compressor1", "outletPressure", 80.0, 100.0, 120.0)
              .addObjective("totalPower", true) // minimize
              .withParallelism(4).build();
      BatchStudyResult result = study.run();
      
      Returns:
      a new batch study builder configured for this process
      See Also:
    • generateSafetyScenarios

      public List<ProcessSafetyScenario> generateSafetyScenarios()
      Generates automatic safety scenarios based on equipment failure modes.

      This method analyzes the process structure and generates scenarios for common failure modes such as:

      • Cooling system failure
      • Valve stuck open/closed
      • Compressor/pump trips
      • Power failure
      • Blocked outlets

      Example usage:

      List<ProcessSafetyScenario> scenarios = system.generateSafetyScenarios();
      for (ProcessSafetyScenario scenario : scenarios) {
        scenario.applyTo(system.copy());
        system.run();
        // Check for dangerous conditions
      }
      
      Returns:
      list of safety scenarios for this process
      See Also:
    • generateCombinationScenarios

      public List<ProcessSafetyScenario> generateCombinationScenarios(int maxSimultaneousFailures)
      Generates combination failure scenarios (multiple simultaneous failures).

      This is useful for analyzing cascading failures and common-cause scenarios.

      Parameters:
      maxSimultaneousFailures - maximum number of failures to combine (2-3 recommended)
      Returns:
      list of combination scenarios
    • toDOT

      public String toDOT()
      Exports the process as a DOT format diagram string.

      Generates a professional oil & gas style process flow diagram (PFD) following industry conventions:

      • Gravity logic - Gas equipment at top, liquid at bottom
      • Phase-aware styling - Streams colored by vapor/liquid fraction
      • Separator semantics - Gas exits top, liquid exits bottom
      • Equipment shapes matching P&ID symbols

      Example usage:

      String dot = process.toDOT();
      Files.writeString(Path.of("process.dot"), dot);
      // Render with: dot -Tsvg process.dot -o process.svg
      
      Returns:
      Graphviz DOT format string
      See Also:
    • toDOT

      public String toDOT(DiagramDetailLevel detailLevel)
      Exports the process as a DOT format diagram with specified detail level.
      Parameters:
      detailLevel - the level of detail to include (CONCEPTUAL, ENGINEERING, DEBUG)
      Returns:
      Graphviz DOT format string
      See Also:
    • createDiagramExporter

      public ProcessDiagramExporter createDiagramExporter()
      Creates a diagram exporter for this process with full configuration options.

      Example usage:

      process.createDiagramExporter().setTitle("Gas Processing Plant")
          .setDetailLevel(DiagramDetailLevel.ENGINEERING).setVerticalLayout(true)
          .exportSVG(Path.of("diagram.svg"));
      
      Returns:
      a new ProcessDiagramExporter configured for this process
      See Also:
    • exportDiagramSVG

      public void exportDiagramSVG(Path path) throws IOException
      Exports the process diagram to SVG format.

      Requires Graphviz (dot) to be installed and available in PATH.

      Parameters:
      path - the output file path
      Throws:
      IOException - if export fails
    • exportDiagramPNG

      public void exportDiagramPNG(Path path) throws IOException
      Exports the process diagram to PNG format.

      Requires Graphviz (dot) to be installed and available in PATH.

      Parameters:
      path - the output file path
      Throws:
      IOException - if export fails