-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Description how to reproduce the bug
Design a simulation which uses sparse Jacobians and does not evaluate the Jacobian before running the simulation (for an example of such a simulation, see this Microgrid benchmark). The Jacobian will not be calculated correctly, and the linear solver in SUNDIALS will error, complaining about being configured incorrectly.
GridKit™ version
develop
System and environment details
N/A
Additional information
The reason for the bug is simple:
This commit changed the sparse linear solver configuration code in ida.cpp to no longer assume that there were n^2 non-zero elements in the jacobian. To do that, it calls (model_->getJacobian()).nnz() but getJacobian() must be called only after calling evaluateJacobian() (un-documented, but true).
The reason that this wasn't caught is because currently, the only simulations we have being tested using sparse Jacobians coincidentally all evaluate their Jacobian before running the simulation:
But...
- This shouldn't be a necessary step.
- Evaluating Jacobians before configuring the simulation isn't even enough - some (potentially) nonzero elements are squashed during Jacobian evaluation if the
alphacoefficient is set to 0, which it often is ifupdateTime()hasn't also been called beforehand. - The number of nonzero elements should probably be allowed to change during simulations - discrete events like faults can introduce new variables into the system.
Luckily, SUNDIALS has an interface for re-allocating sparse matrices, which we can call after evaluating the system Jacobian and realising there isn't enough space.
So the correct steps should probably be something along the lines of:
- When configuring the linear solver, allocate a small (maybe 0 sized if SUNDIALS lets us) jacobian matrix, and keep track of how much space it has for nonzero elements
- After evaluating a system jacobian, compare the number of nonzero elements it has and how much space the SUNDIALS matrix has - if they differ, then re-allocate the SUNDIALS matrix to fit
- Finally, copy the entries from the system Jacobian to the SUNDIALS matrix.
Eventually, the GridKit CSR matrix interface should also be able to handle this re-allocation automatically, without having to copy between two buffers.