This commit refactors the Dartu-Menezes-Pileggi (DMP) effective capacitance
algorithm solver to use the Eigen library, and implements a Determinant Guarded
solver to handle singular and near-singular Jacobians safely and efficiently.
Key changes:
1. Refactored the DMP solver to use Eigen stack-based data structures,
replacing the custom Crout LU decomposition and solver.
2. Extracted the linear solver logic into a dedicated helper function
DmpAlg::solveNewtonStep.
3. Implemented a "Determinant Guarded" solver:
- Manually checks the determinant of the Jacobian (safety guard).
- Throws a DmpError if the determinant is dangerously close to zero (|det| < 1e-12),
safely triggering the lumped capacitance fallback.
- Otherwise, solves using Eigen's highly optimized analytical inverse (fast path).
4. Added documentation in the comments on how to easily swap back to LU
decomposition with partial pivoting (PartialPivLU) if any numerical
precision issues arise in the future.
Benchmark Results (Optimized Release Build, 5,288 DMP calls):
| Test Case | Calls | 1. Original (Crout LU) | 2. Eigen (PartialPivLU) | 3. Eigen (Determinant Guarded) | Speedup (3 vs 1) | Speedup (3 vs 2) |
| :--- | :---: | :---: | :---: | :---: | :---: | :---: |
| power | 2,608 | 1.8822 ms | 1.6791 ms | 1.2702 ms | +32.5% | +24.4% |
| power_vcd | 2,608 | 1.8729 ms | 1.6704 ms | 1.2768 ms | +31.8% | +23.6% |
| spef_parasitics | 24 | 0.0193 ms | 0.0187 ms | 0.0140 ms | +27.5% | +25.1% |
| mcmm3 | 48 | 0.0728 ms | 0.0756 ms | 0.0817 ms | -12.2% | -8.1% |
| Total DMP Time | 5,288 | 3.8472 ms | 3.4438 ms | 2.6427 ms | +31.3% | +23.3% |