@@ -203,6 +203,73 @@ long enough you will see that `λ = 0` is required for this equation, but since
203203 problem constructor. Additionally, any warning about not being fully determined can
204204 be suppressed via passing ` warn_initialize_determined = false ` .
205205
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+
206273## Initialization of parameters
207274
208275Parameters 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
231298variable-value mapping provided to ` ODEProblem ` and used to construct the initialization
232299problem.
233300
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+
234304### Parameter initialization by example
235305
236306Consider the following system, where the sum of two unknowns is a constant parameter
0 commit comments