Difference between revisions of "NovaScript Introduction"
(→Universal Properties and Primops)
|Line 49:||Line 49:|
==Universal Properties and Primops==
==Universal Properties and Primops==
Revision as of 22:56, 3 January 2015
All running Nova simulations are expressed in a language called NovaScript. Even in the simplest stock- flow model, you are already writing NovaScript code when you enter expressions for initial Stock values, Flows, and Terms (we’ll refer to these as component definitions). For these models, however, the code is generally restricted to simple numerical expressions. You will see that to express the relationships required of complex models your definitions will necessarily include a broader set of expressions.
A complete Nova model is expressed in NovaScript. You create the program for this model when you click the Capture button. Nova is able to construct the scaffold for your model using the structure of the visual elements placed on the canvas. As author you are expected to provide the details connecting the various components through the component expressions. In systems dynamics models component expressions generally operate solely on numerical data; i.e., they are simple arithmetic expressions.
As you extend your use of Nova into more complex applications the coding used to link components will also become more complex. This complexity manifests along the following dimensions:
- The data structures used. Simple applications can rely on simple numerical data. For more advanced use you will need to introduce arrays and objects, and may also want to create your own functions.
- The program structures required. Multi-line computations involving loops and conditionals generally accompany the use of data structures such as arrays and objects.
- The use of primitive operators. Models using Nova’s aggregating components rely heavily on primops. You will need to become familiar with these primops and how they provide necessary information to the constituents of the aggregators.
What is NovaScript?
The Capsule is one type of simulator . A simulator is a container whose components are programmed to interact, creating a runnable simulation. The other NovaScript simulators are the four aggregating components described in Component Guide 2: Containers. A Capsule can contain Stocks, Flows, Terms, Commands, Codechips, etc., but also any of the simulator types (a chip is just a Capsule contained in a parent Capsule). Aggregator components (called members), however, must be Capsules.
Note that components such as Stocks, Terms and Flows do not contain other components as constituents. We’ll use the term base components to distinguish Stocks, Terms and Flows from simulators such as Capsules, CellMatrices and AgentVectors.
Except for the top level Capsule, every simulator is the component of some other simulator. For example, Capsule A may contain a chip containing an instance of Capsule B. Capsule A may also contain one of the aggregators, and that aggregator will contain instances of Capsule C. We use the terms container and component to describe this relationship. Every simulator in a model has a container except for the top-level Capsule.
In order to actually carry out a simulation, a simulator must be associated with a clock. With two exceptions a simulator’s clock is used by all of its components, so that only a single top-level system clock is required. However, new clocks are introduced with Clocked Chips, and when running in batch mode. See Clocked Chips.
Component Objects and State Objects; the Self property
Each type of simulator object provides a way of accessing the component objects of its constituents. In the simplest case, a Capsule points to each of its components by name. CellMatrices, AgentVectors, SimWorlds, NodeNetworks and NetWorlds also have methods that produce the component objects of their constituents. Consequently the complete state of any simulator can be found by traversing its structure to extract the value() at all the Stocks, Flows and Terms.
NovaScript however, provides a simpler approach: each simulator has a Self property that references a special state object, in which base component names are bound to the current values of those components. The values in these state objects change as the simulation progresses. If a simulator is not at the top-level, then the state object of its container is the value of the property Super. One can follow the chain of container state objects all the way to the top-level by using Super, Super.Super, etc.
For those familiar with object oriented programming, the scenario serves as a class definition for the creation of NovaScript objects. As we shall see below, the Nova Codechip component is a tool for method definition in such a system.
Universal Properties and Primops
A NovaScript property is a symbol that represents a single constant value throughout the execution of a Nova program. Properties can be defined in several ways, as detailed below.
[[Component Guide 2: Containers|Aggregating components] introduce special properties and primops. Those properties and primops may be used in Capsules contained by the aggregator, but are generally not meaningful outside of the aggregator environment, and their use may cause errors. To distinguish those from properties and primops that may be used anywhere, we’ll refer to the former as restricted and the latter as universal. When describing a primop, we will always distinguish it as either universal or restricted.
Lists of all properties and primops, both universal and restricted to one or more aggregator, are found in the Primop Reference.
Special NovaScript objects
NovaScript also implements several special objects, including the Clock object, Coord object (which models a pair of matrix coordinates with fields for row and column) and RunData object, which contains the history of a Stock’s value over an entire run.
- These names are chosen for historic reasons, and also because they are not likely to conflict with the names of some actual components.