@@ -133,23 +133,73 @@ prob = DE.DAEProblem(f2, du₀, u₀, tspan, differential_vars = differential_va
133133
134134` differential_vars ` is an option which states which of the variables are differential,
135135i.e. not purely algebraic (which means that their derivative shows up in the residual
136- equations). This is required for the algorithm to be able to find consistent initial
137- conditions. Notice that the first two variables are determined by their changes, but
138- the last is simply determined by the conservation equation. Thus, we use
139- ` differential_vars = [true,true,false] ` .
136+ equations). This is required for the initialization algorithm to properly compute
137+ consistent initial conditions. Notice that the first two variables are determined by
138+ their changes, but the last is simply determined by the conservation equation. Thus,
139+ we use ` differential_vars = [true,true,false] ` .
140140
141- As with the other DifferentialEquations problems, the commands are then to solve
142- and plot. Here we will use the IDA solver from Sundials:
141+ ### DAE Initialization
142+
143+ DAEs require that the initial conditions satisfy the constraint equations. In this
144+ example, our initial conditions are already consistent (they satisfy ` f(du₀, u₀, p, t₀) = 0 ` ).
145+ However, in many cases, you may not have consistent initial conditions, and the solver
146+ needs to compute them.
147+
148+ The IDA solver from Sundials can handle initialization through the ` initializealg `
149+ parameter. The most commonly used initialization algorithm is ` BrownFullBasicInit() ` ,
150+ which modifies the algebraic variables and derivatives to satisfy the constraints:
143151
144152``` @example dae
145153import Sundials
146- sol = DE.solve(prob, Sundials.IDA())
154+ import DiffEqBase
155+ # Explicitly use Brown's initialization algorithm
156+ sol = DE.solve(prob, Sundials.IDA(), initializealg = DiffEqBase.BrownFullBasicInit())
147157```
148158
159+ If you're confident your initial conditions are already consistent, you can verify
160+ this using ` CheckInit() ` :
161+
162+ ``` @example dae
163+ # This will verify initial conditions and error if they're inconsistent
164+ sol_check = DE.solve(prob, Sundials.IDA(), initializealg = DiffEqBase.CheckInit())
165+ ```
166+
167+ For more details on DAE initialization options, see the
168+ [ DAE Initialization documentation] ( @ref ) .
169+
149170In order to clearly see all the features of this solution, it should be plotted
150171on a logarithmic scale. We'll also plot each on a different subplot, to allow
151172scaling the y-axis appropriately.
152173
153174``` @example dae
154175Plots.plot(sol, xscale = :log10, tspan = (1e-6, 1e5), layout = (3, 1))
155176```
177+
178+ ### Handling Inconsistent Initial Conditions
179+
180+ Let's see what happens when we provide inconsistent initial conditions and how
181+ the initialization algorithms handle them:
182+
183+ ``` @example dae
184+ # Inconsistent initial conditions - y₃ should be 0 to satisfy y₁ + y₂ + y₃ = 1
185+ u₀_inconsistent = [1.0, 0.0, 0.5] # Sum is 1.5, not 1!
186+ du₀_inconsistent = [-0.04, 0.04, 0.0]
187+
188+ prob_inconsistent = DE.DAEProblem(f2, du₀_inconsistent, u₀_inconsistent, tspan,
189+ differential_vars = differential_vars)
190+
191+ # This would error with CheckInit() because conditions are inconsistent:
192+ # sol_error = DE.solve(prob_inconsistent, Sundials.IDA(),
193+ # initializealg = DiffEqBase.CheckInit())
194+
195+ # But BrownFullBasicInit() will fix the inconsistency automatically:
196+ sol_fixed = DE.solve(prob_inconsistent, Sundials.IDA(),
197+ initializealg = DiffEqBase.BrownFullBasicInit())
198+
199+ println("Original (inconsistent) y₃ = ", u₀_inconsistent[3])
200+ println("Corrected y₃ after initialization = ", sol_fixed.u[1][3])
201+ println("Sum after correction = ", sum(sol_fixed.u[1]))
202+ ```
203+
204+ As you can see, ` BrownFullBasicInit() ` automatically adjusted the algebraic variable
205+ ` y₃ ` to satisfy the constraint equation ` y₁ + y₂ + y₃ = 1 ` .
0 commit comments