Skip to main content

BatchSolver

Struct BatchSolver 

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

Solves many scenarios over one shared topology, in parallel.

let scenarios: Vec<Scenario> = (0..256)
    .map(|k| Scenario::new(vec![BusOverride::new(3).p(-0.1 * k as f64)]))
    .collect();
let batch = BatchSolver::new(JacobianBackend::KluNative);
let reports = batch.solve(&buses, ybus, &scenarios, 1e-6, 20).unwrap();
assert_eq!(reports.len(), 256);

Implementations§

Source§

impl BatchSolver

Source

pub fn new(backend: JacobianBackend) -> Self

Uses rayon’s global thread pool (honors RAYON_NUM_THREADS).

Source

pub fn with_threads( backend: JacobianBackend, threads: usize, ) -> Result<Self, BatchError>

Uses a dedicated pool of exactly threads workers. Built once here and reused by every solve call, so repeated batches never pay thread-creation cost.

Source

pub fn threads(&self) -> usize

Workers this solver will use for a batch.

Source

pub fn solve( &self, buses_template: &[Bus], ybus: &YBusSparse, scenarios: &[Scenario], tol: f64, max_iter: usize, ) -> Result<Vec<PowerFlowReport>, BatchError>

Solves every scenario and returns one PowerFlowReport each, in scenario order regardless of thread count.

Each scenario starts from buses_template with its overrides applied and a fresh linear_initial_guess, so scenarios never influence each other’s starting point — results are identical to a sequential loop over PersistentSolver::solve, which tests/batch_solver_test.rs asserts directly.

A scenario that fails to converge is not an error: its report carries SolveStatus::MaxIterationsReached/Singular and the rest of the batch is unaffected. Divergent contingency scenarios are normal and must not poison the batch.

Source

pub fn solve_contingencies( &self, buses_template: &[Bus], lines: &[Line], transformers: &[Transformer], shunts: &[ShuntAdm], scenarios: &[Scenario], tol: f64, max_iter: usize, ) -> Result<Vec<PowerFlowReport>, BatchError>

Solves every scenario honoring Scenario::branch_outages, returning one PowerFlowReport each in scenario order.

Takes branch lists rather than a finished Y-bus, because an outage changes the network rather than its bus values, and a Y-bus has already summed the branches away.

§Two paths, and why

Most contingencies leave the network connected. Those take the fast path: network::build_ybus_with_outages rebuilds the Y-bus with the outaged branches contributing nothing but keeping their structural entries, so the sparsity pattern — and therefore jacobian::JacobianPattern and the symbolic factorization behind it — is bit-for-bit the intact network’s. A worker reuses one PersistentSolver across every such scenario it handles, exactly as solve does for injection-only batches. That is what this method exists to make possible, and it is why the old “an outage forces its own sparsity pattern” objection turns out to be avoidable in the common case.

A contingency that splits the network cannot use that trick: connected_components reads the same structural entries and cannot tell a zero-valued one from a live one, so it would report the severed buses as still connected and their now-referenceless rows would come back as a singular solve instead of an honest NoReferenceBus. Those scenarios are detected up front with structural_component_count — removing branches can only increase the component count, so a count above the intact network’s is exactly the “something split” condition — and take a slow path: the outaged branches are dropped outright and the worker’s solver is reset around that scenario, since its pattern genuinely differs.

A scenario that fails to converge is not an error: its report carries the failure and the rest of the batch is unaffected. Islanding into a sourceless region is not a failure at all — that island comes back IslandStatus::NoReferenceBus, which for N-1 screening is a result.

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