LCOV - code coverage report
Current view: top level - src/utils - MatrixTools.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 35 39 89.7 %
Date: 2025-07-17 01:28:37 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "MatrixTools.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "Conversion.h"
      14             : #include "MooseError.h"
      15             : #include "MooseException.h"
      16             : 
      17             : // PETSc includes
      18             : #include "petscblaslapack.h"
      19             : 
      20             : namespace MatrixTools
      21             : {
      22             : void
      23           5 : inverse(const std::vector<std::vector<Real>> & m, std::vector<std::vector<Real>> & m_inv)
      24             : {
      25           5 :   unsigned int n = m.size();
      26             : 
      27             :   // check the matrix m exists and is square
      28           5 :   if (n == 0)
      29           1 :     throw MooseException("Input matrix empty during matrix inversion.");
      30           4 :   if (n != m_inv.size() || n != m[0].size() || n != m_inv[0].size())
      31           1 :     throw MooseException("Input and output matrix are not same size square matrices.");
      32             : 
      33             :   // build the vectorial representation
      34           3 :   std::vector<PetscScalar> A;
      35          11 :   for (const auto & rowvec : m)
      36          30 :     for (const auto & matrix_entry : rowvec)
      37          22 :       A.push_back(matrix_entry);
      38             : 
      39           3 :   inverse(A, n);
      40             : 
      41             :   // build the inverse
      42           2 :   unsigned int i = 0;
      43           7 :   for (auto & rowvec : m_inv)
      44          18 :     for (auto & inv_entry : rowvec)
      45          13 :       inv_entry = A[i++];
      46           3 : }
      47             : 
      48             : void
      49           9 : inverse(std::vector<PetscScalar> & A, unsigned int n)
      50             : {
      51             :   mooseAssert(n >= 1, "MatrixTools::inverse - n (leading dimension) needs to be positive");
      52             :   mooseAssert(n <= std::numeric_limits<unsigned int>::max(),
      53             :               "MatrixTools::inverse - n (leading dimension) too large");
      54             : 
      55           9 :   std::vector<PetscBLASInt> ipiv(n);
      56           9 :   std::vector<PetscScalar> buffer(n * 64);
      57             : 
      58             :   // Following does a LU decomposition of "square matrix A"
      59             :   // upon return "A = P*L*U" if return_value == 0
      60             :   // Here I use quotes because A is actually an array of length n^2, not a matrix of size n-by-n
      61             :   PetscBLASInt return_value;
      62           9 :   LAPACKgetrf_(reinterpret_cast<PetscBLASInt *>(&n),
      63             :                reinterpret_cast<PetscBLASInt *>(&n),
      64           9 :                &A[0],
      65             :                reinterpret_cast<PetscBLASInt *>(&n),
      66           9 :                &ipiv[0],
      67             :                &return_value);
      68             : 
      69           9 :   if (return_value != 0)
      70           2 :     throw MooseException(
      71           2 :         return_value < 0
      72           8 :             ? "Argument " + Moose::stringify(-return_value) +
      73             :                   " was invalid during LU factorization in MatrixTools::inverse."
      74           4 :             : "Matrix on-diagonal entry " + Moose::stringify(return_value) +
      75           4 :                   " was exactly zero during LU factorization in MatrixTools::inverse.");
      76             : 
      77             :   // get the inverse of A
      78           7 :   PetscBLASInt buffer_size = buffer.size();
      79           7 :   LAPACKgetri_(reinterpret_cast<PetscBLASInt *>(&n),
      80           7 :                &A[0],
      81             :                reinterpret_cast<PetscBLASInt *>(&n),
      82           7 :                &ipiv[0],
      83           7 :                &buffer[0],
      84             :                &buffer_size,
      85             :                &return_value);
      86             : 
      87           7 :   if (return_value != 0)
      88           0 :     throw MooseException(return_value < 0
      89           0 :                              ? "Argument " + Moose::stringify(-return_value) +
      90             :                                    " was invalid during invert in MatrixTools::inverse."
      91           0 :                              : "Matrix on-diagonal entry " + Moose::stringify(return_value) +
      92           0 :                                    " was exactly zero during invert in MatrixTools::inverse.");
      93          11 : }
      94             : }

Generated by: LCOV version 1.14