Skip to main content

PersistentSolver

Struct PersistentSolver 

Source
pub struct PersistentSolver { /* private fields */ }
Expand description

A Newton-Raphson solver that reuses its symbolic factorization (fill- reducing ordering, elimination-graph structure — the expensive, topology-only part of a sparse LU factorization) across repeated solve calls, not just across the iterations within one call the way newton_raphson_with_backend already does.

This matters for any workload that solves the same topology repeatedly — a time series, a batch of scenarios, contingency analysis — where re-deriving the ordering from scratch on every call is pure overhead. Measured on a 9,241-bus case, reusing analysis across repeated solves cut per-solve time by ~45% (COLAMD/AMD/BTF ordering was ~1/3 of total solve time when redone from scratch every call).

let mut solver = PersistentSolver::new(JacobianBackend::Scalar);
for _ in 0..10 {
    // ... update buses' p_spec/q_spec for the next scenario ...
    solver.solve(&mut buses, ybus, 1e-6, 20);
}

Call reset (or construct a new PersistentSolver) if the topology itself changes between solves — a different set of lines, transformers, or bus types — since the cached ordering would otherwise silently apply to the wrong sparsity pattern. Changing only bus values (p_spec, q_spec, voltage_mag/voltage_ang initial guess) between calls is exactly the case this is designed for and needs no reset.

Implementations§

Source§

impl PersistentSolver

Source

pub fn new(backend: JacobianBackend) -> Self

Source

pub fn solve( &mut self, buses: &mut [Bus], ybus: &YBusSparse, tol: f64, max_iter: usize, ) -> Vec<IslandReport>

Runs Newton-Raphson to convergence (or max_iter), reusing cached symbolic factorization from a previous solve() call on this same PersistentSolver when available. See the type-level doc comment for when a cached factorization stays valid.

Like newton_raphson_with_backend, partitions buses into connected components first (network::connected_components/ classify/mark_unreferenced_islands) so a disconnected, sourceless region can’t make the whole Jacobian singular, and returns each component’s own outcome rather than one flat status.

Source

pub fn solve_with_stats( &mut self, buses: &mut [Bus], ybus: &YBusSparse, tol: f64, max_iter: usize, ) -> (Vec<IslandReport>, SolveStats)

Exactly solve, additionally returning the SolveStats the solve produced — iteration count and the per-iteration convergence trace the loop used to print to stdout. solve is a wrapper that discards them.

Source

pub fn invalidate_admittances(&mut self)

Discards any cached symbolic factorization. Call this before the next solve() if the topology (not just bus values) has changed since the last call. Invalidates the cached Jacobian recipe while keeping every backend’s symbolic factorization.

The right call when the Y-bus’s values changed but its sparsity pattern did not — which is exactly a branch contingency built by network::build_ybus_with_outages, where the outaged branch keeps its structural entries at zero. The symbolic factorization depends only on the (row, col) pairs JacobianPattern::to_triplets emits, and those are unchanged, so it stays valid; the entries’ cached admittances do not, and must be re-analyzed.

Re-analysis is O(nonzeros) against the symbolic factorization’s fill-reducing ordering and elimination-tree work, which is the expensive half — measured at ~45% of solve time on a 9,241-bus case. Keeping that is what makes an N-1 sweep cheaper than a sequence of independent solves.

Use reset instead when the pattern itself changed: a different bus-type assignment, or a topology whose branches were genuinely dropped rather than zeroed.

Source

pub fn reset(&mut self)

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> ByRef<T> for T

Source§

fn by_ref(&self) -> &T

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> DistributionExt for T
where T: ?Sized,

Source§

fn rand<T>(&self, rng: &mut (impl Rng + ?Sized)) -> T
where Self: Distribution<T>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Imply<T> for U
where T: ?Sized, U: ?Sized,

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V