skip to main content
Solution Approaches : Rulebased Simulation : Rulebased Simulation Controller
Rulebased Simulation Controller
The rulebased simulation controller orchestrates the alternation between execution of rules and solving of the simulation during a rulebased simulation run. It manages the dispatching of objects on the dispatch queue, just as the simulation controller does. When no objects can dispatch, the controller invokes the rule processor. The rule processor fires rules on the agenda, in the priority order specified by the user, until a rule is successful. Then, the controller again processes the dispatch queue.
Controller Priority
An additional function of the rulebased simulation controller is to track the controller priority when objects are dispatching. The purpose of the controller priority is to track the priority of the effects of rules as they are simulated in the model.
 
Controller priority
The controller priority during simulation (dispatching) is the priority of the data which is driving the current simulation. The controller priority is zero at each timestep until a rule succeeds, after which it is the priority of the last rule to succeed.
The controller priority during object dispatching reflects the priority of the information driving the dispatching. During Initialization, Beginning of Run, End of Run and each Beginning and End of Timestep, the controller priority is set to 0. During Initialization, user inputs are “set” in the slots. During Beginning of Run and Beginning of Timestep, default values are set where user input has deliberately been left out. Any slots set during these times are considered in rulebased simulation as if they had been directly input by the user. The controller priority of 0 remains in effect during the dispatching which occurs immediately after Beginning of Timestep. Since no rules have fired yet, all of these dispatches result from user input.
After a rule successfully fires and sets one or more slot values, the controller priority is set to the priority of the successful rule. As a result of these slot values, one or more objects may be ready to dispatch. Since the impending dispatch and any subsequent dispatches are a direct result of the rule’s slot assignment, these calculations are performed at the priority of the rule.
Simulation/Rules Interaction
The rulebased simulation controller behaves similarly to the simulation controller. (See Simulation for details of the simulation controller.) During the Initialization, Beginning of Run and Beginning of Timestep method executions, the rulebased simulation controller behaves much like the basic simulation controller: outputs are cleared, inputs set, links are propagated, expression slots are evaluated, and objects are initialized.
This section describes the timestep specific inline rulebased simulation steps in more detail. First, the steps are presented in paragraph format, then they are presented in bullet format. During the timestep-specific inner loop of the rulebased simulation controller, control alternates between dispatching objects and the rule processor as described in the following steps:
1. Processing the object dispatch queue. Objects check their dispatch conditions and may try to dispatch (or redispatch) after a “dispatch slot” on the object changes value. An object maintains a list of its dispatch slots and dispatching only occurs if it has sufficient known values.
2. Executing rules from the agenda one at a time. When a rule is successful, all its slot assignments are made. If it is not successful, none of its assignments are made, i.e. never are some, but not all of the assignments made. When the rule succeeds, the slot cell whose value was changed is given the priority of the rule and the “R” flag. These values show up in the rules analysis dialogs. Each rule maintains a list of the slots on which the outcome of the rule is “dependent”, namely those slots that were read during the rule execution. A rule will re-execute after one or more of its dependency slots changes value. Thus, objects that are dispatching can cause rules to re-execute by changing the values of slots upon which the rules depend, while rules that change dispatch slot values can cause simulation objects to dispatch.
At the start of the timestep (after beginning of timestep behavior has occurred), the dispatch queue (step 1) is fully processed until empty. This simulates the effects of user inputs. In this processing of the dispatch queue, objects may dispatch one or more times or may not dispatch at all depending on the dispatch slots that are set or changed throughout the course of the dispatching.
Once the queue is empty, the rules controller moves to the second step and starts with the full set of enabled rules on its “agenda” in priority order. This ensures that each enabled rule gets at least one chance to execute. The controller tries to execute the first rule on the agenda, in user specified order, at which time the controller removes the rule from its agenda. A successful rule may put objects on the simulation dispatch queue. After a rule succeeds and sets a value, the controller returns to step 1 and dispatches all objects on the queue.
When the dispatch queue is again empty, the controller returns to Step 2. and executes the next rule on its agenda. Once a rule succeeds, it returns to step one and processes the dispatch queue. It continues alternating until both the dispatch queue and the rules agenda are empty.
The rulebased simulation controller follows the procedure outlined below:
1. Initialization
– Clear all output and values set by rules from previous runs for all timesteps in all series slots.
– Set the controller priority to 0.
– Set user inputs
– Propagate user inputs across links for all timesteps.
– Determine first dispatch timestep. See Initialization for details.
1. Execute rules in the Initialization Rules RPL set. See Initialization Rules Set in RiverWare Policy Language (RPL) for details.
2. Beginning of Run
– Execute Beginning of Run methods for all objects.
– Evaluate Beginning of Run expression slots for all timesteps.
3. For each timestep:
a. Set the controller clock to the timestep time.
b. Set controller priority to 0.
c. Execute Beginning of Timestep methods for all objects.
d. Evaluate expression slots that have evaluate-at-beginning-of-timestep selected
e. Put all rules on the agenda (in priority order - whether 3,2,1 or 1,2,3 is user-selectable)
f. Do the following two processes until both the dispatch queue and the rules agenda are empty
1. Process 1. Process the Dispatch Queue: Dispatch objects (as in basic Simulation) until the queue is empty, simulating the effects of any user inputs and default values and any recent changes to slots by rules. For each slot changed by this dispatch:
Put all rules that depend on the changed slot on the agenda, if it's not already there.
If the slot is a dispatch slot, check dispatch conditions and if necessary put the object containing the slot on the simulation dispatch queue
If the Queue is empty, move on to process 2.
2. Process 2. Execute a Rule on the agenda: Set the controller priority to the priority of the next rule on the agenda (either in order 3,2,1 or 1,2,3 based on user-selection), and fire this rule. If not successful, continue firing one rule at a time until a rule is successful and at least one slot is set in the model. Each rule is removed from the agenda after it fires. Once a rule is successful:
Apply the slot changes, giving the changed slot cell the priority of the controller (i.e. the last rule that fired)
Add to this rule’s dependency’s list each slot that was read by this rule.
For each slot set by this rule, put all rules that depend on the changed slot on the agenda if the rule is not already there.
For each slot changed by this rule, if the slot is a dispatch slot, check dispatch conditions and if necessary, place the object containing the slot on the simulation dispatch queue.
3. Return to Process 1 and repeat until the Agenda and the Queue are empty.
g. Set controller priority to zero, and execute End of Timestep methods on all objects.
h. Evaluate end of timestep, current timestep only expression slots
4. If the number of run cycles performed is less than the number of run cycles specified, return to Step 3. and loop through each timestep again. See Run Cycles for details.
5. Execute End of Run methods on all objects including evaluating end of run expression slots.
Timestep Dependence of Rules
In RiverWare Simulation, solutions are possible forward and backwards in time. For example, reaches can solve upstream and backwards in time for some routing methods, and target operations on reservoirs solve previous timestep operations to meet a current target. In Rulebased Simulation, however, the rules should set only current values; i.e., values at the current controller timestep. The simulation should move forward in time, completely solving each timestep, then moving forward to the next.
Run Cycles
Rulebased simulations can cycle through the timesteps multiple times; each pass through the run timesteps is referred to as a Run Cycle. Traditionally (and by default) rulebased simulations cycle through the timesteps a single time, i.e., the default number of Run Cycles is 1. You may adjust this value upwards in the Rulebased Simulation Run Parameters dialog, which is accessed from the Run Control dialog's View menu. See Rulebased Simulation Run Parameters in User Interface for details.
To illustrate one use of this feature, consider a model consisting of two subbasins, where the policy of the lower basin requires knowledge of the upstream basin’s output for all timestep. One way to model this situation is to configure the simulation to cycle through the timesteps twice, solving for the upstream basin on the first run cycle and the downstream basin on the second. To do this, you would add execution constraints to the rules governing the upper basin which constrain them to execute only if the current run cycle is 1, and, similarly, the remaining rules that apply to the lower basin would be constrained to execute only on the second cycle. Execution constraints and RPL expressions in general can access the current run cycle using the predefined function GetRunCycleIndex. See GetRunCycleIndex in RiverWare Policy Language (RPL) for details.
Together these features allow you to control which aspects of the policy apply to which portion of the run, which in turn allows parts of the model to solve fully before other parts—rules have access to slot values computed at all timesteps on previous run cycles.
More complex logic than that used in the previous example could allow rules/objects to solve on multiple cycles. Much like the way in which iterative MRM allows logic to control the number of runs, user logic could control the number of cycles. To do so, you would set the Number of Run Cycles parameter to a larger number, and then use logic and the STOP RUN statement to stop the run when the simulation goal had been achieved.Why might this feature by used instead of Iterative MRM? Run cycles are executed within a single run, you can run a model that is using multiple run cycles within a concurrent MRM to evaluate different hydrologies or policies.
When the number of Run Cycles to be greater than 1, the run control has additional controls for pausing as shown in Figure 2.1. Select both the timestep and the Run Cycle in which to pause. Also, notice that the Run Status at the bottom of the figure also shows the Run Cycle number.
Figure 2.1  Screenshot of Pause Before Timestep when using Run Cycles
Revised: 07/09/2023