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

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2010-2015:  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__SPARSEMATRIX_UTIL__
      34              : #define __H__UG__CPU_ALGEBRA__SPARSEMATRIX_UTIL__
      35              : 
      36              : #include "common/profiler/profiler.h"
      37              : #include "unsorted_sparse_vector.h"
      38              : #include "../small_algebra/small_algebra.h"
      39              : 
      40              : #ifdef UG_PARALLEL
      41              : #include "pcl/pcl.h"
      42              : #include "lib_algebra/parallelization/parallel_matrix.h"
      43              : #include "lib_algebra/parallelization/parallel_vector.h"
      44              : #endif
      45              : 
      46              : namespace ug
      47              : {
      48              : 
      49              : /// \addtogroup lib_algebra
      50              : ///     @{
      51              : 
      52              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
      53              : // CreateAsMultiplyOf:
      54              : //-------------------------
      55              : /**
      56              :  * \brief Calculates M = A*B*C.
      57              :  * \param M (out) Matrix M, M = A*B*C$
      58              :  * \param A (in) Matrix A
      59              :  * \param B (in) Matrix B
      60              :  * \param C (in) Matrix C
      61              :  *
      62              :  * Complete formula for calculating M=A*B*C:
      63              :  *  \f[
      64              :  *       M_{ij} = \sum_{kl} A_{ik} * B_{kl} * C_{lj}
      65              :  *  \f]
      66              :  * Calculation is done on row-basis without
      67              :  * a temporary BC or AB matrix. This has shown to be much faster than
      68              :  * implementations with temporary matrices due to cache effects.
      69              :  * We also added an improved way of storing the results of the calculation:
      70              :  *  when we go through connections of B and C and want to add the connection
      71              :  *  (i, j) to M, we need to know if this connection already exists. For this we have
      72              :  *  an array posInConnections, needs n=A.num_rows() memory.
      73              :  *  posInConnections[i]: index in the connections for current row (if not in row: -1)
      74              :  *  tried this also with std::map, but took 1511.53 ms instead of 393.972 ms
      75              :  *  searching in the connections array is also slower
      76              :  */
      77              : template<typename ABC_type, typename A_type, typename B_type, typename C_type>
      78              : void CreateAsMultiplyOf(ABC_type &M, const A_type &A, const B_type &B, const C_type &C, double epsilonTruncation=0.0)
      79              : {
      80              :         PROFILE_FUNC_GROUP("algebra");
      81              :         UG_ASSERT(C.num_rows() == B.num_cols() && B.num_rows() == A.num_cols(), "sizes must match");
      82              : 
      83              :         // create output matrix M
      84              :         M.resize_and_clear(A.num_rows(), C.num_cols());
      85              : 
      86              : 
      87              :         typename block_multiply_traits<typename A_type::value_type, typename B_type::value_type>::ReturnType ab;
      88              : 
      89              :         typedef UnsortedSparseVector<typename ABC_type::value_type> RowType;
      90              :         typedef typename RowType::iterator RowIterator;
      91              :         RowType row(C.num_cols());;
      92              : 
      93              :         std::vector<typename ABC_type::connection> con2;
      94              :         //typename C_type::value_type cvalue;
      95              : 
      96              :         typename ABC_type::connection c;
      97              : 
      98              :         typedef typename A_type::const_row_iterator cAiterator;
      99              :         typedef typename B_type::const_row_iterator cBiterator;
     100              :         typedef typename C_type::const_row_iterator cCiterator;
     101              : 
     102              :         // do
     103              :         // M_{ij} = \sum_kl A_{ik} * B_{kl} * C_{lj}
     104              :         for(size_t i=0; i < A.num_rows(); i++)
     105              :         {
     106              :                 row.clear();
     107              :                 cAiterator itAikEnd = A.end_row(i);
     108              :                 for(cAiterator itAik = A.begin_row(i); itAik != itAikEnd; ++itAik)
     109              :                 {
     110              :                         if(itAik.value() == 0.0) continue;
     111              : 
     112              :                         size_t k = itAik.index();
     113              :                         cBiterator itBklEnd = B.end_row(k);
     114              :                         for(cBiterator itBkl = B.begin_row(k); itBkl != itBklEnd; ++itBkl)
     115              :                         {
     116              :                                 if(itBkl.value() == 0.0) continue;
     117              :                                 size_t l = itBkl.index();
     118              :                                 // ab = A_{ik} * B_{kl}
     119              :                                 AssignMult(ab, itAik.value(), itBkl.value());
     120              : 
     121              :                                 cCiterator itCljEnd = C.end_row(l);
     122              :                                 for(cCiterator itClj = C.begin_row(l); itClj != itCljEnd; ++itClj)
     123              :                                 {
     124              :                                         if(itClj.value() == 0.0) continue;
     125              :                                         AddMult( row (itClj.index() ), ab, itClj.value());
     126              :                                 }
     127              :                         }
     128              :                 }
     129              : 
     130              :                 if(epsilonTruncation != 0.0)
     131              :                 {
     132              :                         double m=0;
     133              :                         for(RowIterator it = row.begin(); it != row.end(); ++it)
     134              :                         {
     135              :                                 double d = BlockNorm(it->value());
     136              :                                 if(d > m) m = d;
     137              :                         }
     138              :                         m *= epsilonTruncation;
     139              :                         con2.clear();
     140              :                         for(RowIterator it = row.begin(); it != row.end(); ++it)
     141              :                                 if( BlockNorm(it->value()) > m )
     142              :                                         con2.push_back(*it);
     143              :                         M.set_matrix_row(i, &con2[0], con2.size());
     144              :                 }
     145              :                 else
     146              :                         M.set_matrix_row(i, row.unsorted_raw_ptr(), row.num_connections());
     147              :         }
     148              : 
     149              : }
     150              : 
     151              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     152              : // AddMultiplyOf:
     153              : //-------------------------
     154              : /**
     155              :  * \brief Calculates M += A*B*C.
     156              :  * \param M (in/out) Matrix M, M += A*B*C$
     157              :  * \param A (in) Matrix A
     158              :  * \param B (in) Matrix B
     159              :  * \param C (in) Matrix C
     160              :  *
     161              :  * Complete formula for calculating M=A*B*C:
     162              :  *  \f[
     163              :  *       M_{ij} += \sum_{kl} A_{ik} * B_{kl} * C_{lj}
     164              :  *  \f]
     165              :  */
     166              : template<typename ABC_type, typename A_type, typename B_type, typename C_type>
     167            0 : void AddMultiplyOf(ABC_type &M, const A_type &A, const B_type &B, const C_type &C, double epsilonTruncation=0.0)
     168              : {
     169              :         PROFILE_FUNC_GROUP("algebra");
     170              :         UG_ASSERT(C.num_rows() == B.num_cols(), "sizes must match: nRows(C) =" << C.num_rows()<<"!="<< B.num_cols() <<"=Cols(B)");
     171              :         UG_ASSERT(B.num_rows() == A.num_cols(), "sizes must match: nRows(B) =" << B.num_rows()<<"!="<< A.num_cols() <<"=nCols(A)");
     172              : 
     173              :         // check
     174            0 :         if(M.num_rows() != A.num_rows())
     175            0 :                 UG_THROW("AddMultiplyOf: row sizes mismatch: M.num_rows = "<<
     176              :                          M.num_rows()<<", A.num_rows = "<<A.num_rows());
     177            0 :         if(M.num_cols() != C.num_cols())
     178            0 :                 UG_THROW("AddMultiplyOf: column sizes mismatch: M.num_cols = "<<
     179              :                          M.num_cols()<<", C.num_cols = "<<C.num_cols());
     180              : 
     181              :         typename block_multiply_traits<typename A_type::value_type, typename B_type::value_type>::ReturnType ab;
     182              : 
     183              :         typedef UnsortedSparseVector<typename ABC_type::value_type> RowType;
     184              :         typedef typename RowType::iterator RowIterator;
     185            0 :         RowType row(C.num_cols());;
     186              : 
     187              :         std::vector<typename ABC_type::connection> con2;
     188              :         //typename C_type::value_type cvalue;
     189              : 
     190              :         typename ABC_type::connection c;
     191              : 
     192              :         typedef typename A_type::const_row_iterator cAiterator;
     193              :         typedef typename B_type::const_row_iterator cBiterator;
     194              :         typedef typename C_type::const_row_iterator cCiterator;
     195              : 
     196              :         // do
     197              :         // M_{ij} = \sum_kl A_{ik} * B_{kl} * C_{lj}
     198            0 :         for(size_t i=0; i < A.num_rows(); i++)
     199              :         {
     200            0 :                 row.clear();
     201              :                 cAiterator itAikEnd = A.end_row(i);
     202            0 :                 for(cAiterator itAik = A.begin_row(i); itAik != itAikEnd; ++itAik)
     203              :                 {
     204            0 :                         if(itAik.value() == 0.0) continue;
     205              : 
     206              :                         size_t k = itAik.index();
     207              :                         cBiterator itBklEnd = B.end_row(k);
     208            0 :                         for(cBiterator itBkl = B.begin_row(k); itBkl != itBklEnd; ++itBkl)
     209              :                         {
     210            0 :                                 if(itBkl.value() == 0.0) continue;
     211              :                                 size_t l = itBkl.index();
     212              :                                 // ab = A_{ik} * B_{kl}
     213            0 :                                 AssignMult(ab, itAik.value(), itBkl.value());
     214              : 
     215              :                                 cCiterator itCljEnd = C.end_row(l);
     216            0 :                                 for(cCiterator itClj = C.begin_row(l); itClj != itCljEnd; ++itClj)
     217              :                                 {
     218            0 :                                         if(itClj.value() == 0.0) continue;
     219            0 :                                         AddMult( row (itClj.index() ), ab, itClj.value());
     220              :                                 }
     221              :                         }
     222              :                 }
     223              : 
     224            0 :                 if(epsilonTruncation != 0.0)
     225              :                 {
     226              :                         double m=0;
     227            0 :                         for(RowIterator it = row.begin(); it != row.end(); ++it)
     228              :                         {
     229            0 :                                 double d = BlockNorm(it->value());
     230            0 :                                 if(d > m) m = d;
     231              :                         }
     232            0 :                         m *= epsilonTruncation;
     233              :                         con2.clear();
     234            0 :                         for(RowIterator it = row.begin(); it != row.end(); ++it)
     235            0 :                                 if( BlockNorm(it->value()) > m )
     236            0 :                                         con2.push_back(*it);
     237            0 :                         M.add_matrix_row(i, &con2[0], con2.size());
     238              :                 }
     239              :                 else
     240            0 :                         M.add_matrix_row(i, row.unsorted_raw_ptr(), row.num_connections());
     241              :         }
     242              : 
     243            0 : }
     244              : 
     245              : 
     246              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     247              : // CreateAsMultiplyOf:
     248              : //-------------------------
     249              : /**
     250              :  * \brief Calculates M = A*B.
     251              :  * \param M (out) Matrix M, M = A*B$
     252              :  * \param A (in) Matrix A
     253              :  * \param B (in) Matrix B
     254              :  * \f$ M_{ij} = \sum_k A_{ik} * B_{kj} \f$
     255              :  * For implementation details, see also CreateAsMultiplyOf(M, A, B, C).
     256              :  */
     257              : template<typename AB_type, typename A_type, typename B_type>
     258              : void CreateAsMultiplyOf(AB_type &M, const A_type &A, const B_type &B)
     259              : {
     260              :         PROFILE_FUNC_GROUP("algebra");
     261              :         UG_ASSERT(B.num_rows() == A.num_cols(), "sizes must match");
     262              : 
     263              :         // create output matrix M
     264              :         M.resize_and_clear(A.num_rows(), B.num_cols());
     265              : 
     266              :         // types
     267              :         typedef typename A_type::const_row_iterator cAiterator;
     268              :         typedef typename B_type::const_row_iterator cBiterator;
     269              :         typedef UnsortedSparseVector<typename AB_type::value_type> RowType;
     270              : 
     271              :         RowType row(B.num_cols());
     272              : 
     273              :         // M_{ij} = \sum_k A_{ik} * B_{kj}
     274              :         for(size_t i=0; i < A.num_rows(); i++)
     275              :         {
     276              :                 row.clear();
     277              :                 cAiterator itAikEnd = A.end_row(i);
     278              :                 for(cAiterator itAik = A.begin_row(i); itAik != itAikEnd; ++itAik)
     279              :                 {
     280              :                         if(itAik.value() == 0.0) continue;
     281              :                         size_t k = itAik.index();
     282              : 
     283              :                         cBiterator itBklEnd = B.end_row(k);
     284              :                         for(cBiterator itBkj = B.begin_row(k); itBkj != itBklEnd; ++itBkj)
     285              :                         {
     286              :                                 if(itBkj.value() == 0.0) continue;
     287              :                                 size_t j = itBkj.index();
     288              :                                 AddMult( row(j), itAik.value(), itBkj.value());
     289              :                         }
     290              :                 }
     291              : 
     292              :                 M.set_matrix_row(i, row.unsorted_raw_ptr(), row.num_connections());
     293              :         }
     294              : 
     295              : }
     296              : 
     297              : 
     298              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     299              : // MatAdd:
     300              : //-------------------------
     301              : /**
     302              :  * \brief Calculates M = A + B
     303              :  * \param M (out) Matrix M, M = A + B
     304              :  * \param A (in) Matrix A
     305              :  * \param B (in) Matrix B
     306              :  * note: A and/or B may be equal to M.
     307              :  */
     308              : template<typename matrix_type>
     309            0 : void MatAdd(matrix_type &M, number alpha1, const matrix_type &A, number alpha2, const matrix_type &B)
     310              : {
     311              :         PROFILE_FUNC_GROUP("algebra");
     312              :         UG_ASSERT(A.num_rows() == B.num_rows() && A.num_cols() == B.num_cols(), "sizes must match");
     313              :         typedef typename matrix_type::const_row_iterator criterator;
     314              : 
     315              :         // create output matrix M
     316            0 :         if(&M != &A)
     317            0 :                 M.resize_and_clear(A.num_rows(), A.num_cols());
     318              : 
     319              :         // types
     320            0 :         std::vector<typename matrix_type::connection > con; con.reserve(10);
     321              : 
     322              :         typename matrix_type::connection c;
     323            0 :         for(size_t i=0; i < A.num_rows(); i++)
     324              :         {
     325              :                 con.clear();
     326              :                 criterator itA = A.begin_row(i), endA = A.end_row(i);
     327              :                 criterator itB = B.begin_row(i), endB = B.end_row(i);
     328              : 
     329            0 :                 while(itA != endA && itB != endB)
     330              :                 {
     331            0 :                         if(itA.index() == itB.index())
     332              :                         {
     333            0 :                                 c.dValue = alpha1 * itA.value() + alpha2 * itB.value();
     334            0 :                                 c.iIndex = itA.index();
     335              :                                 ++itA; ++itB;
     336              :                         }
     337            0 :                         else if (itA.index() < itB.index())
     338              :                         {
     339            0 :                                 c.dValue = itA.value();
     340            0 :                                 c.dValue *= alpha1;
     341            0 :                                 c.iIndex = itA.index();
     342              :                                 ++itA;
     343              :                         }
     344              :                         else
     345              :                         {
     346            0 :                                 c.dValue = itB.value();
     347            0 :                                 c.dValue *= alpha2;
     348            0 :                                 c.iIndex = itB.index();
     349              :                                 ++itB;
     350              :                         }
     351            0 :                         con.push_back(c);
     352              :                 }
     353            0 :                 while(itA != endA)
     354              :                 {
     355            0 :                         c.dValue = itA.value();
     356            0 :                         c.dValue *= alpha1;
     357            0 :                         c.iIndex = itA.index();
     358              :                         ++itA;
     359            0 :                         con.push_back(c);
     360              :                 }
     361            0 :                 while(itB != endB)
     362              :                 {
     363            0 :                         c.dValue = itB.value();
     364            0 :                         c.dValue *= alpha2;
     365            0 :                         c.iIndex = itB.index();
     366              :                         ++itB;
     367            0 :                         con.push_back(c);
     368              :                 }
     369              : 
     370            0 :                 M.set_matrix_row(i, &con[0], con.size());
     371              :         }
     372            0 :         M.defragment();
     373            0 : }
     374              : 
     375              : /**
     376              :  * \brief Calculates M = A + B
     377              :  * \param M (out) Matrix M, M = A + B
     378              :  * \param A (in) Matrix A
     379              :  * \param B (in) Matrix B
     380              :  * note: A and/or B may be equal to M.
     381              :  */
     382              : template<typename matrix_type>
     383            0 : void MatAddNonDirichlet(matrix_type &M, number alpha1, const matrix_type &A, number alpha2, const matrix_type &B)
     384              : {
     385              :         PROFILE_FUNC_GROUP("algebra");
     386              :         UG_ASSERT(A.num_rows() == B.num_rows() && A.num_cols() == B.num_cols(), "sizes must match");
     387              :         typedef typename matrix_type::const_row_iterator criterator;
     388              : 
     389              :         // create output matrix M
     390            0 :         if(&M != &A)
     391            0 :                 M.resize_and_clear(A.num_rows(), A.num_cols());
     392              : 
     393              :         // types
     394            0 :         std::vector<typename matrix_type::connection > con; con.reserve(10);
     395              : 
     396              :         typename matrix_type::connection c;
     397            0 :         for(size_t i=0; i < A.num_rows(); i++)
     398              :         {
     399              :                 con.clear();
     400              :                 {
     401              :                 criterator itA = A.begin_row(i), endA = A.end_row(i);
     402              :                 criterator itB = B.begin_row(i), endB = B.end_row(i);
     403              : 
     404              :                 // copy only A for dirichlet rows
     405              :                 // -> create a pattern Pii
     406              :                 typedef typename matrix_type::value_type value_type;
     407            0 :                 const value_type &Aii = A(i,i);
     408              :                 value_type Pii = 1.0;
     409              : 
     410              : 
     411              :                 UG_ASSERT (GetRows(Aii)==GetRows(Pii), "Huhh: Numbers of rows does not match!");
     412            0 :                 for(size_t alpha = 0; alpha < (size_t) GetRows(Aii); ++alpha)
     413              :                 {
     414            0 :                         if (IsDirichletRow(A, i, alpha)) BlockRef(Pii, alpha, alpha) =  0.0;
     415              :                 }
     416              : 
     417              : 
     418              :                 // proceed as usual
     419            0 :                 while(itA != endA && itB != endB)
     420              :                 {
     421              :                         // add this value: Bij:=Pii*Bij
     422            0 :                         value_type Bij(Pii*itB.value());
     423              :                         // UG_LOG("Bij =" << Bij << "," << "Pii=" << Pii);
     424              : 
     425            0 :                         if(itA.index() == itB.index())
     426              :                         {
     427            0 :                                 c.dValue = alpha1 * itA.value() + alpha2 * Bij;
     428            0 :                                 c.iIndex = itA.index();
     429              :                                 ++itA; ++itB;
     430              :                         }
     431            0 :                         else if (itA.index() < itB.index())
     432              :                         {
     433            0 :                                 c.dValue = itA.value();
     434            0 :                                 c.dValue *= alpha1;
     435            0 :                                 c.iIndex = itA.index();
     436              :                                 ++itA;
     437              :                         }
     438              :                         else
     439              :                         {
     440              :                                 c.dValue = Bij;
     441            0 :                                 c.dValue *= alpha2;
     442            0 :                                 c.iIndex = itB.index();
     443              :                                 ++itB;
     444              :                         }
     445            0 :                         con.push_back(c);
     446              :                 }
     447            0 :                 while(itA != endA)
     448              :                 {
     449            0 :                         c.dValue = itA.value();
     450            0 :                         c.dValue *= alpha1;
     451            0 :                         c.iIndex = itA.index();
     452              :                         ++itA;
     453            0 :                         con.push_back(c);
     454              :                 }
     455            0 :                 while(itB != endB)
     456              :                 {
     457            0 :                         value_type Bij(Pii*itB.value());
     458              : 
     459              :                         c.dValue = Bij;
     460            0 :                         c.dValue *= alpha2;
     461            0 :                         c.iIndex = itB.index();
     462              :                         ++itB;
     463            0 :                         con.push_back(c);
     464              :                 }
     465              :         }
     466            0 :                 M.set_matrix_row(i, &con[0], con.size());
     467              :         }
     468            0 :         M.defragment();
     469            0 : }
     470              : 
     471              : template<typename TSparseMatrix>
     472            0 : void GetNeighborhood_worker(const TSparseMatrix &A, size_t node, size_t depth, std::vector<size_t> &indices, std::vector<bool> &bVisited)
     473              : {
     474            0 :         if(depth==0) return;
     475              :         size_t iSizeBefore = indices.size();
     476              :         typename TSparseMatrix::const_row_iterator itEnd = A.end_row(node);
     477            0 :         for(typename TSparseMatrix::const_row_iterator it = A.begin_row(node); it != itEnd; ++it)
     478              :         {
     479            0 :                 if(it.value() == 0) continue;
     480            0 :                 if(bVisited[it.index()] == false)
     481              :                 {
     482              : 
     483              :                         bVisited[it.index()] = true;
     484            0 :                         indices.push_back(it.index());
     485              :                 }
     486              :         }
     487              : 
     488            0 :         if(depth==1) return;
     489              :         size_t iSizeAfter = indices.size();
     490            0 :         for(size_t i=iSizeBefore; i<iSizeAfter; i++)
     491            0 :                 GetNeighborhood_worker(A, indices[i], depth-1, indices, bVisited);
     492              : }
     493              : 
     494              : template<typename TSparseMatrix>
     495            0 : void GetNeighborhood(const TSparseMatrix &A, size_t node, size_t depth, std::vector<size_t> &indices, std::vector<bool> &bVisited, bool bResetVisitedFlags=true)
     496              : {
     497              :         PROFILE_FUNC_GROUP("algebra");
     498              :         indices.clear();
     499              : 
     500            0 :         if(bVisited[node] == false)
     501              :         {
     502              :                 bVisited[node] = true;
     503            0 :                 indices.push_back(node);
     504              :         }
     505            0 :         GetNeighborhood_worker(A, node, depth, indices, bVisited);
     506              : 
     507            0 :         if(bResetVisitedFlags)
     508            0 :                 for(size_t i=0; i<indices.size(); i++)
     509            0 :                         bVisited[indices[i]] = false;
     510            0 : }
     511              : 
     512              : template<typename TSparseMatrix>
     513              : void GetNeighborhood(const TSparseMatrix &A, size_t node, size_t depth, std::vector<size_t> &indices)
     514              : {
     515              :         PROFILE_FUNC_GROUP("algebra");
     516              :         std::vector<bool> bVisited(max(A.num_cols(), A.num_rows()), false);
     517              :         GetNeighborhood(A, node, depth, indices, bVisited, false);
     518              : }
     519              : 
     520              : 
     521              : template<typename TSparseMatrix>
     522              : void MarkNeighbors(const TSparseMatrix &A, size_t node, size_t depth, std::vector<bool> &bVisited)
     523              : {
     524              :         typename TSparseMatrix::const_row_iterator itEnd = A.end_row(node);
     525              :         for(typename TSparseMatrix::const_row_iterator it = A.begin_row(node); it != itEnd; ++it)
     526              :         {
     527              :                 if(it.value() == 0) continue;
     528              :                 bVisited[it.index()] = true;
     529              :                 MarkNeighbors(A, it.index(), depth, bVisited);
     530              :         }
     531              : }
     532              : 
     533              : template<typename TSparseMatrix>
     534              : void GetNeighborhoodHierachy_worker(const TSparseMatrix &A, size_t node, size_t depth, size_t maxdepth, std::vector< std::vector<size_t> > &indices, std::vector<bool> &bVisited)
     535              : {
     536              :         size_t iSizeBefore = indices[depth].size();
     537              :         typename TSparseMatrix::const_row_iterator itEnd = A.end_row(node);
     538              :         for(typename TSparseMatrix::const_row_iterator it = A.begin_row(node); it != itEnd; ++it)
     539              :         {
     540              :                 if(it.value() == 0) continue;
     541              :                 if(bVisited[it.index()] == false)
     542              :                 {
     543              :                         bVisited[it.index()] = true;
     544              :                         indices[depth].push_back(it.index());
     545              :                 }
     546              :         }
     547              : 
     548              :         if(depth==maxdepth) return;
     549              :         size_t iSizeAfter = indices[depth].size();
     550              :         for(size_t i=iSizeBefore; i<iSizeAfter; i++)
     551              :                 GetNeighborhoodHierachy_worker(A, indices[i], depth+1, maxdepth, indices, bVisited);
     552              : }
     553              : 
     554              : template<typename TSparseMatrix>
     555              : void GetNeighborhoodHierachy(const TSparseMatrix &A, size_t node, size_t depth, std::vector< std::vector<size_t> > &indices, std::vector<bool> &bVisited,
     556              :                 bool bResetVisitedFlags=true)
     557              : {
     558              :         PROFILE_FUNC_GROUP("algebra");
     559              :         if(indices.size() != depth+1)
     560              :                 indices.resize(depth+1);
     561              :         for(size_t i=0; i < depth+1; i++)
     562              :                 indices[i].clear();
     563              : 
     564              :         bVisited[node] = true;
     565              :         indices[0].push_back(node);
     566              : 
     567              :         if(depth==0) return;
     568              : 
     569              :         for(size_t d = 0; d < depth; d++)
     570              :         {
     571              :                 for(size_t i=0; i<indices[d].size(); i++)
     572              :                 {
     573              :                         size_t k = indices[d][i];
     574              :                         typename TSparseMatrix::const_row_iterator itEnd = A.end_row(k);
     575              :                         for(typename TSparseMatrix::const_row_iterator it = A.begin_row(k); it != itEnd; ++it)
     576              :                         {
     577              :                                 if(it.value() == 0) continue;
     578              :                                 if(bVisited[it.index()] == false)
     579              :                                 {
     580              :                                         bVisited[it.index()] = true;
     581              :                                         indices[d+1].push_back(it.index());
     582              :                                 }
     583              :                         }
     584              : 
     585              :                 }
     586              :         }
     587              : 
     588              :         if(bResetVisitedFlags)
     589              :                 for(size_t i=0; i < depth+1; i++)
     590              :                         for(size_t j=0; i<indices[j].size(); j++)
     591              :                                 bVisited[j] = false;
     592              : }
     593              : 
     594              : 
     595              : template<typename TSparseMatrix>
     596              : void GetNeighborhoodHierachy(const TSparseMatrix &A, size_t node, size_t depth, std::vector< std::vector<size_t> > &indices)
     597              : {
     598              :         std::vector<bool> bVisited(std::max(A.num_cols(), A.num_rows()), false);
     599              :         GetNeighborhoodHierachy(A, node, depth, indices, bVisited, false);
     600              : }
     601              : 
     602              : 
     603              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     604              : // GetNeighborhood:
     605              : //-------------------------
     606              : /**
     607              :  * \brief gets the neighborhood of a node in the connectivity graph of a SparseMatrix.
     608              :  * \param A (in) Matrix A
     609              :  * \param node (in) the node where to start
     610              :  * \param depth (in) the depth of neighborhood. 0 = empty.
     611              :  * \param indices (out) the indices of the neighbors
     612              :  * \param posInConnections array to speed up computation. Has to be posInConnections[i] = 0 for all i=0..A.num_rows(). Can be NULL.
     613              :  * \note the node itself is only included if there is a connection from node to node.
     614              :   */
     615              : #if 0
     616              : template<typename T>
     617              : void GetNeighborhood(SparseMatrix<T> &A, size_t node, size_t depth, std::vector<size_t> &indices, int *posInConnections=NULL)
     618              : {
     619              :         // perhaps this is better with recursion
     620              :         indices.clear();
     621              : 
     622              : 
     623              : 
     624              :         vector<typename SparseMatrix<T>::const_row_iterator> iterators;
     625              :         iterators.reserve(depth);
     626              : 
     627              :         iterators.push_back( A.begin_row(node) );
     628              : 
     629              :         while(iterators.size() != 0)
     630              :         {
     631              :                 if(iterators.back().isEnd())
     632              :                         iterators.pop_back();
     633              :                 else
     634              :                 {
     635              :                         size_t index = iterators.back().index();
     636              :                         ++iterators.back();
     637              :                         if(iterators.size() < depth)
     638              :                                 iterators.push_back( A.begin_row(index) );
     639              :                         else
     640              :                         {
     641              :                                 size_t pos;
     642              :                                 if(posInConnections == NULL)
     643              :                                 {
     644              :                                         for(pos=0; pos<indices.size(); pos++)
     645              :                                                 if(indices[pos] == index)
     646              :                                                         break;
     647              :                                         if(pos == indices.size())
     648              :                                                 indices.push_back(index);
     649              :                                 }
     650              :                                 else
     651              :                                 {
     652              :                                         pos = posInConnections[index];
     653              :                                         if(pos == -1)
     654              :                                         {
     655              :                                                 pos = posInConnections[index] = indices.size();
     656              :                                                 indices.push_back(index);
     657              :                                         }
     658              :                                 }
     659              :                                 // else (count etc.)
     660              :                         }
     661              :                 }
     662              :         }
     663              : 
     664              :         // reset posInConnections
     665              :         if(posInConnections)
     666              :         {
     667              :                 for(size_t i=0; i<indices.size(); i++)
     668              :                         posInConnections[indices[i]] = -1;
     669              :         }
     670              : 
     671              :         // sort indices
     672              :         sort(indices.begin(), indices.end());
     673              : }
     674              : #endif
     675              : 
     676              : 
     677              : 
     678              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     679              : // IsCloseToBoundary:
     680              : //-------------------------
     681              : /**
     682              :  * \brief determines if a node is close to a unconnected node in the connectivity graph of a SparseMatrix.
     683              :  * \param A (in) Matrix A
     684              :  * \param node (in) the node where to start
     685              :  * \param distance (in) up to which distance "close" is.
     686              :  * \return if there is a distance long path in graph(A) to an unconnected node, true. otherwise false.
     687              :   */
     688              : template<typename TSparseMatrix>
     689              : bool IsCloseToBoundary(const TSparseMatrix &A, size_t node, size_t distance)
     690              : {
     691              :         typedef typename TSparseMatrix::const_row_iterator iterator;
     692              :         if(distance == 0) return A.is_isolated(node);
     693              :         bool bFound = false;
     694              :         iterator itEnd = A.end_row(node);
     695              :         for(iterator itA = A.begin_row(node); itA != itEnd && !bFound; ++itA)
     696              :                 bFound = IsCloseToBoundary(A, itA.index(), distance-1);
     697              : 
     698              :         return bFound;
     699              : }
     700              : 
     701              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     702              : /**
     703              :  * set value for row for entry (i,alpha).
     704              :  * \param A (in) Matrix A
     705              :  * \param i (in) row to set
     706              :  * \param alpha the alpha index
     707              :  * \param val the value to be set
     708              :  */
     709              : template <typename TSparseMatrix>
     710            0 : void SetRow(TSparseMatrix &A, size_t i, size_t alpha, number val = 0.0)
     711              : {
     712              :         typedef typename TSparseMatrix::row_iterator iterator;
     713              :         typedef typename TSparseMatrix::value_type value_type;
     714              :         iterator itEnd = A.end_row(i);
     715            0 :         for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     716              :         {
     717              :                 value_type& block = conn.value();
     718              :                 // block : 1x1 (CPU=1), 3x3 (CPU=3)
     719            0 :                 for(size_t beta = 0; beta < (size_t) GetCols(block); ++beta)
     720              :                 {
     721            0 :                         BlockRef(block, alpha, beta) = val;
     722              :                 }
     723              :         }
     724            0 : }
     725              : 
     726              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     727              : /**
     728              :  * set value for col for entry (i,alpha).
     729              :  * \param A (in) Matrix A
     730              :  * \param i (in) col to set
     731              :  * \param alpha the alpha index
     732              :  * \param val the value to be set
     733              :  */
     734              : template <typename TSparseMatrix>
     735            0 : void SetCol(TSparseMatrix &A, size_t i, size_t alpha, number val = 0.0)
     736              : {
     737              :         typedef typename TSparseMatrix::value_type value_type;
     738            0 :         for(size_t row = 0; row != A.num_rows(); ++row)
     739              :         {
     740              :                 value_type& block = A(row, i);
     741              :                 // block : 1x1 (CPU=1), 3x3 (CPU=3)
     742            0 :                 for(size_t beta = 0; beta < (size_t) GetRows(block); ++beta)
     743              :                 {
     744            0 :                         BlockRef(block, beta, alpha) = val;
     745              :                 }
     746              :         }
     747            0 : }
     748              : 
     749              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     750              : // SetRow:
     751              : //-------------------------
     752              : /**
     753              :  * set value for (block-)row i.
     754              :  * \param A (in) Matrix A
     755              :  * \param i (in) row to scales
     756              :  * \param val (in) value to be set
     757              :  */
     758              : template <typename TSparseMatrix>
     759            0 : void SetRow(TSparseMatrix& A, size_t i, number val = 0.0)
     760              : {
     761              :         typedef typename TSparseMatrix::row_iterator iterator;
     762            0 :         iterator itEnd = A.end_row(i);
     763            0 :         for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     764            0 :                 conn.value() = val;
     765            0 : }
     766              : 
     767              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     768              : // ScaleRow:
     769              : //-------------------------
     770              : /**
     771              :  * scales (block-)row i.
     772              :  * \param A (in) Matrix A
     773              :  * \param i (in) row to scales
     774              :  * \param fac (in) Scaling factor
     775              :  */
     776              : template <typename TSparseMatrix>
     777              : void ScaleRow(TSparseMatrix& A, size_t i, number fac)
     778              : {
     779              :         typedef typename TSparseMatrix::row_iterator iterator;
     780              :         iterator itEnd = A.end_row(i);
     781              :         for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     782              :                 conn.value() *= fac;
     783              : }
     784              : 
     785              : 
     786              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     787              : // SetDirichletRow:
     788              : //-------------------------
     789              : /**
     790              :  * set Dirichlet row for entry (i,alpha).
     791              :  * \param A (in) Matrix A
     792              :  * \param i (in) row to set dirichlet, that is A(i,i)(alpha, alpha) = 1.0, A(i,k)(alpha, beta) = 0.0 for all (k, beta) != (i, alpha)$.
     793              :  * \param alpha the alpha index
     794              :  */
     795              : template <typename TSparseMatrix>
     796            0 : void SetDirichletRow(TSparseMatrix &A, size_t i, size_t alpha)
     797              : {
     798              :         typedef typename TSparseMatrix::row_iterator iterator;
     799              :         typedef typename TSparseMatrix::value_type value_type;
     800            0 :         BlockRef(A(i,i), alpha, alpha) = 1.0;
     801              : 
     802              :         iterator itEnd = A.end_row(i);
     803            0 :         for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     804              :         {
     805              :                 value_type& block = conn.value();
     806              :                 // block : 1x1 (CPU=1), 3x3 (CPU=3)
     807            0 :                 for(size_t beta = 0; beta < (size_t) GetCols(block); ++beta)
     808              :                 {
     809            0 :                         if(conn.index() != i) BlockRef(block, alpha, beta) = 0.0;
     810            0 :                         else if(beta != alpha) BlockRef(block, alpha, beta) = 0.0;
     811              :                 }
     812              :         }
     813            0 : }
     814              : 
     815              : //! Evaluates 'true', iff corresponding row is Dirichlet
     816              : template <typename TSparseMatrix>
     817            0 : bool IsDirichletRow(const TSparseMatrix &A, size_t i, size_t alpha)
     818              : {
     819              :         typedef typename TSparseMatrix::const_row_iterator iterator;
     820              :         typedef typename TSparseMatrix::value_type value_type;
     821              : 
     822              :         // no Dirichlet row,
     823            0 :         if (BlockRef(A(i,i), alpha, alpha) != 1.0) return false;
     824              : 
     825              :         // check, if row sum equals 1
     826              :         number sum=0.0;
     827              :         iterator itEnd = A.end_row(i);
     828            0 :         for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     829              :         {
     830              :                 const value_type& block = conn.value();
     831              :                 // block : 1x1 (CPU=1), 3x3 (CPU=3)
     832            0 :                 for(size_t beta = 0; beta < (size_t) GetCols(block); ++beta)
     833              :                 {
     834            0 :                         sum += BlockRef(block, alpha, beta) * BlockRef(block, alpha, beta);
     835              :                 }
     836              :         }
     837            0 :         return (sum==1.0);
     838              : }
     839              : 
     840              : 
     841              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     842              : // SetDirichletRow:
     843              : //-------------------------
     844              : /**
     845              :  * set Dirichlet row for block i.
     846              :  * \param A (in) Matrix A
     847              :  * \param i (in) row to set dirichlet, that is A(i,i) = 1.0, A(i,k) = 0.0 for all k != i.
     848              :  */
     849              : template <typename TSparseMatrix>
     850              : void SetDirichletRow(TSparseMatrix& A, size_t i)
     851              : {
     852              :         typedef typename TSparseMatrix::row_iterator iterator;
     853              :         typedef typename TSparseMatrix::value_type value_type;
     854              :         iterator itEnd = A.end_row(i);
     855              :         for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     856              :         {
     857              :                 value_type& block = conn.value();
     858              :                 block = 0.0;
     859              :         }
     860              :         A(i,i) = 1.0;
     861              : }
     862              : 
     863              : ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     864              : // SetDirichletRow:
     865              : //-------------------------
     866              : /**
     867              :  * set Dirichlet row for block i.
     868              :  * \param[in/out] Matrix A
     869              :  * \param[in] vIndex vector of row indices to set dirichlet, that is A(i,i) = 1.0, A(i,k) = 0.0 for all k != i.
     870              :  */
     871              : template <typename TSparseMatrix>
     872              : void SetDirichletRow(TSparseMatrix& A, const std::vector<size_t> vIndex)
     873              : {
     874              :         typedef typename TSparseMatrix::row_iterator iterator;
     875              :         typedef typename TSparseMatrix::value_type value_type;
     876              :         std::vector<size_t>::const_iterator iter = vIndex.begin();
     877              :         std::vector<size_t>::const_iterator iterEnd = vIndex.end();
     878              : 
     879              :         for(; iter < iterEnd; ++iter)
     880              :         {
     881              :                 const size_t i = *iter;
     882              :                 UG_ASSERT(i < A.num_rows(), "Index to large in index set.");
     883              : 
     884              :                 iterator itEnd = A.end_row(i);
     885              :                 for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     886              :                 {
     887              :                         value_type& block = conn.value();
     888              :                         block = 0.0;
     889              :                 }
     890              :                 A(i,i) = 1.0;
     891              :         }
     892              : }
     893              : 
     894              : template<typename TSparseMatrix, class TOStream>
     895              : void SerializeMatrix(TOStream &buf, const TSparseMatrix &A)
     896              : {
     897              :         typedef typename TSparseMatrix::const_row_iterator iterator;
     898              :         Serialize(buf, A.num_rows());
     899              :         Serialize(buf, A.num_cols());
     900              : 
     901              :         for(size_t i=0; i < A.num_rows(); i++)
     902              :         {
     903              :                 size_t num_connections = A.num_connections(i);
     904              : 
     905              :                 // serialize number of connections
     906              :                 Serialize(buf, num_connections);
     907              : 
     908              :                 iterator itEnd = A.end_row(i);
     909              :                 for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
     910              :                 {
     911              :                         // serialize connection
     912              :                         Serialize(buf, conn.index());
     913              :                         Serialize(buf, conn.value());
     914              :                 }
     915              :         }
     916              : }
     917              : 
     918              : template <typename TSparseMatrix, class TIStream>
     919              : void DeserializeMatrix(TIStream& buf, TSparseMatrix &A)
     920              : {
     921              :         size_t numRows, numCols, num_connections;
     922              : 
     923              :         Deserialize(buf, numRows);
     924              :         Deserialize(buf, numCols);
     925              :         A.resize_and_clear(numRows, numCols);
     926              : 
     927              :         std::vector<typename TSparseMatrix::connection> con; con.reserve(16);
     928              : 
     929              :         for(size_t i=0; i < A.num_rows; i++)
     930              :         {
     931              :                 Deserialize(buf, num_connections);
     932              : 
     933              :                 con.resize(num_connections);
     934              : 
     935              :                 for(size_t j=0; j<num_connections; j++)
     936              :                 {
     937              :                         Deserialize(buf, con[j].iIndex);
     938              :                         Deserialize(buf, con[j].dValue);
     939              :                 }
     940              :                 A.set_matrix_row(i, &con[0], num_connections);
     941              :         }
     942              :         A.defragment();
     943              : }
     944              : 
     945              : template<typename TSparseMatrix>
     946              : void ScaleSparseMatrixCommon(TSparseMatrix &A, double d)
     947              : {
     948              :         typedef typename TSparseMatrix::row_iterator iterator;
     949              :         for(size_t r=0; r < A.num_rows(); r++)
     950              :         {
     951              :                 iterator itEnd = A.end_row(r);
     952              :                 for(iterator it = A.begin_row(r); it != itEnd; ++it)
     953              :                         it.value() *= d;
     954              :         }
     955              : }
     956              : 
     957              : 
     958              : template<typename TSparseMatrix, typename vector_t>
     959              : bool AxpyCommonSparseMatrix(const TSparseMatrix &A, vector_t &dest,
     960              :                 const number &alpha1, const vector_t &v1,
     961              :                 const number &beta1, const vector_t &w1)
     962              : {
     963              :         typedef typename TSparseMatrix::const_row_iterator iterator;
     964              : //      UG_ASSERT(cols == x.size(), "x: " << x << " has wrong length (should be " << cols << "). A: " << *this);
     965              : //      UG_ASSERT(rows == res.size(), "res: " << x << " has wrong length (should be " << rows << "). A: " << *this);
     966              : 
     967              :         if(alpha1 == 0.0)
     968              :         {
     969              :                 for(size_t i=0; i < A.num_rows(); i++)
     970              :                 {
     971              :                         iterator conn = A.begin_row(i);
     972              :                         iterator itEnd = A.end_row(i);
     973              :                         if(conn  == itEnd) continue;
     974              :                         MatMult(dest[i], beta1, conn.value(), w1[conn.index()]);
     975              :                         for(++conn; conn != itEnd; ++conn)
     976              :                                 // res[i] += conn.value() * x[conn.index()];
     977              :                                 MatMultAdd(dest[i], 1.0, dest[i], beta1, conn.value(), w1[conn.index()]);
     978              :                 }
     979              :         }
     980              :         else if(&dest == &v1)
     981              :         {
     982              :                 if(alpha1 != 1.0)
     983              :                         for(size_t i=0; i < A.num_rows(); i++)
     984              :                         {
     985              :                                 dest[i] *= alpha1;
     986              :                                 A.mat_mult_add_row(i, dest[i], beta1, w1);
     987              :                         }
     988              :                 else
     989              :                         for(size_t i=0; i < A.num_rows(); i++)
     990              :                                 A.mat_mult_add_row(i, dest[i], beta1, w1);
     991              : 
     992              :         }
     993              :         else
     994              :         {
     995              :                 for(size_t i=0; i < A.num_rows(); i++)
     996              :                 {
     997              :                         VecScaleAssign(dest[i], alpha1, v1[i]);
     998              :                         A.mat_mult_add_row(i, dest[i], beta1, w1);
     999              :                 }
    1000              :         }
    1001              : 
    1002              :         return true;
    1003              : }
    1004              :         
    1005              : 
    1006              : template<typename TSparseMatrix, typename vector_t>
    1007              : bool Axpy_transposedCommonSparseMatrix(const TSparseMatrix &A, vector_t &dest,
    1008              :                 const number &alpha1, const vector_t &v1,
    1009              :                 const number &beta1, const vector_t &w1)
    1010              : {
    1011              :         typedef typename TSparseMatrix::const_row_iterator iterator;
    1012              : //      UG_ASSERT(rows == x.size(), "x: " << x << " has wrong length (should be " << rows << "). A: " << *this);
    1013              : //      UG_ASSERT(cols == res.size(), "res: " << x << " has wrong length (should be " << cols << "). A: " << *this);
    1014              : 
    1015              :         if(&dest == &v1) {
    1016              :                 if(alpha1 == 0.0)
    1017              :                         dest.set(0.0);
    1018              :                 else if(alpha1 != 1.0)
    1019              :                         dest *= alpha1;
    1020              :         }
    1021              :         else if(alpha1 == 0.0)
    1022              :                 dest.set(0.0);
    1023              :         else
    1024              :                 VecScaleAssign(dest, alpha1, v1);
    1025              : 
    1026              :         for(size_t i=0; i<A.num_rows(); i++)
    1027              :         {
    1028              :                 iterator itEnd = A.end_row(i);
    1029              :                 for(iterator conn = A.begin_row(i); conn != itEnd; ++conn)
    1030              :                 {
    1031              :                         if(conn.value() != 0.0)
    1032              :                                 // dest[conn.index()] += beta1 * conn.value() * w1[i];
    1033              :                                 MatMultTransposedAdd(dest[conn.index()], 1.0, dest[conn.index()], beta1, conn.value(), w1[i]);
    1034              :                 }
    1035              :         }
    1036              :         return true;
    1037              : }
    1038              : 
    1039              : 
    1040              : /// returns the number of non-zeroes (!= number of connections)
    1041              : template<typename TSparseMatrix>
    1042              : size_t GetNNZs(const TSparseMatrix &A)
    1043              : {
    1044              :         typedef typename TSparseMatrix::const_row_iterator iterator;
    1045              :         size_t m=0;
    1046              :         for(size_t i=0; i<A.num_rows(); i++)
    1047              :         {
    1048              :                 iterator itEnd = A.end_row(i);
    1049              :                 for(iterator it = A.begin_row(i); it != itEnd; ++it)
    1050              :                         if(it.value() != 0.0) m++;
    1051              :         }
    1052              :         return m;
    1053              : }
    1054              : 
    1055              : /// returns max number of non-zero connections in rows
    1056              : template<typename TSparseMatrix>
    1057              : size_t GetMaxConnections(const TSparseMatrix &A)
    1058              : {
    1059              :         typedef typename TSparseMatrix::const_row_iterator iterator;
    1060              :         size_t m=0;
    1061              :         for(size_t i=0; i<A.num_rows(); i++)
    1062              :         {
    1063              :                 //if(m < A.num_connections(i)) m = A.num_connections(i);
    1064              : 
    1065              :                 size_t n=0;
    1066              :                 iterator itEnd = A.end_row(i);
    1067              :                 for(iterator it = A.begin_row(i); it != itEnd; ++it)
    1068              :                         if(it.value() != 0.0) n++;
    1069              :                 if(m < n) m = n;
    1070              :         }
    1071              : 
    1072              :         return m;
    1073              : }
    1074              : 
    1075              : 
    1076              : template<typename TSparseMatrix>
    1077              : bool CheckRowIterators(const TSparseMatrix &A)
    1078              : {
    1079              : #ifndef NDEBUG
    1080              :         bool iIter=0;
    1081              : 
    1082              :         for(size_t i=0; i<A.num_rows(); i++)
    1083              :         {
    1084              :                 if (A.nrOfRowIterators[i] !=0) UG_LOG ("CheckRowIterators: Failed for row " << i << std::endl);
    1085              :                 iIter += A.nrOfRowIterators[i];
    1086              :         }
    1087              :         return iIter==0;
    1088              : #else
    1089              :         return true;
    1090              : #endif
    1091              : }
    1092              : 
    1093              : template<typename TSparseMatrix>
    1094              : bool CheckDiagonalInvertible(const TSparseMatrix &A)
    1095              : {
    1096              : #ifndef NDEBUG
    1097              :         typedef typename block_traits<typename TSparseMatrix::value_type>::inverse_type inverse_type;
    1098              :         bool bsucc=true;
    1099              :         inverse_type inv;
    1100              :         for(size_t i=0; i<A.num_rows(); i++)
    1101              :         {
    1102              :                 bool b = GetInverse(inv, A(i,i));
    1103              :                 if(!b)
    1104              :                 {
    1105              :                         UG_LOG("WARNING: entry " << i << " = " << A(i,i) << " not invertible\n");
    1106              :                         bsucc = false;
    1107              :                 }
    1108              :         }
    1109              :         return bsucc;
    1110              : #else
    1111              :         return true;
    1112              : #endif
    1113              : }
    1114              : 
    1115              : template<typename TVector>
    1116              : bool CheckVectorInvertible(const TVector &v)
    1117              : {
    1118              : #ifndef NDEBUG
    1119              :         typedef typename block_traits<typename TVector::value_type>::inverse_type inverse_type;
    1120              :         bool bsucc=true;
    1121              :         inverse_type inv;
    1122              : 
    1123              :         for(size_t i=0; i<v.size(); i++)
    1124              :         {
    1125              :                 bool b = GetInverse(inv, v[i]);
    1126              :                 if(!b)
    1127              :                 {
    1128              :                         UG_LOG("WARNING: entry " << i << " = " << v[i] << " not invertible\n");
    1129              :                         bsucc = false;
    1130              :                 }
    1131              :         }
    1132              :         return bsucc;
    1133              : #else
    1134              :         return true;
    1135              : #endif
    1136              : }
    1137              : 
    1138              : #ifdef UG_PARALLEL
    1139              : template<typename TSparseMatrix>
    1140              : bool CheckDiagonalInvertible(const ParallelMatrix<TSparseMatrix> &m)
    1141              : {
    1142              :         return AllProcsTrue(CheckDiagonalInvertible((TSparseMatrix&)m), m.layouts()->proc_comm());
    1143              : }
    1144              : 
    1145              : template<typename TVector>
    1146              : bool CheckVectorInvertible(const ParallelVector<TVector> &v)
    1147              : {
    1148              :         return AllProcsTrue(CheckVectorInvertible((TVector&)v), v.layouts()->proc_comm());
    1149              : }
    1150              : #endif
    1151              : 
    1152              : 
    1153              : template<typename TSparseMatrix>
    1154              : struct DenseMatrixFromSparseMatrix
    1155              : {
    1156              :         typedef DenseMatrix<VariableArray2<typename TSparseMatrix::value_type> > type;
    1157              : };
    1158              : 
    1159              : template<typename TSparseMatrix>
    1160              : typename DenseMatrixFromSparseMatrix<TSparseMatrix>::type &
    1161              : GetDenseFromSparse(typename DenseMatrixFromSparseMatrix<TSparseMatrix>::type &A, const TSparseMatrix &S)
    1162              : {
    1163              : 
    1164              :         typedef typename TSparseMatrix::const_row_iterator sparse_row_iterator;
    1165              :         size_t numRows = S.num_rows();
    1166              :         size_t numCols = S.num_cols();
    1167              : //      PROGRESS_START(prog, n, "GetDenseFromSparse " << n);
    1168              :         A.resize(numRows, numCols);
    1169              :         for(size_t r=0; r<numRows; r++)
    1170              :                 for(size_t c=0; c<numCols; c++)
    1171              :                         A(r, c) = 0;
    1172              :         for(size_t r=0; r<numRows; r++)
    1173              :         {
    1174              : //              PROGRESS_UPDATE(prog, r);
    1175              :                 sparse_row_iterator itEnd = S.end_row(r);
    1176              :                 for(sparse_row_iterator it = S.begin_row(r); it != itEnd; ++it)
    1177              :                         A(r, it.index()) = it.value();
    1178              :         }
    1179              : //      PROGRESS_FINISH(prog);
    1180              :         return A;
    1181              : }
    1182              : 
    1183              : template<typename TSparseMatrix>
    1184              : size_t GetDoubleSize(const TSparseMatrix &S)
    1185              : {
    1186              :         const size_t nrOfRows = block_traits<typename TSparseMatrix::value_type>::static_num_rows;
    1187              :         UG_COND_THROW(nrOfRows != block_traits<typename TSparseMatrix::value_type>::static_num_cols, "only square matrices supported");
    1188            0 :         return S.num_rows() * nrOfRows;
    1189              : }
    1190              : 
    1191              : template<typename TDoubleType, typename TSparseMatrix>
    1192            0 : void GetDoubleFromSparseBlock(TDoubleType &A, const TSparseMatrix &S)
    1193              : {
    1194              :         const size_t nrOfRows = block_traits<typename TSparseMatrix::value_type>::static_num_rows;
    1195            0 :         for(size_t r=0; r<S.num_rows(); r++)
    1196            0 :                 for(typename TSparseMatrix::const_row_iterator it = S.begin_row(r); it != S.end_row(r); ++it)
    1197              :                 {
    1198            0 :                         size_t rr = r*nrOfRows;
    1199            0 :                         size_t cc = it.index()*nrOfRows;
    1200            0 :                         for(size_t r2=0; r2<nrOfRows; r2++)
    1201            0 :                                         for(size_t c2=0; c2<nrOfRows; c2++)
    1202            0 :                                           A(rr + r2, cc + c2) = BlockRef(it.value(), r2, c2);
    1203              :                 }
    1204            0 : }
    1205              : 
    1206              : template<typename TDenseType, typename TSparseMatrix>
    1207            0 : size_t GetDenseDoubleFromSparse(TDenseType &A, const TSparseMatrix &S)
    1208              : {
    1209              :         size_t N = GetDoubleSize(S);
    1210            0 :         A.resize(0,0);
    1211            0 :         A.resize(N, N);
    1212            0 :         GetDoubleFromSparseBlock(A, S);
    1213            0 :         return N;
    1214              : }
    1215              : 
    1216              : template<typename TDoubleSparse, typename TSparseMatrix>
    1217            0 : size_t GetDoubleSparseFromBlockSparse(TDoubleSparse &A, const TSparseMatrix &S)
    1218              : {
    1219              :         size_t N = GetDoubleSize(S);
    1220              : 
    1221            0 :         A.resize_and_clear(N, N);
    1222            0 :         GetDoubleFromSparseBlock(A, S);
    1223            0 :         A.defragment();
    1224            0 :         return N;
    1225              : }
    1226              : 
    1227              : 
    1228              : 
    1229              : 
    1230              : /// @}
    1231              : } // end namespace ug
    1232              : 
    1233              : 
    1234              : #endif
        

Generated by: LCOV version 2.0-1