Routines#

Logical predicates for arrays, matrices and reference frames.

sigmaepsilon.math.linalg.logical.has_full_column_rank(matrix: ndarray) bool[source]#

Return True if the input matrix has full column rank.

This means that all its columns are linearly independent.

sigmaepsilon.math.linalg.logical.has_full_rank(matrix: ndarray | MutableDenseMatrix) bool[source]#

Return True if the input matrix has full rank, False otherwise.

Parameters:

matrix (numpy.ndarray | sympy.Matrix) – The input matrix.

sigmaepsilon.math.linalg.logical.has_full_row_rank(matrix: ndarray) bool[source]#

Return True if the input matrix has full row rank.

This means that all its rows are linearly independent.

sigmaepsilon.math.linalg.logical.is_hermitian(arr: ndarray) bool[source]#

Return True if the input is a hermitian array.

sigmaepsilon.math.linalg.logical.is_independent_frame(axes: ndarray, tol: float = 0) bool[source]#

Return True if the base vectors of a frame are linearly independent.

Parameters:

axes (numpy.ndarray) – A matrix where the i-th row is the i-th basis vector.

sigmaepsilon.math.linalg.logical.is_normal_frame(axes: ndarray) bool[source]#

Return True if a frame is normal.

This means that its base vectors are all of unit length.

Parameters:

axes (numpy.ndarray) – A matrix where the i-th row is the i-th basis vector.

sigmaepsilon.math.linalg.logical.is_orthonormal_frame(axes: ndarray) bool[source]#

Return True if a frame is orthonormal.

Parameters:

axes (numpy.ndarray) – A matrix where the i-th row is the i-th basis vector.

sigmaepsilon.math.linalg.logical.is_pos_def(arr) bool[source]#

Return True if the input is positive definite.

sigmaepsilon.math.linalg.logical.is_pos_semidef(arr) bool[source]#

Return True if the input is positive semi definite.

sigmaepsilon.math.linalg.logical.is_rectangular_frame(axes: ndarray) bool[source]#

Return True if a frame is Cartesian.

Parameters:

axes (numpy.ndarray) – A matrix where the i-th row is the i-th basis vector.

Utility functions for reference frames, vectors, and matrix algebra.

sigmaepsilon.math.linalg.utils.Gram(axes: ndarray) ndarray[source]#

Return the Gram matrix of a frame.

Parameters:

axes (numpy.ndarray) – A matrix where the i-th row is the i-th basis vector.

sigmaepsilon.math.linalg.utils.cross(a: TensorLike | ArrayWrapper, b: TensorLike | ArrayWrapper, *args, frame: FrameLike = None, **kwargs) TensorLike | ndarray[source]#

Calculate the cross product of two vectors or one vector and a second order tensor.

The behaviour coincides with NumPy when all inputs are arrays and generalizes when they are not, but all inputs must be either all arrays or all tensors of some kind.

Parameters:
  • *args (Tuple, Optional) – Positional arguments forwarded to NumPy, if all input objects are arrays.

  • a (TensorLike or ArrayLike) – A tensor or an array.

  • b (TensorLike or ArrayLike) – A tensor or an array.

  • frame (FrameLike, Optional) – The target frame of the output. Only if all inputs are TensorLike. If not specified, the returned tensor migh be returned in an arbitrary frame, depending on the inputs. Default is None.

  • **kwargs (dict, Optional) – Keyword arguments forwarded to numpy.cross. As of NumPy version ‘1.22.4’, there are no keyword arguments for numpy.cross, this is to assure compliance with all future versions of numpy.

Returns:

An 1d or 2d array, or an 1d or 2d tensor, depending on the inputs.

Return type:

numpy.ndarray or TensorLike

References

https://mathworld.wolfram.com/CrossProduct.html

Examples

The cross product of two vectors results in a vector:

>>> from sigmaepsilon.math.linalg import ReferenceFrame, Vector, Tensor2
>>> from sigmaepsilon.math.linalg import cross
>>> import numpy as np
>>> frame = ReferenceFrame(np.eye(3))
>>> a = Vector(np.array([1., 0, 0]), frame=frame)
>>> b = Vector(np.array([0, 1., 0]), frame=frame)
>>> cross(a, b)
Array([0., 0., 1.])

The cross product of a second order tensor and a vector result a second order tensor:

>>> A = Tensor2(np.eye(3), frame=frame)
>>> cross(A, b)
Array([[ 0.,  0., -1.],
       [ 0.,  0.,  0.],
       [ 1.,  0.,  0.]])
sigmaepsilon.math.linalg.utils.dot(a: TensorLike | ArrayWrapper, b: TensorLike | ArrayWrapper, out: TensorLike | ArrayWrapper = None, frame: FrameLike = None, axes: list | tuple = None) TensorLike | ndarray | Number[source]#

Return the dot product (without complex conjugation) of two quantities.

The behaviour coincides with NumPy when all inputs are arrays and generalizes when they are not, but all inputs must be either all arrays or all tensors of some kind. The operation for tensors of order 1 and 2 have dedicated implementations, for higher order tensors it generalizes to tensor contraction along specified axes.

Parameters:
  • a (TensorLike or ArrayLike) – A tensor or an array.

  • b (TensorLike or ArrayLike) – A tensor or an array.

  • out (ArrayLike, Optional) – Output argument. This must have the exact kind that would be returned if it was not used. See numpy.dot for the details. Only if all inputs are ArrayLike. Default is None.

  • frame (FrameLike, Optional) – The target frame of the output. Only if all inputs are TensorLike. If not specified, the returned tensor migh be returned in an arbitrary frame, depending on the inputs. Default is None.

  • axes (tuple or list, Optional) – The indices along which contraction happens if any of the input tensors have a rank higher than 2. Default is None.

Returns:

An array or a tensor, depending on the inputs.

Return type:

TensorLike or numpy.ndarray or scalar

Notes

For general tensors, the current implementation has an upper limit considering the rank of the input tensors. The sum of the ranks of the input tensors plus the sum of contraction indices must be at most 26.

References

https://mathworld.wolfram.com/DotProduct.html

Examples

When working with NumPy arrays, the behaviour coincides with numpy.dot. To take the dot product of a 2nd order tensor and a vector, use it like this:

>>> from sigmaepsilon.math.linalg import ReferenceFrame, Vector, Tensor2
>>> from sigmaepsilon.math.linalg import dot
>>> import numpy as np
>>> frame = ReferenceFrame(np.eye(3))
>>> A = Tensor2(np.eye(3), frame=frame)
>>> v = Vector(np.array([1., 0, 0]), frame=frame)
>>> dot(A, v)
Array([1., 0., 0.])

For general tensors, you have to specify the axes along which contraction happens:

>>> from sigmaepsilon.math.linalg import Tensor
>>> A = Tensor(np.ones((3, 3, 3, 3)), frame=frame)  # a tensor of order 4
>>> B = Tensor(np.ones((3, 3, 3)), frame=frame)  # a tensor of order 3
>>> dot(A, B, axes=(0, 0)).rank
5
sigmaepsilon.math.linalg.utils.dual_frame(axes: ndarray) ndarray[source]#

Return the dual frame of the input.

Parameters:

axes (numpy.ndarray) – A matrix where the i-th row is the i-th basis vector.

sigmaepsilon.math.linalg.utils.generalized_inverse(matrix: ndarray) ndarray[source]#

Return the generalized inverse of the input matrix.

This is applicable in any of the following cases:

  1. The matrix is square and has full rank. In this case the returned matrix is the usual inverse.

  2. The matrix has more columns than rows and has full row rank. In this case the generalized right inverse is returned.

  3. The matrix has more rows than columns and has full column rank. In this case the generalized left inverse is returned.

sigmaepsilon.math.linalg.utils.generalized_left_inverse(matrix: ndarray) ndarray[source]#

Return the generalized left inverse.

\begin{equation} \left( \mathbf{A}^{T} \mathbf{A} \right)^{-1} \mathbf{A}^{T} \end{equation}
sigmaepsilon.math.linalg.utils.generalized_right_inverse(matrix: ndarray) ndarray[source]#

Return the generalized right inverse.

\begin{equation} \mathbf{A}^{T} \left( \mathbf{A} \mathbf{A}^{T} \right)^{-1} \end{equation}
sigmaepsilon.math.linalg.utils.inv(A: ndarray) ndarray[source]#

Return the inverse of a square matrix.

sigmaepsilon.math.linalg.utils.inv2x2(A) ndarray[source]#

Return the inverse of a 2x2 matrix.

sigmaepsilon.math.linalg.utils.inv3x3(A)[source]#

Return the inverse of a 3x3 matrix.

sigmaepsilon.math.linalg.utils.inv3x3_bulk(A) ndarray[source]#

Return the inverse of a stack of 3x3 matrices.

sigmaepsilon.math.linalg.utils.inv3x3_bulk2(A) ndarray[source]#

Return the inverse of a stack of 3x3 matrices (alternative implementation).

sigmaepsilon.math.linalg.utils.inv_sym_3x3(m: MutableDenseMatrix, as_adj_det=False) MutableDenseMatrix[source]#

Return the symbolic inverse of a 3x3 symmetric matrix.

Parameters:
  • m (sympy.Matrix) – A 3x3 symmetric symbolic matrix.

  • as_adj_det (bool, Optional) – If True, return the determinant and the adjugate of m separately, instead of the inverse. Default is False.

Returns:

The symbolic inverse of m, or a tuple of the determinant and the adjugate of m if as_adj_det is True.

Return type:

sympy.Matrix or tuple

sigmaepsilon.math.linalg.utils.linspace(start, stop, N) ndarray[source]#

Return N evenly spaced values (or points) between start and stop.

sigmaepsilon.math.linalg.utils.linspace1d(start, stop, N) ndarray[source]#

Return N evenly spaced scalar values between start and stop.

sigmaepsilon.math.linalg.utils.norm(A) float[source]#

Return the Euclidean norm of A.

sigmaepsilon.math.linalg.utils.norm2d(A) ndarray[source]#

Return the Euclidean norm of each row of A.

sigmaepsilon.math.linalg.utils.normalize(A) ndarray[source]#

Return A normalized by its Euclidean norm.

sigmaepsilon.math.linalg.utils.normalize2d(A) ndarray[source]#

Return each row of A normalized by its Euclidean norm.

sigmaepsilon.math.linalg.utils.normalize_frame(axes: ndarray) ndarray[source]#

Return the frame with normalized base vectors.

Parameters:

axes (numpy.ndarray) – A matrix where the i-th row is the i-th basis vector.

sigmaepsilon.math.linalg.utils.permutation_tensor(dim: int = 3) ndarray[source]#

Return the Levi-Civita pseudotensor for N dimensions as a NumPy array.

Parameters:

N (int, Optional) – The number of dimensions. Default is 3.

sigmaepsilon.math.linalg.utils.random_pos_semidef_matrix(N) ndarray[source]#

Return a random positive semidefinite matrix of shape (N, N).

Example

>>> from sigmaepsilon.math.linalg import random_pos_semidef_matrix, is_pos_semidef
>>> arr = random_pos_semidef_matrix(2)
>>> is_pos_semidef(arr)
True
sigmaepsilon.math.linalg.utils.random_posdef_matrix(N, alpha: float = 1e-12) ndarray[source]#

Return a random positive definite matrix of shape (N, N).

All eigenvalues of this matrix are >= alpha.

Example

>>> from sigmaepsilon.math.linalg import random_posdef_matrix, is_pos_def
>>> arr = random_posdef_matrix(2)
>>> is_pos_def(arr)
True
sigmaepsilon.math.linalg.utils.rotation_matrix(rot_type: str, amounts: Iterable, rot_order: str | int = '') ndarray[source]#

Return a rotation matrix.

Uses the mechanism provided by sympy.physics.vector.ReferenceFrame.orientnew.

Parameters:
  • rot_type (str) –

    The method used to generate the direction cosine matrix. Supported methods are:

    • 'Axis': simple rotations about a single common axis

    • 'DCM': for setting the direction cosine matrix directly

    • 'Body': three successive rotations about new intermediate

      axes, also called “Euler and Tait-Bryan angles”

    • 'Space': three successive rotations about the parent

      frames’ unit vectors

    • 'Quaternion': rotations defined by four parameters which

      result in a singularity free direction cosine matrix

  • amounts (Iterable) –

    Expressions defining the rotation angles or direction cosine matrix. These must match the rot_type. See examples below for details. The input types are:

    • 'Axis': 2-tuple (expr/sym/func, Vector)

    • 'DCM': Matrix, shape(3, 3)

    • 'Body': 3-tuple of expressions, symbols, or functions

    • 'Space': 3-tuple of expressions, symbols, or functions

    • 'Quaternion': 4-tuple of expressions, symbols, or

      functions

  • rot_order (str or int, Optional) – If applicable, the order of the successive of rotations. The string '123' and integer 123 are equivalent, for example. Required for 'Body' and 'Space'.

Returns:

A new ReferenceFrame object.

Return type:

ReferenceFrame

See also

sympy.physics.vector.ReferenceFrame.orientnew()

Example

Define a standard Cartesian frame and rotate it around axis ‘Z’ with 180 degrees:

>>> from sigmaepsilon.math.linalg.utils import rotation_matrix
>>> import numpy as np
>>> R = rotation_matrix('Space', [0, 0, np.pi], 'XYZ')
sigmaepsilon.math.linalg.utils.show_frame(dcm: ndarray, arr: ndarray) ndarray[source]#

Return the coordinates of a frame or stack of frames in a target frame.

The target frame is specified by one or several DCM matrices, dispatching to the appropriate implementation based on the shapes of dcm and arr.

sigmaepsilon.math.linalg.utils.show_vector(dcm: ndarray, arr: ndarray) ndarray[source]#

Return the coordinates of a single or multiple vectors in a frame.

The frame is specified by one or several DCM matrices. The function can handle the following scenarios:

  • a single (1d) vector and a single (2d) dcm matrix (trivial case)

  • a stack of vectors (2d) and a single (2d) dcm matrix

  • a stack of fectors (2d) and dcm matrices for each vector in the stack (3d)

Added in version 1.0.5.

Parameters:
  • dcm (numpy.ndarray) – The dcm matrix of the transformation as a 2d or 3d float array.

  • arr (numpy.ndarray) – 1d or 2d float array of coordinates of a single vector. If it is 2d, then it is assumed that the coordinates of the i-th vector are accessible as arr[i].

Returns:

The new coordinates with the same shape as arr.

Return type:

numpy.ndarray

sigmaepsilon.math.linalg.utils.unit_basis_vector(length: int, index: int = 0, value: float = 1.0) ndarray[source]#

Return a unit basis vector.

The vector has length length with a value of value at the index index.

sigmaepsilon.math.linalg.utils.vpath(p1: ndarray, p2: ndarray, n: int) ndarray[source]#

Return n points along the straight line connecting p1 and p2.