The core concepts of the simulation engine are the Machine, Element , State , and Config.
A Config is a container for key/value pairs. This is the interface through which Elements are specialized (eg. length=2 vs. length=3). The lattice file parser populates a Config, which may then be used to construct a Machine.
A Machine represents a ordered list of Elements (instances of ElementVoid).
A State (sub-class of StateBase) represents "the beam", which is to say, a particle or bunch of particles which pass from Element to Element through a Machine. The operation of the simulation is for an Element to transform a State. This new (output) state is then passed as input to the next element.
In code, passing State between Elements is implemented in Machine::propagate. Transformation of State is encapsulated in ElementVoid::advance.
The precise meanings of State and Element are governed by the "sim_type" key. When a Machine is constructed, the "sim_type" is used to select particular sub-classes of ElementVoid and StateBase.
For example, "sim_type=Vector" selects VectorState and a sub-class of LinearElementBase depending on the elements "type" key. "type=drift" selects ElementDrift.
These selections are made from a global table which is populated by Machine::registerState and Machine::registerElement.
A simulation is configured by passing a Config to Machine::Machine. A Config can be obtained in several ways:
At minimum, Machine::Machine requires that a Config has the two keys. "sim_type" which is a string, and "elements" which is a vector<Config>. Each element must in turn have "type" as a string.
By convention the nested Config for an element should use the enclosing Config as an enclosing scope ( Config::new_scope() ).