The Causality Sequence and Element Updating

In order for GoldSim to determine how to carry out its calculations, it first must create the causality sequence for all of the elements. This represents the sequence in which the elements must be logically computed. For example, if A was a function of B, and B was a function of C, then C would be sequenced first, followed by B, and then followed by A.  Although the sequence is obvious in this trivial example, in complex models the correct causality sequence may not be as obvious.

The internal logic within GoldSim for updating a model based on its causality sequence is very complex, and you don’t generally need to be concerned with it.  However, to better understand the basic concepts of the causality sequence and how GoldSim actually updates a model every timestep, let’s consider another example that is a bit more complex:

In this model, we are computing the volume of water in a pond (represented by a Reservoir).  The outflow (Withdrawal Request) from the pond (Pumping_Rate) is an Expression that is defined as a function of time.  Inflow1, Inflow2, and therefore Total_Inflow are constant values.  The Water_Level is a function of the Volume (the function being defined by a Lookup Table). So what does the causality sequence look like for this model? 

We can actually view the causality sequence by pressing F10, which brings up the following dialog:

What should immediately catch your attention here is that four of the elements (Stage_Storage, Inflow1, Inflow2 and Total_Inflow) do not appear in the list.

This can be explained by pointing out that there are actually two different sequences: the Static Sequence and the Function Sequence. The Static Sequence consists of those elements that only need to be computed once (at the beginning of the simulation), since they cannot change with time.  The Function Sequence consists of those elements that can change as a function of time.

By default, the dialog displays the Function Sequence.  If we choose to view the Static Sequence (in the top right corner of the dialog), it looks like this:

These three elements cannot change with time, and only need to be computed once.  Note, however, that the sequence indicates that Inflow1 and Inflow2 must logically be computed before Total_Inflow.

   Note: The Lookup Table element Stage_Storage is a special case in that it does not appear in either list.  This is because it actually does not compute an output itself and hence never really needs to be updated; it is used to define a static function (completely analogous to a built-in function such as sin or max) that is used by other elements (in this case, Water_Level). Hence, Lookup Tables do not appear in the causality sequence.

Returning to the Function Sequence, let’s walk through how GoldSim actually carries out its calculations every timestep for this example.  As noted above, at the beginning of the simulation, GoldSim first computes all of the static elements (i.e., those elements in the Static Sequence).  After doing so, it does not have to compute these again for the rest of the simulation.

Every timestep, GoldSim carries then out its calculations in three steps:

1.  It changes the system clock to the appropriate time (e.g., moves it forward a timestep).

2.  It computes those elements that have state variable outputs that are intrinsic functions of time (e.g., Reservoirs). In the discussion below, this is referred to as the intrinsic update of the element.

3.  It computes the elements in the Function Sequence.

So prior to evaluating the Function Sequence, every timestep, after changing the system clock, GoldSim first updates the state variable outputs for elements that are intrinsic functions of time.  In this example, the only output that falls into this category is the primary output (the current value) of the Reservoir element named Volume. Note that to do this, GoldSim uses the Additions and Withdrawal Requests that were computed at the previous timestep. (This is because Additions and Withdrawal Requests are forward-looking; they represent the values over the next timestep).

It then computes the Function Sequence. First it updates the Pumping_Rate.

It then updates the Reservoir again. In this particular model, however, other than the intrinsic changes (represented by the Additions and Withdrawal Requests) there are no other elements that impact the primary output of the Reservoir, so it is not changed by the Function Sequence calculation. However, other outputs of the Reservoir that are not state variables (e.g., the Withdrawal_Rate) are updated at this time. Moreover, the inputs for the Reservoir (e.g., its Withdrawal Request input) are updated (e.g., due to a change in the Pumping_Rate) and “remembered” so that they can be used for the next intrinsic update the following timestep.

Finally, it computes the Water_Level (based on the current value of the Volume).

   Note: Outputs that are intrinsic functions of time may actually be evaluated twice under some circumstances within the same timestep: first in step #2 (e.g., for the case of a Reservoir, to bring it up to the current time via its intrinsic behavior of time integration of additions and withdrawals), and then again in step #3 (e.g., in the case of a Reservoir, if an Upper Bound changes, forcing the output to a certain value).

Several additional points should be noted regarding the causality sequence:

   The three steps above are not only carried out during scheduled timesteps.  They are also carried out during unscheduled timesteps that GoldSim automatically inserts to more accurately represent the system, and in some cases, may be carried out multiple times within the same timestep (e.g., within a looping Container).

   Looping systems obviously complicate the causality sequence.  In some cases, GoldSim can handle these systems automatically.  In other cases, you may need to take action in order to represent logic that is recursive.

   For some complex looping systems (particularly those involving events that impact state variables), there may exist more than one way to sequence that system (and these may produce different results).  In these cases, you can manually force a particular causality sequence to ensure that the model accurately represents your system.

   When Discrete Changes are present in a Function Sequence, the Discrete Changes are propagated to any affected stock elements instantaneously when the Discrete Change is updated in the sequence (regardless of where the affected stocks are in the sequence).

Related Topics…

Learn more about: