LCOV - code coverage report
Current view: top level - ugbase/lib_algebra/small_algebra/no_lapack - lu_decomp.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 56 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 8 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2014:  G-CSC, Goethe University Frankfurt
       3              :  * Author: Martin Rupp
       4              :  * 
       5              :  * This file is part of UG4.
       6              :  * 
       7              :  * UG4 is free software: you can redistribute it and/or modify it under the
       8              :  * terms of the GNU Lesser General Public License version 3 (as published by the
       9              :  * Free Software Foundation) with the following additional attribution
      10              :  * requirements (according to LGPL/GPL v3 §7):
      11              :  * 
      12              :  * (1) The following notice must be displayed in the Appropriate Legal Notices
      13              :  * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
      14              :  * 
      15              :  * (2) The following notice must be displayed at a prominent place in the
      16              :  * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
      17              :  * 
      18              :  * (3) The following bibliography is recommended for citation and must be
      19              :  * preserved in all covered files:
      20              :  * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
      21              :  *   parallel geometric multigrid solver on hierarchically distributed grids.
      22              :  *   Computing and visualization in science 16, 4 (2013), 151-164"
      23              :  * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
      24              :  *   flexible software system for simulating pde based models on high performance
      25              :  *   computers. Computing and visualization in science 16, 4 (2013), 165-179"
      26              :  * 
      27              :  * This program is distributed in the hope that it will be useful,
      28              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      29              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      30              :  * GNU Lesser General Public License for more details.
      31              :  */
      32              : 
      33              : #ifndef __H__UG__CPU_ALGEBRA__LU_DECOMP_H__
      34              : #define __H__UG__CPU_ALGEBRA__LU_DECOMP_H__
      35              : 
      36              : #include "../small_matrix/densematrix.h"
      37              : #include "../small_matrix/densevector.h"
      38              : #include "../../common/operations.h"
      39              : 
      40              : #include <vector>
      41              : 
      42              : #ifndef LAPACK_AVAILABLE
      43              : 
      44              : namespace ug
      45              : {
      46              : 
      47              : template<typename matrix_t>
      48            0 : bool LUDecomp(DenseMatrix<matrix_t> &A, size_t *pInterchange)
      49              : {
      50              :         // LU Decomposition, IKJ Variant
      51              :         UG_ASSERT(A.num_rows() == A.num_cols(), "LU decomposition only for square matrices");
      52            0 :         if(A.num_rows() != A.num_cols()) return false;
      53              : 
      54              :         size_t n = A.num_rows();
      55              : 
      56            0 :         if(pInterchange)
      57              :         {
      58            0 :                 pInterchange[0] = 0;
      59            0 :                 for(size_t k=0; k<n; k++)
      60              :                 {
      61              :                         size_t biggest = k;
      62            0 :                         for(size_t j=k+1; j<n; j++)
      63            0 :                                 if(dabs(A(biggest, k)) < dabs(A(j,k)))
      64              :                                         biggest = j; // costly.
      65            0 :                         if(biggest != k)
      66            0 :                                 for(size_t j=0; j<n; j++)
      67              :                                         std::swap(A(k, j), A(biggest, j));
      68              : 
      69            0 :                         pInterchange[k] = biggest;
      70            0 :                         if(dabs(A(k,k)) < 1e-10)
      71              :                                 return false;
      72              : 
      73            0 :                         for(size_t i=k+1; i<n; i++)
      74              :                         {
      75            0 :                                 A(i,k) = A(i,k)/A(k,k);
      76            0 :                                 for(size_t j=k+1; j<n; j++)
      77            0 :                                         A(i,j) = A(i,j) - A(i,k)*A(k,j);
      78              :                         }
      79              :                 }
      80              :         }
      81              :         else
      82              :         {
      83            0 :                 for(size_t k=0; k<n; k++)
      84              :                 {
      85            0 :                         if(dabs(A(k,k)) < 1e-10)
      86              :                                 return false;
      87              : 
      88            0 :                         for(size_t i=k+1; i<n; i++)
      89              :                         {
      90            0 :                                 A(i,k) = A(i,k)/A(k,k);
      91            0 :                                 for(size_t j=k+1; j<n; j++)
      92            0 :                                         A(i,j) = A(i,j) - A(i,k)*A(k,j);
      93              :                         }
      94              :                 }
      95              :         }
      96              :         return true;
      97              : }
      98              : 
      99              : template<typename matrix_t>
     100              : bool LUDecompIKJ(DenseMatrix<matrix_t> &A, size_t *pInterchange)
     101              : {
     102              :         // LU Decomposition, IKJ Variant
     103              :         UG_ASSERT(A.num_rows() == A.num_cols(), "LU decomposition only for square matrices");
     104              :         if(A.num_rows() != A.num_cols()) return false;
     105              : 
     106              :         size_t n = A.num_rows();
     107              : 
     108              :         if(pInterchange)
     109              :         {
     110              :                 pInterchange[0] = 0;
     111              :                 for(size_t i=0; i < n; i++)
     112              :                 {
     113              :                         UG_LOG("i=" << i << ": \n")
     114              :                         size_t biggest = i;
     115              :                         UG_LOG("A(i,i) = " << A(i,i) << "\n");
     116              :                         for(size_t j=i+1; j<n; j++)
     117              :                         {
     118              :                                 UG_LOG("A(" << j << ", " << i << ")=" << A(j,i) << "\n");
     119              :                                 if(dabs(A(biggest, i)) < dabs(A(j,i))) biggest = j; // costly.
     120              :                         }
     121              :                         UG_LOG(biggest << " is biggest.");
     122              : 
     123              :                         if(biggest != i)
     124              :                                 for(size_t j=0; j<n; j++)
     125              :                                         std::swap(A(i, j), A(biggest, j));
     126              : 
     127              :                         pInterchange[i] = biggest;
     128              :                         if(dabs(A(i,i)) < 1e-10)
     129              :                                 return false;
     130              : 
     131              :                         // eliminate all entries A(i, k) with k<i with rows A(k, .) and k<i
     132              :                         for(size_t k=0; k<i; k++)
     133              :                         {
     134              :                                 // add row k to row i by A(i, .) -= A(k,.)  A(i,k) / A(k,k)
     135              :                                 // so that A(i,k) is zero (elements A(i, <k) are already "zero")
     136              :                                 // safe A(i,k)/A(k,k) in A(i,k)
     137              :                                 double a_ik = (A(i,k) /= A(k,k));
     138              : 
     139              :                                 for(size_t j=k+1; j<n; j++)
     140              :                                         A(i,j) -= A(k,j) * a_ik;
     141              :                         }
     142              :                 }
     143              :                 // P A = L R
     144              :         }
     145              :         else
     146              :         {
     147              :                 // for all rows
     148              :                 for(size_t i=0; i < n; i++)
     149              :                 {
     150              :                         if(dabs(A(i,i)) < 1e-10)
     151              :                                 return false;
     152              :                         // eliminate all entries A(i, k) with k<i with rows A(k, .) and k<i
     153              :                         for(size_t k=0; k<i; k++)
     154              :                         {
     155              :                                 // add row k to row i by A(i, .) -= A(k,.)  A(i,k) / A(k,k)
     156              :                                 // so that A(i,k) is zero (elements A(i, <k) are already "zero")
     157              :                                 // safe A(i,k)/A(k,k) in A(i,k)
     158              :                                 double a_ik = (A(i,k) /= A(k,k));
     159              : 
     160              :                                 for(size_t j=k+1; j<n; j++)
     161              :                                         A(i,j) -= A(k,j) * a_ik;
     162              :                         }
     163              :                 }
     164              :         }
     165              : 
     166              :         return true;
     167              : }
     168              : template<typename matrix_t, typename vector_t>
     169            0 : bool SolveLU(const DenseMatrix<matrix_t> &A, DenseVector<vector_t> &x, const size_t *pInterchange)
     170              : {
     171              :         size_t n=A.num_rows();
     172              : 
     173            0 :         if(pInterchange)
     174            0 :                 for(size_t i=0; i<n; i++)
     175            0 :                         if(i < pInterchange[i])
     176              :                                 std::swap(x[i], x[pInterchange[i]]);
     177              : 
     178              :         // LU x = b, -> U x = L^{-1} b
     179              :         // solve lower left
     180              :         double s;
     181            0 :         for(size_t i=0; i<n; i++)
     182              :         {
     183            0 :                 s = x[i];
     184            0 :                 for(size_t k=0; k<i; k++)
     185            0 :                         s -= A(i, k)*x[k];
     186            0 :                 x[i] = s;
     187              :         }
     188              : 
     189              :         // -> x = U^{-1} (L^{-1} b)
     190              :         // solve upper right
     191            0 :         for(size_t i=n-1; ; i--)
     192              :         {
     193            0 :                 s = x[i];
     194            0 :                 for(size_t k=i+1; k<n; k++)
     195            0 :                         s -= A(i, k)*x[k];
     196            0 :                 x[i] = s/A(i,i);
     197            0 :                 if(i==0) break;
     198              :         }
     199              : 
     200            0 :         return true;
     201              : }
     202              : 
     203              : 
     204              : ///////////////////////////////////////////////////////////////////////////////////////
     205              : /**
     206              :  * smallInverse<size_t n>
     207              :  * A class to hold a inverse of a smallMatrix<n>
     208              :  */
     209              : template<typename TStorage>
     210              : class DenseMatrixInverse
     211              : {
     212              : private: // storage
     213              :         DenseMatrix<TStorage> densemat;
     214              :         std::vector<size_t> interchange;
     215              : 
     216              : public:
     217              :         inline size_t num_cols() const
     218              :         {
     219              :                 return densemat.num_cols();
     220              :         }
     221              : 
     222              :         inline size_t num_rows() const
     223              :         {
     224              :                 return densemat.num_rows();
     225              :         }
     226              : 
     227            0 :         inline void resize(size_t k, size_t k2)
     228              :         {
     229            0 :                 UG_COND_THROW(k!=k2, "only square matrices supported");
     230            0 :                 resize(k);
     231            0 :         }
     232            0 :         inline void resize(size_t k)
     233              :         {
     234            0 :                 densemat.resize(k,k);
     235            0 :                 densemat = 0.0;
     236            0 :         }
     237              : 
     238              :         double &operator()(int r, int c)
     239              :         {
     240            0 :                 return densemat(r,c);
     241              :         }
     242              :         const double &operator()(int r, int c) const
     243              :         {
     244              :                 return densemat(r,c);
     245              :         }
     246              : public:
     247              :         //! initializes this object as inverse of mat
     248              :         bool set_as_inverse_of(const DenseMatrix<TStorage> &mat)
     249              :         {
     250              :                 UG_ASSERT(mat.num_rows() == mat.num_cols(), "only for square matrices");
     251            0 :                 densemat = mat;
     252            0 :                 return invert();
     253              :         }
     254              : 
     255            0 :         bool invert()
     256              :         {
     257            0 :                 interchange.resize(densemat.num_rows());
     258              : 
     259            0 :                 if(!interchange.empty()){
     260            0 :                         bool bLUDecomp = LUDecomp(densemat, &interchange[0]);
     261              : 
     262            0 :                         if(bLUDecomp!=true)
     263              :                         {
     264              :                                 UG_LOG("ERROR in 'DenseMatrixInverse::invert': Matrix is singular, "
     265              :                                                 "cannot calculate Inverse.\n");
     266              :                         }
     267              : 
     268            0 :                         return bLUDecomp;
     269              :                 }
     270              :                 else
     271              :                         return true;
     272              :         }
     273              : 
     274              :         template<typename vector_t>
     275              :         void apply(DenseVector<vector_t> &vec) const
     276              :         {
     277            0 :                 if(!interchange.empty())
     278            0 :                         SolveLU(densemat, vec, &interchange[0]);
     279              :         }
     280              : 
     281              :         // todo: implem
     282              : 
     283              :         // todo: implement operator *=
     284              : 
     285              :         template<typename T> friend std::ostream &operator << (std::ostream &out, const DenseMatrixInverse<T> &mat);
     286              : };
     287              : 
     288              : 
     289              : template<typename T>
     290              : std::ostream &operator << (std::ostream &out, const DenseMatrixInverse<T> &mat)
     291              : {
     292              :         out << "[ ";
     293              :         for(size_t r=0; r<mat.num_rows(); ++r)
     294              :         {
     295              :                 for(size_t c=0; c<mat.num_cols(); ++c)
     296              :                         out << mat.densemat(r, c) << " ";
     297              :                 if(r != mat.num_rows()-1) out << "| ";
     298              :         }
     299              :         out << "]";
     300              :         out << " (DenseMatrixInverse " << mat.num_rows() << "x" << mat.num_cols() << ", " << ((T::ordering == ColMajor) ? "ColMajor)" : "RowMajor)");
     301              : 
     302              :         return out;
     303              : }
     304              : 
     305              : 
     306              : template<typename T>
     307              : struct matrix_algebra_type_traits<DenseMatrixInverse<T> >
     308              : {
     309              :         static const int type = MATRIX_USE_GLOBAL_FUNCTIONS;
     310              : };
     311              : 
     312              : }  // namespace ug
     313              : 
     314              : #endif // not LAPACK_AVAILABLE
     315              : 
     316              : #endif // __H__UG__CPU_ALGEBRA__LU_DECOMP_H__
        

Generated by: LCOV version 2.0-1