Flow Statistics Providers in AnyLogic: Java Abstract Classes in Petroleum Refining Library

Why separate physical flows from flow statistics?

       Flow Statistics Providers in AnyLogic are an essential part of petroleum refinery simulation, enabling consistent monitoring and reporting of material flows between process units. In Petroleum Refining Library (PRL), Java-based provider classes encapsulate flow measurement, aggregation, and statistical formatting for individual and multiple process connections. This approach provides a consistent interface for retrieving flow measurements, aggregating multiple connections, analyzing input and output streams, and preparing formatted statistical reports. The architecture is based on abstract provider classes that define common functionality and specialized implementations that handle different flow configurations.

Flow Statistics Provider Architecture in AnyLogic

       The flow statistics architecture in PRL is built around the abstract AbstractFlowProvider class. It defines the common interface for accessing flow measurements and provides functionality shared by all flow providers.
The architecture separates flow providers into two main branches:
  • Multiple Flow Providers — handle several connected fluid flows.
  • Single Flow Providers — handle an individual flow controlled by a valve.
The multiple-flow branch is further divided into input and output providers.
Common functionality
       AbstractFlowProvider stores a reference to the owning PrlObject and defines the abstract getFlow(MeasurementType) method. This method provides a common interface for retrieving flow measurements in different units. The base class also implements hasFlow(), which checks whether the current mass flow is greater than zero. The specialized classes extend this functionality according to the flow configuration.

Dynamic flow connections
An important feature of the architecture is support for dynamically resolved flow connections. AbstractFlowsProvider can receive either direct arrays of FluidBlock and Valve objects or Supplier instances that provide these arrays on demand. This allows the provider to work with both fixed and dynamically changing process configurations without duplicating flow measurement logic.
The common implementation also handles flow aggregation, product identification, flow indexing, and statistical formatting.

Input and Output Flow Statistics Providers

       Multiple Flow Providers are designed to handle process units with several connected input or output streams. Both provider types inherit their common functionality from AbstractFlowsProvider, avoiding duplication of flow measurement and aggregation logic. The main difference between them is the additional information associated with each flow direction.

Input Flow Provider
       AbstractInputFlowsProvider extends the common functionality with input-specific features. Its main responsibilities include:
  • Retrieving and aggregating connected input flows.
  • Accessing an optional Mixer associated with the input connections.
  • Providing mixing factors for individual input streams.
  • Calculating normalized mixing ratios.
  • Formatting input flow statistics.
The getMixFactors() method can be overridden by subclasses to provide mixing factors in the order of connected input flows. By default, it returns an empty array.
Two methods are available for presenting mixing information:
  • getFormattedFactors() — displays the original mixing factors.
  • getFormattedRatios() — normalizes the factors by their sum to obtain relative proportions.
This functionality is particularly useful for refinery process units where several feedstock streams are combined before further processing.

Output Flow Provider
       AbstractOutputFlowsProvider provides corresponding functionality for process units with multiple output streams.
Its additional responsibility is to provide separation factors through the getSepFactors() method. Subclasses can override this method to define the distribution of output flows across connected streams.
As with input providers, two formatting methods are available:
  • getFormattedFactors() — displays the original separation factors.
  • getFormattedRatios() — converts the factors into normalized ratios.
These methods help describe how a process unit distributes its output among different products or destinations.

Shared Flow Statistics
Both input and output providers inherit the core functionality from AbstractFlowsProvider, including:
  • Flow aggregation: calculating total flow across connected FluidBlock objects.
  • Product identification: finding connected flows assigned to a specific product.
  • Indexed access: retrieving individual flow values by connection index.
  • Flow distribution: calculating the contribution of an individual stream to the total flow.
  • Statistical formatting: generating formatted reports with product names, flow values, percentages, and available valve limits.
The shared implementation also supports dynamically resolved connections through Java Supplier interfaces. This allows flow data to be retrieved on demand rather than relying exclusively on arrays captured during provider initialization. As a result, input and output providers offer a consistent approach to flow monitoring and statistics in AnyLogic refinery simulation, while retaining their specific responsibilities for mixing and separation data.

Single Flow Statistics Provider

       AbstractSingleFlowProvider handles individual flows controlled by a Valve. It extends AbstractFlowProvider and provides common functionality for flow measurement, valve state monitoring, and statistical formatting. Each provider is associated with a productId and a Valve instance.
       Key functionality:
  • Flow measurement: Retrieves mass or mass flow using getFlow(MeasurementType).
  • Valve state: getFormattedValveState() returns the current valve state (open or closed).
  • Maximum flow rate: getFormattedMaxSpeedIfChanged() reports a non-default valve capacity in tons per hour.
  • Flow formatting: Generates a flow description containing its direction, measurement unit, product name, and current value.
The class provides reusable functionality for specialized providers monitoring individual process connections.

Flow Statistics Report Formatting

       FlowStatisticsReportFormatter generates formatted input and output statistics reports by combining product flow data with supplementary information from the PRL Exporter. Its main functions include:
  • Product statistics: Displays individual flow rates and their percentage contributions.
  • Exporter integration: Adds supplementary statistical rows and supports custom product names.
  • Loss accounting: Includes flow losses in the total calculation.
  • Total flow: Calculates and displays the combined flow rate.
This class separates report generation from flow measurement, providing a consistent way to present process unit statistics.

Conclusion

       Petroleum Refining Library flow statistics are built around a modular provider architecture that separates flow measurement, aggregation, and report generation. Abstract providers offer reusable functionality for monitoring individual and multiple flows, while specialized input and output providers extend this functionality with mixing and separation data. Together with FlowStatisticsReportFormatter, this architecture provides a consistent approach to flow monitoring and statistical reporting across Petroleum Refining Library components.

FAQ

1 Does the library use Java interfaces for these flow providers?
The current provider structure is based on abstract classes. Statistics classes extend the appropriate provider class.

2 Can a Tank Farm use a statistics source different from its physical input?
Yes. Its inputFlowProvider parameter can refer to an AbstractInputFlowsProvider, such as the input statistics of a ShipmentNode.

3 Does using an external provider change the physical flow path?
No. It changes where the Tank Farm obtains its input flow information for statistics. The physical route remains defined by the model connections.

4 Can a Tank Farm have several physical inputs while using an external input provider?
No. When an external provider is set, the Tank Farm requires exactly one element in inputFlows[].