Source code for edelweissfe.numerics.vijsystemmatrix

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#  ---------------------------------------------------------------------
#
#  _____    _      _              _         _____ _____
# | ____|__| | ___| |_      _____(_)___ ___|  ___| ____|
# |  _| / _` |/ _ \ \ \ /\ / / _ \ / __/ __| |_  |  _|
# | |__| (_| |  __/ |\ V  V /  __/ \__ \__ \  _| | |___
# |_____\__,_|\___|_| \_/\_/ \___|_|___/___/_|   |_____|
#
#
#  Unit of Strength of Materials and Structural Analysis
#  University of Innsbruck,
#  2017 - today
#
#  Matthias Neuner matthias.neuner@uibk.ac.at
#
#  This file is part of EdelweissFE.
#
#  This library is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2.1 of the License, or (at your option) any later version.
#
#  The full text of the license can be found in the file LICENSE.md at
#  the top level directory of EdelweissFE.
#  ---------------------------------------------------------------------

import numpy as np


[docs] class VIJSystemMatrix(np.ndarray): """ Represents the value vector `V` of a COO (VIJ triple) sparse matrix. `VIJSystemMatrix` stores matrix entry values for sparse global systems (Coordinate format), maintaining associated row indices `I`, column indices `J`, and an `entitiesInVIJ` mapping. It supports entity-aware indexing to slice, reshape, and assign local entity matrices directly. Parameters ---------- nDof : int The dimension (number of rows/columns) of the system matrix. I : ndarray The 1D integer array of global row indices. J : ndarray The 1D integer array of global column indices. entitiesInVIJ : dict A dictionary mapping entities to their starting offset index in `V`. """ def __new__(cls, nDof: int, I: np.ndarray, J: np.ndarray, entitiesInVIJ: dict): # noqa: E741 obj = np.zeros_like(I, dtype=float).view(cls) obj.nDof = nDof obj.I = I # noqa: E741 obj.J = J obj.entitiesInVIJ = entitiesInVIJ return obj def __array_finalize__(self, obj): if obj is None: return self.nDof = getattr(obj, "nDof", None) self.I = getattr(obj, "I", None) # noqa: E741 self.J = getattr(obj, "J", None) # noqa: E741 self.entitiesInVIJ = getattr(obj, "entitiesInVIJ", None) def __getitem__(self, key): """ Get value(s) or shaped entity matrix slice. Parameters ---------- key : int, slice, np.ndarray, list, tuple, or entity Standard array index/slice or entity instance. Returns ------- ndarray or float Sub-array or shaped entity matrix view. """ if isinstance(key, (int, slice, np.ndarray, list, tuple)): return super().__getitem__(key) if self.entitiesInVIJ is not None: try: idxInVIJ = self.entitiesInVIJ[key] size = key.getVIJContributionSize() flat_view = super().__getitem__(slice(idxInVIJ, idxInVIJ + size)) return key.shapeVIJContribution(flat_view) except (KeyError, TypeError, AttributeError): pass return super().__getitem__(key) def __setitem__(self, key, value): """ Set value(s) in the system matrix. Parameters ---------- key : int, slice, np.ndarray, list, tuple, or entity Standard array index/slice or entity instance. value : array_like or float Value(s) to assign. """ if isinstance(key, (int, slice, np.ndarray, list, tuple)): super().__setitem__(key, value) return if self.entitiesInVIJ is not None: try: idxInVIJ = self.entitiesInVIJ[key] size = key.getVIJContributionSize() super().__setitem__(slice(idxInVIJ, idxInVIJ + size), value) return except (KeyError, TypeError, AttributeError): pass super().__setitem__(key, value)
[docs] def copy(self, order: str = "C") -> "VIJSystemMatrix": """ Create a copy of this VIJSystemMatrix. Parameters ---------- order : str, optional The memory layout order ('C' for C-contiguous, 'F' for Fortran-contiguous). Default is 'C'. Returns ------- VIJSystemMatrix A new `VIJSystemMatrix` instance with copied values and metadata. """ new_mat = super().copy(order).view(VIJSystemMatrix) new_mat.nDof = self.nDof if self.I is not None: new_mat.I = self.I.copy() # noqa: E741 if self.J is not None: new_mat.J = self.J.copy() if self.entitiesInVIJ is not None: new_mat.entitiesInVIJ = self.entitiesInVIJ.copy() return new_mat