• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/data/development/ViennaCL/dev/viennacl/linalg/detail/amg/amg_coarse.hpp

Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_DETAIL_AMG_AMG_COARSE_HPP
00002 #define VIENNACL_LINALG_DETAIL_AMG_AMG_COARSE_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2011, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                   ViennaCL - The Vienna Computing Library
00011                             -----------------
00012 
00013    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00014                
00015    (A list of authors and contributors can be found in the PDF manual)
00016 
00017    License:         MIT (X11), see file LICENSE in the base directory
00018 ============================================================================= */
00019 
00024 #include <cmath>
00025 #include "viennacl/linalg/amg.hpp"
00026 
00027 #include <map>
00028 #ifdef _OPENMP
00029 #include <omp.h>
00030 #endif
00031 
00032 #include "amg_debug.hpp"
00033 
00034 namespace viennacl
00035 {
00036   namespace linalg
00037   {    
00038     namespace detail
00039     {
00040       namespace amg
00041       {
00042     
00050     template <typename InternalType1, typename InternalType2, typename InternalType3>
00051     void amg_coarse(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, InternalType3 & Slicing, amg_tag & tag)
00052     {
00053   switch (tag.get_coarse())
00054   {
00055     case VIENNACL_AMG_COARSE_RS: amg_coarse_classic (level, A, Pointvector, tag); break;
00056     case VIENNACL_AMG_COARSE_ONEPASS: amg_coarse_classic_onepass (level, A, Pointvector, tag); break;
00057     case VIENNACL_AMG_COARSE_RS0: amg_coarse_rs0 (level, A, Pointvector, Slicing, tag); break;
00058     case VIENNACL_AMG_COARSE_RS3: amg_coarse_rs3 (level, A, Pointvector, Slicing, tag); break;
00059     case VIENNACL_AMG_COARSE_AG:   amg_coarse_ag (level, A, Pointvector, tag); break;
00060   }
00061     } 
00062     
00069     template <typename InternalType1, typename InternalType2>
00070     void amg_influence(unsigned int level, InternalType1 const & A, InternalType2 & Pointvector, amg_tag & tag)
00071     {
00072       typedef typename InternalType1::value_type SparseMatrixType;
00073       typedef typename InternalType2::value_type PointVectorType;
00074       typedef typename SparseMatrixType::value_type ScalarType;
00075       typedef typename SparseMatrixType::value_type ScalarType;
00076       typedef typename SparseMatrixType::const_iterator1 ConstRowIterator;
00077       typedef typename SparseMatrixType::const_iterator2 ConstColIterator;
00078       
00079       ScalarType max;
00080       int diag_sign;
00081       //unsigned int i;
00082         
00083 #ifdef _OPENMP
00084       #pragma omp parallel for private (max,diag_sign) shared (A,Pointvector)
00085 #endif      
00086       for (unsigned int i=0; i<A[level].size1(); ++i)
00087       {  
00088   diag_sign = 1;
00089   if (A[level](i,i) < 0)
00090     diag_sign = -1;
00091   
00092   ConstRowIterator row_iter = A[level].begin1();
00093   row_iter += i;
00094   // Find greatest non-diagonal negative value (positive if diagonal is negative) in row
00095   max = 0;
00096   for (ConstColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
00097   {
00098       if (i == (unsigned int) col_iter.index2()) continue;
00099       if (diag_sign == 1)
00100         if (max > *col_iter)  max = *col_iter;
00101       if (diag_sign == -1)
00102         if (max < *col_iter)  max = *col_iter;
00103   }
00104   
00105   // If maximum is 0 then the row is independent of the others
00106   if (max == 0)
00107     continue;
00108   
00109   // Find all points that strongly influence current point (Yang, p.5)
00110   for (ConstColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
00111   {
00112     unsigned int j = col_iter.index2();  
00113     if (i == j) continue;
00114     if (diag_sign * (-*col_iter) >= tag.get_threshold() * (diag_sign * (-max)))
00115     {
00116       // Strong influence from j to i found, save information
00117       Pointvector[level][i]->add_influencing_point(Pointvector[level][j]);
00118     }
00119   }
00120       }
00121       
00122       #ifdef DEBUG
00123       std::cout << "Influence Matrix: " << std::endl;
00124       boost::numeric::ublas::matrix<bool> mat;
00125       Pointvector[level].get_influence_matrix(mat);
00126       printmatrix (mat);
00127       #endif
00128       
00129       // Save influenced points
00130       for (typename PointVectorType::iterator iter = Pointvector[level].begin(); iter != Pointvector[level].end(); ++iter)
00131       {
00132   for (typename amg_point::iterator iter2 = (*iter)->begin_influencing(); iter2 != (*iter)->end_influencing(); ++iter2)
00133   {
00134     (*iter2)->add_influenced_point(*iter);
00135   }
00136       }
00137         
00138       #ifdef DEBUG
00139       std::cout << "Influence Measures: " << std::endl;
00140       boost::numeric::ublas::vector<unsigned int> temp;
00141       Pointvector[level].get_influence(temp);
00142       printvector (temp);
00143       std::cout << "Point Sorting: " << std::endl;
00144       Pointvector[level].get_sorting(temp);
00145       printvector (temp);
00146       #endif 
00147     }
00148         
00155     template <typename InternalType1, typename InternalType2>
00156     void amg_coarse_classic_onepass(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, amg_tag & tag)
00157     {
00158       typedef typename InternalType1::value_type SparseMatrixType;
00159       typedef typename InternalType2::value_type PointVectorType;
00160       typedef typename SparseMatrixType::value_type ScalarType;
00161       
00162       typedef typename SparseMatrixType::iterator1 InternalRowIterator;
00163       typedef typename SparseMatrixType::iterator2 InternalColIterator;
00164       
00165       amg_point* c_point, *point1, *point2;
00166       unsigned int i;
00167         
00168       // Check and save all strong influences
00169       amg_influence (level, A, Pointvector, tag);    
00170       
00171       // Traverse through points and calculate initial influence measure
00172 #ifdef _OPENMP
00173       #pragma omp parallel for private (i) shared (Pointvector)
00174 #endif      
00175       for (i=0; i<Pointvector[level].size(); ++i)
00176   Pointvector[level][i]->calc_influence();
00177       
00178        // Do initial sorting
00179       Pointvector[level].sort();
00180       
00181       // Get undecided point with highest influence measure
00182       while ((c_point = Pointvector[level].get_nextpoint()) != NULL)
00183       {    
00184   // Make this point C point
00185   Pointvector[level].make_cpoint(c_point);
00186   
00187   // All strongly influenced points become F points
00188   for (typename amg_point::iterator iter = c_point->begin_influenced(); iter != c_point->end_influenced(); ++iter)
00189   {
00190     point1 = *iter;
00191     // Found strong influence from C point (c_point influences point1), check whether point is still undecided, otherwise skip
00192     if (!point1->is_undecided()) continue;
00193     // Make this point F point if it is still undecided point
00194     Pointvector[level].make_fpoint(point1);
00195     
00196     // Add +1 to influence measure for all undecided points that strongly influence new F point
00197     for (typename amg_point::iterator iter2 = point1->begin_influencing(); iter2 != point1->end_influencing(); ++iter2)
00198     {
00199       point2 = *iter2;
00200       // Found strong influence to F point (point2 influences point1)
00201       if (point2->is_undecided())
00202         Pointvector[level].add_influence(point2,1);
00203     }
00204   }
00205       }
00206       
00207       // If a point is neither C nor F point but is nevertheless influenced by other points make it F point
00208       // (this situation can happen when this point does not influence other points and the points that influence this point became F points already)
00209       /*#pragma omp parallel for private (i,point1)
00210       for (i=0; i<Pointvector[level].size(); ++i)
00211       {
00212   point1 = Pointvector[level][i];
00213   if (point1->is_undecided())
00214   {
00215     // Undecided point found. Check whether it is influenced by other point and if so: Make it F point.
00216     if (point1->number_influencing() > 0)
00217     {
00218       #pragma omp critical
00219       Pointvector[level].make_fpoint(point1);
00220     }
00221   }
00222       }*/
00223 
00224       #if defined (DEBUG)//  or defined (DEBUGBENCH)
00225       unsigned int c_points = Pointvector[level].get_cpoints();
00226       unsigned int f_points = Pointvector[level].get_fpoints();
00227       std::cout << "1st pass: Level " << level << ": ";
00228       std::cout << "No of C points = " << c_points << ", ";
00229       std::cout << "No of F points = " << f_points << std::endl;
00230       #endif
00231 
00232       #ifdef DEBUG
00233       std::cout << "Coarse Points:" << std::endl;
00234       boost::numeric::ublas::vector<bool> C;
00235       Pointvector[level].get_C(C);
00236       printvector (C);
00237       std::cout << "Fine Points:" << std::endl;
00238       boost::numeric::ublas::vector<bool> F;
00239       Pointvector[level].get_F(F);
00240       printvector (F);
00241       #endif
00242     }    
00243         
00250     template <typename InternalType1, typename InternalType2>
00251     void amg_coarse_classic(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, amg_tag & tag)
00252     {
00253       typedef typename InternalType1::value_type SparseMatrixType;
00254       typedef typename InternalType2::value_type PointVectorType;
00255       typedef typename SparseMatrixType::value_type ScalarType;
00256       
00257       typedef typename SparseMatrixType::iterator1 InternalRowIterator;
00258       typedef typename SparseMatrixType::iterator2 InternalColIterator;
00259       
00260       bool add_C;
00261       amg_point *c_point, *point1, *point2;     
00262       
00263       // Use one-pass-coarsening as first pass.
00264       amg_coarse_classic_onepass(level, A, Pointvector, tag);
00265     
00266       // 2nd pass: Add more C points if F-F connection does not have a common C point.
00267       for (typename PointVectorType::iterator iter = Pointvector[level].begin(); iter != Pointvector[level].end(); ++iter)
00268       {
00269   point1 = *iter;
00270   // If point is F point, check for strong connections.
00271   if (point1->is_fpoint())
00272   {
00273     // Check for strong connections from influencing and influenced points.
00274     amg_point::iterator iter2 = point1->begin_influencing();
00275     amg_point::iterator iter3 = point1->begin_influenced();
00276     
00277     // Iterate over both lists at once. This makes sure that points are no checked twice when influence relation is symmetric (which is often the case).
00278     // Note: Only works because influencing and influenced lists are sorted by point-index.
00279     while(iter2 != point1->end_influencing() || iter3 != point1->end_influenced())
00280     {     
00281       if (iter2 == point1->end_influencing())
00282       {
00283         point2 = *iter3;
00284         ++iter3;
00285       }
00286       else if (iter3 == point1->end_influenced())
00287       {
00288         point2 = *iter2;
00289         ++iter2;
00290       }
00291       else
00292       {      
00293         if ((*iter2)->get_index() == (*iter3)->get_index())   
00294         {
00295     point2 = *iter2;
00296     ++iter2;
00297     ++iter3;
00298         }
00299         else if ((*iter2)->get_index() < (*iter3)->get_index())
00300         {
00301     point2 = *iter2;
00302     ++iter2;
00303         }
00304         else
00305         {
00306     point2 = *iter3;
00307     ++iter3;
00308         }
00309       }
00310       // Only check points with higher index as points with lower index have been checked already.
00311       if (point2->get_index() < point1->get_index())
00312         continue;
00313       
00314       // If there is a strong connection then it has to either be a C point or a F point with common C point.
00315       // C point? Then skip as everything is ok.
00316       if (point2->is_cpoint())
00317         continue;
00318       // F point? Then check whether F points point1 and point2 have a common C point.
00319       if (point2->is_fpoint())
00320       {
00321         add_C = true;
00322         // C point is common for two F points if they are both strongly influenced by that C point.
00323         // Compare strong influences for point1 and point2.
00324         for (amg_point::iterator iter3 = point1->begin_influencing(); iter3 != point1 -> end_influencing(); ++iter3)
00325         {
00326     c_point = *iter3;
00327     // Stop search when strong common influence is found via c_point.
00328     if (c_point->is_cpoint())
00329     {
00330       if (point2->is_influencing(c_point))
00331       {
00332         add_C = false;
00333         break;            
00334       }
00335     }
00336         }
00337         // No common C point found? Then make second F point to C point.
00338         if (add_C == true)
00339     Pointvector[level].switch_ftoc(point2);
00340       }
00341     }
00342   }
00343       }
00344       
00345       #ifdef DEBUG
00346       std::cout << "After 2nd pass:" << std::endl;
00347       std::cout << "Coarse Points:" << std::endl;
00348       boost::numeric::ublas::vector<bool> C;
00349       Pointvector[level].get_C(C);
00350       printvector (C);
00351       std::cout << "Fine Points:" << std::endl;
00352       boost::numeric::ublas::vector<bool> F;
00353       Pointvector[level].get_F(F);
00354       printvector (F);
00355       #endif
00356 
00357       #ifdef DEBUG
00358 #ifdef _OPENMP
00359       #pragma omp critical
00360 #endif      
00361       {
00362       std::cout << "No C and no F point: ";
00363       for (typename PointVectorType::iterator iter = Pointvector[level].begin(); iter != Pointvector[level].end(); ++iter)
00364   if ((*iter)->is_undecided())
00365     std::cout << (*iter)->get_index() << " ";
00366       std::cout << std::endl;
00367       }
00368       #endif
00369     }
00370 
00378     template <typename InternalType1, typename InternalType2, typename InternalType3>
00379     void amg_coarse_rs0(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, InternalType3 & Slicing, amg_tag & tag)
00380     {
00381       typedef typename InternalType1::value_type SparseMatrixType;
00382       typedef typename InternalType2::value_type PointVectorType;
00383       typedef typename SparseMatrixType::value_type ScalarType;
00384       
00385       typedef typename SparseMatrixType::iterator1 InternalRowIterator;
00386       typedef typename SparseMatrixType::iterator2 InternalColIterator;
00387       
00388       unsigned int total_points;
00389       
00390       // Slice matrix into parts such that points are distributed among threads
00391       Slicing.slice(level, A, Pointvector);     
00392       
00393       // Run classical coarsening in parallel
00394       total_points = 0;
00395 #ifdef _OPENMP
00396       #pragma omp parallel for shared (total_points,Slicing,level)
00397 #endif      
00398       for (unsigned int i=0; i<Slicing._threads; ++i)
00399       {
00400   amg_coarse_classic(level,Slicing.A_slice[i],Slicing.Pointvector_slice[i],tag);
00401   
00402   // Save C points (using Slicing.Offset on the next level as temporary memory)
00403   // Note: Number of C points for point i is saved in i+1!! (makes it easier later to compute offset)
00404   Slicing.Offset[i+1][level+1] = Slicing.Pointvector_slice[i][level].get_cpoints();
00405 #ifdef _OPENMP
00406   #pragma omp critical
00407 #endif  
00408   total_points += Slicing.Pointvector_slice[i][level].get_cpoints();
00409       }      
00410       
00411       // If no coarser level can be found on any level then resume and coarsening will stop in amg_coarse()
00412       if (total_points != 0)
00413       {    
00414 #ifdef _OPENMP
00415   #pragma omp parallel for shared (Slicing)
00416 #endif  
00417   for (unsigned int i=0; i<Slicing._threads; ++i)
00418   {
00419     // If no higher coarse level can be found on slice i (saved in Slicing.Offset[i+1][level+1]) then pull C point(s) to the next level
00420     if (Slicing.Offset[i+1][level+1] == 0)
00421     {
00422       // All points become C points
00423       for (unsigned int j=0; j<Slicing.A_slice[i][level].size1(); ++j)
00424         Slicing.Pointvector_slice[i][level].make_cpoint(Slicing.Pointvector_slice[i][level][j]);
00425       Slicing.Offset[i+1][level+1] = Slicing.A_slice[i][level].size1();
00426     }
00427   }
00428     
00429   // Build slicing offset from number of C points (offset = total sum of C points on threads with lower number)
00430   for (unsigned int i=2; i<=Slicing._threads; ++i)
00431     Slicing.Offset[i][level+1] += Slicing.Offset[i-1][level+1];
00432       
00433   // Join C and F points
00434   Slicing.join(level, Pointvector);
00435       }
00436       
00437       // Calculate global influence measures for interpolation and/or RS3.
00438       amg_influence(level, A, Pointvector, tag); 
00439       
00440       #if defined(DEBUG)// or defined (DEBUGBENCH)
00441       for (unsigned int i=0; i<Slicing._threads; ++i)
00442       {
00443   unsigned int c_points = Slicing.Pointvector_slice[i][level].get_cpoints();
00444   unsigned int f_points = Slicing.Pointvector_slice[i][level].get_fpoints();
00445   std::cout << "Thread " << i << ": ";
00446   std::cout << "No of C points = " << c_points << ", ";
00447   std::cout << "No of F points = " << f_points << std::endl;
00448       }
00449       #endif
00450     }
00451     
00459     template <typename InternalType1, typename InternalType2, typename InternalType3>
00460     void amg_coarse_rs3(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, InternalType3 & Slicing, amg_tag & tag)
00461     {
00462       typedef typename InternalType1::value_type SparseMatrixType;
00463       typedef typename InternalType2::value_type PointVectorType;
00464       typedef typename SparseMatrixType::value_type ScalarType;
00465       
00466       typedef typename SparseMatrixType::iterator1 InternalRowIterator;
00467       typedef typename SparseMatrixType::iterator2 InternalColIterator;
00468       
00469       amg_point *c_point, *point1, *point2;
00470       bool add_C;
00471       unsigned int i, j;
00472             
00473       // Run RS0 first (parallel).
00474       amg_coarse_rs0(level, A, Pointvector, Slicing, tag);
00475       
00476       // Save slicing offset
00477       boost::numeric::ublas::vector<unsigned int> Offset = boost::numeric::ublas::vector<unsigned int> (Slicing.Offset.size());
00478       for (i=0; i<Slicing.Offset.size(); ++i)
00479   Offset[i] = Slicing.Offset[i][level];
00480       
00481       // Correct the coarsening with a third pass: Don't allow strong F-F connections without common C point
00482       for (i=0; i<Slicing._threads; ++i)
00483       {
00484   //for (j=Slicing.Offset[i][level]; j<Slicing.Offset[i+1][level]; ++j)
00485   for (j=Offset[i]; j<Offset[i+1]; ++j)
00486   {
00487     point1 = Pointvector[level][j];
00488     // If point is F point, check for strong connections.
00489     if (point1->is_fpoint())
00490     {
00491       // Check for strong connections from influencing and influenced points.
00492       amg_point::iterator iter2 = point1->begin_influencing();
00493       amg_point::iterator iter3 = point1->begin_influenced();
00494       
00495       // Iterate over both lists at once. This makes sure that points are no checked twice when influence relation is symmetric (which is often the case).
00496       // Note: Only works because influencing and influenced lists are sorted by point-index.
00497       while(iter2 != point1->end_influencing() || iter3 != point1->end_influenced())
00498       {     
00499         if (iter2 == point1->end_influencing())
00500         {
00501     point2 = *iter3;
00502     ++iter3;
00503         }
00504         else if (iter3 == point1->end_influenced())
00505         {
00506     point2 = *iter2;
00507     ++iter2;
00508         }
00509         else
00510         {      
00511     if ((*iter2)->get_index() == (*iter3)->get_index())   
00512     {
00513       point2 = *iter2;
00514       ++iter2;
00515       ++iter3;
00516     }
00517     else if ((*iter2)->get_index() < (*iter3)->get_index())
00518     {
00519       point2 = *iter2;
00520       ++iter2;
00521     }
00522     else
00523     {
00524       point2 = *iter3;
00525       ++iter3;
00526     }
00527         }
00528               
00529         // Only check points with higher index as points with lower index have been checked already.
00530         if (point2->get_index() < point1->get_index())
00531     continue;
00532                 
00533         // Only check points that are outside the slicing boundaries (interior F-F connections have already been checked in second pass)
00534         //if (point2->get_index() >= Slicing.Offset[i][level] || point2->get_index() < Slicing.Offset[i+1][level])
00535         if (point2->get_index() >= Offset[i] && point2->get_index() < Offset[i+1])
00536     continue;
00537         
00538         // If there is a strong connection then it has to either be a C point or a F point with common C point.
00539         // C point? Then skip as everything is ok.
00540         if (point2->is_cpoint())
00541     continue;
00542         // F point? Then check whether F points point1 and point2 have a common C point.
00543         if (point2->is_fpoint())
00544         {
00545     add_C = true;
00546     // C point is common for two F points if they are both strongly influenced by that C point.
00547     // Compare strong influences for point1 and point2.
00548     for (amg_point::iterator iter3 = point1->begin_influencing(); iter3 != point1 -> end_influencing(); ++iter3)
00549     {
00550       c_point = *iter3;
00551       // Stop search when strong common influence is found via c_point.
00552       if (c_point->is_cpoint())
00553       {
00554         if (point2->is_influencing(c_point))
00555         {
00556           add_C = false;
00557           break;            
00558         }
00559       }
00560     }
00561     // No common C point found? Then make second F point to C point.
00562     if (add_C == true)
00563     {
00564       Pointvector[level].switch_ftoc(point2);
00565       // Add +1 to offsets as one C point has been added.
00566       for (unsigned int j=i+1; j<=Slicing._threads; ++j)
00567         Slicing.Offset[j][level+1]++;
00568     }
00569         }
00570       }
00571     }
00572   }
00573       }
00574       
00575       #ifdef DEBUG
00576       std::cout << "After 3rd pass:" << std::endl;
00577       std::cout << "Coarse Points:" << std::endl;
00578       boost::numeric::ublas::vector<bool> C;
00579       Pointvector[level].get_C(C);
00580       printvector (C);
00581       std::cout << "Fine Points:" << std::endl;
00582       boost::numeric::ublas::vector<bool> F;
00583       Pointvector[level].get_F(F);
00584       printvector (F);
00585       #endif
00586 
00587       #ifdef DEBUG
00588       unsigned int i;
00589 #ifdef _OPENMP
00590       #pragma omp critical
00591 #endif      
00592       {
00593       std::cout << "No C and no F point: ";
00594       for (typename PointVectorType::iterator iter = Pointvector[level].begin(); iter != Pointvector[level].end(); ++iter)
00595   if ((*iter)->is_undecided())
00596     std::cout << i << " ";
00597       std::cout << std::endl;
00598       }
00599       #endif
00600     }
00601     
00609     template <typename InternalType1, typename InternalType2>
00610     void amg_coarse_ag(unsigned int level, InternalType1 & A, InternalType2 & Pointvector, amg_tag & tag)
00611     {
00612       typedef typename InternalType1::value_type SparseMatrixType;
00613       typedef typename InternalType2::value_type PointVectorType;
00614       typedef typename SparseMatrixType::value_type ScalarType;
00615       
00616       typedef typename SparseMatrixType::iterator1 InternalRowIterator;
00617       typedef typename SparseMatrixType::iterator2 InternalColIterator;
00618       
00619       unsigned int x,y;
00620       ScalarType diag;
00621       amg_point *pointx, *pointy;
00622     
00623       // Cannot determine aggregates if size == 1 as then a new aggregate would always consist of this point (infinite loop)
00624       if (A[level].size1() == 1) return;
00625       
00626       // SA algorithm (Vanek et al. p.6)     
00627       // Build neighborhoods
00628 #ifdef _OPENMP
00629       #pragma omp parallel for private (x,y,diag) shared (A)
00630 #endif      
00631       for (x=0; x<A[level].size1(); ++x)
00632       {
00633   InternalRowIterator row_iter = A[level].begin1();
00634   row_iter += x;
00635   diag = A[level](x,x);
00636   for (InternalColIterator col_iter = row_iter.begin(); col_iter != row_iter.end(); ++col_iter)
00637   {
00638     y = col_iter.index2();
00639     if (y == x || (std::abs(*col_iter) >= tag.get_threshold()*pow(0.5,level-1) * sqrt(std::abs(diag*A[level](y,y)))))
00640     {
00641       // Neighborhood x includes point y
00642       Pointvector[level][x]->add_influencing_point(Pointvector[level][y]);
00643     }
00644   }
00645       }
00646       
00647       #ifdef DEBUG
00648       std::cout << "Neighborhoods:" << std::endl;
00649       boost::numeric::ublas::matrix<bool> mat;
00650       Pointvector[level].get_influence_matrix(mat);
00651       printmatrix (mat);
00652       #endif
00653 
00654       // Build aggregates from neighborhoods  
00655       for (typename PointVectorType::iterator iter = Pointvector[level].begin(); iter != Pointvector[level].end(); ++iter)
00656       {
00657   pointx = (*iter);
00658   
00659   if (pointx->is_undecided())
00660   {
00661     // Make center of aggregate to C point and include it to aggregate x.
00662     Pointvector[level].make_cpoint(pointx);
00663     pointx->set_aggregate (pointx->get_index());
00664     for (amg_point::iterator iter2 = pointx->begin_influencing(); iter2 != pointx->end_influencing(); ++iter2)
00665     {
00666      pointy = (*iter2);
00667       
00668       if (pointy->is_undecided())
00669       {
00670         // Make neighbor y to F point and include it to aggregate x.
00671         Pointvector[level].make_fpoint(pointy);
00672         pointy->set_aggregate (pointx->get_index());
00673       }
00674     }
00675   }
00676       }
00677       
00678       #ifdef DEBUG
00679       std::cout << "After aggregation:" << std::endl;
00680       std::cout << "Coarse Points:" << std::endl;
00681       boost::numeric::ublas::vector<bool> C;
00682       Pointvector[level].get_C(C);
00683       printvector (C);
00684       std::cout << "Fine Points:" << std::endl;
00685       boost::numeric::ublas::vector<bool> F;
00686       Pointvector[level].get_F(F);
00687       printvector (F);
00688       std::cout << "Aggregates:" << std::endl;
00689       printvector (Aggregates[level]);          
00690       #endif
00691     }
00692       } //namespace amg
00693     }
00694   }
00695 }
00696 
00697 #endif

Generated on Fri Dec 30 2011 23:20:43 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1