LCOV - code coverage report
Current view: top level - ugbase/lib_disc/operator/linear_operator/element_gauss_seidel - component_gauss_seidel.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 168 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 171 0

            Line data    Source code
       1              : /*
       2              :  * Copyright (c) 2013-2015:  G-CSC, Goethe University Frankfurt
       3              :  * Authors: Christian Wehner, Andreas Vogel
       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              : /*
      34              :  *  Remark: Base on Vanka idea and implementation
      35              :  */
      36              : 
      37              : #ifndef __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__COMPONENT_GAUSS_SEIDEL__
      38              : #define __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__COMPONENT_GAUSS_SEIDEL__
      39              : 
      40              : #include "lib_algebra/operator/interface/preconditioner.h"
      41              : 
      42              : #include <vector>
      43              : #include <algorithm>
      44              : 
      45              : #ifdef UG_PARALLEL
      46              :         #include "pcl/pcl_util.h"
      47              :         #include "lib_algebra/parallelization/parallelization_util.h"
      48              :         #include "lib_algebra/parallelization/parallel_matrix_overlap_impl.h"
      49              : #endif
      50              : 
      51              : namespace ug{
      52              : 
      53              : ///     ComponentGaussSeidel Preconditioner
      54              : template <typename TDomain, typename TAlgebra>
      55              : class ComponentGaussSeidel : public IPreconditioner<TAlgebra>
      56              : {
      57              :         public:
      58              :         /// World dimension
      59              :                 typedef GridFunction<TDomain, TAlgebra> GF;
      60              :                 typedef typename GF::element_type Element;
      61              :                 typedef typename GF::side_type Side;
      62              :                 static const int dim = TDomain::dim;
      63              : 
      64              :         ///     Algebra types
      65              :         /// \{
      66              :                 typedef TAlgebra algebra_type;
      67              :                 typedef typename TAlgebra::vector_type vector_type;
      68              :                 typedef typename TAlgebra::matrix_type matrix_type;
      69              :         /// \}
      70              : 
      71              :         protected:
      72              :                 typedef IPreconditioner<TAlgebra> base_type;
      73              :                 using base_type::set_debug;
      74              :                 using base_type::debug_writer;
      75              :                 using base_type::write_debug;
      76              : 
      77              :         public:
      78              :         ///     default constructor
      79            0 :                 ComponentGaussSeidel(const std::vector<std::string>& vFullRowCmp)
      80            0 :                         : m_bInit(false), m_relax(1), m_alpha(1.0), m_beta(1.0), m_bWeighted(false), m_vFullRowCmp(vFullRowCmp) {}
      81              : 
      82              :         ///     constructor setting relaxation and type
      83            0 :                 ComponentGaussSeidel(number relax, const std::vector<std::string>& vFullRowCmp)
      84            0 :                         : m_bInit(false), m_relax(relax),  m_alpha(1.0), m_beta(1.0), m_bWeighted(false), m_vFullRowCmp(vFullRowCmp){}
      85              : 
      86              :         ///     constructor setting relaxation and type
      87            0 :                 ComponentGaussSeidel(number relax, const std::vector<std::string>& vFullRowCmp,
      88              :                                      const std::vector<int>& vSmooth, const std::vector<number>& vDamp)
      89            0 :                 : m_bInit(false), m_relax(relax),  m_alpha(1.0), m_beta(1.0), m_bWeighted(false), m_vFullRowCmp(vFullRowCmp),
      90            0 :                   m_vGroupObj(vSmooth), m_vDamp(vDamp) {};
      91              : 
      92              :         ///     Clone
      93              :                 virtual SmartPtr<ILinearIterator<vector_type> > clone();
      94              : 
      95              :         ///     returns if parallel solving is supported
      96            0 :                 virtual bool supports_parallel() const {return true;}
      97              : 
      98            0 :                 void set_alpha(number alpha)
      99            0 :                 {m_alpha = alpha;}
     100              : 
     101            0 :                 void set_beta(number beta)
     102            0 :                 {m_beta = beta;}
     103              : 
     104            0 :                 void set_weights(bool b)
     105            0 :                 {m_bWeighted = b;}
     106              : 
     107              :         protected:
     108              :         ///     Name of preconditioner
     109            0 :                 virtual const char* name() const {return "ComponentGaussSeidel";}
     110              : 
     111              :         ///     Preprocess routine
     112              :                 virtual bool preprocess(SmartPtr<MatrixOperator<matrix_type, vector_type> > pOp);
     113              : 
     114              :                 struct DimCache{
     115              :                         std::vector<std::vector<DoFIndex> > vvDoFIndex;
     116              :                         std::vector<DenseMatrix< VariableArray2<number> > > vBlockInverse;
     117              :                 };
     118              : 
     119              :                 void apply_blocks(const matrix_type& A, GF& c,
     120              :                                   const vector_type& d, number relax,
     121              :                                   const DimCache& dimCache,
     122              :                                   bool bReverse);
     123              : 
     124              :                 void apply_blocks_weighted(const matrix_type& A, GF& c,
     125              :                                                   const vector_type& d, number relax,
     126              :                                                   const DimCache& dimCache,
     127              :                                                   bool bReverse);
     128              : 
     129              :                 void extract_blocks(const matrix_type& A, const GF& c);
     130              : 
     131              :         ///     step method
     132              :                 virtual bool step(SmartPtr<MatrixOperator<matrix_type, vector_type> > pOp, vector_type& c, const vector_type& d);
     133              : 
     134              :         ///     Postprocess routine
     135            0 :                 virtual bool postprocess() {return true;}
     136              : 
     137              :         protected:
     138              : #ifdef UG_PARALLEL
     139              :                 matrix_type m_A;
     140              : #endif
     141              : 
     142              :         ///     init flag
     143              :                 bool m_bInit;
     144              : 
     145              :         ///     relaxing parameter
     146              :                 number m_relax;
     147              :                 number m_alpha;
     148              :                 number m_beta;
     149              : 
     150              :                 bool m_bWeighted;
     151              :                 SmartPtr<GF> m_weight;
     152              : 
     153              :         ///     components, whose matrix row must be fulfilled completely on gs-block
     154              :                 std::vector<std::string> m_vFullRowCmp;
     155              : 
     156              :         /// smooth order
     157              :                 std::vector<int> m_vGroupObj;
     158              :                 std::vector<number> m_vDamp;
     159              : 
     160              :         ///     caching storage
     161              :                 DimCache m_vDimCache[VOLUME+1];
     162              : };
     163              : 
     164              : template <typename TDomain, typename TAlgebra>
     165            0 : bool ComponentGaussSeidel<TDomain, TAlgebra>::
     166              : preprocess(SmartPtr<MatrixOperator<matrix_type, vector_type> > pOp)
     167              : {
     168              : #ifdef UG_PARALLEL
     169              :         if(pcl::NumProcs() > 1)
     170              :         {
     171              :                 //      copy original matrix
     172              :                 MakeConsistent(*pOp, m_A);
     173              :                 //      set zero on slaves
     174              :                 std::vector<IndexLayout::Element> vIndex;
     175              :                 CollectUniqueElements(vIndex,  m_A.layouts()->slave());
     176              :                 SetDirichletRow(m_A, vIndex);
     177              :         }
     178              : #endif
     179              : 
     180            0 :         m_bInit = false;
     181              : 
     182            0 :         return true;
     183              : }
     184              : 
     185              : template <typename TDomain, typename TAlgebra>
     186            0 : void ComponentGaussSeidel<TDomain, TAlgebra>::
     187              : apply_blocks(const matrix_type& A, GF& c,
     188              :              const vector_type& d, number relax,
     189              :              const DimCache& dimCache,
     190              :              bool bReverse)
     191              : {
     192              : //      memory for local algebra
     193              :         DenseVector< VariableArray1<number> > s;
     194              :         DenseVector< VariableArray1<number> > x;
     195              : 
     196              : //      get caches
     197              :         const std::vector<std::vector<DoFIndex> >& vvDoFIndex = dimCache.vvDoFIndex;
     198              :         const std::vector<DenseMatrix< VariableArray2<number> > >& vBlockInverse = dimCache.vBlockInverse;
     199              : 
     200              : //      loop blocks
     201            0 :         for(size_t b = 0; b < vvDoFIndex.size(); ++b)
     202              :         {
     203            0 :                 size_t block = (!bReverse) ? b : (vvDoFIndex.size()-1 - b);
     204              : 
     205              :         //      get storage
     206              :                 const std::vector<DoFIndex>& vDoFIndex = vvDoFIndex[block];
     207              :                 const DenseMatrix<VariableArray2<number> >& BlockInv = vBlockInverse[block];
     208              :                 const size_t numIndex = vDoFIndex.size();
     209              : 
     210              :         //      compute s[j] := d[j] - sum_k A(j,k)*c[k]
     211              :         //      note: the loop over k is the whole matrix row (not only selected indices)
     212              :                 typedef typename matrix_type::const_row_iterator const_row_iterator;
     213              :                 const static int blockSize = TAlgebra::blockSize;
     214            0 :                 s.resize(numIndex);
     215            0 :                 for (size_t j = 0; j<numIndex; j++){
     216            0 :                         typename vector_type::value_type sj = d[vDoFIndex[j][0]];
     217              :                         for(const_row_iterator it = A.begin_row(vDoFIndex[j][0]);
     218            0 :                                                                         it != A.end_row(vDoFIndex[j][0]) ; ++it){
     219            0 :                                 MatMultAdd(sj, 1.0, sj, -1.0, it.value(), c[it.index()]);
     220              :                         };
     221            0 :                         s.subassign(j*blockSize,sj);
     222              :                 };
     223              : 
     224              :         //      solve block
     225            0 :                 x.resize(numIndex);
     226            0 :                 MatMult(x, relax, BlockInv, s);
     227              : 
     228              :         //      add to global correction
     229            0 :                 for (size_t j=0;j<numIndex;j++)
     230            0 :                         DoFRef(c, vDoFIndex[j]) += x[j];
     231              :         }
     232            0 : }
     233              : 
     234              : 
     235              : template <typename TDomain, typename TAlgebra>
     236            0 : void ComponentGaussSeidel<TDomain, TAlgebra>::
     237              : apply_blocks_weighted(const matrix_type& A, GF& c,
     238              :              const vector_type& d, number relax,
     239              :              const DimCache& dimCache,
     240              :              bool bReverse)
     241              : {
     242              : //      memory for local algebra
     243              :         DenseVector< VariableArray1<number> > s;
     244              :         DenseVector< VariableArray1<number> > x;
     245              : 
     246              : //      get caches
     247              :         const std::vector<std::vector<DoFIndex> >& vvDoFIndex = dimCache.vvDoFIndex;
     248              :         const std::vector<DenseMatrix< VariableArray2<number> > >& vBlockInverse = dimCache.vBlockInverse;
     249              : 
     250              : //      loop blocks
     251            0 :         for(size_t b = 0; b < vvDoFIndex.size(); ++b)
     252              :         {
     253            0 :                 size_t block = (!bReverse) ? b : (vvDoFIndex.size()-1 - b);
     254              : 
     255              :         //      get storage
     256              :                 const std::vector<DoFIndex>& vDoFIndex = vvDoFIndex[block];
     257              :                 const DenseMatrix<VariableArray2<number> >& BlockInv = vBlockInverse[block];
     258              :                 const size_t numIndex = vDoFIndex.size();
     259              : 
     260              :         //      compute s[i] := d[i] - sum_k A(i,k)*c[k]
     261              :         //      note: the loop over k is the whole matrix row (not only selected indices)
     262              :                 typedef typename matrix_type::const_row_iterator const_row_iterator;
     263              :                 const static int blockSize = TAlgebra::blockSize;
     264            0 :                 s.resize(numIndex);
     265            0 :                 for (size_t i = 0; i<numIndex; i++)
     266              :                 {
     267            0 :                         typename vector_type::value_type si = d[vDoFIndex[i][0]];
     268              :                         for(const_row_iterator it = A.begin_row(vDoFIndex[i][0]);
     269            0 :                                                                         it != A.end_row(vDoFIndex[i][0]) ; ++it)
     270              :                         {
     271            0 :                                 MatMultAdd(si, 1.0, si, -1.0, it.value(), c[it.index()]);
     272              :                         }
     273            0 :                         s.subassign(i*blockSize, si);
     274              :                 }
     275              : 
     276              :         // restrict
     277            0 :                 for (size_t i = 0; i<numIndex; ++i)
     278              :                 {
     279            0 :                         number wi = sqrt(DoFRef(*m_weight, vDoFIndex[i]));
     280              :                         UG_ASSERT(wi!=0.0, "Huhh: Zero weights found!" << i << "dofIndex" << vDoFIndex[i])
     281            0 :                         s[i] /= wi;
     282              :                 }
     283              : 
     284              :         //      solve block
     285            0 :                 x.resize(numIndex);
     286            0 :                 MatMult(x, relax, BlockInv, s);
     287              : 
     288              :         //      add to global correction
     289            0 :                 for (size_t i=0; i<numIndex;i++)
     290              :                 {
     291            0 :                         number wi = sqrt(DoFRef(*m_weight, vDoFIndex[i]));
     292            0 :                         DoFRef(c, vDoFIndex[i]) += x[i]/wi;
     293              :                 }
     294              :         }
     295            0 : }
     296              : 
     297              : // extract_by_grouping(std::vector<std::vector<DoFIndex> >& vvDoFIndex,
     298              : template<typename TGroupObj, typename GF>
     299            0 : void extract_by_grouping(std::vector<std::vector<DoFIndex> >& vvDoFIndex,
     300              :                     const GF& c,
     301              :                     const std::vector<size_t>& vFullRowCmp,
     302              :                     const std::vector<size_t>& vRemainCmp)
     303              : {
     304              : 
     305              :         typedef typename GF::element_type Element;
     306              : 
     307              : //      memory for local algebra
     308              :         std::vector<DoFIndex> vFullRowDoFIndex;
     309              :         std::vector<Element*> vElem;
     310              : 
     311              : //      clear indices
     312              : //      \todo: improve this by precomputing size
     313              :         vvDoFIndex.clear();
     314              : 
     315              : // loop all grouping objects
     316              :         typedef typename GF::template traits<TGroupObj>::const_iterator GroupObjIter;
     317            0 :         for(GroupObjIter iter = c.template begin<TGroupObj>();
     318            0 :                                          iter != c.template end<TGroupObj>(); ++iter)
     319              :         {
     320              :         //      get grouping obj
     321              :                 TGroupObj* groupObj = *iter;
     322              : 
     323              :         //      get all dof indices on obj associated to cmps
     324              :                 vFullRowDoFIndex.clear();
     325            0 :                 for(size_t f = 0; f < vFullRowCmp.size(); ++f)
     326            0 :                         c.inner_dof_indices(groupObj, vFullRowCmp[f], vFullRowDoFIndex, false);
     327              : 
     328              :         //      check if equation present
     329            0 :                 if(vFullRowDoFIndex.empty())
     330            0 :                         UG_THROW("extract_by_grouping: Should not happen.");
     331              : 
     332              :         //      get all algebraic indices on element
     333              :                 if(TGroupObj::dim <= VERTEX){
     334              :                         std::vector<Edge*> vSub;
     335              :                         c.collect_associated(vSub, groupObj);
     336            0 :                         for(size_t i = 0; i < vSub.size(); ++i)
     337            0 :                                 for(size_t f = 0; f < vFullRowCmp.size(); ++f)
     338            0 :                                         c.inner_dof_indices(vSub[i], vFullRowCmp[f], vFullRowDoFIndex, false);
     339            0 :                 }
     340              :                 if(TGroupObj::dim <= EDGE){
     341              :                         std::vector<Face*> vSub;
     342              :                         c.collect_associated(vSub, groupObj);
     343            0 :                         for(size_t i = 0; i < vSub.size(); ++i)
     344            0 :                                 for(size_t f = 0; f < vFullRowCmp.size(); ++f)
     345            0 :                                         c.inner_dof_indices(vSub[i], vFullRowCmp[f], vFullRowDoFIndex, false);
     346            0 :                 }
     347              : 
     348              :         //      collect elems associated to grouping object
     349              :                 c.collect_associated(vElem, groupObj);
     350              : 
     351              :         //      get all algebraic indices on element
     352              :                 std::vector<DoFIndex> vDoFIndex;
     353            0 :                 for(size_t i = 0; i < vElem.size(); ++i)
     354            0 :                         for(size_t f = 0; f < vRemainCmp.size(); ++f)
     355            0 :                                 c.dof_indices(vElem[i], vRemainCmp[f], vDoFIndex, false, false);
     356              : 
     357              :         //      check for dublicates
     358            0 :                 if(vElem.size() > 1){
     359            0 :                     std::sort(vDoFIndex.begin(), vDoFIndex.end());
     360            0 :                     vDoFIndex.erase(std::unique(vDoFIndex.begin(), vDoFIndex.end()), vDoFIndex.end());
     361              :                 }
     362              : 
     363              :         //      concat all indices
     364            0 :                 vDoFIndex.insert(vDoFIndex.end(), vFullRowDoFIndex.begin(), vFullRowDoFIndex.end());
     365              : 
     366              :         //      add
     367            0 :                 vvDoFIndex.push_back(vDoFIndex);
     368              :         }
     369            0 : }
     370              : 
     371              : template <typename TDomain, typename TAlgebra>
     372            0 : void ComponentGaussSeidel<TDomain, TAlgebra>::
     373              : extract_blocks(const matrix_type& A, const GF& c)
     374              : {
     375              : 
     376              :         ConstSmartPtr<DoFDistributionInfo> ddinfo =
     377            0 :                                                         c.approx_space()->dof_distribution_info();
     378              : 
     379              :         // tokenize passed functions
     380            0 :         if(m_vFullRowCmp.empty())
     381            0 :                 UG_THROW("ComponentGaussSeidel: No components set.")
     382              : 
     383              :         // get ids of selected functions
     384              :         std::vector<size_t> vFullRowCmp;
     385            0 :         for(size_t i = 0; i < m_vFullRowCmp.size(); ++i)
     386            0 :                 vFullRowCmp.push_back(ddinfo->fct_id_by_name(m_vFullRowCmp[i].c_str()));
     387              : 
     388              :         // compute remaining functions
     389              :         std::vector<size_t> vRemainCmp;
     390            0 :         for(size_t f = 0; f < ddinfo->num_fct(); ++f)
     391            0 :                 if(std::find(vFullRowCmp.begin(), vFullRowCmp.end(), f) == vFullRowCmp.end())
     392            0 :                         vRemainCmp.push_back(f);
     393              : 
     394              :         /// Create 'm_vGroupObj' contain all dimensions containg objects from 'vFullRowCmp'
     395            0 :         if(m_vGroupObj.empty()){
     396            0 :                 for(int d = VERTEX; d <= VOLUME; ++d){
     397              :                         bool bCarryDoFs = false;
     398            0 :                         for(size_t f = 0; f < vFullRowCmp.size(); ++f)
     399            0 :                                 if(ddinfo->max_fct_dofs(vFullRowCmp[f], d) > 0)
     400              :                                         bCarryDoFs = true;
     401            0 :                         if(bCarryDoFs)
     402            0 :                                 m_vGroupObj.push_back(d);
     403              :                 }
     404              :         }
     405              : 
     406              : //      extract for each dim-grouping objects
     407            0 :         for(int d = VERTEX; d <= VOLUME; ++d)
     408              :         {
     409              :         //      only extract if needed
     410            0 :                 if(std::find(m_vGroupObj.begin(), m_vGroupObj.end(), d) == m_vGroupObj.end())
     411            0 :                         continue;
     412              : 
     413              :         //      only extract if carrying dofs
     414              :                 bool bCarryDoFs = false;
     415            0 :                 for(size_t f = 0; f < vFullRowCmp.size(); ++f)
     416            0 :                         if(ddinfo->max_fct_dofs(vFullRowCmp[f], d) > 0)
     417              :                                 bCarryDoFs = true;
     418            0 :                 if(!bCarryDoFs)
     419            0 :                         continue;
     420              : 
     421              :         //      extract
     422            0 :                 std::vector<std::vector<DoFIndex> >& vvDoFIndex = m_vDimCache[d].vvDoFIndex;
     423            0 :                 switch(d){
     424            0 :                         case VERTEX: extract_by_grouping<Vertex, GF>(vvDoFIndex, c, vFullRowCmp, vRemainCmp); break;
     425            0 :                         case EDGE:   extract_by_grouping<Edge, GF>(vvDoFIndex, c, vFullRowCmp, vRemainCmp); break;
     426            0 :                         case FACE:   extract_by_grouping<Face, GF>(vvDoFIndex, c, vFullRowCmp, vRemainCmp); break;
     427            0 :                         case VOLUME: extract_by_grouping<Volume, GF>(vvDoFIndex, c, vFullRowCmp, vRemainCmp); break;
     428            0 :                         default: UG_THROW("wrong dim");
     429              :                 }
     430              :         }
     431              : 
     432              :         // compute weights v(i) (= number of groups j that i belongs to)
     433            0 :         if (m_bWeighted)
     434              :         {
     435            0 :                 m_weight = c.clone_without_values();
     436              :                 m_weight->set(0.0);
     437            0 :                 for(int d = VERTEX; d <= VOLUME; ++d)
     438              :                 {
     439              :                         std::vector<std::vector<DoFIndex> >& vvDoFIndex = m_vDimCache[d].vvDoFIndex;
     440              : 
     441            0 :                         for(size_t j = 0; j < vvDoFIndex.size(); ++j)
     442              :                         {
     443              : 
     444              :                                 std::vector<DoFIndex>& vDoFIndex = vvDoFIndex[j];
     445              :                                 const size_t numIndex = vDoFIndex.size();
     446              : 
     447              :                                         // count number of connections for this row
     448            0 :                                         DoFRef(*m_weight, vDoFIndex[numIndex-1]) = 1.0;
     449            0 :                                         for (size_t i =0; i<numIndex-1; ++i)
     450            0 :                                                 DoFRef(*m_weight, vDoFIndex[i]) += 1.0;
     451              :                         }
     452              : 
     453              :                 }
     454              :         }
     455              : 
     456              :         //      extract local matrices
     457            0 :         for(int d = VERTEX; d <= VOLUME; ++d)
     458              :         {
     459              :                 std::vector<std::vector<DoFIndex> >& vvDoFIndex = m_vDimCache[d].vvDoFIndex;
     460            0 :                 std::vector<DenseMatrix<VariableArray2<number> > >& vBlockInverse = m_vDimCache[d].vBlockInverse;
     461              : 
     462            0 :                 vBlockInverse.resize(vvDoFIndex.size());
     463            0 :                 for(size_t b = 0; b < vvDoFIndex.size(); ++b)
     464              :                 {
     465              :                 //      get storage
     466              :                         std::vector<DoFIndex>& vDoFIndex = vvDoFIndex[b];
     467              :                         DenseMatrix<VariableArray2<number> >& BlockInv = vBlockInverse[b];
     468              : 
     469              :                 //      get number of indices on patch
     470              :                         const size_t numIndex = vDoFIndex.size();
     471              :                         // std::cerr << "locSize" << numIndex << std::endl;
     472              : 
     473              :                 //      fill local block matrix
     474            0 :                         BlockInv.resize(numIndex, numIndex);
     475            0 :                         BlockInv = 0.0;
     476              : 
     477              :                 //      copy matrix rows (only including cols of selected indices)
     478            0 :                         for (size_t i = 0; i < numIndex; i++)
     479              :                         {
     480              :                                 // Diag (A)
     481            0 :                                 BlockInv(i,i) = m_alpha*DoFRef(A, vDoFIndex[i], vDoFIndex[i]);
     482            0 :                                 BlockInv(numIndex-1,i) = DoFRef(A, vDoFIndex[numIndex-1], vDoFIndex[i]);
     483            0 :                                 BlockInv(i,numIndex-1) = DoFRef(A, vDoFIndex[i], vDoFIndex[numIndex-1]);
     484              : 
     485              :                                 //for (size_t k = 0; k < numIndex; k++)
     486              :                                 //      BlockInv(i,k) = DoFRef(A, vDoFIndex[i], vDoFIndex[k]);
     487              :                         }
     488              : 
     489              : 
     490              :                         // schur complement correction
     491              : 
     492              : 
     493              :                         number schur = 0.0;
     494            0 :                         if (m_weight.invalid())
     495              :                         {
     496            0 :                                 for (size_t i = 0; i < numIndex-1; i++)
     497              :                                 {
     498            0 :                                         schur += BlockInv(numIndex-1,i)/BlockInv(i,i)*BlockInv(i,numIndex-1);
     499              :                                 }
     500              :                                 // std::cerr << "unweighted:" << schur << " " << BlockInv(numIndex-1, numIndex-1)<< m_beta<<  "=>";
     501              : 
     502            0 :                                 BlockInv(numIndex-1, numIndex-1) = schur + (BlockInv(numIndex-1, numIndex-1)-schur)/m_beta;
     503              : 
     504              :                                 //std::cerr << BlockInv(numIndex-1, numIndex-1) << std::endl;
     505              : 
     506              :                         } else {
     507            0 :                                 for (size_t i = 0; i < numIndex-1; i++)
     508              :                                 {
     509            0 :                                         number wi2 = DoFRef(*m_weight, vDoFIndex[i]);
     510            0 :                                         schur += wi2*BlockInv(numIndex-1,i)/BlockInv(i,i)*BlockInv(i,numIndex-1);
     511              :                                 }
     512              :                            //std::cerr <<  "weighted:"<< schur << " " << BlockInv(numIndex-1, numIndex-1)<< m_beta<<  "=>";
     513              : 
     514              :                            //  BlockInv(numIndex-1, numIndex-1) = - schur - (BlockInv(numIndex-1, numIndex-1)-schur)/m_beta; // worked with alpha=1, beta=-2.0
     515            0 :                            BlockInv(numIndex-1, numIndex-1) =  schur + (BlockInv(numIndex-1, numIndex-1) - schur)/m_beta;
     516              : 
     517              :                            //std::cerr << BlockInv(numIndex-1, numIndex-1) << std::endl;
     518              :                         }
     519              : 
     520              : 
     521              :                         //BlockInv(numIndex-1, numIndex-1) = - 2.0*schur;
     522              : 
     523              : 
     524              : 
     525              : 
     526              :                 //      get inverse
     527            0 :                         if(!Invert(BlockInv)){
     528            0 :                                 std::stringstream ss;
     529            0 :                                 ss << d <<"dim - Elem-Mat "<<b<<" singular. size: "<<numIndex<<"\n";
     530            0 :                                 for (size_t j = 0; j < numIndex; j++)
     531            0 :                                         ss << vDoFIndex[j][0] << ", ";
     532            0 :                                 ss << "\n";
     533              : 
     534            0 :                                 BlockInv = 0.0;
     535            0 :                                 for (size_t j = 0; j < numIndex; j++)
     536            0 :                                         for (size_t k = 0; k < numIndex; k++)
     537            0 :                                                 BlockInv(j,k) = DoFRef(A, vDoFIndex[j], vDoFIndex[k]);
     538              : 
     539            0 :                                 ss << BlockInv;
     540              : 
     541            0 :                                 UG_THROW(ss.str());
     542            0 :                         }
     543              :                 }
     544              :         }
     545              : 
     546            0 :         m_bInit = true;
     547            0 : }
     548              : 
     549              : template <typename TDomain, typename TAlgebra>
     550            0 : bool ComponentGaussSeidel<TDomain, TAlgebra>::
     551              : step(SmartPtr<MatrixOperator<matrix_type, vector_type> > pOp, vector_type& c, const vector_type& d)
     552              : {
     553              : //      check that grid funtion passed
     554              :         GridFunction<TDomain, TAlgebra>* pC
     555            0 :                                         = dynamic_cast<GridFunction<TDomain, TAlgebra>*>(&c);
     556            0 :         if(pC == NULL)
     557            0 :                 UG_THROW("ComponentGaussSeidel: expects correction to be a GridFunction.");
     558              : 
     559              :         const vector_type* pD = &d;
     560              :         const matrix_type* pMat = pOp.get();
     561              : #ifdef UG_PARALLEL
     562              :         SmartPtr<vector_type> spDtmp;
     563              :         if(pcl::NumProcs() > 1){
     564              :         //      make defect unique
     565              :                 spDtmp = d.clone();
     566              :                 spDtmp->change_storage_type(PST_UNIQUE);
     567              :                 pD = spDtmp.get();
     568              :                 pMat = &m_A;
     569              :         }
     570              : #endif
     571              : 
     572              : //      check if initialized
     573            0 :         if(!m_bInit)
     574            0 :                 extract_blocks(*pMat, *pC);
     575              : 
     576              : //      set correction to zero
     577              :         pC->set(0.0);
     578              : 
     579              : //      loop Grouping objects
     580            0 :         for(size_t i = 0; i < m_vGroupObj.size(); ++i)
     581              :         {
     582              :         //      get its dimension
     583            0 :                 const int d = m_vGroupObj[i];
     584              : 
     585              :         //      get relax param
     586            0 :                 number damp = m_relax;
     587            0 :                 if(d < (int)m_vDamp.size()) damp *= m_vDamp[d];
     588              : 
     589              :         //      apply
     590            0 :                 if (m_weight.invalid()) {
     591            0 :                         apply_blocks(*pMat, *pC, *pD, damp, m_vDimCache[d], false);
     592            0 :                         apply_blocks(*pMat, *pC, *pD, damp, m_vDimCache[d], true);
     593              :                 } else {
     594            0 :                         apply_blocks_weighted(*pMat, *pC, *pD, damp, m_vDimCache[d], false);
     595            0 :                         apply_blocks_weighted(*pMat, *pC, *pD, damp, m_vDimCache[d], true);
     596              :                 }
     597              : 
     598              :         }
     599              : 
     600              : #ifdef UG_PARALLEL
     601              :          pC->set_storage_type(PST_UNIQUE);
     602              : #endif
     603              : 
     604            0 :         return true;
     605              : }
     606              : 
     607              : 
     608              : template <typename TDomain, typename TAlgebra>
     609              : SmartPtr<ILinearIterator<typename TAlgebra::vector_type> >
     610            0 : ComponentGaussSeidel<TDomain, TAlgebra>::clone()
     611              : {
     612              :         SmartPtr<ComponentGaussSeidel<TDomain, TAlgebra> >
     613            0 :                                         newInst(new ComponentGaussSeidel<TDomain, TAlgebra>(m_relax, m_vFullRowCmp, m_vGroupObj, m_vDamp));
     614            0 :         newInst->set_debug(debug_writer());
     615            0 :         newInst->set_damp(this->damping());
     616            0 :         newInst->set_alpha(this->m_alpha);
     617            0 :         newInst->set_beta(this->m_beta);
     618            0 :         newInst->set_weights(this->m_bWeighted);
     619            0 :         return newInst;
     620              : }
     621              : 
     622              : 
     623              : } // end namespace ug
     624              : 
     625              : #endif /* __H__UG__LIB_DISC__OPERATOR__LINEAR_OPERATOR__COMPONENT_GAUSS_SEIDEL__ */
        

Generated by: LCOV version 2.0-1