Variable
In Cropbox, a variable is defined as a unit element of modeling that denotes a value determined by a specific operation relying on other variables. Each variable represents a field within the system struct defined by the @system macro.
Variable Declaration
Variables are declared when a system is declared with the @system macro. @system macro accepts lines of variable declaration specified by its own syntax. They are loosely based on Julia syntax sharing common expressions and operators, but have distinct semantics as explained below.
name[(args..; kwargs..)][: alias] [=> body] ~ [state][::type][(tags..)]
name: variable name (usually short abbreviation)args: automatically bound depending variableskwargs: custom bound depending variables (only for call now)alias: alternative name (long description)body: code snippet (state/type specific,begin .. endblock for multiple lines)state: verb indicating kind of state (empty if notState-based)type: internal type (i.e.Float64by default for mostStatevariable)tags: variable specific options (i.e. unit, min/max, etc.)
Example
Here is an example of a system declaration where all three variables are valid declarations:
@system S begin
    a: variable_a ~ advance
    b(a) => a^2 ~ track
    c => true ~ ::Bool
endMain.SVariable States
Within Cropbox, a variable inside a system can be one of many different abstract types based on the variable's purpose. Depending on its type, each variable has its own behavior when a system is instantiated. In Cropbox, we refer to these as the state of the variables, originating from the term state variables often used in mathematical modeling.
Specifying a state is not mandatory when declaring a variable. Cropbox also allows plain variables, which are commonly used for creating variable references to other systems.
Currently, there are 19 different variable states implemented in Cropbox.
Instant derivation
preserve: keeps an initially assigned value with no further updates; constants, parameterstrack: evaluates expression and assigns a new value for each time stepflag: checks a conditional logic; similar to track with boolean type, but composition is allowedremember: keeps tracking the variable until a certain condition is met; like track switching to preserve
Cumulative update
accumulate: emulates integration of a rate variable over time; essentially Euler methodcapture: calculates the difference between time stepsintegrate: calculates an integral over a non-time variable using Gaussian methodadvance: updates an internal time-keeping variable
Data source
provide: provides a table-like multi-column time-series data; i.e. weather datadrive: fetches the current value from a time-series; often used with provide; i.e. air temperaturetabulate: makes a two dimensional table with named keys; i.e. partitioning tableinterpolate: makes a curve function interpolated with discrete values; i.e. soil characteristic curve
Equation solving
solve: solves a polynomial equation symbolically; i.e. quadratic equation for coupling photosynthesisbisect: solves a nonlinear equation using bisection method; i.e. energy balance equation
Dynamic structure
produce: attaches a new instance of dynamically generated system; i.e. root structure growth
Language extension
hold: marks a placeholder for the variable shared between mixinswrap: allows passing a reference to the state variable object, not a dereferenced valuecall: defines a partial function accepting user-defined arguments, while bound to other variablesbring: duplicates variables declaration from another system into the current system
Instant derivation
preserve
preserve variables are fixed values with no further modification after instantiation of a system. As a result, they are often used as the state for parameter variables, which allow any initial value to be set via a configuration object supplied at the start of a simulation. Non-parameter constants are also used for fixed variables that do not need to be computed at each time step.
Supported tags: unit, optional, parameter, override, extern, ref, min, max, round
Example
@system S(Controller) begin
    a => 1 ~ preserve
end
simulate(S; stop=2)| Row | time | a | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 1.0 | 
| 2 | 1.0 hr | 1.0 | 
| 3 | 2.0 hr | 1.0 | 
track
track variables are evaluated and assigned a new value at every time step. In a conventional model, these are the variables that would be computed in every update loop. At every time step, the formula in the variable code is evaluated and saved for use. This assignment of value occurs only once per time step, as intended by the Cropbox framework. No manual assignment of computation at an arbitrary time is allowed. This is to ensure that that there are no logical errors resulting from premature or incorrectly ordered variable assignments. For example, a cyclical reference between two track variables is caught by Cropbox as an error.
Supported tags: unit, override, extern, ref, skip, init, min, max, round, when
Example
@system S(Controller) begin
    a ~ advance
    b(a) => 2*a ~ track
end
simulate(S; stop=2)| Row | time | a | b | 
|---|---|---|---|
| Quantity… | Float64 | Float64 | |
| 1 | 0.0 hr | 0.0 | 0.0 | 
| 2 | 1.0 hr | 1.0 | 2.0 | 
| 3 | 2.0 hr | 2.0 | 4.0 | 
flag
flag variables are expressed in a conditional statement or logical operator for which a boolean value is evaluated at every time step. They function like a track variable but with a boolean value.
Supported tags: parameter, override, extern, once, when
Example
@system S(Controller) begin
    a ~ advance
    b => 1 ~ preserve
    f(a, b) => (a > b) ~ flag
end
simulate(S; stop=2)| Row | time | a | b | f | 
|---|---|---|---|---|
| Quantity… | Float64 | Float64 | Bool | |
| 1 | 0.0 hr | 0.0 | 1.0 | false | 
| 2 | 1.0 hr | 1.0 | 1.0 | false | 
| 3 | 2.0 hr | 2.0 | 1.0 | true | 
remember
remember variables keep track of a variable until a specified condition is met. When the condition is met, it is saved as either its latest update or a specified value. They are like track variables that turn into preserve variables. The when tag is required to specify condition. Unless specified, the initial value for remember defaults to 0.
Supported tags: unit, init, when
Example
@system S(Controller) begin
    t(context.clock.tick) ~ track
    f(t) => t > 1 ~ flag
    r1(t) ~ remember(when=f)
    r2(t) => t^2 ~ remember(when=f)
end
simulate(S; stop=2)| Row | time | t | f | r1 | r2 | 
|---|---|---|---|---|---|
| Quantity… | Float64 | Bool | Float64 | Float64 | |
| 1 | 0.0 hr | 0.0 | false | 0.0 | 0.0 | 
| 2 | 1.0 hr | 1.0 | false | 0.0 | 0.0 | 
| 3 | 2.0 hr | 2.0 | true | 2.0 | 4.0 | 
Cumulative update
accumulate
accumulate variables emulate the integration of a rate variable over time. It uses the Euler's method of integration. By default, an accumulate variable accumulates every hour, unless a unit of time is specified.
Supported tags: unit, init, time, timeunit, reset, min, max, when
Example
@system S(Controller) begin
    a => 1 ~ accumulate
    b => 1 ~ accumulate(u"d")
end
simulate(S; stop=2)| Row | time | a | b | 
|---|---|---|---|
| Quantity… | Float64 | Quantity… | |
| 1 | 0.0 hr | 0.0 | 0.0 d | 
| 2 | 1.0 hr | 1.0 | 0.0416667 d | 
| 3 | 2.0 hr | 2.0 | 0.0833333 d | 
capture
capture variables calculate the difference of a variable between time steps. The time tag allows evaluations for varying rates of time.
Supported tags: unit, time, timeunit, when
Example
@system S(Controller) begin
    a => 1 ~ track
    b(a) => a + 1 ~ capture
    c(a) => a + 1 ~ accumulate
end
simulate(S; stop=2)| Row | time | a | b | c | 
|---|---|---|---|---|
| Quantity… | Float64 | Float64 | Float64 | |
| 1 | 0.0 hr | 1.0 | 0.0 | 0.0 | 
| 2 | 1.0 hr | 1.0 | 2.0 | 2.0 | 
| 3 | 2.0 hr | 1.0 | 2.0 | 4.0 | 
integrate
integrate variables calculate an integral over a non-time variable using the Gaussian method.
Supported tags: unit, from, to
Example
@system S(Controller) begin
    w => 1 ~ preserve(parameter)
    a => 0 ~ preserve(parameter)
    b => π ~ preserve(parameter)
    f(w; x) => w*sin(x) ~ integrate(from=a, to=b)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| w | = | 1.0 | |
| a | = | 0.0 | |
| b | = | 3.14159 | |
| f | = | 2.0 | |
advance
advance variables update an internal time-keeping variable. By default, it starts at 0 and increases by 1 every time step. Note that the unit does not have to be time-related.
Supported tags: init, step, unit
Example
@system S(Controller) begin
    a ~ advance(init=1)
    b ~ advance(step=2)
    c ~ advance(u"m")
end
simulate(S; stop=2)| Row | time | a | b | c | 
|---|---|---|---|---|
| Quantity… | Float64 | Float64 | Quantity… | |
| 1 | 0.0 hr | 1.0 | 0.0 | 0.0 m | 
| 2 | 1.0 hr | 2.0 | 2.0 | 1.0 m | 
| 3 | 2.0 hr | 3.0 | 4.0 | 2.0 m | 
Data source
provide
provide variables provide a DataFrame with a given index (index) starting from an initial value (init). By default, autounit is true, meaning that provide variables will attempt to get units from column names.
Supported tags: index, init, step, autounit, parameter
Example
@system S(Controller) begin
    a => DataFrame("index (hr)" => 0:2, "value (m)" => 0:10:20) ~ provide
end
instance(S).a3×2 DataFrame
 Row │ index      value     
     │ Quantity…  Quantity… 
─────┼──────────────────────
   1 │      0 hr        0 m
   2 │      1 hr       10 m
   3 │      2 hr       20 mdrive
drive variables fetch the current value from a time-series. It is often used in conjunction with provide.
Supported tags: tick, unit, from, by, parameter, override
Example
@system S(Controller) begin
    a => [2, 4, 6] ~ drive
end
simulate(S; stop=2)| Row | time | a | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 2.0 | 
| 2 | 1.0 hr | 4.0 | 
| 3 | 2.0 hr | 6.0 | 
tabulate
tabulate variables make a two dimensional table with named keys. The rows tag must be assigned.
Supported tags: unit, rows, columns, parameter
Example
@system S(Controller) begin
    T => [
      # a b
        0 4 ; # A
        1 5 ; # B
        2 6 ; # C
        3 7 ; # D
    ] ~ tabulate(rows=(:A, :B, :C, :D), columns=(:a, :b))
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| T | = | [0.0 4.0; 1.0 5.0; 2.0 6.0; 3.0 7.0] | |
interpolate
interpolate variables make a curve function for a provided set of discrete values.
Supported tags: unit, knotunit, reverse, parameter
Example
@system S(Controller) begin
    m => [1 => 10, 2 => 20, 3 => 30] ~ interpolate
    a(m) => m(2.5) ~ track
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| m | = | 3-element extrapolate(interpolate((::Vector{Int64},), ::Vector{Int64}, Gridded(Linear())), Throw()) with element type Float64:… | |
| a | = | 25.0 | |
A matrix can also be used instead of a vector of pairs.
@system S(Controller) begin
    m => [1 10; 2 20; 3 30] ~ interpolate
    a(m) => m(2.5) ~ track
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| m | = | 3-element extrapolate(interpolate((::Vector{Int64},), ::Vector{Int64}, Gridded(Linear())), Throw()) with element type Float64:… | |
| a | = | 25.0 | |
Equation solving
solve
solve variables solve a polynomial equation symbolically. By default, it will return the highest solution. Therefore, when using the lower tag, it is recommended to pair it with another tag.
Supported tags: unit, lower, upper, pick
Example
The solution is x = 1, 2, 3
@system S(Controller) begin
    a => 1 ~ preserve(parameter)
    b => -6 ~ preserve(parameter)
    c => 11 ~ preserve(parameter)
    d => -6 ~ preserve(parameter)
    x(a, b, c, d) => begin
        a*x^3 + b*x^2 + c*x + d
    end ~ solve
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| b | = | -6.0 | |
| c | = | 11.0 | |
| d | = | -6.0 | |
| x | = | 3.0 | |
bisect
bisect variables solve a nonlinear equation using the bisection method. The tags lower and upper must be provided.
Supported tags: unit, evalunit, lower, upper, maxiter, tol, min, max
Example
The solution is x = 1, 2, 3
@system S(Controller) begin
    x(x) => x^3 - 6x^2 + 11x - 6 ~ bisect(lower=0, upper=3)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| x | = | 3.0 | |
Dynamic structure
produce
produce variables attach a new instance of a dynamically generated system.
Example
@system S begin
    a => produce(S) ~ produce
end
@system SController(Controller) begin
    s(context) ~ ::S
end
instance(SController)| SController | |||
| context | = | <Context> | |
| config | = | <Config> | |
| s | = | <S> | |
Language extension
hold
hold variables are placeholders for variables that are supplied by another system as a mixin.
Supported tags: None
Example
@system S1 begin
    a ~ advance
end
@system S2(S1, Controller) begin
    a ~ hold
    b(a) => 2*a ~ track
end
simulate(S2; stop=2)| Row | time | a | b | 
|---|---|---|---|
| Quantity… | Float64 | Float64 | |
| 1 | 0.0 hr | 0.0 | 0.0 | 
| 2 | 1.0 hr | 1.0 | 2.0 | 
| 3 | 2.0 hr | 2.0 | 4.0 | 
wrap
wrap allows passing a reference to the state variable object, not a dereferenced value
Supported tags: None
Example
@system S(Controller) begin
    a          => 1       ~ preserve
    b(a)       => a == a' ~ flag
    c(wrap(a)) => a == a' ~ flag
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| b | = | true | |
| c | = | false | |
call
call defines a partial function accepting user-defined arguments
Supported tags: unit
Example
@system S(Controller) begin
    a => 1 ~ preserve
    f(a; x) => a + x ~ call
    b(f) => f(1) ~ track
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| f | = | <call> | |
| b | = | 2.0 | |
bring
bring duplicates variable declaration from another system into the current system
Supported tags: parameters, override
Example
@system S1 begin
    a => 1 ~ preserve
    b(a) => 2a ~ track
end
@system S2(Controller) begin
    c(context) ~ bring::S1
end
instance(S2)| S2 | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| b | = | 2.0 | |
| c | = | <S1> | |
Variable Tags
Most variable states have tags in the form of (tag) for tag-specific behaviors. Available tags vary between variable states. Some tags are shared by multiple variable states while some tags are exclusive to certain variable states.
autounit
Allows provide variables to automatically assign units to variables depending on column headers of the DataFrame. By default, autounit is true and only needs to be specified when false.
Used by: provide
Example
@system S(Controller) begin
    a => DataFrame("index" => (0:2)u"hr", "value (m)" => 0:10:20) ~ provide
    b => DataFrame("index" => (0:2)u"hr", "value (m)" => 0:10:20) ~ provide(autounit=false)
endMain.Sinstance(S).a3×2 DataFrame
 Row │ index      value     
     │ Quantity…  Quantity… 
─────┼──────────────────────
   1 │      0 hr        0 m
   2 │      1 hr       10 m
   3 │      2 hr       20 minstance(S).b3×2 DataFrame
 Row │ index      value (m) 
     │ Quantity…  Int64     
─────┼──────────────────────
   1 │      0 hr          0
   2 │      1 hr         10
   3 │      2 hr         20by
Specifies the column and series from which the drive variable receives data. Can be omitted if the variable name is identical to column name.
Used by: drive
Example
@system S(Controller) begin
    p => DataFrame(index=(0:2)u"hr", a=[2,4,6], x=1:3) ~ provide
    a ~ drive(from=p)
    b ~ drive(from=p, by=:x)
end
simulate(S; stop=2)| Row | time | a | b | 
|---|---|---|---|
| Quantity… | Float64 | Float64 | |
| 1 | 0.0 hr | 2.0 | 1.0 | 
| 2 | 1.0 hr | 4.0 | 2.0 | 
| 3 | 2.0 hr | 6.0 | 3.0 | 
columns
Specifies the names of columns from the table created by the tabulate variable.
Used by: tabulate
Example
@system S(Controller) begin
    T => [
      # a b
        0 4 ; # A
        1 5 ; # B
        2 6 ; # C
        3 7 ; # D
    ] ~ tabulate(rows=(:A, :B, :C, :D), columns=(:a, :b))
end
instance(S).T   │ a    b   
───┼──────────
 A │ 0.0  4.0
 B │ 1.0  5.0
 C │ 2.0  6.0
 D │ 3.0  7.0evalunit
Specifies the evaluation unit of bisect, as opposed to the unit of solution.
Used by: bisect
Example
@system S(Controller) begin
    f(x) => (x/1u"s" - 1u"m/s") ~ track(u"m/s")
    x(f) ~ bisect(lower=0, upper=2, u"m", evalunit=u"m/s")
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| f | = | 0.0 m s^-1 | |
| x | = | 1.0 m | |
extern
Used by: preserve, track, flag
from
drive: Specifies the DataFrame that the drive variable will receive data from. If the variable name of the drive variable differs from column name, from must be accompanied with by.
integrate: Specifies lower bound of integration.
Example: drive
@system S(Controller) begin
    p => DataFrame(index=(0:2)u"hr", a=[2,4,6], x=1:3) ~ provide
    a ~ drive(from=p)
    b ~ drive(from=p, by=:x)
end
simulate(S; stop=2)| Row | time | a | b | 
|---|---|---|---|
| Quantity… | Float64 | Float64 | |
| 1 | 0.0 hr | 2.0 | 1.0 | 
| 2 | 1.0 hr | 4.0 | 2.0 | 
| 3 | 2.0 hr | 6.0 | 3.0 | 
 Example: integrate
@system S(Controller) begin
    w => 1 ~ preserve(parameter)
    a => 0 ~ preserve(parameter)
    b => π ~ preserve(parameter)
    f(w; x) => w*sin(x) ~ integrate(from=a, to=b)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| w | = | 1.0 | |
| a | = | 0.0 | |
| b | = | 3.14159 | |
| f | = | 2.0 | |
index
Used by provide variables to specify the index column from provided DataFrame. Can be omitted if DataFrame contains column "index".
Used by: provide
Example
@system S(Controller) begin
    a => DataFrame(i=(0:3)u"hr", value=0:10:30) ~ provide(index=:i)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 4×2 DataFrame… | |
init
Assigns the first value of the variable at system instantiation.
Used by: track, remember, accumulate, advance, provide
Example
@system S(Controller) begin
    a => 1 ~ accumulate(init=100)
end
simulate(S; stop=2)| Row | time | a | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 100.0 | 
| 2 | 1.0 hr | 101.0 | 
| 3 | 2.0 hr | 102.0 | 
knotunit
Specifies the unit of discrete x-values of interpolate.
Used by: interpolate
Example
@system S(Controller) begin
    m => ([1 => 10, 2 => 20, 3 => 30]) ~ interpolate(u"s", knotunit=u"m")
    n(m) ~ interpolate(u"m", reverse)
    a(m) => m(2.5u"m") ~ track(u"s")
    b(n) => n(25u"s") ~ track(u"m")
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| m | = | 3-element extrapolate(interpolate((::Vector{Quantity{Int64, 𝐋, FreeUnits{(m,), 𝐋, nothing}}},), ::Vector{Quantity{Int64, 𝐓, FreeUnits{(s,), 𝐓, nothing}}}, Gridded(Linear())), Throw()) with element type Quantity{Float64, 𝐓, FreeUnits{(s,), 𝐓, nothing}}:… | |
| n | = | 3-element extrapolate(interpolate((::Vector{Quantity{Int64, 𝐓, FreeUnits{(s,), 𝐓, nothing}}},), ::Vector{Quantity{Int64, 𝐋, FreeUnits{(m,), 𝐋, nothing}}}, Gridded(Linear())), Throw()) with element type Quantity{Float64, 𝐋, FreeUnits{(m,), 𝐋, nothing}}:… | |
| a | = | 25.0 s | |
| b | = | 2.5 m | |
lower
Specifies the lower bound of the solution for solve and bisect variables.
Example
The solution is x = 1, 2, 3
@system S(Controller) begin
    a => 1 ~ preserve(parameter)
    b => -6 ~ preserve(parameter)
    c => 11 ~ preserve(parameter)
    d => -6 ~ preserve(parameter)
    x(a, b, c, d) => begin
        a*x^3 + b*x^2 + c*x + d
    end ~ solve(lower=1.1, upper=2.9)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| b | = | -6.0 | |
| c | = | 11.0 | |
| d | = | -6.0 | |
| x | = | 2.0 | |
max
Defines the maximum value of the variable.
Used by: preserve, track, accumulate, bisect
Example
@system S(Controller) begin
    a => 1 ~ accumulate(max=1)
end
simulate(S; stop=2)| Row | time | a | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 0.0 | 
| 2 | 1.0 hr | 1.0 | 
| 3 | 2.0 hr | 1.0 | 
maxiter
Defines the maximum number of iterations for the bisect.
Used by: bisect
Example
@system S(Controller) begin
    x(x) => x - 0.25 ~ bisect(lower=0, upper=1, maxiter=4)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| x | = | 0.25 | |
min
Defines the minimum value of the variable.
Used by: preserve, track, accumulate, bisect
Example
@system S(Controller) begin
    a => -1 ~ accumulate(min=-1)
end
simulate(S; stop=2)| Row | time | a | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 0.0 | 
| 2 | 1.0 hr | -1.0 | 
| 3 | 2.0 hr | -1.0 | 
once
Makes a flag variable unable to go from true to false.
Used by: flag
Example
@system S(Controller)begin
    a ~ advance(init=1)
    f(a) => (a % 2 == 0) ~ flag(once)
end
simulate(S; stop=2)| Row | time | a | f | 
|---|---|---|---|
| Quantity… | Float64 | Bool | |
| 1 | 0.0 hr | 1.0 | false | 
| 2 | 1.0 hr | 2.0 | true | 
| 3 | 2.0 hr | 3.0 | true | 
optional
Makes a preserve variable optional, allowing a system to be instantiated without variable assignment.
Used by: preserve
Example
@system S(Controller) begin
    a ~ preserve(optional, parameter)
    b => 1 ~ preserve
end
simulate(S; stop=2)| Row | time | b | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 1.0 | 
| 2 | 1.0 hr | 1.0 | 
| 3 | 2.0 hr | 1.0 | 
override
Used by: preserve, track, flag, drive, bring
Example
@system S1 begin
    a ~ track(override)
end
@system S2(Controller) begin
    c(context, a) ~ ::S1
    a => 1 ~ track
end
instance(S2)| S2 | |||
| context | = | <Context> | |
| config | = | <Config> | |
| c | = | <S1> | |
| a | = | 1.0 | |
parameter
Allows the variable to be altered through a configuration at system instantiation.
Used by: preserve, flag, provide, drive, tabulate, interpolate
Example
@system S(Controller) begin
    a ~ preserve(parameter)
end
instance(S; config = :S => :a => 1)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
parameters
Use by bring variables to duplicate only variables that can have the parameter tag (if they did not have the parameter tag originally, they become parameters regardless). The duplicated variables must have their values reassigned through a configuration.
Used by: bring
Example
@system S1 begin
    a => 1 ~ preserve
    b(a) => 2a ~ track
    c => true ~ flag
    d(a) ~ accumulate
end
@system S2(Controller) begin
    p(context) ~ bring::S1(parameters)
end
instance(S2; config = :S2 => (:a => 2, :b => 3, :c => false))| S2 | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 2.0 | |
| b | = | 3.0 | |
| c | = | 0.0 | |
| p | = | <S1> | |
pick
Picks which solution to return based on tag argument.
Used by: solve
Example
The solution is x = 1, 2, 3
@system S(Controller) begin
    a => 1 ~ preserve(parameter)
    b => -3 ~ preserve(parameter)
    c => 2 ~ preserve(parameter)
    x(a, b, c) => begin
        a*x^2 + b*x + c
    end ~ solve(pick=:minimum)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| b | = | -3.0 | |
| c | = | 2.0 | |
| x | = | 1.0 | |
ref
reset
Resets the sum to 0 at every time step.
Used by: accumulate
Example
@system S(Controller) begin
    a => 1 ~ accumulate(reset)
end
simulate(S; stop=2)| Row | time | a | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 0.0 | 
| 2 | 1.0 hr | 1.0 | 
| 3 | 2.0 hr | 1.0 | 
reverse
Returns the inverse function of an existing interpolate variable.
Used by: interpolate
Example
@system S(Controller) begin
    m => ([1 => 10, 2 => 20, 3 => 30]) ~ interpolate
    n(m) ~ interpolate(reverse)
    a(m) => m(2.5) ~ preserve
    b(n) => n(25) ~ preserve
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| m | = | 3-element extrapolate(interpolate((::Vector{Int64},), ::Vector{Int64}, Gridded(Linear())), Throw()) with element type Float64:… | |
| n | = | 3-element extrapolate(interpolate((::Vector{Int64},), ::Vector{Int64}, Gridded(Linear())), Throw()) with element type Float64:… | |
| a | = | 25.0 | |
| b | = | 2.5 | |
round
Rounds to the nearest integer or to a floor or ceiling based on tag argument.
Example
@system S(Controller) begin
    a => 1.4 ~ preserve(round)
    b => 1.4 ~ preserve(round=:round)
    c => 1.4 ~ preserve(round=:ceil)
    d => 1.6 ~ preserve(round=:floor)
    e => 1.6 ~ preserve(round=:trunc)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| b | = | 1.0 | |
| c | = | 2.0 | |
| d | = | 1.0 | |
| e | = | 1.0 | |
rows
Specifies the names of rows from the table created by the tabulate variable. Required tag for tabulate.
Used by: tabulate
Example
@system S(Controller) begin
    T => [
      # a b
        0 4 ; # A
        1 5 ; # B
        2 6 ; # C
        3 7 ; # D
    ] ~ tabulate(rows=(:A, :B, :C, :D), columns=(:a, :b))
endMain.Ssingle
Used by: produce
skip
Used by: track
Example
@system S(Controller) begin
    a ~ advance
    b(a) => 2*a ~ track(skip=true)
end
simulate(S; stop=2)| Row | time | a | b | 
|---|---|---|---|
| Quantity… | Float64 | Float64 | |
| 1 | 0.0 hr | 0.0 | 0.0 | 
| 2 | 1.0 hr | 1.0 | 0.0 | 
| 3 | 2.0 hr | 2.0 | 0.0 | 
step
advance: Specifies the increments of the advance variable.
provide: Specifies the intervals of the index column.
Example: advance
@system S(Controller) begin
    a ~ advance
    b ~ advance(step=2)
    c ~ advance(step=-1)
end
simulate(S; stop=2)| Row | time | a | b | c | 
|---|---|---|---|---|
| Quantity… | Float64 | Float64 | Float64 | |
| 1 | 0.0 hr | 0.0 | 0.0 | 0.0 | 
| 2 | 1.0 hr | 1.0 | 2.0 | -1.0 | 
| 3 | 2.0 hr | 2.0 | 4.0 | -2.0 | 
 Example: integrate
@system S(Controller) begin
    a => DataFrame("index (hr)" => 0:4, "value (m)" => 0:10:40) ~ provide(step=2u"hr")
end
instance(S).a3×2 DataFrame
 Row │ index      value     
     │ Quantity…  Quantity… 
─────┼──────────────────────
   1 │      0 hr        0 m
   2 │      2 hr       20 m
   3 │      4 hr       40 mtick
Used by: drive
time
Accumulates variable at a specified rate of time.
Used by: accumulate, capture
Example
@system S(Controller) begin
    t(x=context.clock.time) => 0.5x ~ track(u"hr")
    a => 1 ~ accumulate
    b => 1 ~ accumulate(time=t)
end
simulate(S; stop=5)| Row | time | t | a | b | 
|---|---|---|---|---|
| Quantity… | Quantity… | Float64 | Float64 | |
| 1 | 0.0 hr | 0.0 hr | 0.0 | 0.0 | 
| 2 | 1.0 hr | 0.5 hr | 1.0 | 0.5 | 
| 3 | 2.0 hr | 1.0 hr | 2.0 | 1.0 | 
| 4 | 3.0 hr | 1.5 hr | 3.0 | 1.5 | 
| 5 | 4.0 hr | 2.0 hr | 4.0 | 2.0 | 
| 6 | 5.0 hr | 2.5 hr | 5.0 | 2.5 | 
timeunit
Specifies the time unit of the variable.
Used by: accumulate, capture
Example
@system S(Controller) begin
    a => 1 ~ accumulate(timeunit=u"d")
end
simulate(S; stop=2)| Row | time | a | 
|---|---|---|
| Quantity… | Float64 | |
| 1 | 0.0 hr | 0.0 | 
| 2 | 1.0 hr | 0.0416667 | 
| 3 | 2.0 hr | 0.0833333 | 
to
Specifies upper bound of integration.
Used by: integrate
Example
@system S(Controller) begin
    w => 1 ~ preserve(parameter)
    a => 0 ~ preserve(parameter)
    b => π ~ preserve(parameter)
    f(w; x) => w*sin(x) ~ integrate(from=a, to=b)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| w | = | 1.0 | |
| a | = | 0.0 | |
| b | = | 3.14159 | |
| f | = | 2.0 | |
tol
Defines the tolerance for the bisection method used in bisect.
Used by: bisect
Example
@system S(Controller) begin
    x(x) => x - 2.7 ~ bisect(lower=1, upper=3)
    y(y) => y - 2.7 ~ bisect(lower=1, upper=3, tol=0.05)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| x | = | 2.7 | |
| y | = | 2.71875 | |
unit
Specifies the unit of the variable. The tag unit can be omitted.
Used by: preserve, track, remember, accumulate, capture, integrate, advance, drive, tabulate, interpolate, solve, bisect, call
@system S(Controller) begin
    a => 1 ~ preserve(unit=u"hr")
    b => 1 ~ preserve(u"hr")
end
instance(S)upper
Specifies the upper bound of solution.
Example
The solution is x = 1, 2, 3
@system S(Controller) begin
    a => 1 ~ preserve(parameter)
    b => -6 ~ preserve(parameter)
    c => 11 ~ preserve(parameter)
    d => -6 ~ preserve(parameter)
    x(a, b, c, d) => begin
        a*x^3 + b*x^2 + c*x + d
    end ~ solve(upper=2.9)
end
instance(S)| S | |||
| context | = | <Context> | |
| config | = | <Config> | |
| a | = | 1.0 | |
| b | = | -6.0 | |
| c | = | 11.0 | |
| d | = | -6.0 | |
| x | = | 2.0 | |
when
Specifies when a variable should be evaluated. It is supplied with a flag variable, and the specified variable is evaluated when the flag variable is true.
Used by: track, flag, remember, accumulate, capture, produce
Example
@system S(Controller) begin
    a ~ advance
    flag(a) => (a >= 2) ~ flag
    b(a) => a ~ track(when=flag)
end
simulate(S; stop=3u"hr")| Row | time | a | flag | b | 
|---|---|---|---|---|
| Quantity… | Float64 | Bool | Float64 | |
| 1 | 0.0 hr | 0.0 | false | 0.0 | 
| 2 | 1.0 hr | 1.0 | false | 0.0 | 
| 3 | 2.0 hr | 2.0 | true | 2.0 | 
| 4 | 3.0 hr | 3.0 | true | 3.0 |