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 : }