Memosa-FVM  0.2
AMG.cpp
Go to the documentation of this file.
1 // This file os part of FVM
2 // Copyright (c) 2012 FVM Authors
3 // See LICENSE file for terms.
4 
5 #ifdef FVM_PARALLEL
6 #include <mpi.h>
7 #endif
8 
9 #include "AMG.h"
10 #include "LinearSystemMerger.h"
11 #include "CRConnectivity.h"
12 #include <set>
13 int AMG::amg_indx = 0;
14 
16  maxCoarseLevels(30),
17  nPreSweeps(0),
18  nPostSweeps(1),
19  coarseGroupSize(2),
20  weightRatioThreshold(0.65),
21  cycleType(V_CYCLE),
22  smootherType(GAUSS_SEIDEL),
23  scaleCorrections(true),
24  _finestLinearSystem(0),
25  _mergeLevelSize(0),
26  _mergeLevel(-1),
27  _isMerge(false),
28  _totalIterations(0),
29 #ifdef FVM_PARALLEL
30  _commTarget(MPI::COMM_WORLD),
31 #endif
32  _isCOMMWORLD(true)
33 {
34  logCtor();
35 
36 }
37 
39 {
40  logDtor();
41 }
42 
43 void
44 AMG::doSweeps(const int nSweeps, const int level)
45 {
46 
47  LinearSystem& ls = (level == 0) ?
49 
50  const MultiFieldMatrix& m = ls.getMatrix();
51  MultiField& delta = ls.getDelta();
52  const MultiField& b = ls.getB();
53  MultiField& r = ls.getResidual();
54 
55  for(int i=0; i<nSweeps; i++)
56  {
58  {
59  m.forwardGS(delta,b,r);
60  m.reverseGS(delta,b,r);
61  }
62  else
63  {
64  m.Jacobi(delta,b,r);
65  m.Jacobi(delta,b,r);
66  }
67  }
68 }
69 
70 void
71 AMG::cycle( CycleType cycleType, const int level)
72 {
73  doSweeps(nPreSweeps,level);
74 
75  if (level < (int)_coarseLinearSystems.size())
76  {
77  LinearSystem& fineLS = (level == 0) ?
79 
80 
81  LinearSystem& coarseLS = *_coarseLinearSystems[level];
82 
83 
84  MultiFieldMatrix& fineMatrix = fineLS.getMatrix();
85 
86  fineMatrix.computeResidual(fineLS.getDelta(),fineLS.getB(),fineLS.getResidual());
87  coarseLS.getB().zero();
88  coarseLS.getDelta().zero();
89 
90  fineMatrix.injectResidual(fineLS.getCoarseIndex(),
91  fineLS.getResidual(),
92  coarseLS.getB());
93 
94  int nextLevel = level+1;
95 #ifdef FVM_PARALLEL
96  if ( nextLevel == _mergeLevel )
97  {
98  _mergeLS->gatherB();
99  nextLevel++;
100  }
101 #endif
102  //if ( level == 4 )
103  // cycleType = W_CYCLE;
104 
105  cycle(cycleType,nextLevel);
106 
107  if (cycleType == W_CYCLE)
108  cycle(W_CYCLE,nextLevel);
109  else if (cycleType == F_CYCLE)
110  cycle(V_CYCLE,nextLevel);
111 
112 #ifdef FVM_PARALLEL
113  if ( level+1 == _mergeLevel ) {
114  _mergeLS->scatterDelta();
115  }
116 #endif
117 
118  MFRPtr scale;
119  if (coarseLS.isSymmetric && scaleCorrections)
120  {
121  const MultiField& x = coarseLS.getDelta();
122  const MultiField& b = coarseLS.getB();
123  const MultiFieldMatrix& A = coarseLS.getMatrix();
124  MFRPtr xb = x.dotWith(b);
125  xb->reduceSum();
126 
127  MFRPtr mxb = -(*xb);
128  MFRPtr xTAx = A.quadProduct(x);
129 
130  xTAx->reduceSum();
131 
132  scale = (*mxb)/(*xTAx);
133  scale->limit(1.0, 1.0);
134 
135  }
136 
137  fineMatrix.correctSolution(fineLS.getCoarseIndex(),
138  fineLS.getDelta(),
139  scale,
140  coarseLS.getDelta()) ;
141 
142 
143  }
144 
145 doSweeps(nPostSweeps,level);
146 
147 }
148 
149 void
151 {
152 
153  _coarseLinearSystems.clear();
154  for(int n=0; n<maxCoarseLevels; n++)
155  {
156  LinearSystem& fineLS = (n == 0) ?
158  shared_ptr<LinearSystem>
160 
161  coarseLS->isSymmetric = fineLS.isSymmetric;
162 
163  int isContinue = int( fineLS.getMatrix().getLocalSize() != coarseLS->getMatrix().getLocalSize() );
164 #ifdef FVM_PARALLEL
165  _commTarget.Allreduce(MPI::IN_PLACE, &isContinue, 1, MPI::INT, MPI::SUM);
166 #endif
167  if ( isContinue == 0 )
168  break;
169 
170 #ifdef FVM_PARALLEL
171  _coarseLinearSystems.push_back(coarseLS);
172 
173  int min_size = coarseLS->getMatrix().getMinSize( _commTarget );
174 
175 
176  if ( verbosity > 1 && MPI::COMM_WORLD.Get_rank() == 0 )
177  cout << " proc_id = " << MPI::COMM_WORLD.Get_rank() << " Created coarse level " << n << " of size "
178  << min_size << endl;
179 
180  if ( min_size <= 3 )
181  break;
182 
183  if ( coarseLS->getMatrix().getMergeSize( _commTarget ) < _mergeLevelSize && _mergeLevel == -1 && _isMerge ){
184  _mergeLevel = n+1;
185  set<int> group;
186  int size = MPI::COMM_WORLD.Get_size();
187  for ( int i = 0; i < size; i++ )
188  group.insert(i);
189 
190  _mergeLS = shared_ptr<LinearSystemMerger> ( new LinearSystemMerger( 0, group, *coarseLS ) );
191  _mergeLS->gatherMatrix();
192  _coarseLinearSystems.push_back( _mergeLS->getLS() );
193  n++;
194  flipComm(); //this change to COMM_WORLD to one-processedGROUP
195  }
196 
197 #endif
198 
199 #ifndef FVM_PARALLEL
200  if ( coarseLS->getMatrix().getSize() <= 3 )
201  break;
202  if ( verbosity > 1 )
203  cout << "Created coarse level " << n << " of size " << coarseLS->getMatrix().getSize() << endl;
204  _coarseLinearSystems.push_back(coarseLS);
205 #endif
206 
207  }
208 
209 
210 }
211 
212 void
214 {
216  _coarseLinearSystems.clear();
217 }
218 
219 MFRPtr
221 {
222  if (_finestLinearSystem != &ls)
223  {
224  _finestLinearSystem = &ls;
226  }
227  _finestLinearSystem = &ls;
228 
229 
230  const MultiFieldMatrix& finestMatrix = _finestLinearSystem->getMatrix();
234 
236 
237 #ifdef FVM_PARALLEL
238  if (verbosity >0 && MPI::COMM_WORLD.Get_rank() == 0 )
239  cout << "0: " << *rNorm0 << endl;
240 #endif
241 
242 #ifndef FVM_PARALLEL
243  if ( verbosity > 0 )
244  cout << "0: " << *rNorm0 << endl;
245 #endif
246 
247  if (*rNorm0 < absoluteTolerance )
248  return rNorm0;
249 
250  for(int i=1; i<nMaxIterations; i++)
251  {
253  cycle(cycleType,0);
258  MFRPtr normRatio(rNorm->normalize(*rNorm0));
259 
260 #ifndef FVM_PARALLEL
261  if (verbosity >0 )
262  cout << i << ": " << *rNorm << endl;
263 
264 
265 #endif
266 
267 
268 #ifdef FVM_PARALLEL
269  if (*rNorm < absoluteTolerance || *normRatio < relativeTolerance || i == nMaxIterations-1)
270  if (verbosity >0 && MPI::COMM_WORLD.Get_rank() == 0 )
271  cout <<i << ": " << *rNorm << endl;
272 #endif
273 
274  if (*rNorm < absoluteTolerance || *normRatio < relativeTolerance)
275  break;
276 
277  }
278 
280 
281  return rNorm0;
282 }
283 
284 
285 void
287 {
288  if (_finestLinearSystem != &ls)
289  {
290  _finestLinearSystem = &ls;
292  }
293  _finestLinearSystem = &ls;
294 
295  {
296  cycle(cycleType,0);
297  }
298 }
299 
300 
301 //this will flip COMM from COMM_WORLD to single-process goruped Communicator
302 void
304 {
305 
306 #ifdef FVM_PARALLEL
307  if ( _isCOMMWORLD ){
308  int color = ( MPI::COMM_WORLD.Get_rank() == 0 );
309  int key = MPI::COMM_WORLD.Get_rank();
310  _commTarget = MPI::COMM_WORLD.Split( color, key );
312  } else {
313  _commTarget = MPI::COMM_WORLD;
315  }
316 #endif
317 
318 
319 
320 }
321 
322 
323 //this will dump convergence history to file rather than screen
324 void
325 AMG::redirectPrintToFile( const string& fname ) {
326  m_filestr.open ( fname.c_str() );
327  m_backup = cout.rdbuf(); // back up cout's streambuf
328  m_psbuf = m_filestr.rdbuf(); // get file's streambuf
329  cout.rdbuf(m_psbuf);
330 }
331 
332 
333 void
335  cout.rdbuf(m_backup); // restore cout's original streambuf
336  m_filestr.close();
337 }
virtual void smooth(LinearSystem &ls)
Definition: AMG.cpp:286
int _mergeLevelSize
Definition: AMG.h:97
CycleType
Definition: AMG.h:31
int nPostSweeps
Definition: AMG.h:76
int nPreSweeps
Definition: AMG.h:75
void redirectPrintToScreen()
Definition: AMG.cpp:334
MultiField & getResidual()
Definition: LinearSystem.h:35
streambuf * m_backup
Definition: AMG.h:107
void createCoarseLevels()
Definition: AMG.cpp:150
void correctSolution(const MultiField &coarseIndex, MultiField &fineSolutionField, MFRPtr scaleField, const MultiField &coarseSolutionField)
virtual void forwardGS(IContainer &xB, const IContainer &bB, IContainer &temp) const
vector< shared_ptr< LinearSystem > > _coarseLinearSystems
Definition: AMG.h:87
virtual MFRPtr solve(LinearSystem &ls)
Definition: AMG.cpp:220
SmootherType smootherType
Definition: AMG.h:80
void redirectPrintToFile(const string &fname)
Definition: AMG.cpp:325
void doSweeps(const int nSweeps, const int level)
Definition: AMG.cpp:44
bool scaleCorrections
Definition: AMG.h:81
MultiField & getCoarseIndex()
Definition: LinearSystem.h:39
streambuf * m_psbuf
Definition: AMG.h:106
virtual void zero()
Definition: MultiField.cpp:115
#define logCtor()
Definition: RLogInterface.h:26
int getLocalSize() const
MultiField & getDelta()
Definition: LinearSystem.h:34
int _mergeLevel
Definition: AMG.h:98
ofstream m_filestr
Definition: AMG.h:108
int maxCoarseLevels
Definition: AMG.h:74
bool _isMerge
Definition: AMG.h:99
int _totalIterations
Definition: AMG.h:100
virtual void cleanup()
Definition: AMG.cpp:213
AMG()
Definition: AMG.cpp:15
int nMaxIterations
Definition: LinearSolver.h:31
shared_ptr< LinearSystemMerger > _mergeLS
Definition: AMG.h:88
shared_ptr< MultiFieldReduction > getOneNorm() const
Definition: MultiField.cpp:216
virtual void reverseGS(IContainer &xB, const IContainer &bB, IContainer &temp) const
double relativeTolerance
Definition: LinearSolver.h:33
bool _isCOMMWORLD
Definition: AMG.h:109
LinearSystem * _finestLinearSystem
Definition: AMG.h:86
virtual void computeResidual(const IContainer &xB, const IContainer &bB, IContainer &rB) const
shared_ptr< LinearSystem > createCoarse(const int groupSize, const double weightRatioThreshold)
virtual void Jacobi(IContainer &xB, const IContainer &bB, IContainer &tempB) const
#define logDtor()
Definition: RLogInterface.h:33
double absoluteTolerance
Definition: LinearSolver.h:34
MultiField & getB()
Definition: LinearSystem.h:33
static int amg_indx
Definition: AMG.h:95
virtual ~AMG()
Definition: AMG.cpp:38
shared_ptr< MultiFieldReduction > MFRPtr
void flipComm()
Definition: AMG.cpp:303
void cycle(CycleType cycleType, const int level)
Definition: AMG.cpp:71
CycleType cycleType
Definition: AMG.h:79
bool isSymmetric
Definition: LinearSystem.h:50
double weightRatioThreshold
Definition: AMG.h:78
shared_ptr< MultiFieldReduction > dotWith(const MultiField &ofield) const
Definition: MultiField.cpp:231
void sync()
Definition: MultiField.cpp:489
void injectResidual(const MultiField &coarseIndex, const MultiField &fineResidualField, MultiField &coarseBField)
MultiFieldMatrix & getMatrix()
Definition: LinearSystem.h:37
MFRPtr quadProduct(const MultiField &x) const
int coarseGroupSize
Definition: AMG.h:77