Fix bugs from 5-2 code review

This commit is contained in:
Sepehr
2026-02-21 10:43:55 +01:00
parent 400f1c420e
commit 0d9a0e4231
27 changed files with 9838 additions and 114 deletions

View File

@@ -23,7 +23,6 @@
use nalgebra::{DMatrix, DVector};
/// Wrapper around `nalgebra::DMatrix<f64>` for Jacobian operations.
///
/// The Jacobian matrix J represents the partial derivatives of the residual vector
@@ -142,11 +141,11 @@ impl JacobianMatrix {
// For square systems, use LU decomposition
if self.0.nrows() == self.0.ncols() {
let lu = self.0.clone().lu();
// Solve J·Δx = -r
let r_vec = DVector::from_row_slice(residuals);
let neg_r = -r_vec;
match lu.solve(&neg_r) {
Some(delta) => Some(delta.iter().copied().collect()),
None => {
@@ -162,10 +161,10 @@ impl JacobianMatrix {
self.0.nrows(),
self.0.ncols()
);
let r_vec = DVector::from_row_slice(residuals);
let neg_r = -r_vec;
// Use SVD for robust least-squares solution
let svd = self.0.clone().svd(true, true);
match svd.solve(&neg_r, 1e-10) {
@@ -283,10 +282,10 @@ impl JacobianMatrix {
pub fn condition_number(&self) -> Option<f64> {
let svd = self.0.clone().svd(false, false);
let singular_values = svd.singular_values;
let max_sv = singular_values.max();
let min_sv = singular_values.min();
if min_sv > 1e-14 {
Some(max_sv / min_sv)
} else {
@@ -310,7 +309,10 @@ impl JacobianMatrix {
/// - Row/col ranges are inclusive-start, exclusive-end: `row_start..row_end`.
///
/// # AC: #6
pub fn block_structure(&self, system: &crate::system::System) -> Vec<(usize, usize, usize, usize)> {
pub fn block_structure(
&self,
system: &crate::system::System,
) -> Vec<(usize, usize, usize, usize)> {
let n_circuits = system.circuit_count();
let mut blocks = Vec::with_capacity(n_circuits);
@@ -335,7 +337,7 @@ impl JacobianMatrix {
let col_start = *indices.iter().min().unwrap();
let col_end = *indices.iter().max().unwrap() + 1; // exclusive
// Equations mirror state layout for square systems
// Equations mirror state layout for square systems
let row_start = col_start;
let row_end = col_end;
@@ -583,7 +585,7 @@ mod tests {
let mut j = JacobianMatrix::zeros(2, 2);
j.set(0, 0, 5.0);
j.set(1, 1, 7.0);
assert_relative_eq!(j.get(0, 0).unwrap(), 5.0);
assert_relative_eq!(j.get(1, 1).unwrap(), 7.0);
assert_relative_eq!(j.get(0, 1).unwrap(), 0.0);
@@ -606,7 +608,7 @@ mod tests {
// r[0] = x0^2 + x0*x1
// r[1] = sin(x0) + cos(x1)
// J = [[2*x0 + x1, x0], [cos(x0), -sin(x1)]]
let state: Vec<f64> = vec![0.5, 1.0];
let residuals: Vec<f64> = vec![
state[0].powi(2) + state[0] * state[1],
@@ -623,13 +625,13 @@ mod tests {
// Analytical values
let j00 = 2.0 * state[0] + state[1]; // 2*0.5 + 1.0 = 2.0
let j01 = state[0]; // 0.5
let j10 = state[0].cos(); // cos(0.5)
let j11 = -state[1].sin(); // -sin(1.0)
let j01 = state[0]; // 0.5
let j10 = state[0].cos(); // cos(0.5)
let j11 = -state[1].sin(); // -sin(1.0)
assert_relative_eq!(j_num.get(0, 0).unwrap(), j00, epsilon = 1e-5);
assert_relative_eq!(j_num.get(0, 1).unwrap(), j01, epsilon = 1e-5);
assert_relative_eq!(j_num.get(1, 0).unwrap(), j10, epsilon = 1e-5);
assert_relative_eq!(j_num.get(1, 1).unwrap(), j11, epsilon = 1e-5);
}
}
}