Discrete Rate Library
1. Subject area
1.1. Introduction
Discrete rate library helps to simulate the behavior of a system of interconnected flow elements that can receive, store, or send out a continuous quantity of some material.
While the material quantities are continuous, the name of the library includes the word 'discrete'. The rationale for that is the event-based nature of the modeling approach used to simulate the continuous material flow. Material quantities are continuous, but all flow rates in the system change stepwise. These flow rate changes are either proactively scheduled or fired as a response to a capacity-related event, such as material container underflow, overflow, or quantity threshold hit. Between consecutive flow rate changes, all material flow rates are constant.
For more information see:
-
Discrete rate simulation article and references therein;
-
A Global Approach For Discrete Rate Simulation article by Cecile Damiron and David Krahl
1.2. Material
By material we mean some homogeneous substance in the modelled system, regardless of its mass, volume, length or other 'size'-related features. Examples of materials include liquids ('Crude oil with density 0.7', 'Drinking water', etc.) and loose solid cargo ('Sand', 'Gravel', etc.).
Amount of material is a continuous non-negative numerical characteristic of a material having physical embodiment. Typically, a 'size'-related feature like volume or mass is chosen to calculate the amount of material. This choice is made once for all materials. That is, this amount feature should be applicable to and have the same semantics among all materials. For instance, volume is a common choice if all materials are liquids.
A portion of material, or material portion, represents a material taken in some amount: '7 tons of sand', '3 m³ of drinking water', etc.
In general, a portion of any material used in Discrete Rate Library must have two abilities:
-
Ability to be split into unlimited number of portions of arbitrary amount. Each resulting material portion consists of the same material as the parent material portion. The sum of material amounts in the resulting material portions is equal to the amount of material in the initial material portion.
-
Ability to be merged with another material portion of the same material into a single material portion. The resulting material portion consists of the same material as the parent material portions. The amount of material in the resulting material portion is equal to the sum of amounts of initial material portions.
Hence, material survives splitting and merging of material portions. Also, when material is moved around the system or stored, it is not changed: 'water' does not turn into 'sand' when it enters some point of the system, etc.
1.2.1. Material mixing
Materials can be mixed, producing a mix of materials. A mix of materials consists of one or several materials combined in some proportion. This proportion is called material proportion of the mix. An example of a material mix is 'sand and gravel 50/50 mix'.
A material mix portion is a mix of materials taken in some amount. Since the material mix consists of several materials, any material mix portion can be viewed as a combination of several material portions, with their amounts proportional to the material proportion of the mix. The amount of material for a material mix portion is equal to the sum of amounts of its constituent material portions. For instance, '1 ton of sand and gravel 50/50 mix' is a material mix portion.
When several material portions with different materials are mixed, the material amount in the resulting material portion is equal to the sum of amounts in the initial material portions.
Consider what happens when five material portions are mixed:
1 m³ of clear water, 2 m³ of oil, 3 m³ of clear water, 4 m³ of sand, 5 m³ of oil.
Since there are three distinct materials ('clear water', 'oil', and 'sand'), there will be three materials in the material mix. The material mix portion will contain these 3 materials with their amounts as follows: 4 m³ of clear water, 7 m³ of oil, and 4 m³ of sand.
1.2.2. Material grouping
An ordered group of one or several material mix portions is called a material mix portion sequence. Each material mix portion in a sequence has its own combination of materials (material mix) and size (amount). Same materials within different material mix portions of a sequence are considered separate. The amount of material of a sequence is calculated as the sum of amounts of materials in the constituent material mix portions.
1.3. Flow of material
A flow of material, or material flow, is a mix of materials that moves through some point of the system.
1.4. Flow rate
The amount of material that passes some point of the modeled system during one unit of model time is called flow rate, or simply rate (for instance, '1 m³ per hour') at that point.
The flow rate remains constant between the flow events and may only change on a flow event.
The possible flow events are:
-
Adding a new flow element or a new flow connection.
-
Removing a flow connection.
-
Changing the properties of a flow element (storage capacity, max flow rate, etc.).
-
Flow element becoming full/empty.
-
A material mix portion transported through one of its Conveyor's material import points.
Flow element bounds (i.e., material entry points and exit points) are typical points for calculating the rate and applying rate limits. For most flow elements, their current inflow rate and outflow rate can be calculated, and max inflow rate and max outflow rate can be set.
The maximum rate of a connection will be limited by both source’s max outflow rate and destination’s max inflow rate.
If a material source contains a mix of materials, its connection to a material destination will convey this mix, i.e., several materials will be delivered concurrently. A flow connection does not change the material mix it transfers: the amount proportions of delivered materials will be equal to the amount proportions of the material mix at the source flow element.
Consider the case when there is a mix of two materials in the material source: '10 m³ of oil' and '30 m³ of water', and the current rate of the connection to the (single) material destination is 1 m³ per hour. So, there are two materials in the source element (oil and water), with quantity proportions being 1:3. In an hour, the connection will deliver 1 m³ of the material mix to the material destination. The delivered mix portion will contain 250 liters of oil and 750 liters of water, thus keeping the material proportions of the initial mix (1:3).
Let’s consider another example when five materials are placed in the material source and mixed:
1 m³ of clear water, 2 m³ of oil, 3 m³ of clear water, 4 m³ of sand, 5 m³ of oil.
The mix contains three material types ('clear water', 'oil', and 'sand'), with their amount proportions being 4:7:4. If there is a connection to the (only) material destination with unlimited storage capacity, and the actual rate of the connection is 1.5 m³/hour, then in an hour 0.4 m³ of clear water, 0.7 m³ of oil, and 0.4 m³ of sand will be delivered, for a total of 1.5 m³. At the outset, the total material amount in the source element is 15 m³, so it will take 10 hours to deliver all the source mix to the destination (15 divided by 1.5).
1.5. Flow environment
The system of flow elements and their interconnections is referred to as the flow environment.
1.6. Flow elements
Flow elements can receive, contain, or send out a mix of materials.
There are several types of flow elements: tanks, bunkers, splits, merges, conveyors, and valves.
The element type defines its material storage ability and the maximum number of incoming (inflow) and outgoing (outflow) connections.
The table below describes each flow element.
Flow element | Can store material | Max # of supported inflow connections | Max # of supported outflow connections |
---|---|---|---|
Tank |
Yes |
1 |
1 |
Bunker |
Yes |
Unlimited |
1 |
Split |
No |
1 |
Unlimited |
Merge |
No |
Unlimited |
1 |
Conveyor |
Yes |
Unlimited |
1 |
Valve |
No |
1 |
1 |
1.6.1. Tank
Tank is a flow element that can store materials:

Tank can have at most one inflow connection and at most one outflow connection. It requires an additional Merge element to be able to receive material from several sources. In that case, a Bunker flow element may be more convenient.
Inside a Tank, several material mix portions can coexist in a form of a material mix portion sequence. Each such material mix portion is called a 'Layer'. Materials from different layers are separated. Layers are ordered in FIFO fashion: the 1st portion of material mix that is added to the Tank becomes the 1st portion of material mix to be exported.
1.6.2. Bunker
Bunker is a flow element that can store materials:

Bunker can have an unlimited number of inflow connections. Bunker, like a Tank, can have at most one outflow connection.
Unlike most other flow elements, Bunker is a composite element. It consists of a Merge, an inflow Valve, a Tank, and an outflow Valve, connected sequentially to one another:
-
The Merge allows the Bunker to be connected to several sources of material.
-
The inflow Valve sets up the maximum inflow rate of the Bunker.
-
The Tank works as a storage means that provides storage capacity and material layering.
-
The outflow Valve sets up the maximum outflow rate of the Bunker.
1.6.3. Split
Split is a flow element that receives material from exactly one input and can divide it into several outputs:

Split can have at most one incoming flow connection and many outflow connections. Split has no storage capacity, so its inflow rate is always the sum of rates of all its outflow connections.
The material proportions in the material mix of each outgoing connection are the same as in the incoming material mix.
Split flow rate distribution
The rates of outflow connections of a Split may differ.
When the outflow rate of a Split’s upstream flow element becomes less than the total max flow rate of Split’s downstream elements, the rate distribution among the outflow connections is regulated by the Split’s flow rate distribution policy. Two options exist:
Flow rate distribution policy | Behavior |
---|---|
Priority |
Material is sent to the top priority outputs first until the upstream element’s outflow rate limit is reached. For instance, if the upstream flow element can supply material at the max rate of 12 and the Split has five outflow connections, with their respective flow rates and priorities being from 1 to 5, then connections 1-4 will be used at their full flow rates (for a total outflow rate of 10), and the 5th connection will only be used at its partial rate of 2 (12 - (1+2+3+4) = 2). Note that priority=1 is higher than priority=2. |
Proportional |
Material is sent to all outflow connections. For each connection, a 'rate fraction' parameter is set, indicating the fraction of that connection’s rate in the overall outflow rate of the Split. Rate limits of each outgoing connection are respected. For instance, if the upstream flow element can send material at the max rate of 5 and the Split has five outflow connections, with their respective max flow rates being 1 to 4 and 'rate fractions' being 0.25, then the actual outflow rate via each of the outflow connections will be equal to 1, for a total outflow rate of 4. On the other hand, if rate fractions are set to be 0.1, 0.2, 0.3, and 0.4 - then the outflow connections will have respective actual rates of 0.5, 1.0, 1.5, and 2.0, for a total of 5 (this is the flow rate limit of the upstream element). |
1.6.4. Merge
Merge is a flow element that receives material from several inputs and combines them into a single output:

Merge can have many inflow connections and at most one outflow connection. Merge has no storage capacity, so its total inflow rate is always equal to the outflow rate.
Merge flow rate distribution
The rates of inflow connections of a Merge may differ.
When the inflow rate of a Merge’s downstream flow element becomes less than the total max flow rate of Merge’s upstream elements, the flow rate distribution among the inflow connections is regulated by the Merge’s flow rate distribution policy. Two options exist:
Flow rate distribution policy | Behavior |
---|---|
Priority |
Material is taken from the top priority inputs first until the downstream element’s inflow rate limit is reached. For instance, if the downstream flow element can accept material at the max rate of 12 and the Merge has five inflow connections, with their respective inflow rates and priorities being from 1 to 5, then connections 1-4 will be used at their full rates (for a total rate of 10), and the 5th connection will only be used at its partial rate of 2 (12 - (1+2+3+4) = 2). Note that priority=1 is higher than priority=2. |
Proportional |
Material is taken from all inflow connections. For each connection, a 'rate fraction' parameter is set, indicating the fraction of that connection’s rate in the overall inflow rate of the Merge. Rate limits of each incoming connection are respected. For instance, if the downstream flow element can accept material at the max rate of 5 and the Merge has five inflow connections, with their respective max inflow rates being 1 to 4 and 'rate fractions' being 0.25, then the actual inflow rate via each of the inflow connections will be equal to 1, for a total inflow rate of 4. On the other hand, if rate fractions are set to be 0.1, 0.2, 0.3, and 0.4 - then the inflow connections will have respective actual rates of 0.5, 1.0, 1.5, and 2.0, for a total of 5 (this is the limit of the downstream element). |
1.6.5. Conveyor
A Conveyor is a flow element that transports material from one point in space to another point at a given speed:

In the image above, material mix portions move inside the Conveyor from left to right, towards the Conveyor’s exit. When a portion gets to the end of the Conveyor (its rightmost point), it starts being exported from the Conveyor to the downstream flow element via the outflow connection, if any.
At most one outflow connection can be specified for a Conveyor.
Material arrival points
A Conveyor can accept incoming material at several points along its internal material path. Each such 'material arrival point' has a Merge, so several inflow connections can supply material to the same point of a Conveyor.
Material arrival points mark the start of so-called 'conveyor segments', i.e., the non-overlapping areas along the material path. These segments, however, are not independent. Rather, a Conveyor can be thought of as having a 'single conveyor belt': all material is placed onto that belt and moves along internal material path at the same speed.
In the image above there are 2 material arrival points, so the Conveyor has 2 segments.
Material is delivered by conveyor and by its segments in a FIFO fashion: the first material portion that enters the segment of a Conveyor will be the first portion to be exported from that segment. A material portion enters a conveyor segment at segment’s starting point either through one of the segment’s inflow connections (the material portion comes from outside the Conveyor) or directly from the previous conveyor segment, if any. A material portion leaves a segment at the segment’s end point only. Entering and leaving a segment is not instantaneous for a material portion, it is a continuous process since a material portion occupies some non-zero length of a Conveyor’s internal path.
It might still happen that a material mix portion that enters a Conveyor through one connection will be exported after a portion that enters a Conveyor later through another connection. Consider the case when a Conveyor has 2 segments of equal length, and it takes an hour to move material along each segment. Then, if some material portion is added to the first segment (at the beginning of the Conveyor), and then, half an hour later, another material portion is added to the second segment, then this second material portion will be 1/2 h ahead of the 1st material portion and will leave the Conveyor sooner.

In the image above, the orange material portion in the center, although added later in time, will be exported from the Conveyor earlier than the green one on the left.
Conveyor length and speed
The delivery of material from an entry point to the exit of a Conveyor is not instantaneous. After material enters a Conveyor, it will take some time to deliver it to the Conveyor’s output. This delivery duration (i.e. time required to deliver the material) depends on the 'logical length' of the path of material inside the Conveyor and the speed at which material is being transported within the Conveyor.
The logical length is measured in so-called 'logical pixels'. A 'logical pixel' is a measure of distance, and its correspondence to some 'real' measurement units (like meters, inches, etc.) is arbitrary, lies beyond the realm of a Conveyor setup and is not specified explicitly for a Conveyor.
Speed of a Conveyor defines how fast material mix portions move along the Conveyor. The speed is measured in 'logical pixels' per unit of model time. Speed is the same along the whole length of a Conveyor. For example, if it is not possible to export material from a Conveyor due to the downstream element’s current inability to accept material, not only the final segment of the Conveyor but the whole Conveyor gets stopped.
A Conveyor has a max speed.
Material distribution along a Conveyor
Material mix portions of the same amount can occupy continuous areas of various sizes on a Conveyor:

In this example, all five material mix portions have the same amount, but are distributed differently along the Conveyor.
For a material mix portion inside a Conveyor, its effective portion flow rate is the current internal material flow rate at any point along its length. Conveyor speed affects this flow rate.
The size of the area occupied by a material mix portion along its Conveyor is called portion length. This length remains the same after the portion is added and until it starts being exported from the Conveyor. In the image above, the rightmost portion has the greatest length.
Portion transportation time - time required to transport a material mix portion through some internal point of a Conveyor - is calculated as portion length / Conveyor speed.
Hence, the effective portion flow rate is equal to the portion amount / transportation time.
We also need a parameter that shows the (constant) 'height' of a material mix portion. A good real-world example is a belt conveyor transporting bulk materials such as sand, gravel, etc. The 'height' in the image above corresponds to the physical height of some bulk material on the conveyor belt.
The portion height should be calculated as portion amount / portion length. From the previous calculations we see that this proportion is equal to the following: effective portion flow rate / Conveyor speed. So, if we multiply the portion height by the current Conveyor speed, we get exactly the effective flow rate of the portion.
Conveyor performance and inflow rate limit
A Conveyor has the internal flow rate limit, or 'performance'. Effective portion flow rates never exceed the Conveyor’s performance, even if the Conveyor transports material at the max speed.
Some time after a material mix portion enters a Conveyor, the Conveyor’s speed may change. If the speed increases, material starts moving faster, thus increasing the flow rate at some point of the Conveyor.
The idea behind enforcing a rate limit for incoming material flow connections is to prevent the effective flow rate of a material portion from exceeding its Conveyor’s performance.
Consider an example Conveyor whose speed is 1 m/s, max speed is 5 m/s, and performance is 10 units of material per second. We need to calculate the max inflow rate of any 'material arrival point' in this Conveyor. If we supply a material portion to the Conveyor at some rate R now, then, if the Conveyor (moving at 1 m/s during material import) later starts moving at its max speed of 5 m/s, the internal flow rate along this material portion lying on the conveyor belt will also become 5x more than R, i.e. 5 * R. This internal flow rate is limited by the performance: 5 * R ⇐ performance, i.e., 5 * R ≤ 10 units of material per second. From the last expression we can conclude that R should not exceed 2 units of material per second. This is the max inflow rate of any 'material arriving point' of our Conveyor.
When another material mix portion crosses a 'material arrival point', the portion’s effective rate is further subtracted from the max inflow rate of that point. In particular, the effective rate of the portion passing the point can be so large that no material will be imported through this point until the material mix portion passes the point completely.
More generally, max inflow rate R is calculated as
(Conveyor performance) * [(current speed) / (max speed)] - (effective rate of the material mix portion coming from the prev. segment)
Since each inflow connection of a Conveyor first enters a Merge element, the actual rate of each connection is also defined by the Merge flow rate distribution, which is set to 'Priority' for all such built-in Merge elements.
Conveyor outflow rate
Conveyor outflow rate is equal to the effective flow rate of the exported material mix portion.
Conveyor rate shortage policy
A Conveyor handles a situation when it can export material at a higher rate than the downstream flow element can accept. In this case, its downstream inflow rate shortage policy is applied. Two options exist:
Rate shortage policy | Behavior |
---|---|
Stop |
If the rate of the current material mix portion being exported from the Conveyor exceeds the rate at which material can be imported by the downstream flow element, the Conveyor is stopped. The Conveyor starts moving again when the downstream flow element becomes available for receiving material at the rate of the material mix portion being exported from the Conveyor. |
Change speed |
If the rate of the current material mix portion being exported from the Conveyor exceeds the rate at which material can be imported by the downstream flow element, the speed of the Conveyor is reduced accordingly, which causes the current export rate of the Conveyor to decrease. At the same time, the max inflow rate of the Conveyor is reduced proportionally. After the current material mix portion has been exported, the speed of the Conveyor and its initial max inflow rate are restored. |
1.7. Flow element connection
Flow elements can be connected to other flow elements or disconnected from them. Flow connections between flow elements are one-way, each connects a material source to a material destination, thus setting up the direction of the flow of material in the system.
For two connected flow elements, the connection between them is called an outflow connection for the material source element and an inflow connection for the material destination element.
A flow connection between elements does not have a storage capacity and brings no delay to the system: all the material that has left the source is instantly delivered to the destination.
2. Classes
The system of flow elements and their interconnections is referred to as the flow environment and is modeled with a FlowEnvironment
class.
FlowEnvironment is a generic class parameterized by a type whose instances represent materials used in the system.
Each flow element and each flow connection belongs to one and only one flow environment.
Each type of a flow element has a corresponding class to model its behavior: Tank, Split, Merge, Bunker, Conveyor, and Valve,
For a Conveyor, the separate material mix portions are modeled as instances of the ConveyorRateRecord class. Tanks and Bunkers store their material mix portions as layers, modeled by Tank.Layer class.
Connections between flow elements are modeled by instances of the FlowConnection class.
Finally, a mix of materials of different types flowing through or contained in a flow element is represented with Accumulator class. The same universal Accumulator class is also used to describe rate proportions, material proportions, and the overall rate distribution among several materials.
3. Example 1: 'Hello world'

Let’s create a simple example of a system that contains two connected Tanks, with material flowing from one Tank to another.
The first Tank has some initial amount of material inside, and the second Tank is initially empty. We want to connect the tanks and see the material flowing from one to the other.
(1)
Engine engine = new Engine();
FlowEnvironment<String> flowEnvironment = new FlowEnvironment<>(engine);
(2)
Tank<String> sourceTank = new Tank<>(flowEnvironment, "source tank", 100);
Valve<String> valve = new Valve<>(flowEnvironment, 10);
Tank<String> destinationTank = new Tank<>(flowEnvironment, "destination tank", 100);
sourceTank.connectToElement(valve);
valve.connectToElement(destinationTank);
(3)
sourceTank.addContents(Accumulator.of("Water", 50));
(4)
flowEnvironment.init();
(5)
engine.scheduleStop(3, "Stop engine");
engine.setFastMode(true);
engine.run(true);
(6)
assertEquals(20, sourceTank.getContentsAmount());
assertEquals(30, destinationTank.getContentsAmount());
Here is what happens in the code:
1 | We create a new Engine and a new FlowEnvironment.
All materials will be instances of the String class.
An instance of Engine is typically shared among several flow environments. |
2 | Several flow elements are created and connected. The 'sourceTank' and the 'destinationTank' are Tanks, and 'valve' is a Valve between them to set the flow rate. |
3 | The 'sourceTank' is filled with 50 units of water. |
4 | The flow environment is initialized. This should be done only once per FlowEnvironment instance. |
5 | The engine is scheduled to stop at model time 3 and is set up to run in fast mode. Then the engine starts to run the model synchronously. |
6 | The results are checked: after 3 units of model time, 30 units of water (at a flow rate of 10 set by the Valve) have been transported from sourceTank to destinationTank. |
4. Example 2: Proportional Split

In this example we will use a Split to send material to several destinations.
The Split takes material from one Tank and sends it to three destination Tanks. Between each Tank and the Split a Valve is added to regulate the flow rate.
Engine engine = new Engine();
FlowEnvironment<String> flowEnvironment = new FlowEnvironment<>(engine);
(1)
Tank<String> sourceTank = new Tank<>(flowEnvironment, "source tank", 100);
Valve<String> valveAfterSource = new Valve<>(flowEnvironment, 18);
Split<String> split = new Split<>(flowEnvironment, FlowRateDistributionPolicy.PROPORTIONAL);
Valve<String> valve1 = new Valve<>(flowEnvironment, 21);
Tank<String> destinationTank1 = new Tank<>(flowEnvironment, "dest tank 1", 100);
Valve<String> valve2 = new Valve<>(flowEnvironment, 21);
Tank<String> destinationTank2 = new Tank<>(flowEnvironment, "dest tank 2", 100);
Valve<String> valve3 = new Valve<>(flowEnvironment, 21);
Tank<String> destinationTank3 = new Tank<>(flowEnvironment, "dest tank 3", 100);
(2)
sourceTank.connectToElement(valveAfterSource);
valveAfterSource.connectToElement(split);
valve1.connectToElement(destinationTank1);
valve2.connectToElement(destinationTank2);
valve3.connectToElement(destinationTank3);
(3)
split.setOutflowRateFraction(split.connectToElement(valve1), 0.1);
split.setOutflowRateFraction(split.connectToElement(valve2), 0.3);
split.setOutflowRateFraction(split.connectToElement(valve3), 0.6);
sourceTank.addContents(Accumulator.of("Water", 60));
flowEnvironment.init();
engine.scheduleStop(3, "Stop engine");
engine.setFastMode(true);
engine.run(true);
(4)
assertEquals(60 - 18 * 3, sourceTank.getContentsAmount());
assertEquals(18 * 0.1 * 3, destinationTank1.getContentsAmount());
assertEquals(18 * 0.3 * 3, destinationTank2.getContentsAmount());
assertEquals(18 * 0.6 * 3, destinationTank3.getContentsAmount());
1 | A Split and several Tanks and Valves are created. |
2 | Note that the order in which connections are created between elements is not important, so blocks 2 and 3 can be swapped. |
3 | The connectToElement method returns a FlowConnection object. We tune each such connection’s flow rate fraction in the overall flow rate through the Split. |
4 | The outflow rate of the source Tank is limited by the Valve between the source Tank and the Split. Other Valves do not use their full bandwidth. |
In this example, the overall flow rate is limited by the Valve that stands before the Split, because of its low rate limit.
5. Example 3: Proportional Split with source Valve removed

Let’s see what happens if we remove the Valve that stands before the Split and keep other Valves in place.
Engine engine = new Engine();
FlowEnvironment<String> flowEnvironment = new FlowEnvironment<>(engine);
Tank<String> sourceTank = new Tank<>(flowEnvironment, "source tank", 100);
Split<String> split = new Split<>(flowEnvironment, FlowRateDistributionPolicy.PROPORTIONAL);
Valve<String> valve1 = new Valve<>(flowEnvironment, 21);
Tank<String> destinationTank1 = new Tank<>(flowEnvironment, "dest tank 1", 100);
Valve<String> valve2 = new Valve<>(flowEnvironment, 21);
Tank<String> destinationTank2 = new Tank<>(flowEnvironment, "dest tank 2", 100);
Valve<String> valve3 = new Valve<>(flowEnvironment, 21);
Tank<String> destinationTank3 = new Tank<>(flowEnvironment, "dest tank 3", 100);
(1)
sourceTank.connectToElement(split);
valve1.connectToElement(destinationTank1);
valve2.connectToElement(destinationTank2);
valve3.connectToElement(destinationTank3);
split.setOutflowRateFraction(split.connectToElement(valve1), 0.1);
split.setOutflowRateFraction(split.connectToElement(valve2), 0.3);
split.setOutflowRateFraction(split.connectToElement(valve3), 0.6);
sourceTank.addContents(Accumulator.of("Water", 60));
flowEnvironment.init();
(2)
engine.scheduleStop(1, "Stop engine");
engine.setFastMode(true);
engine.run(true);
(3)
assertEquals(60 - 21 / 0.6, sourceTank.getContentsAmount());
assertEquals(21 / 0.6 * 0.1, destinationTank1.getContentsAmount());
assertEquals(21 / 0.6 * 0.3, destinationTank2.getContentsAmount());
assertEquals(21 / 0.6 * 0.6, destinationTank3.getContentsAmount());
1 | We connect the source Tank directly to the Split, Valve is removed. |
2 | Note the modeling duration change, now it is 1 second only. |
3 | Each of remaining Valves has a flow rate limit of 21. These limits are applied to the outflow connections of the Split, which results in the third Tank being filled at a rate of 21, the second Tank - 10.5, and the first Tank - 3.5. The total amount of material that has left the source tank is calculated as follows: the third tank accepts 21 units of water per second, and that is 0.6 of the total Split’s outflow rate, so the Split has transferred 35 units of water from the source Tank. |
6. Example 4: Conveyor

In this example, we will see the delivery delay given by a Conveyor.
The Conveyor has length 7 and its speed is equal to 1. So, it takes a material 7 seconds to travel from the entrance of the Conveyor to its exit.
Conveyor’s performance (max internal flow rate) is equal to 10. Since the Conveyor speed in this example is equal to the max speed of the Conveyor, its inflow rate limit is equal to the performance. This time we connect a source Tank directly to a Conveyor without a Valve, so the max rate of this connection is limited from the Conveyor’s side only.
Conveyor then delivers material to the destination Tank.
Engine engine = new Engine();
FlowEnvironment<String> flowEnvironment = new FlowEnvironment<>(engine);
Tank<String> sourceTank = new Tank<>(flowEnvironment, "source tank", 100);
(1)
Conveyor<String> conveyor = Conveyor.builder(flowEnvironment)
.polyline(new Polyline(new Point(0, 0), new Point(1, 1)))
.policy(DownstreamInflowRateShortagePolicy.CHANGE_SPEED)
.maxSpeed(1)
.performance(10)
.logicalLength(7)
.build();
conveyor.setSpeed(1);
Tank<String> destinationTank = new Tank<>(flowEnvironment, "dest tank", 100);
(2)
conveyor.connectInputFlowWithLogicalOffset(sourceTank, 0);
(3)
conveyor.connectToElement(destinationTank);
sourceTank.addContents(Accumulator.of("Water", 100));
flowEnvironment.init();
engine.scheduleStop(8, "Stop engine");
engine.setFastMode(true);
engine.run(true);
(4)
assertEquals(100 - 10 * 8, sourceTank.getContentsAmount());
assertEquals(10 * 8 - 10 * 7, destinationTank.getContentsAmount());
1 | The Builder pattern is used to construct a new Conveyor. |
2 | Note that using Conveyor’s connectInputflow… methods is the only correct way to add an inflow connection to a Conveyor. |
3 | Connection to a downstream element, however, is made in a usual fashion, unless the downstream element is a Conveyor itself. |
4 | The source Tank exports 80 units of material. However, 70 of 80 material units are now inside the Conveyor, and only 10 are inside the destination Tank. |