@@ -203,6 +203,73 @@ long enough you will see that `λ = 0` is required for this equation, but since
203
203
problem constructor. Additionally, any warning about not being fully determined can
204
204
be suppressed via passing ` warn_initialize_determined = false ` .
205
205
206
+ ## Constant constraints in initialization
207
+
208
+ Consider the pendulum system again:
209
+
210
+ ``` @repl init
211
+ equations(pend)
212
+ observed(pend)
213
+ ```
214
+
215
+ Suppose we want to solve the same system with multiple different initial
216
+ y-velocities from a given position.
217
+
218
+ ``` @example init
219
+ prob = ODEProblem(
220
+ pend, [x => 1, D(y) => 0], (0.0, 1.5), [g => 1], guesses = [λ => 0, y => 1, x => 1])
221
+ sol1 = solve(prob, Rodas5P())
222
+ ```
223
+
224
+ ``` @example init
225
+ sol1[D(y), 1]
226
+ ```
227
+
228
+ Repeatedly re-creating the ` ODEProblem ` with different values of ` D(y) ` and ` x ` or
229
+ repeatedly calling ` remake ` is slow. Instead, for any ` variable => constant ` constraint
230
+ in the ` ODEProblem ` initialization (whether provided to the ` ODEProblem ` constructor or
231
+ a default value) we can update the ` constant ` value. ModelingToolkit refers to these
232
+ values using the ` Initial ` operator. For example:
233
+
234
+ ``` @example init
235
+ prob.ps[[Initial(x), Initial(D(y))]]
236
+ ```
237
+
238
+ To solve with a different starting y-velocity, we can simply do
239
+
240
+ ``` @example init
241
+ prob.ps[Initial(D(y))] = -0.1
242
+ sol2 = solve(prob, Rodas5P())
243
+ ```
244
+
245
+ ``` @example init
246
+ sol2[D(y), 1]
247
+ ```
248
+
249
+ Note that this _ only_ applies for constant constraints for the current ODEProblem.
250
+ For example, ` D(x) ` does not have a constant constraint - it is solved for by
251
+ initialization. Thus, mutating ` Initial(D(x)) ` does not have any effect:
252
+
253
+ ``` @repl init
254
+ sol2[D(x), 1]
255
+ prob.ps[Initial(D(x))] = 1.0
256
+ sol3 = solve(prob, Rodas5P())
257
+ sol3[D(x), 1]
258
+ ```
259
+
260
+ To enforce this constraint, we would have to ` remake ` the problem (or construct a new one).
261
+
262
+ ``` @repl init
263
+ prob2 = remake(prob; u0 = [y => 0.0, D(x) => 0.0, x => nothing, D(y) => nothing]);
264
+ sol4 = solve(prob2, Rodas5P())
265
+ sol4[D(x), 1]
266
+ ```
267
+
268
+ Note the need to provide ` x => nothing, D(y) => nothing ` to override the previously
269
+ provided initial conditions. Since ` remake ` is a partial update, the constraints provided
270
+ to it are merged with the ones already present in the problem. Existing constraints can be
271
+ removed by providing a value of ` nothing ` .
272
+
206
273
## Initialization of parameters
207
274
208
275
Parameters may also be treated as unknowns in the initialization system. Doing so works
@@ -231,6 +298,9 @@ constraints provided to it. The new values will be combined with the original
231
298
variable-value mapping provided to ` ODEProblem ` and used to construct the initialization
232
299
problem.
233
300
301
+ The variable on the left hand side of all parameter dependencies also has an ` Initial `
302
+ variant, which is used if a constant constraint is provided for the variable.
303
+
234
304
### Parameter initialization by example
235
305
236
306
Consider the following system, where the sum of two unknowns is a constant parameter
0 commit comments