Skip to content

Commit 92fef85

Browse files
authored
Improve docs a bit more (#9)
* improve docs significantly * bump version
1 parent e17ebb0 commit 92fef85

File tree

5 files changed

+60
-25
lines changed

5 files changed

+60
-25
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ProcessBasedModelling"
22
uuid = "ca969041-2cf3-4b10-bc21-86f4417093eb"
33
authors = ["Datseris <[email protected]>"]
4-
version = "1.2.1"
4+
version = "1.2.2"
55

66
[deps]
77
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
ProcessBasedModelling.jl is an extension to [ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/stable/) (MTK) for building a model of equations using symbolic expressions.
1010
It is an alternative framework to MTK's [native component-based modelling](https://docs.sciml.ai/ModelingToolkit/stable/tutorials/acausal_components/), but, instead of components, there are "processes".
1111
This approach is useful in the modelling of physical/biological/whatever systems, where each variable corresponds to a particular physical concept or observable and there are few (or none) duplicate variables to make the definition of MTK "factories" worthwhile.
12-
On the other hand, there plenty of different physical representations, or _processes_ to represent a given physical concept.
12+
On the other hand, there plenty of different physical representations, or _processes_ to represent a given physical concept in equation form.
1313
In many scientific fields this approach parallels the modelling reasoning of the researcher more closely than the "components" approach.
1414

1515
Beyond this reasoning style, the biggest strength of ProcessBasedModelling.jl is the **informative errors and automation** it provides regarding incorrect/incomplete equations. When building the MTK model via ProcessBasedModelling.jl the user provides a vector of "processes": equations or custom types that have a well defined and single left-hand-side variable.
@@ -22,7 +22,7 @@ This allows ProcessBasedModelling.jl to:
2222
- Else, throw an informative error saying exactly which originally provided variable introduced this new "process-less" variable.
2323
3. Throw an informative error if a variable has two processes assigned to it (by mistake).
2424

25-
In our experience, and as we also highlight explicitly in the online documentation, this approach typically yields simpler, less ambiguous and more targeted warning or error messages than the native MTK one's, leading to faster identification and resolution of the problems with the composed equations.
25+
In our experience, and as we also highlight explicitly in the online documentation, this approach typically yields simpler, less ambiguous, and more targeted warning or error messages than the native MTK one's. This leads to faster identification and resolution of the problems with the composed equations.
2626

2727
ProcessBasedModelling.jl is particularly suited for developing a model about a physical/biological/whatever system and being able to try various physical "rules" (couplings, feedbacks, mechanisms, ...) for a given physical observable efficiently.
2828
This means switching arbitrarily between different processes that correspond to the same variable.
@@ -36,4 +36,4 @@ Besides the informative errors, ProcessBasedModelling.jl also
3636

3737
See the documentation online for details on how to use this package as well as examples highlighting its usefulness.
3838

39-
ProcessBasedModelling.jl development is funded by UKRI's Engineering and Physical Sciences Research Council, grant no. EP/Y01653X/1 (grant agreement for a EU Marie Sklodowska-Curie Postdoctoral Fellowship).
39+
ProcessBasedModelling.jl development is funded by UKRI's Engineering and Physical Sciences Research Council, grant no. EP/Y01653X/1 (grant agreement for a EU Marie Sklodowska-Curie Postdoctoral Fellowship for George Datseris).

docs/src/index.md

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ ProcessBasedModelling
1414

1515
In ProcessBasedModelling.jl, each variable is governed by a "process".
1616
Conceptually this is just an equation that _defines_ the given variable.
17-
To couple the variable with the process it is governed by, a user either defines simple equations of the form "variable = expression", or creates an instance of [`Process`](@ref) if the left-hand-side of the equation needs to be anything more complex (or, simply if you want to utilize the conveniences of predefined processes).
18-
In either case, the variable and the expression are both _symbolic expressions_ created via ModellingToolkit.jl (more specifically, via Symbolics.jl).
17+
To couple the variable with the process it is governed by, a user either defines simple equations of the form `variable ~ expression`, or creates an instance of [`Process`](@ref) if the left-hand-side of the equation needs to be anything more complex (or, simply if you want to utilize the conveniences of predefined processes).
18+
In either case, the `variable` and the `expression` are both _symbolic expressions_ created via ModellingToolkit.jl.
1919

20-
Once all the processes about the physical system are collected, they are given as a `Vector` to the [`processes_to_mtkmodel`](@ref) central function, similarly to how one gives a `Vector` of `Equation`s to e.g., `ModelingToolkit.ODESystem`. This function also defines what quantifies as a "process" in more specificity.
20+
Once all the processes about the physical system are collected, they are given as a `Vector` to the [`processes_to_mtkmodel`](@ref) central function, similarly to how one gives a `Vector` of `Equation`s to e.g., `ModelingToolkit.ODESystem`. `processes_to_mtkmodel` also defines what quantifies as a "process" in more specificity.
21+
Then `processes_to_mtkmodel` ensures that all variables in the relational graph of your equations have a defining equation, or throws informative errors/warnings otherwise.
22+
It also provides some useful automation, see the example below.
2123

2224
## Example
2325

@@ -60,8 +62,13 @@ equations(model)
6062

6163
All good. Now, if we missed the process for one variable (because of our own error/sloppyness/very-large-codebase), MTK will throw an error when we try to _structurally simplify_ the model (a step necessary before solving the ODE problem):
6264

63-
```julia
65+
```@example MAIN
66+
# no errors:
6467
model = ODESystem(eqs[1:2], t; name = :example)
68+
```
69+
70+
```julia
71+
# here is the error
6572
model = structural_simplify(model)
6673
```
6774
```
@@ -92,7 +99,7 @@ Here is what the user defines to make the same system of equations via **PBM**:
9299
using ProcessBasedModelling
93100
94101
processes = [
95-
ExpRelaxation(z, x^2), # defines z, introduces x; `Process` subtype (optional)
102+
ExpRelaxation(z, x^2), # defines z, introduces x; `Process` subtype
96103
Differential(t)(x) ~ 0.1*y, # defines x, introduces y; normal `Equation`
97104
y ~ z - x, # defines y; normal `Equation`
98105
]
@@ -108,15 +115,15 @@ equations(model)
108115
Notice that the resulting **MTK** model is not `structural_simplify`-ed, to allow composing it with other models. By default `t` is taken as the independent variable.
109116

110117
Now, in contrast to before, if we "forgot" a process, **PBM** will react accordingly.
111-
For example, if we forgot the 2nd process, then the construction will error informatively,
118+
For example, if we forgot the process for ``x``, then the construction will error informatively,
112119
telling us exactly which variable is missing, and because of which processes it is missing:
113120
```julia
114121
model = processes_to_mtkmodel(processes[[1, 3]])
115122
```
116123
```
117124
ERROR: ArgumentError: Variable x(t) was introduced in process of variable z(t).
118125
However, a process for x(t) was not provided,
119-
there is no default process for x(t), and (t)x doesn't have a default value.
126+
there is no default process for x(t), and x(t) doesn't have a default value.
120127
Please provide a process for variable x(t).
121128
```
122129

@@ -154,6 +161,10 @@ equations(model)
154161

155162
does not throw any warnings as it obtained a process for ``y`` from the given default processes.
156163

164+
!!! note "Default processes example"
165+
The default process infrastructure of **PBM** is arguably its most powerful quality when it comes to building field-specific libraries. Its usefulness is illustrated in the derivative package [ConceptualClimateModels.jl](https://github.com/JuliaDynamics/ConceptualClimateModels.jl).
166+
167+
157168
## Special handling of timescales
158169

159170
In dynamical systems modelling the timescale associated with a process is a special parameter. That is why, if a timescale is given for either the [`TimeDerivative`](@ref) or [`ExpRelaxation`](@ref) processes, it is converted to a named `@parameter` by default:
@@ -173,9 +184,18 @@ equations(model)
173184
parameters(model)
174185
```
175186

187+
Note the automatically created parameters ``\tau_x, \tau_z``.
176188
This special handling is also why each process can declare a timescale via the [`ProcessBasedModelling.timescale`](@ref) function that one can optionally extend
177189
(although in our experience the default behaviour covers almost all cases).
178190

191+
If you do not want this automation, you can opt out in two ways:
192+
193+
- Provide your own created parameter as the third argument in e.g., `ExpRelaxation`
194+
- Wrap the numeric value into [`LiteralParameter`](@ref). This will insert the numeric literal into the equation.
195+
196+
See the section on [automatic parameters](@ref auto_params) for more related automation,
197+
such as the macro [`@convert_to_parameters`](@ref) which can be particularly useful
198+
when developing a field-specific library.
179199

180200
## Main API function
181201

@@ -205,7 +225,7 @@ ProcessBasedModelling.NoTimeDerivative
205225
ProcessBasedModelling.lhs
206226
```
207227

208-
## Automatic named parameters
228+
## [Automatic named parameters](@id auto_params)
209229

210230
```@docs
211231
new_derived_named_parameter

src/default.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Register a `process` (`Equation` or `Process`) as a default process for its LHS
99
in the list of default processes tracked by the given module.
1010
If `warn`, throw a warning if a default process with same LHS variable already
1111
exists and will be overwritten.
12+
13+
You can use [`default_processes`](@ref) to obtain the list of tracked default processes.
1214
"""
1315
function register_default_process!(process::Union{Process, Equation}, m::Module; warn = true)
1416
mdict = default_processes(m)

src/make.jl

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,50 @@
22
processes_to_mtkmodel(processes::Vector [, default]; kw...)
33
44
Construct a ModelingToolkit.jl model/system using the provided `processes` and `default` processes.
5-
The model/system is _not_ structurally simplified.
5+
The model/system is _not_ structurally simplified. During construction, the following automations
6+
improve user experience:
67
7-
`processes` is a vector whose elements can be:
8+
- Variable(s) introduced in `processes` that does not itself have a process obtain
9+
a default process from `default`.
10+
- If no default exists, but the variable(s) itself has a default numerical value,
11+
a [`ParameterProcess`](@ref) is created for said variable and a warning is thrown.
12+
- Else, an informative error is thrown.
13+
- An error is also thrown if any variable has two or more processes assigned to it.
14+
15+
`processes` is a `Vector` whose elements can be:
816
917
1. Any instance of a subtype of [`Process`](@ref). `Process` is a
1018
wrapper around `Equation` that provides some conveniences, e.g., handling of timescales
1119
or not having limitations on the left-hand-side (LHS) form.
1220
1. An `Equation`. The LHS format of the equation is limited.
1321
Let `x` be a `@variable` and `p` be a `@parameter`. Then, the LHS can only be one of:
1422
`x`, `Differential(t)(x)`, `Differential(t)(x)*p`, `p*Differential(t)(x)`,
15-
however, the versions with `p` may fail unexpectedly.
16-
Anything else will either error or fail unexpectedly.
17-
2. A vector of the above two, which is then expanded. This allows the convenience of
18-
functions representing a physical process that may require many equations to be defined.
23+
however, the versions with `p` may fail unexpectedly. Anything else will error.
24+
2. A `Vector` of the above two, which is then expanded. This allows the convenience of
25+
functions representing a physical process that may require many equations to be defined
26+
(because e.g., they may introduce more variables).
1927
3. A ModelingToolkit.jl `XDESystem`, in which case the `equations` of the system are expanded
2028
as if they were given as a vector of equations like above. This allows the convenience
21-
of straightforwardly coupling already existing systems.
29+
of straightforwardly coupling with already existing `XDESystem`s.
2230
2331
## Default processes
2432
2533
`processes_to_mtkmodel` allows for specifying default processes by giving `default`.
26-
These default processes are assigned to variables introduced in the main input `processes`
27-
without themselves having an assigned process in the main input.
34+
These default processes are assigned to variables introduced in the main input `processes`,
35+
but themselves do not have an assigned process in the main input.
2836
2937
`default` can be a `Vector` of individual processes (`Equation` or `Process`).
30-
Alternatively, `default` can be a `Module`. ProcessBasedModelling.jl allows modules to
31-
register their own default processes via the function [`register_default_process!`](@ref).
38+
Alternatively, `default` can be a `Module`. The recommended way to build field-specific
39+
modelling libraries based on ProcessBasedModelling.jl is to define modules/submodules
40+
that offer a pool of pre-defined variables and processes.
41+
Modules may register their own default processes via the function
42+
[`register_default_process!`](@ref).
3243
These registered processes are used when `default` is a `Module`.
3344
3445
## Keyword arguments
3546
36-
- `type = ODESystem`: the model type to make
37-
- `name = nameof(type)`: the name of the model
47+
- `type = ODESystem`: the model type to make.
48+
- `name = nameof(type)`: the name of the model.
3849
- `independent = t`: the independent variable (default: `@variables t`).
3950
`t` is also exported by ProcessBasedModelling.jl for convenience.
4051
- `warn_default::Bool = true`: if `true`, throw a warning when a variable does not
@@ -47,6 +58,8 @@ processes_to_mtkmodel(procs, default_processes(m); kw...)
4758
processes_to_mtkmodel(procs::Vector, v::Vector; kw...) =
4859
processes_to_mtkmodel(procs, default_dict(v); kw...)
4960

61+
# The main implementation has the defaults to be a map from variable to process
62+
# because this simplifies a bit the code
5063
function processes_to_mtkmodel(_processes::Vector, default::Dict{Num, Any};
5164
type = ODESystem, name = nameof(type), independent = t, warn_default::Bool = true,
5265
)

0 commit comments

Comments
 (0)