Skip to content

Algorithmic Ordering

Stephen Berry edited this page May 24, 2016 · 10 revisions

Module Based Simulation

Ascent is designed to handle simulation correctness, in terms of initialization, ordering, and variable access at the module level and no lower. In other words, there should never be a need to individually check whether a module's input variables (i.e. linked variables) can be obtained or set. Instead, simulation correctness is determined at the module level. If a linked module is accessible then all its contained variables must also be validly accessible.

Automatic Ordering

A simulation designer using Ascent doesn't have to keep track of global module ordering. Large systems become too complex for anyone to keep track of in the long run, and nearly impossible when the systems are dynamic.
Ascent ensures proper global ordering via Link's overloaded access operator (->).

Use Link Containers To Ensure Proper Ordering

In order to ensure that the system is properly solved and not dependent upon construction or storage sequence, use Link classes for sharing data across modules. Modules can be uncontained (not within Link), but these shouldn't be directly accessed by an external modules.

Dynamic, Inter-Pass, Access-Level Ordering

The order that modules, methods, and even lines of code are evaluated is never required to be fixed, meaning case statements within module phase method calls (e.g. init(), update(), ...) can change how the simulation is run. This may occur at the integration internal pass level.

Example

asc::Link<A> a;
asc::Link<B> b;

if (x > 2.5)
   a->var = x;
else
   b->var = x;

This is a contrived example, but in this case, a would be evaluated before b if x is greater than 2.5. Otherwise, b would be evaluated first. (Assuming that the module implementing this code is run first and more complex ordering isn't handled.)

Default Post-Computation Ordering

By default, modules will be forced to access from updated (phase-computed) modules. So, the user only needs specify if one module must run before another module, never that it must run after.

Pre-Computation Ordering

Though modules contained in Link are by default post-computation accessed, they can be specified for pre-computation access. The method runBefore() enforces pre-computation access. It does this for all accessing depths, not only direct accessing. In other words, if runBefore(target) is called, then this module will run before the target regardless of whether this module actually accesses the target or if the target is accessed via a stream of other modules. Ascent's design also guarantees that over-defining module ordering will not produce errors in the simulation, though it may affect the simulation run time speed. Note that fewer runBefore() calls usually helps the simulation to run faster.

Circular Dependencies

Ascent will automatically catch circular ordering dependencies. The simulation will be stopped when one occurs and an error will be printed.

Module Level Connections

The Link container ensures proper ordering, but it doesn't maintain runBefore connections. Rather, connections are stored within the modules themselves. This means that when a module is shared, its ordering is also shared.


Note on Post-Computation Ordering
While post-computation ordering ensures that the module being accessed has had it's phase method called, it does not guarantee that the module's parameters will not change during the given phase. This is because post-computation access allows the manipulation of a module after it's phase method has been called. It is therefore important as a simulation designer to know which modules act as drivers, manipulating other modules. And, typically driving modules should run before the module they are driving. The fact that a driving module may run after another module is what this note is pointing out. While this is a useful simulation methodology, it is one that must be carefully implemented within the Ascent architecture.