Skip to content

added: NonLinModelDAE for differential and algebraic equations + sim! support - #442

Merged
franckgaga merged 72 commits into
mainfrom
dae_model
Sep 11, 2026
Merged

added: NonLinModelDAE for differential and algebraic equations + sim! support#442
franckgaga merged 72 commits into
mainfrom
dae_model

Conversation

@franckgaga

@franckgaga franckgaga commented Sep 10, 2026

Copy link
Copy Markdown
Member

The new SimModel type introduces the support of plant model expressed as differential and algebraic equation (DAE) systems. The API and the code base rely on the following notation (to avoid any confusions with the decision variable $\mathbf{Z}$ and the nonlinear inequality constraint $\mathbf{g}$):

$$\begin{aligned} \mathbf{\dot{x}}(t) &= \mathbf{f}\Big( \mathbf{x}(t), \mathbf{a}(t), \mathbf{u}(t), \mathbf{d}(t), \mathbf{p} \Big) \\\ \mathbf{0} &= \mathbf{q}\Big( \mathbf{x}(t), \mathbf{a}(t), \mathbf{u}(t), \mathbf{d}(t), \mathbf{p} \Big) \\\ \mathbf{y}(t) &= \mathbf{h}\Big( \mathbf{x}(t), \mathbf{a}(t), \mathbf{d}(t), \mathbf{p} \Big) \end{aligned}$$

Pure discrete-time DAEs are not supported for now. This PR added the functionalities for open-loop simulations of DAEs using collocation methods (TrapezoidalCollocation or OrthogonalCollocation). The following generic functions now support NonLinModelDAE objects:

  • evaloutput(model::NonLinModelDAE, d) -> y : solve the algebraic equation (if required, see below) and compute the current output $\mathbf{y}(k)$
  • updatestate!(model::NonLinModelDAE, u, d) -> xnext : solve the collocation problem and compute the next state $\mathbf{x}(k+1)$
  • getinfo(model::NonLinModelDAE) -> info : return information post-solving for troubleshooting, for example $\mathbf{a}(k)$
  • sim!(model::NonLinMidelDAE, N, u, <kw args>) -> res: quick open-loop simulations, similar other model types.

As described in #332 and the docstring, the open-loop simulation code base uses JuMP.jl, MOI.VectorNonlinearOracle and DifferentiationInterface.jl to solve the two nonlinear root problems of evalouput and updatestate!. They both use Ipopt.jl and dense ForwardDiff.jl Jacobians by default. Note that SparseConnectivityTracer.jl will analyze the system and return an error if it is not strictly proper. Also note that evaloutput will skip the algebraic equation solving if it is not required, according to SparseConnectivityTracer.jl.

To global goal here is to support plant model generated by acausal modeling tools like ModelingToolkit.jl, since they typically produces DAEs instead of ODEs. I still want to mention that ODEs are insanely simpler in terms of algorithmic complexity, so NonLinModel objects for ODEs should be used when possible to reduce the dimensions and complexity (thanks to multiple dispatch!).

Important

NonLinMPC and MovingHorizonEstimator do not support NonLinModelDAE objects for now.

Related to #332

There is no possible ambiguity in the camel-casing this way.
This is more consistent with julia base style
If it is a supertype it is necessarily abstract. It's more concise like this.
The continuity constraint is a linear constraint.
It will be consistent with upcoming `A0` and `Ā` vectors with the algebraic variables.
This is clearer like this since it's only in the `LinModel` case that the steady-state is computed.
This is not strictly needed to update the state, but it is still useful to compute it, for diagnosis (e.g. with `getinfo`). Otherwise this specific value is never explicitly computed.
Now `a0` is at the same position for `OC` and `TC`, to simplify the logic in `f!` method.
This computation is expensive so it's better to skip it if the provided `h!` argument is not a function of the algebraic variable.
@codecov-commenter

codecov-commenter commented Sep 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.07159% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.93%. Comparing base (4275fa7) to head (fad8cf5).
⚠️ Report is 81 commits behind head on main.

Files with missing lines Patch % Lines
src/model/nonlinmodeldae.jl 92.94% 23 Missing ⚠️
src/estimator/execute.jl 50.00% 2 Missing ⚠️
src/controller/execute.jl 80.00% 1 Missing ⚠️
src/model/linearization.jl 50.00% 1 Missing ⚠️
src/model/linmodel.jl 75.00% 1 Missing ⚠️
src/model/nonlinmodel.jl 66.66% 1 Missing ⚠️
src/sim_model.jl 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #442      +/-   ##
==========================================
- Coverage   97.17%   96.93%   -0.24%     
==========================================
  Files          27       28       +1     
  Lines        6270     6600     +330     
==========================================
+ Hits         6093     6398     +305     
- Misses        177      202      +25     
Flag Coverage Δ
unittests 96.93% <93.07%> (-0.24%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@franckgaga

Copy link
Copy Markdown
Member Author

The failling test on Win11 and LTS is unrelated. Seems to be an issue with and old manifest file and the cache on GitHub actions.

@franckgaga
franckgaga merged commit fc06e8b into main Sep 11, 2026
19 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants