Class SteadyStateDetector

java.lang.Object
neqsim.process.util.reconciliation.SteadyStateDetector
All Implemented Interfaces:
Serializable

public class SteadyStateDetector extends Object implements Serializable
Steady-State Detector (SSD) for process variables.

Monitors a set of process variables over a sliding window and determines whether the process has reached steady state. The primary criterion is the R-statistic: the ratio of filtered variance (successive differences) to unfiltered variance (sample variance). At steady state, both variances are similar and R approaches 1.0. During ramps, steps, or oscillations, R drops well below 1.0.

Two additional optional criteria can be enabled:

  • Slope test: the absolute slope from linear regression through the window must be below a threshold. This catches slow drifts that the R-test may miss.
  • Standard deviation test: the standard deviation of the window must be below a threshold. This catches excessive noise.

The detector is designed for use in online optimization workflows where data is collected externally (e.g., in Python from a DCS historian) and fed into the detector one sample at a time. When all variables pass the SSD test, the process is at steady state and safe for data reconciliation or model calibration.

Typical usage from Python:

detector = SteadyStateDetector(30)  # 30-sample window
detector.addVariable(SteadyStateVariable("feed_flow", 30).setUnit("kg/hr"))
detector.addVariable(SteadyStateVariable("temperature", 30).setUnit("C"))

# In a loop, push new readings:
detector.updateVariable("feed_flow", 1005.2)
detector.updateVariable("temperature", 82.1)
result = detector.evaluate()
if result.isAtSteadyState():
    # safe to reconcile
    ...

References:

  • Cao, S. and Rhinehart, R.R. (1995), "An efficient method for on-line identification of steady state", Journal of Process Control, 5(6), 363-374.
  • Jiang, T., Chen, B. and He, X. (2003), "Industrial application of Wavelet-based steady state detection", Computers and Chemical Engineering, 27, 569-578.
Version:
1.0
Author:
Process Optimization Team
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      See Also:
    • logger

      private static final org.apache.logging.log4j.Logger logger
      Logger for this class.
    • variableMap

      private final Map<String, SteadyStateVariable> variableMap
      Registered variables, keyed by name.
    • variableList

      private final List<SteadyStateVariable> variableList
      Ordered list of variables (preserves insertion order).
    • defaultWindowSize

      private int defaultWindowSize
      Default window size for new variables.
    • rThreshold

      private double rThreshold
      R-statistic threshold. A variable is at steady state if R >= this threshold. Default 0.5 (Cao-Rhinehart recommended range 0.1-1.0; 0.5 is a good balance).
    • slopeThreshold

      private double slopeThreshold
      Maximum allowed slope (units per sample). If > 0 and |slope| exceeds this, the variable is not at steady state. Default 0 (disabled).
    • stdDevThreshold

      private double stdDevThreshold
      Maximum allowed standard deviation. If > 0 and std.dev exceeds this, the variable is not at steady state. Default 0 (disabled).
    • requiredFraction

      private double requiredFraction
      Minimum fraction (0-1) of variables that must be at steady state for the overall verdict. Default 1.0 (all variables must be steady).
    • requireFullWindow

      private boolean requireFullWindow
      Whether a full window is required before declaring steady state. Default true.
  • Constructor Details

    • SteadyStateDetector

      public SteadyStateDetector(int defaultWindowSize)
      Creates a steady-state detector with the given default window size.
      Parameters:
      defaultWindowSize - the default number of samples in the sliding window (must be at least 3)
      Throws:
      IllegalArgumentException - if defaultWindowSize is less than 3
    • SteadyStateDetector

      public SteadyStateDetector()
      Creates a steady-state detector with a default window size of 30.
  • Method Details

    • addVariable

      public SteadyStateDetector addVariable(SteadyStateVariable variable)
      Adds a variable to the detector.
      Parameters:
      variable - the steady-state variable to monitor
      Returns:
      this detector for chaining
      Throws:
      IllegalArgumentException - if a variable with the same name already exists
    • addVariable

      public SteadyStateVariable addVariable(String name)
      Adds a variable by name using the default window size.
      Parameters:
      name - the tag name
      Returns:
      the created variable (for further configuration)
    • getVariable

      public SteadyStateVariable getVariable(String name)
      Returns a variable by name.
      Parameters:
      name - the variable name
      Returns:
      the variable, or null if not found
    • getVariables

      public List<SteadyStateVariable> getVariables()
      Returns all registered variables.
      Returns:
      unmodifiable list of variables in insertion order
    • getVariableCount

      public int getVariableCount()
      Returns the number of registered variables.
      Returns:
      variable count
    • removeVariable

      public boolean removeVariable(String name)
      Removes a variable by name.
      Parameters:
      name - the variable name to remove
      Returns:
      true if the variable was found and removed
    • clear

      public void clear()
      Clears all variables.
    • updateVariable

      public void updateVariable(String name, double value)
      Updates a single variable with a new measurement value.
      Parameters:
      name - variable name (tag)
      value - new measurement reading
      Throws:
      IllegalArgumentException - if the variable name is not found
    • updateAll

      public void updateAll(Map<String,Double> values)
      Updates all variables at once from a map of name-value pairs.

      Convenient for pushing a batch of readings from a DCS scan.

      Parameters:
      values - map of variable name to measurement value
      Throws:
      IllegalArgumentException - if any variable name is not found
    • evaluate

      public SteadyStateResult evaluate()
      Evaluates all variables against the SSD criteria and returns the result.

      A variable is at steady state if:

      1. Its window is full (if requireFullWindow is true)
      2. R-statistic >= rThreshold
      3. |slope| <= slopeThreshold (if slopeThreshold > 0)
      4. std.dev <= stdDevThreshold (if stdDevThreshold > 0)

      The overall process is at steady state if the fraction of steady-state variables is at least requiredFraction.

      Returns:
      the SSD result with per-variable diagnostics and overall verdict
    • evaluateVariable

      private boolean evaluateVariable(SteadyStateVariable v)
      Evaluates a single variable against the SSD criteria.
      Parameters:
      v - the variable to evaluate
      Returns:
      true if the variable passes all active SSD tests
    • updateAndEvaluate

      public SteadyStateResult updateAndEvaluate(Map<String,Double> values)
      Convenience method: updates all variables and evaluates in one call.
      Parameters:
      values - map of variable name to new measurement value
      Returns:
      the SSD result
    • createReconciliationEngine

      public DataReconciliationEngine createReconciliationEngine()
      Creates a DataReconciliationEngine pre-populated with variables from this detector.

      Each steady-state variable that has a defined uncertainty is converted to a ReconciliationVariable using the latest value as the measurement and the configured uncertainty. Only variables currently at steady state are included (to avoid reconciling transient data).

      Returns:
      a new engine with variables added, ready for constraints and reconciliation
    • getDefaultWindowSize

      public int getDefaultWindowSize()
      Returns the default window size.
      Returns:
      default window size for new variables
    • setDefaultWindowSize

      public SteadyStateDetector setDefaultWindowSize(int defaultWindowSize)
      Sets the default window size for new variables.
      Parameters:
      defaultWindowSize - window size (must be at least 3)
      Returns:
      this detector for chaining
      Throws:
      IllegalArgumentException - if less than 3
    • getRThreshold

      public double getRThreshold()
      Returns the R-statistic threshold.
      Returns:
      threshold value (default 0.5)
    • setRThreshold

      public SteadyStateDetector setRThreshold(double rThreshold)
      Sets the R-statistic threshold.

      A lower threshold (e.g., 0.3) is more lenient — allows more variability before declaring transient. A higher threshold (e.g., 0.8) is stricter — requires very stable signals.

      Cao-Rhinehart recommended range: 0.1 to 1.0, with 0.5 as a good default.

      Parameters:
      rThreshold - R-statistic threshold in the range (0, 1]
      Returns:
      this detector for chaining
      Throws:
      IllegalArgumentException - if threshold is not in (0, 2]
    • getSlopeThreshold

      public double getSlopeThreshold()
      Returns the slope threshold.
      Returns:
      max allowed absolute slope (units per sample), or 0 if disabled
    • setSlopeThreshold

      public SteadyStateDetector setSlopeThreshold(double slopeThreshold)
      Sets the slope threshold.

      The slope is expressed in engineering-units per sample. Set to 0 to disable the slope test.

      Parameters:
      slopeThreshold - maximum allowed |slope|, or 0 to disable
      Returns:
      this detector for chaining
      Throws:
      IllegalArgumentException - if negative
    • getStdDevThreshold

      public double getStdDevThreshold()
      Returns the standard deviation threshold.
      Returns:
      max allowed standard deviation, or 0 if disabled
    • setStdDevThreshold

      public SteadyStateDetector setStdDevThreshold(double stdDevThreshold)
      Sets the standard deviation threshold.

      Set to 0 to disable the std.dev test. When enabled, a variable is only at steady state if its window standard deviation is at or below this threshold.

      Parameters:
      stdDevThreshold - max standard deviation, or 0 to disable
      Returns:
      this detector for chaining
      Throws:
      IllegalArgumentException - if negative
    • getRequiredFraction

      public double getRequiredFraction()
      Returns the required fraction of variables that must be steady for the overall verdict.
      Returns:
      fraction in [0, 1]
    • setRequiredFraction

      public SteadyStateDetector setRequiredFraction(double requiredFraction)
      Sets the required fraction of variables that must be at steady state.

      Default is 1.0 (all variables must pass). Set to 0.8 to allow 20% of variables to be transient and still declare overall steady state.

      Parameters:
      requiredFraction - fraction in [0, 1]
      Returns:
      this detector for chaining
      Throws:
      IllegalArgumentException - if not in [0, 1]
    • isRequireFullWindow

      public boolean isRequireFullWindow()
      Returns whether a full window is required before declaring steady state.
      Returns:
      true if full window is required (default)
    • setRequireFullWindow

      public SteadyStateDetector setRequireFullWindow(boolean requireFullWindow)
      Sets whether a full window is required before declaring steady state.
      Parameters:
      requireFullWindow - true to require full window
      Returns:
      this detector for chaining
    • toString

      public String toString()
      Returns a summary string.
      Overrides:
      toString in class Object
      Returns:
      brief summary of the detector configuration