Add, change, or erase variables in a stock-and-flow model. Variables may be stocks, flows, constants, auxiliaries, or graphical functions.
Usage
build(
sfm,
name,
type,
eqn = "0.0",
units = "1",
label = name,
doc = "",
change_name = NULL,
change_type = NULL,
erase = FALSE,
to = NULL,
from = NULL,
non_negative = FALSE,
xpts = NULL,
ypts = NULL,
source = NULL,
interpolation = "linear",
extrapolation = "nearest",
df = NULL
)Arguments
- sfm
Stock-and-flow model, object of class
sdbuildR_xmile.- name
Variable name. Character vector.
- type
Type of building block(s); one of 'stock', 'flow', 'constant', 'aux', or 'gf'). Does not need to be specified to modify an existing variable.
- eqn
Equation (or initial value in the case of stocks). Defaults to "0.0".
- units
Unit of variable, such as 'meter'. Defaults to "1" (no units).
- label
Name of variable used for plotting. Defaults to the same as name.
- doc
Description of variable. Defaults to "" (no description).
- change_name
New name for variable (optional). Defaults to NULL to indicate no change.
- change_type
New type for variable (optional). Defaults to NULL to indicate no change.
- erase
If TRUE, remove variable from model. Defaults to FALSE.
- to
Target of flow. Must be a stock in the model. Defaults to NULL to indicate no target.
- from
Source of flow. Must be a stock in the model. Defaults to NULL to indicate no source.
- non_negative
If TRUE, variable is enforced to be non-negative (i.e. strictly 0 or positive). Defaults to FALSE.
- xpts
Only for graphical functions: vector of x-domain points. Must be of the same length as ypts.
- ypts
Only for graphical functions: vector of y-domain points. Must be of the same length as xpts.
- source
Only for graphical functions: name of the variable which will serve as the input to the graphical function. Necessary to specify if units are used. Defaults to NULL.
- interpolation
Only for graphical functions: interpolation method. Must be either "constant" or "linear". Defaults to "linear".
- extrapolation
Only for graphical functions: extrapolation method. Must be either "nearest" or "NA". Defaults to "nearest".
- df
A data.frame with variable properties to add and/or modify. Each row represents one variable to build. Required columns depend on the variable type being created:
All types require: 'type', 'name'
Stocks require: 'eqn' (initial value)
Flows require: 'eqn', and at least one of 'from' or 'to'
Constants require: 'eqn'
Auxiliaries require: 'eqn'
Graphical functions require: 'xpts', 'ypts'
Optional columns for all types: 'units', 'label', 'doc', 'non_negative' Optional columns for graphical functions: 'source', 'interpolation', 'extrapolation'
Columns not applicable to a variable type should be set to NA. See Examples for a complete demonstration.
Value
A stock-and-flow model object of class sdbuildR_xmile
Stocks
Stocks define the state of the system. They accumulate material or information over time, such as people, products, or beliefs, which creates memory and inertia in the system. As such, stocks need not be tangible. Stocks are variables that can increase and decrease, and can be measured at a single moment in time. The value of a stock is increased or decreased by flows. A stock may have multiple inflows and multiple outflows. The net change in a stock is the sum of its inflows minus the sum of its outflows.
The obligatory properties of a stock are "name", "type", and "eqn". Optional additional properties are "units", "label", "doc", "non_negative".
Flows
Flows move material and information through the system. Stocks can only decrease or increase through flows. A flow must flow from and/or flow to a stock. If a flow is not flowing from a stock, the source of the flow is outside of the model boundary. Similarly, if a flow is not flowing to a stock, the destination of the flow is outside the model boundary. Flows are defined in units of material or information moved over time, such as birth rates, revenue, and sales.
The obligatory properties of a flow are "name", "type", "eqn", and either "from", "to", or both. Optional additional properties are "units", "label", "doc", "non_negative".
Constants
Constants are variables that do not change over the course of the simulation - they are time-independent. These may be numbers, but also functions. They can depend only on other constants.
The obligatory properties of a constant are "name", "type", and "eqn". Optional additional properties are "units", "label", "doc", "non_negative".
Auxiliaries
Auxiliaries are dynamic variables that change over time. They are used for intermediate calculations in the system, and can depend on other flows, auxiliaries, constants, and stocks.
The obligatory properties of an auxiliary are "name", "type", and "eqn". Optional additional properties are "units", "label", "doc", "non_negative".
Graphical functions
Graphical functions, also known as table or lookup functions, are interpolation functions used to define the desired output (y) for a specified input (x). They are defined by a set of x- and y-domain points, which are used to create a piecewise linear function. The interpolation method defines the behavior of the graphical function between x-points ("constant" to return the value of the previous x-point, "linear" to linearly interpolate between defined x-points), and the extrapolation method defines the behavior outside of the x-points ("NA" to return NA values outside of defined x-points, "nearest" to return the value of the closest x-point).
The obligatory properties of a graphical function are "name", "type", "xpts", and "ypts". "xpts" and "ypts" must be of the same length. Optional additional properties are "units", "label", "doc", "source", "interpolation", "extrapolation".
Examples
# First initialize an empty model
sfm <- xmile()
summary(sfm)
#> Your model contains:
#> * 0 Stocks
#> * 0 Flows
#> * 0 Constants
#> * 0 Auxiliaries
#> * 0 Graphical Functions
#> * 0 Custom model units
#> * 0 Macros
#>
#> Simulation time: 0.0 to 100.0 seconds (dt = 0.01)
#> Simulation settings: solver euler in R
# Add two stocks. Specify their initial values in the "eqn" property
# and their plotting label.
sfm <- build(sfm, "predator", "stock", eqn = 10, label = "Predator") |>
build("prey", "stock", eqn = 50, label = "Prey")
# Add four flows: the births and deaths of both the predators and prey. The
# "eqn" property of flows represents the rate of the flow. In addition, we
# specify which stock the flow is coming from ("from") or flowing to ("to").
sfm <- build(sfm, "predator_births", "flow",
eqn = "delta*prey*predator",
label = "Predator Births", to = "predator"
) |>
build("predator_deaths", "flow",
eqn = "gamma*predator",
label = "Predator Deaths", from = "predator"
) |>
build("prey_births", "flow",
eqn = "alpha*prey",
label = "Prey Births", to = "prey"
) |>
build("prey_deaths", "flow",
eqn = "beta*prey*predator",
label = "Prey Deaths", from = "prey"
)
plot(sfm)
# The flows make use of four other variables: "delta", "gamma", "alpha", and
# "beta". Define these as constants in a vectorized manner for efficiency.
sfm <- build(sfm, c("delta", "gamma", "alpha", "beta"), "constant",
eqn = c(.025, .5, .5, .05),
label = c("Delta", "Gamma", "Alpha", "Beta"),
doc = c(
"Birth rate of predators", "Death rate of predators",
"Birth rate of prey", "Death rate of prey by predators"
)
)
# We now have a complete predator-prey model which is ready to be simulated.
sim <- simulate(sfm)
plot(sim)
# Modify a variable - note that we no longer need to specify type
sfm <- build(sfm, "delta", eqn = .03, label = "DELTA")
# Change variable name (throughout the model)
sfm <- build(sfm, "delta", change_name = "DELTA")
# Change variable type
sfm <- build(sfm, "DELTA", change_type = "stock")
# Remove variable
sfm <- build(sfm, "prey", erase = TRUE)
# To add and/or modify variables more quickly, pass a data.frame.
# The data.frame is processed row-wise.
# For instance, to create a logistic population growth model:
df <- data.frame(
type = c("stock", "flow", "flow", "constant", "constant"),
name = c("X", "inflow", "outflow", "r", "K"),
eqn = c(.01, "r * X", "r * X^2 / K", 0.1, 1),
label = c(
"Population size", "Births", "Deaths", "Growth rate",
"Carrying capacity"
),
to = c(NA, "X", NA, NA, NA),
from = c(NA, NA, "X", NA, NA)
)
sfm <- build(xmile(), df = df)
# Check for errors in the model
debugger(sfm)
#> No problems detected!