Advanced How-to Guide: Build and Init Functions
In some cases, it may be useful for a user to better understand the inner-workings of the internal
build function, as well as the ModelInstance and ModelDef types. In addition, components with one-time computations irrespective of timesteps may lend themselves to the use of the optional
init function, as described below.
The Internal 'build' Function and Model Instances
The structural definition of a Model is held in the mutable ModelDef, and then when you call the run function on your model, first the internal
build function is called, which produces a ModelInstance, and then the ModelInstance is run. A model instance is an instantiated version of the model you have designed where all of the component constructors have been called and all of the data arrays have been allocated. If you wish to create and run multiple versions of your model, you can use the intermediate build function and store the separate ModelInstances. This may be useful if you want to change some parameter values, while keeping the model's structure mostly the same. For example:
instance1 = Mimi.build(m) run(instance1) update_param!(m, ParameterName, newvalue) instance2 = Mimi.build(m) run(instance2) result1 = instance1[:Comp, :Var] result2 = instance2[:Comp, :Var]
Note that you can retrieve values from a ModelInstance in the same way you index into a model.
The init function
init function can optionally be called within
@defcomp and before
run_timestep. Similarly to
run_timestep, this function is called with parameters
init(p, v, d), where the component state (defined by the first three arguments) has fields for the Parameters, Variables, and Dimensions of the component you defined.
If defined for a specific component, this function will run before the timestep loop, and should only be used for parameters or variables without a time index e.g. to compute the values of scalar variables that only depend on scalar parameters. Note that when using
init, it may be necessary to add special handling in the
run_timestep function for the first timestep, in particular for difference equations. A skeleton
@defcomp script using both
init would appear as follows:
@defcomp component1 begin # First define the state this component will hold savingsrate = Parameter() # Second, define the (optional) init function for the component function init(p, v, d) end # Third, define the run_timestep function for the component function run_timestep(p, v, d, t) end end