MeshAnalysis

Struct MeshAnalysis 

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

Implementation of the mesh analysis algorithm for a nonlinear Network.

§Overview

This struct holds components (mainly conversion matrices and buffers) needed to perform a mesh analysis of a Network. The aforementioned conversion matrices are derived within the NetworkAnalysis::new method. They are then used within the NetworkAnalysis::solve method to try and solve the problem defined by the network, its excitation and resistances. An in-depth description of the solving process is given in lib module docstring.

To get an general overview over mesh analysis, please have a look at the corresponding [Wikipedia entry]((https://en.wikipedia.org/wiki/Mesh_analysis). Some advanced features such as e.g. custom Jacobians require an in-depth understanding of the method. It is therefore recommended to consult specialist literature such as [1].

In comparison to the closely related nodal analysis method, which is available via the [NodalAnalysis] struct, mesh analysis is especially well suited for networks with many nodes and few loops (i.e. many elements in serial) or with many voltage sources. The number of equations is equal to the number of meshes (MeshAnalysis::mesh_count).

§Examples

The docstring of NetworkAnalysis::solve as well as the lib module docstring show some examples on how to perform mesh analysis. Furthermore, a variety of examples is provided in the examples directory of the repository.

§Literature

  1. Schmidt, Lorenz-Peter; Schaller, Gerd; Martius, Siegfried: Grundlagen der Elektrotechnik 3 - Netzwerke. 1st edition (2006). Pearson, Munich

Implementations§

Source§

impl MeshAnalysis

Source

pub fn edge_to_mesh(&self) -> &DMatrix<f64>

Returns a matrix describing the coupling between the meshes and the equation system.

The mesh analysis method derives m system equations from the input matrix, where m is the number of meshes. Together with the n edges of the underlying Network, this results in a matrix m x n which directly describes the coupling between meshes and edges:

  • -1: Mesh direction is opposite to edge direction (as defined via source -> target).
  • 0: Edge is not part of the mesh.
  • 1: Mesh direction corresponds to edge direction.

Therefore, this matrix together with MeshAnalysis::edge_types describes the entire equation system of the mesh analysis.

Source

pub fn edge_to_mesh_resistance(&self) -> &DMatrix<Vec<f64>>

Returns a conversion matrix for calculating the mesh resistance matrix from the edge resistances.

This conversion matrix allows calculating the system matrix (the A in A * x = b). Each element of the conversion matrix is a vector whose length is either zero (if the mesh with the same index as the column has a current source) or equal to that of the edge resistance vector otherwise. Pairwise multiplication of this vector with the edge resistance vector and summing the resulting vector up returns the value of the corresponding system matrix element.

This means that the system matrix columns for meshes containing a current source contains only zeros. For further explanation, see [1], p. 62ff.

§Examples
use network_analysis::*;
use nalgebra::Matrix2;

/*
This creates the following network with a voltage source at 0
 ┌─[1]─┬─[2]─┐
[0]   [6]   [3]
 └─[5]─┴─[4]─┘
 */
let mut edges: Vec<EdgeListEdge> = Vec::new();
edges.push(EdgeListEdge::new(vec![5], vec![1], Type::Voltage));
edges.push(EdgeListEdge::new(vec![0], vec![2, 6], Type::Resistance));
edges.push(EdgeListEdge::new(vec![1, 6], vec![3], Type::Resistance));
edges.push(EdgeListEdge::new(vec![2], vec![4], Type::Resistance));
edges.push(EdgeListEdge::new(vec![3], vec![5, 6], Type::Resistance));
edges.push(EdgeListEdge::new(vec![4, 6], vec![0], Type::Resistance));
edges.push(EdgeListEdge::new(vec![1, 2], vec![4, 5], Type::Resistance));
let network = Network::from_edge_list_edges(&edges).expect("valid network");

/*
This network forms two meshes -> The conversion matrix is 2x2 and each element
is a vector of length 7 (since the matrix has seven edges)
 */
let mesh_analysis = MeshAnalysis::new(&network);
let conv = mesh_analysis.edge_to_mesh_resistance();
assert_eq!(conv.nrows(), 2);
assert_eq!(conv.ncols(), 2);
for elem in conv.iter() {
    assert_eq!(elem.len(), 7);
}

// Use the conversion matrix to calculate the system matrix
let edge_resistances = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
let mut system_matrix = Matrix2::from_element(0.0);
for (sys_elem, conv_vec) in system_matrix.iter_mut().zip(conv.iter()) {
    *sys_elem = conv_vec.iter().zip(edge_resistances.into_iter()).map(|(factor, edge_resistance)| factor * edge_resistance).sum();
}

// No current sources - matrix is symmetrical
assert_eq!(system_matrix[(0, 0)], 3.0);
assert_eq!(system_matrix[(0, 1)], -1.0);
assert_eq!(system_matrix[(1, 0)], -1.0);
assert_eq!(system_matrix[(1, 1)], 4.0);
§Literature
  1. Schmidt, Lorenz-Peter; Schaller, Gerd; Martius, Siegfried: Grundlagen der Elektrotechnik 3 - Netzwerke. 1st edition (2006). Pearson, Munich
Source

pub fn unknowns_to_edge_currents(&self) -> &DMatrix<f64>

Returns a conversion matrix from mesh to edge currents. This function is mainly meant to be used in custom Jacobian implementations.

As explained in the docstring of [JacobianFunctionSignature], a custom Jacobian function receives the mesh currents as an input argument. The matrix provided by this function can then be used to calculate the edge currents via matrix multiplication:

C * m = e, where C is this matrix, m is the mesh current vector and e is the edge current vector.

Source

pub fn mesh_count(&self) -> usize

Returns the number of meshes.

§Examples
use network_analysis::*;

/*
This creates the following network with a voltage source at 0
 ┌─[1]─┬─[2]─┐
[0]   [6]   [3]
 └─[5]─┴─[4]─┘
 */
let mut edges: Vec<EdgeListEdge> = Vec::new();
edges.push(EdgeListEdge::new(vec![5], vec![1], Type::Voltage));
edges.push(EdgeListEdge::new(vec![0], vec![2, 6], Type::Resistance));
edges.push(EdgeListEdge::new(vec![1, 6], vec![3], Type::Resistance));
edges.push(EdgeListEdge::new(vec![2], vec![4], Type::Resistance));
edges.push(EdgeListEdge::new(vec![3], vec![5, 6], Type::Resistance));
edges.push(EdgeListEdge::new(vec![4, 6], vec![0], Type::Resistance));
edges.push(EdgeListEdge::new(vec![1, 2], vec![4, 5], Type::Resistance));
let network = Network::from_edge_list_edges(&edges).expect("valid network");

let mesh_analysis = MeshAnalysis::new(&network);
assert_eq!(mesh_analysis.mesh_count(), 2);
Source

pub fn edge_count(&self) -> usize

Returns the number of edges of the underlying network.

§Examples
use network_analysis::*;

/*
This creates the following network with a voltage source at 0
 ┌─[1]─┬─[2]─┐
[0]   [6]   [3]
 └─[5]─┴─[4]─┘
 */
let mut edges: Vec<EdgeListEdge> = Vec::new();
edges.push(EdgeListEdge::new(vec![5], vec![1], Type::Voltage));
edges.push(EdgeListEdge::new(vec![0], vec![2, 6], Type::Resistance));
edges.push(EdgeListEdge::new(vec![1, 6], vec![3], Type::Resistance));
edges.push(EdgeListEdge::new(vec![2], vec![4], Type::Resistance));
edges.push(EdgeListEdge::new(vec![3], vec![5, 6], Type::Resistance));
edges.push(EdgeListEdge::new(vec![4, 6], vec![0], Type::Resistance));
edges.push(EdgeListEdge::new(vec![1, 2], vec![4, 5], Type::Resistance));
let network = Network::from_edge_list_edges(&edges).expect("valid network");

let mesh_analysis = MeshAnalysis::new(&network);
assert_eq!(mesh_analysis.edge_count(), 7);

Trait Implementations§

Source§

impl Clone for MeshAnalysis

Source§

fn clone(&self) -> MeshAnalysis

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MeshAnalysis

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl NetworkAnalysis for MeshAnalysis

Source§

fn new(network: &Network) -> Self

Create a new MeshAnalysis or NodalAnalysis instance from the given network. Since the network has already been checked during its creation, this operation is infallible.
Source§

fn solve<'a>( &'a mut self, resistances: Resistances<'_>, current_exc: CurrentSources<'_>, voltage_src: VoltageSources<'_>, initial_edge_resistances: Option<&[f64]>, initial_edge_currents: Option<&[f64]>, jacobian: Option<&mut (dyn for<'b> FnMut(JacobianData<'b>) + 'a)>, config: &SolverConfig, ) -> Result<Solution<'a>, SolveError>

Try to solve the network for the given excitations and resistances. Read more
Source§

fn edge_types(&self) -> &[Type]

Returns the edge types.

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.