|
| 1 | +## Defining components with `@mtkmodel` |
| 2 | + |
| 3 | +`@mtkmodel` is a convenience macro to define ModelingToolkit components. It returns `ModelingToolkit.Model`, which includes a constructor that returns an ODESystem, a `structure` dictionary with metadata and flag `isconnector` which is set to `false`. |
| 4 | + |
| 5 | +### What can an MTK-Model definition have? |
| 6 | + |
| 7 | +`@mtkmodel` definition contains begin blocks of |
| 8 | + |
| 9 | + - `@components`: for listing sub-components of the system |
| 10 | + - `@equations`: for the list of equations |
| 11 | + - `@extend`: for extending a base system and unpacking its states |
| 12 | + - `@parameters`: for specifying the symbolic parameters |
| 13 | + - `@structural_parameters`: for specifying non-symbolic parameters |
| 14 | + - `@variables`: for specifing the states |
| 15 | + |
| 16 | +Let's explore these in more detail with the following example: |
| 17 | + |
| 18 | +```@example mtkmodel-example |
| 19 | +using ModelingToolkit |
| 20 | +
|
| 21 | +@mtkmodel ModelA begin |
| 22 | + @parameters begin |
| 23 | + k1 |
| 24 | + k2 |
| 25 | + end |
| 26 | +end |
| 27 | +
|
| 28 | +@mtkmodel ModelB begin |
| 29 | + @parameters begin |
| 30 | + p1 = 1.0, [description = "Parameter of ModelB"] |
| 31 | + p2 = 1.0, [description = "Parameter of ModelB"] |
| 32 | + end |
| 33 | +end |
| 34 | +
|
| 35 | +@mtkmodel ModelC begin |
| 36 | + @structural_parameters begin |
| 37 | + f = sin |
| 38 | + end |
| 39 | + begin |
| 40 | + v_var = 1.0 |
| 41 | + end |
| 42 | + @variables begin |
| 43 | + v(t) = v_var |
| 44 | + end |
| 45 | + @extend p1, p2 = model_b = ModelB(; p1) |
| 46 | + @components begin |
| 47 | + model_a = ModelA(; k1) |
| 48 | + end |
| 49 | + @equations begin |
| 50 | + model_a.k1 ~ f(v) |
| 51 | + end |
| 52 | +end |
| 53 | +``` |
| 54 | + |
| 55 | +#### `@parameters` and `@variables` begin block |
| 56 | + |
| 57 | + - Parameters and variables are declared with respective begin blocks. |
| 58 | + - Variables must be functions of an independent variable. |
| 59 | + - Optionally, default values and metadata can be specified for these parameters and variables. See `ModelB` in the above example. |
| 60 | + - Along with creating parameters and variables, keyword arguments of same name with default value `nothing` are created. |
| 61 | + - Whenever a parameter or variable has default value, for example `v(t) = 0.0`, a symbolic variable named `v` with default value 0.0 and a keyword argument `v`, with default value `nothing` are created. <br> This way, users can optionally pass new value of `v` while creating a component. |
| 62 | + |
| 63 | +```julia |
| 64 | +julia > @named model_c = ModelC(; v = 2.0); |
| 65 | + |
| 66 | +julia > ModelingToolkit.getdefault(model_c.v) |
| 67 | +2.0 |
| 68 | +``` |
| 69 | + |
| 70 | +#### `@structural_parameters` begin block |
| 71 | + |
| 72 | + - This block is for non symbolic input arguements. These are for inputs that usually are not meant to be part of components; but influence how they are defined. One can list inputs like boolean flags, functions etc... here. |
| 73 | + - Whenever default values are specified, unlike parameters/variables, they are reflected in the keyword argument list. |
| 74 | + |
| 75 | +#### `@extend` block |
| 76 | + |
| 77 | +To extend a partial system, |
| 78 | + |
| 79 | + - List the variables to unpack. If there is a single variable, explicitly specify it as a tuple. |
| 80 | + - Give a name to the base system |
| 81 | + - List the kwargs of the base system that should be listed as kwargs of the main component. |
| 82 | + - Note that in above example, `p1` is promoted as an argument of `ModelC`. Users can set the value of `p1` as |
| 83 | + |
| 84 | +```julia |
| 85 | +julia> @named model_c = ModelC(; p1 = 2.0) |
| 86 | + |
| 87 | +``` |
| 88 | + |
| 89 | +However, as `p2` isn't listed in the model definition, its default can't be modified by users. |
| 90 | + |
| 91 | +#### `@components` begin block |
| 92 | + |
| 93 | + - Declare the subcomponents within `@components` begin block. |
| 94 | + - The arguments in these subcomponents are promoted as keyword arguments as `subcomponent_name__argname` with `nothing` as default value. |
| 95 | + - Whenever components are created with `@named` macro, these can be accessed with `.` operator as `subcomponent_name.argname` |
| 96 | + - In the above example, `k1` of `model_a` can be set in following ways: |
| 97 | + |
| 98 | +```julia |
| 99 | +julia> @named model_c1 = ModelC(; model_a.k1 = 1); |
| 100 | +# or as |
| 101 | + |
| 102 | +julia> model_c2 = ModelC(; name = :model_c, model_a__k1 = 1); |
| 103 | + |
| 104 | +``` |
| 105 | + |
| 106 | +And as `k2` isn't listed in the sub-component definition of `ModelC`, its default value can't be modified by users. |
| 107 | + |
| 108 | +#### `@equations` begin block |
| 109 | + |
| 110 | + - List all the equations here |
| 111 | + |
| 112 | +#### A begin block |
| 113 | + |
| 114 | + - Any other Julia operations can be included with dedicated begin blocks. |
| 115 | + |
| 116 | +## Defining connectors with `@connector` |
| 117 | + |
| 118 | +`@connector` returns `ModelingToolkit.Model`. It includes a constructor that returns a connector ODESystem, a `structure` dictionary with metadata and flag `isconnector` which is set to `true`. |
| 119 | + |
| 120 | +A simple connector can be defined with syntax similar to following example: |
| 121 | + |
| 122 | +```julia |
| 123 | +using ModelingToolkit |
| 124 | + |
| 125 | +@connector Pin begin |
| 126 | + v(t) = 0.0, [description = "Voltage"] |
| 127 | + i(t), [connect = Flow] |
| 128 | +end |
| 129 | +``` |
| 130 | + |
| 131 | + - Variables (as function of independent variable) are listed out in the definition. These variables can optionally have default values and metadata like `descrption`, `connect` and so on. |
| 132 | + |
| 133 | +`@connector`s accepts begin blocks of `@components`, `@equations`, `@extend`, `@parameters`, `@structural_parameters`, `@variables`. These keywords mean the same as described above for `@mtkmodel`. |
| 134 | + |
| 135 | +!!! note |
| 136 | + |
| 137 | + For more examples of usage, checkout [ModelingToolkitStandardLibrary.jl](https://github.com/SciML/ModelingToolkitStandardLibrary.jl/) |
| 138 | + |
| 139 | +* * * |
| 140 | + |
| 141 | +### What's a `structure` dictionary? |
| 142 | + |
| 143 | +For components defined with `@mtkmodel` or `@connector`, a dictionary with metadata is created. It lists `:components` (sub-component list), `:extend` (the extended states and base system), `:parameters`, `:variables`, ``:kwargs`` (list of keyword arguments), `:independent_variable`, `:equations`. |
| 144 | + |
| 145 | +For example, the structure of `ModelC` is: |
| 146 | + |
| 147 | +```julia |
| 148 | +julia> ModelC.structure |
| 149 | +Dict{Symbol, Any} with 6 entries: |
| 150 | + :components => [[:model_a, :ModelA]] |
| 151 | + :variables => Dict{Symbol, Dict{Symbol, Any}}(:v=>Dict(:default=>:v_var)) |
| 152 | + :kwargs => Dict{Symbol, Any}(:f=>:sin, :v=>:v_var, :p1=>nothing, :model_a__k1=>nothing) |
| 153 | + :independent_variable => t |
| 154 | + :extend => Any[[:p1, :p2], :model_b, :ModelB] |
| 155 | + :equations => ["model_a.k1 ~ f(v)"] |
| 156 | +``` |
0 commit comments