Source code for animate.math

import numpy as np
import ufl
import ufl.core.expr

__all__ = ["gram_schmidt", "construct_basis"]


[docs] def gram_schmidt(*vectors, normalise=False): """ Given some vectors, construct an orthogonal basis using Gram-Schmidt orthogonalisation. :args vectors: the vectors to orthogonalise :kwargs normalise: do we want an orthonormal basis? """ if isinstance(vectors[0], np.ndarray): expected = np.ndarray dot = np.dot sqrt = np.sqrt else: expected = ufl.core.expr.Expr dot = ufl.dot sqrt = ufl.sqrt # Check that vector types match for vi in vectors[1:]: if not isinstance(vi, expected): raise TypeError( f"Inconsistent vector types: '{expected}' vs. '{type(vi)}'." ) def proj(x, y): return dot(x, y) / dot(x, x) * x # Apply Gram-Schmidt algorithm u = [] for i, vi in enumerate(vectors): if i > 0: vi -= sum([proj(uj, vi) for uj in u]) u.append(vi / sqrt(dot(vi, vi)) if normalise else vi) # Ensure consistency of outputs if isinstance(vectors[0], np.ndarray): u = [np.array(ui) for ui in u] return u
[docs] def construct_basis(vector, normalise=True): """ Construct a basis from a given vector. :arg vector: the starting vector :kwargs normalise: do we want an orthonormal basis? """ is_numpy = isinstance(vector, np.ndarray) if is_numpy: if len(vector.shape) > 1: raise ValueError( f"Expected a vector, got an array of shape {vector.shape}." ) as_vector = np.array dim = vector.shape[0] else: if not isinstance(vector, ufl.core.expr.Expr): raise TypeError(f"Expected UFL Expr, not '{type(vector)}'.") as_vector = ufl.as_vector dim = ufl.domain.extract_unique_domain(vector).topological_dimension() if dim not in (2, 3): raise ValueError(f"Dimension {dim} not supported.") vectors = [vector] # Generate some arbitrary vectors and apply Gram-Schmidt if dim == 2: vectors.append(as_vector((-vector[1], vector[0]))) else: vectors.append(as_vector((vector[1], vector[2], vector[0]))) vectors.append(as_vector((vector[2], vector[0], vector[1]))) # TODO: Account for the case where all three components match (#129) return gram_schmidt(*vectors, normalise=normalise)