ViennaCL - The Vienna Computing Library  1.5.2
amg_coarse.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_LINALG_DETAIL_AMG_AMG_COARSE_HPP
2 #define VIENNACL_LINALG_DETAIL_AMG_AMG_COARSE_HPP
3 
4 /* =========================================================================
5  Copyright (c) 2010-2014, Institute for Microelectronics,
6  Institute for Analysis and Scientific Computing,
7  TU Wien.
8  Portions of this software are copyright by UChicago Argonne, LLC.
9 
10  -----------------
11  ViennaCL - The Vienna Computing Library
12  -----------------
13 
14  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15 
16  (A list of authors and contributors can be found in the PDF manual)
17 
18  License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20 
25 #include <cmath>
27 
28 #include <map>
29 #ifdef VIENNACL_WITH_OPENMP
30 #include <omp.h>
31 #endif
32 
34 
35 namespace viennacl
36 {
37  namespace linalg
38  {
39  namespace detail
40  {
41  namespace amg
42  {
43 
51  template <typename InternalType1, typename InternalType2, typename InternalType3>
52  void amg_coarse(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, InternalType3 & Slicing, amg_tag & tag)
53  {
54  switch (tag.get_coarse())
55  {
56  case VIENNACL_AMG_COARSE_RS: amg_coarse_classic (level, A, Pointvector, tag); break;
57  case VIENNACL_AMG_COARSE_ONEPASS: amg_coarse_classic_onepass (level, A, Pointvector, tag); break;
58  case VIENNACL_AMG_COARSE_RS0: amg_coarse_rs0 (level, A, Pointvector, Slicing, tag); break;
59  case VIENNACL_AMG_COARSE_RS3: amg_coarse_rs3 (level, A, Pointvector, Slicing, tag); break;
60  case VIENNACL_AMG_COARSE_AG: amg_coarse_ag (level, A, Pointvector, tag); break;
61  }
62  }
63 
70  template <typename InternalType1, typename InternalType2>
71  void amg_influence(unsigned int level, InternalType1 const & A, InternalType2 & Pointvector, amg_tag & tag)
72  {
73  typedef typename InternalType1::value_type SparseMatrixType;
74  typedef typename InternalType2::value_type PointVectorType;
75  typedef typename SparseMatrixType::value_type ScalarType;
76  typedef typename SparseMatrixType::value_type ScalarType;
77  typedef typename SparseMatrixType::const_iterator1 ConstRowIterator;
78  typedef typename SparseMatrixType::const_iterator2 ConstColIterator;
79 
80  ScalarType max;
81  int diag_sign;
82  //unsigned int i;
83 
84 #ifdef VIENNACL_WITH_OPENMP
85  #pragma omp parallel for private (max,diag_sign)
86 #endif
87  for (long i=0; i<static_cast<long>(A[level].size1()); ++i)
88  {
89  diag_sign = 1;
90  if (A[level](i,i) < 0)
91  diag_sign = -1;
92 
93  ConstRowIterator row_iter = A[level].begin1();
94  row_iter += i;
95  // Find greatest non-diagonal negative value (positive if diagonal is negative) in row
96  max = 0;
97  for (ConstColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
98  {
99  if (i == (unsigned int) col_iter.index2()) continue;
100  if (diag_sign == 1)
101  if (max > *col_iter) max = *col_iter;
102  if (diag_sign == -1)
103  if (max < *col_iter) max = *col_iter;
104  }
105 
106  // If maximum is 0 then the row is independent of the others
107  if (max == 0)
108  continue;
109 
110  // Find all points that strongly influence current point (Yang, p.5)
111  for (ConstColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
112  {
113  unsigned int j = static_cast<unsigned int>(col_iter.index2());
114  if (i == j) continue;
115  if (diag_sign * (-*col_iter) >= tag.get_threshold() * (diag_sign * (-max)))
116  {
117  // Strong influence from j to i found, save information
118  Pointvector[level][i]->add_influencing_point(Pointvector[level][j]);
119  }
120  }
121  }
122 
123  #ifdef VIENNACL_AMG_DEBUG
124  std::cout << "Influence Matrix: " << std::endl;
125  boost::numeric::ublas::matrix<bool> mat;
126  Pointvector[level].get_influence_matrix(mat);
127  printmatrix (mat);
128  #endif
129 
130  // Save influenced points
131  for (typename PointVectorType::iterator iter = Pointvector[level].begin(); iter != Pointvector[level].end(); ++iter)
132  {
133  for (typename amg_point::iterator iter2 = (*iter)->begin_influencing(); iter2 != (*iter)->end_influencing(); ++iter2)
134  {
135  (*iter2)->add_influenced_point(*iter);
136  }
137  }
138 
139  #ifdef VIENNACL_AMG_DEBUG
140  std::cout << "Influence Measures: " << std::endl;
141  boost::numeric::ublas::vector<unsigned int> temp;
142  Pointvector[level].get_influence(temp);
143  printvector (temp);
144  std::cout << "Point Sorting: " << std::endl;
145  Pointvector[level].get_sorting(temp);
146  printvector (temp);
147  #endif
148  }
149 
156  template <typename InternalType1, typename InternalType2>
157  void amg_coarse_classic_onepass(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, amg_tag & tag)
158  {
159  amg_point* c_point, *point1, *point2;
160 
161  // Check and save all strong influences
162  amg_influence (level, A, Pointvector, tag);
163 
164  // Traverse through points and calculate initial influence measure
165  long i;
166 #ifdef VIENNACL_WITH_OPENMP
167  #pragma omp parallel for private (i)
168 #endif
169  for (i=0; i<static_cast<long>(Pointvector[level].size()); ++i)
170  Pointvector[level][i]->calc_influence();
171 
172  // Do initial sorting
173  Pointvector[level].sort();
174 
175  // Get undecided point with highest influence measure
176  while ((c_point = Pointvector[level].get_nextpoint()) != NULL)
177  {
178  // Make this point C point
179  Pointvector[level].make_cpoint(c_point);
180 
181  // All strongly influenced points become F points