Index Reduction
Not all DAEs are created equal. The index of a DAE determines how difficult it is to solve numerically. Numra’s solvers handle index-1 DAEs natively, but many physical systems naturally produce higher-index DAEs. This section explains what the index means, why it matters, and how to reduce a higher-index DAE to index-1 form so that Numra can solve it.
What Is the DAE Index?
Section titled “What Is the DAE Index?”The differentiation index of a DAE is the minimum number of times you must differentiate the system (or parts of it) with respect to time before you can express it as an explicit ODE:
Index-0: Regular ODE
Section titled “Index-0: Regular ODE”The mass matrix is the identity (or any nonsingular matrix). No differentiation needed. Every standard ODE solver works.
Index-1: One Differentiation
Section titled “Index-1: One Differentiation”where are differential variables and are algebraic variables. The key requirement is that is nonsingular, meaning we can solve for from the constraint.
Differentiating the constraint once:
gives an expression for , making the system an ODE. One differentiation = index 1.
Example: The RC circuit DAE from the previous section is index-1. The algebraic equation can be solved directly for .
Index-2: Two Differentiations
Section titled “Index-2: Two Differentiations”Notice that the constraint depends only on , not on . You must differentiate twice to get an ODE for :
- First differentiation: (this is a hidden constraint on )
- Second differentiation: gives explicitly
Example: A constrained mechanical system with the constraint expressed at the position level (not velocity or acceleration).
Index-3: Three Differentiations
Section titled “Index-3: Three Differentiations”The most famous example is the pendulum in Cartesian coordinates from the DAE Systems chapter:
The constraint involves only positions (), not velocities or the multiplier . You must differentiate three times:
- (velocity-level constraint)
- (acceleration-level)
- Differentiate again to find
This is an index-3 DAE. Standard solvers (including Numra’s) cannot handle it directly.
Why Does Index Matter?
Section titled “Why Does Index Matter?”Higher-index DAEs are progressively harder to solve numerically:
| Index | Difficulty | Solver requirements |
|---|---|---|
| 0 | Easy | Any ODE solver |
| 1 | Moderate | Implicit solver with mass matrix (Radau5, BDF) |
| 2 | Hard | Specialized index-2 solver or index reduction |
| 3 | Very hard | Almost always requires index reduction |
| > 3 | Extreme | Reformulate the problem |
The fundamental issue is that numerical errors accumulate differently at each index level. For an index-1 DAE, the algebraic constraint is satisfied to the solver’s tolerance. For index-2, errors in the constraint can grow linearly with time. For index-3, they can grow quadratically. This is called drift.
Index Reduction Techniques
Section titled “Index Reduction Techniques”Technique 1: Differentiate the Constraints
Section titled “Technique 1: Differentiate the Constraints”The most direct approach: differentiate the algebraic constraints until the system becomes index-1 (or even index-0).
Pendulum example: Replace the position-level constraint with the acceleration-level constraint:
This is now index-1 (we can solve directly for from the last equation).
Problem: The position-level constraint is no longer enforced. Numerical errors will cause the pendulum length to drift over time.
Technique 2: Baumgarte Stabilization
Section titled “Technique 2: Baumgarte Stabilization”Add damping terms to the differentiated constraint to prevent drift. Instead of replacing the constraint, modify the acceleration-level equation:
where , , and are damping parameters.
This drives both the constraint violation and its time derivative to zero exponentially. The resulting system is index-1.
For the pendulum:
Choosing and : Typical values are where is the characteristic time of the system. Too large causes stiffness; too small allows drift.
Technique 3: GGL Formulation (Gear-Gupta-Leimkuhler)
Section titled “Technique 3: GGL Formulation (Gear-Gupta-Leimkuhler)”This adds the original constraint as an additional equation alongside the differentiated form. The system is augmented with a new multiplier :
The extra multiplier projects the velocity onto the constraint manifold. This formulation is index-2 (which some specialized solvers can handle), and with one more differentiation becomes a well-conditioned index-1 system.
Technique 4: Reformulate as ODE
Section titled “Technique 4: Reformulate as ODE”Sometimes the cleanest approach is to eliminate the algebraic variables entirely. For the pendulum, use the angle instead of Cartesian coordinates:
This is a pure ODE — no algebraic constraints at all!
use numra::ode::{DoPri5, Solver, OdeProblem, SolverOptions};
let g = 9.81;let l = 1.0;
// State: [theta, omega] where omega = theta'let problem = OdeProblem::new( move |_t, y: &[f64], dydt: &mut [f64]| { dydt[0] = y[1]; // theta' = omega dydt[1] = -(g / l) * y[0].sin(); // omega' = -(g/L) sin(theta) }, 0.0, 10.0, vec![std::f64::consts::PI / 6.0, 0.0], // 30 degrees, zero velocity);
let options = SolverOptions::default().rtol(1e-10).atol(1e-12);let result = DoPri5::solve( &problem, 0.0, 10.0, &[std::f64::consts::PI / 6.0, 0.0], &options,).expect("Pendulum ODE is non-stiff");Of course, this requires insight into the problem structure and is not always possible for complex multi-body systems.
Practical Example: Stabilized Pendulum DAE
Section titled “Practical Example: Stabilized Pendulum DAE”Here is a complete example of the pendulum using Baumgarte stabilization to reduce the index-3 DAE to index-1, solvable by Numra:
use numra::ode::{DaeProblem, Radau5, Solver, SolverOptions};
let grav = 9.81;let l = 1.0;let alpha = 10.0; // Baumgarte stabilization parameterlet beta = 10.0;
let theta0: f64 = std::f64::consts::PI / 6.0;let x0 = l * theta0.sin();let y0 = -l * theta0.cos();
// Compute consistent initial lambda:// From acceleration constraint at rest (vx=vy=0):// 0 = 0 + 0 - lambda*(x0^2 + y0^2) - grav*y0 + 0 + beta^2*(0)// => lambda = -grav*y0 / (x0^2 + y0^2) = -grav*y0 / L^2let lam0 = -grav * y0 / (l * l);
let dae = DaeProblem::new( move |_t, y: &[f64], dydt: &mut [f64]| { let x = y[0]; let yp = y[1]; // y-position let vx = y[2]; let vy = y[3]; let lam = y[4];
dydt[0] = vx; dydt[1] = vy; dydt[2] = -lam * x; dydt[3] = -lam * yp - grav;
// Baumgarte-stabilized acceleration-level constraint (index-1): let g_pos = x * x + yp * yp - l * l; // position constraint let g_vel = 2.0 * (x * vx + yp * vy); // velocity constraint let g_acc = 2.0 * (vx * vx + vy * vy) - 2.0 * lam * (x * x + yp * yp) - 2.0 * grav * yp; dydt[4] = g_acc + 2.0 * alpha * g_vel + beta * beta * g_pos; }, |mass: &mut [f64]| { for i in 0..25 { mass[i] = 0.0; } mass[0] = 1.0; mass[6] = 1.0; mass[12] = 1.0; mass[18] = 1.0; // mass[24] = 0 (algebraic) }, 0.0, 10.0, vec![x0, y0, 0.0, 0.0, lam0], vec![4], // lambda is algebraic);
let options = SolverOptions::default() .rtol(1e-8) .atol(1e-10);
let result = Radau5::solve( &dae, 0.0, 10.0, &[x0, y0, 0.0, 0.0, lam0], &options,).expect("Stabilized pendulum DAE should solve");
// Check that the length constraint is approximately maintainedlet yf = result.y_final().unwrap();let length_err = (yf[0] * yf[0] + yf[1] * yf[1]).sqrt() - l;assert!(length_err.abs() < 1e-4, "Pendulum length drifted by {}", length_err);Which Solvers Handle Which Indices?
Section titled “Which Solvers Handle Which Indices?”| DAE index | Numra solvers | Notes |
|---|---|---|
| Index-0 (ODE) | All solvers | No special handling needed |
| Index-1 | Radau5, BDF | Native support via mass matrix |
| Index-2 | None directly | Apply index reduction first |
| Index-3+ | None directly | Apply index reduction first |
Why Only Index-1?
Section titled “Why Only Index-1?”Radau5 and BDF solve systems of the form . The Newton iteration for the implicit stages requires solving:
For index-1 DAEs, the matrix is nonsingular (even though itself is singular), because the Jacobian has the right structure to “fill in” the zero rows of . For index-2 and higher, this matrix can become singular or very ill-conditioned, causing the Newton iteration to fail.
Additionally, Radau5’s stiffly-accurate property (the last stage equals the step endpoint) ensures that the algebraic constraints are satisfied at each time step for index-1 problems. This property does not extend to higher-index DAEs.
Index Reduction Checklist
Section titled “Index Reduction Checklist”When you encounter a higher-index DAE:
-
Identify the index. Count how many times you must differentiate the algebraic constraints to express all variables as ODEs.
-
Try reformulation first. Can you use generalized coordinates that eliminate constraints entirely? (e.g., angles instead of Cartesian coordinates)
-
If reformulation is not possible, use Baumgarte stabilization:
- Differentiate constraints to the acceleration level.
- Add stabilization terms.
- Choose based on the system timescale.
-
Verify consistent initial conditions. After index reduction, all algebraic constraints (including the differentiated ones) must be satisfied at .
-
Monitor constraint drift. Even with stabilization, check the original constraint at the end of integration.
Summary
Section titled “Summary”- The DAE index counts differentiations needed to reach ODE form.
- Numra supports index-1 DAEs natively with Radau5 and BDF.
- Higher-index DAEs require index reduction before solving.
- Baumgarte stabilization is the most practical technique: differentiate constraints and add damping to prevent drift.
- When possible, reformulate using minimal coordinates to avoid DAEs entirely.
- Always provide consistent initial conditions for the reduced system.