Memosa-FVM  0.2
MultiFieldMatrix.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 #include "MultiFieldMatrix.h"
6 #include "CRConnectivity.h"
7 #include "MultiField.h"
8 #include "IContainer.h"
9 #include "StorageSite.h"
10 #include "OneToOneIndexMap.h"
11 #include "SpikeStorage.h"
12 #ifdef FVM_PARALLEL
13  #include "mpi.h"
14 #endif
15 
17  _matrices(),
18  _coarseSizes(),
19  _coarseGhostSizes(),
20  _coarseSites(),
21  _coarseToFineMappings(),
22  _coarseConnectivities(),
23  _coarseMatrices()
24 {
25  logCtor();
26 }
27 
29 {
30  logDtor();
31 }
32 
33 bool
35  const Index& col) const
36 {
37  EntryIndex i(row,col);
38  return _matrices.find(i) != _matrices.end();
39 }
40 
41 Matrix&
43  const Index& col)
44 {
45  EntryIndex i(row,col);
46  return *_matrices.find(i)->second;
47 }
48 
49 const Matrix&
51  const Index& col) const
52 {
53  EntryIndex i(row,col);
54  return *_matrices.find(i)->second;
55 }
56 
57 void
59 {
60  foreach(MatrixMap::value_type& pos, _matrices)
61  pos.second->initAssembly();
62 }
63 
64 void
66 {
67  MultiField& y = dynamic_cast<MultiField&>(yB);
68  const MultiField& x = dynamic_cast<const MultiField&>(xB);
69 
70  const int yLen = y.getLength();
71  const int xLen = x.getLength();
72 
73  //#pragma omp parallel for
74  for(int i=0; i<yLen; i++)
75  {
76  const Index rowIndex = y.getArrayIndex(i);
77  ArrayBase& yI = y[rowIndex];
78  yI.zero();
79  for(int j=0; j<xLen; j++)
80  {
81  const Index colIndex = x.getArrayIndex(j);
82  if (hasMatrix(rowIndex,colIndex))
83  {
84  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
85  mIJ.multiplyAndAdd(yI,x[colIndex]);
86  }
87  }
88  }
89 #ifdef FVM_PARALLEL
90  y.sync();
91 #endif
92 }
93 
94 void
96 {
97  MultiField& y = dynamic_cast<MultiField&>(yB);
98  const MultiField& x = dynamic_cast<const MultiField&>(xB);
99 
100  const int yLen = y.getLength();
101  const int xLen = x.getLength();
102 
103  //#pragma omp parallel for
104  for(int i=0; i<yLen; i++)
105  {
106  const Index rowIndex = y.getArrayIndex(i);
107  ArrayBase& yI = y[rowIndex];
108  for(int j=0; j<xLen; j++)
109  {
110  const Index colIndex = x.getArrayIndex(j);
111  if (hasMatrix(rowIndex,colIndex))
112  {
113  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
114  mIJ.multiplyAndAdd(yI,x[colIndex]);
115  }
116  }
117  }
118 
119 #ifdef FVM_PARALLEL
120  y.sync();
121 #endif
122 
123 }
124 
125 void
127 {
128  MultiField& x = dynamic_cast<MultiField&>(xB);
129  const MultiField& b = dynamic_cast<const MultiField&>(bB);
130  MultiField& temp = dynamic_cast<MultiField&>(tempB);
131 
132  const int xLen = x.getLength();
133  //#pragma omp parallel for
134  for(int i=0; i<xLen; i++)
135  {
136  const Index rowIndex = x.getArrayIndex(i);
137  if (hasMatrix(rowIndex,rowIndex))
138  {
139  const ArrayBase& bI = b[rowIndex];
140  ArrayBase& r = temp[rowIndex];
141  const StorageSite& rowSite = *rowIndex.second;
142  r.copyPartial(bI,0,rowSite.getSelfCount());
143 
144  for(int j=0; j<xLen; j++)
145  {
146  const Index colIndex = x.getArrayIndex(j);
147  if ((rowIndex!=colIndex) && hasMatrix(rowIndex,colIndex))
148  {
149  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
150  mIJ.multiplyAndAdd(r,x[colIndex]);
151  }
152  }
153 
154  const Matrix& mII = getMatrix(rowIndex,rowIndex);
155 #ifndef FVM_PARALLEL
156  x.syncGather(rowIndex);
157 #endif
158  mII.forwardGS(x[rowIndex],r,r);
159 #ifndef FVM_PARALLEL
160  x.syncScatter(rowIndex);
161 #endif
162  }
163  }
164  x.sync();
165 }
166 
167 void
169 {
170  MultiField& x = dynamic_cast<MultiField&>(xB);
171  const MultiField& b = dynamic_cast<const MultiField&>(bB);
172  MultiField& temp = dynamic_cast<MultiField&>(tempB);
173 
174  shared_ptr<MultiField> xnew = dynamic_pointer_cast<MultiField>(x.newClone());
175 
176  const int xLen = x.getLength();
177  //#pragma omp parallel for
178  for(int i=0; i<xLen; i++)
179  {
180  const Index rowIndex = x.getArrayIndex(i);
181  if (hasMatrix(rowIndex,rowIndex))
182  {
183  const ArrayBase& bI = b[rowIndex];
184  ArrayBase& r = temp[rowIndex];
185  const StorageSite& rowSite = *rowIndex.second;
186  r.copyPartial(bI,0,rowSite.getSelfCount());
187 
188  for(int j=0; j<xLen; j++)
189  {
190  const Index colIndex = x.getArrayIndex(j);
191  if ((rowIndex!=colIndex) && hasMatrix(rowIndex,colIndex))
192  {
193  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
194  mIJ.multiplyAndAdd(r,x[colIndex]);
195  }
196  }
197 
198  const Matrix& mII = getMatrix(rowIndex,rowIndex);
199  mII.Jacobi((*xnew)[rowIndex],x[rowIndex],r);
200 
201  }
202  }
203 
204  //#pragma omp parallel for
205  for(int i=0; i<xLen; i++)
206  {
207  const Index rowIndex = x.getArrayIndex(i);
208  if (hasMatrix(rowIndex,rowIndex))
209  {
210  const ArrayBase& xnewI = (*xnew)[rowIndex];
211  ArrayBase& xI = x[rowIndex];
212  const StorageSite& rowSite = *rowIndex.second;
213  xI.copyPartial(xnewI,0,rowSite.getSelfCount());
214  }
215  }
216  x.sync();
217 }
218 
219 void
221 {
222  // keep the transposed offdiagonals in this map since we can't modify _matrices while looping over it
223  MatrixMap transposedMap;
224 
225  foreach(const MatrixMap::value_type& pos, _matrices)
226  {
227  EntryIndex k = pos.first;
228 
229  if (k.first == k.second)
230  {
231  pos.second->transpose();
232  }
233  else
234  {
235  EntryIndex kt(k.second,k.first);
236  if ( (transposedMap.count(k) + transposedMap.count(kt)) == 0)
237  {
238  shared_ptr<Matrix> mIJ = pos.second;
239  mIJ->transpose();
240 
241  if (_matrices.find(kt) != _matrices.end())
242  {
243  shared_ptr<Matrix> mJI = _matrices[kt];
244  mJI->transpose();
245 
246  transposedMap[k] = mJI;
247  transposedMap[kt] = mIJ;
248  }
249  else
250  {
251  transposedMap[kt] = mIJ;
252  // store a null matrix so in the loop below we can
253  // erase the entry at this location in _matrices
254  transposedMap[k] = shared_ptr<Matrix>();
255  }
256  }
257  }
258  }
259 
260  // set the matrices from transposedMap in the transposed locations in _matrices
261  foreach(const MatrixMap::value_type& pos, transposedMap)
262  {
263  EntryIndex k = pos.first;
264 
265  if (pos.second)
266  _matrices[k] = pos.second;
267  else
268  _matrices.erase(k);
269  }
270 }
271 
272 // iluSolve only works on the diagonal matrices since we intend for it
273 // to be used in a BlockJacobi preconditioner.
274 
275 void
277 {
278  MultiField& x = dynamic_cast<MultiField&>(xB);
279  const MultiField& b = dynamic_cast<const MultiField&>(bB);
280  MultiField& temp = dynamic_cast<MultiField&>(tempB);
281 
282 
283  const int xLen = x.getLength();
284  //#pragma omp parallel for
285  for(int i=0; i<xLen; i++)
286  {
287  const Index rowIndex = x.getArrayIndex(i);
288  if (hasMatrix(rowIndex,rowIndex))
289  {
290  const Matrix& mII = getMatrix(rowIndex,rowIndex);
291  mII.iluSolve(x[rowIndex],b[rowIndex],temp);
292  }
293  }
294  x.sync();
295 }
296 
297 // spike preconditioner
298 void
299 MultiFieldMatrix::spikeSolve(IContainer& xB, const IContainer& bB, IContainer& tempB, const SpikeStorage& spike_storage) const
300 {
301  MultiField& x = dynamic_cast<MultiField&>(xB);
302  const MultiField& b = dynamic_cast<const MultiField&>(bB);
303  MultiField& temp = dynamic_cast<MultiField&>(tempB);
304 
305  const int xLen = x.getLength();
306  //#pragma omp parallel for
307  for(int i=0; i<xLen; i++)
308  {
309  const Index rowIndex = x.getArrayIndex(i);
310  if (hasMatrix(rowIndex,rowIndex))
311  {
312  const Matrix& mII = getMatrix(rowIndex,rowIndex);
313  mII.spikeSolve(x[rowIndex], b[rowIndex], temp, spike_storage);
314  }
315  }
316  x.sync();
317 }
318 
319 
320 void
322 {
323  MultiField& x = dynamic_cast<MultiField&>(xB);
324  const MultiField& b = dynamic_cast<const MultiField&>(bB);
325  MultiField& temp = dynamic_cast<MultiField&>(tempB);
326 
327  const int xLen = x.getLength();
328 
329  //#pragma omp parallel for
330  for(int i=0; i<xLen; i++)
331  {
332  const Index rowIndex = x.getArrayIndex(i);
333  if (hasMatrix(rowIndex,rowIndex))
334  {
335  const ArrayBase& bI = b[rowIndex];
336  ArrayBase& r = temp[rowIndex];
337  r.copyFrom(bI);
338 
339  for(int j=0; j<xLen; j++)
340  {
341  const Index colIndex = x.getArrayIndex(j);
342  if ((rowIndex!=colIndex) && hasMatrix(rowIndex,colIndex))
343  {
344  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
345  mIJ.multiplyAndAdd(r,x[colIndex]);
346  }
347  }
348 
349  const Matrix& mII = getMatrix(rowIndex,rowIndex);
350  mII.solveBoundary(x[rowIndex],r,r);
351  }
352  }
353 }
354 
355 
356 
357 void
359 {
360  MultiField& x = dynamic_cast<MultiField&>(xB);
361  const MultiField& b = dynamic_cast<const MultiField&>(bB);
362  MultiField& temp = dynamic_cast<MultiField&>(tempB);
363 
364  const int xLen = x.getLength();
365 
366  for(int i=xLen-1; i>=0; i--)
367  {
368  const Index rowIndex = x.getArrayIndex(i);
369  if (hasMatrix(rowIndex,rowIndex))
370  {
371  const ArrayBase& bI = b[rowIndex];
372  ArrayBase& r = temp[rowIndex];
373  const StorageSite& rowSite = *rowIndex.second;
374  r.copyPartial(bI,0,rowSite.getSelfCount());
375 
376  for(int j=0; j<xLen; j++)
377  {
378  const Index colIndex = x.getArrayIndex(j);
379  if ((rowIndex!=colIndex) && hasMatrix(rowIndex,colIndex))
380  {
381  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
382  mIJ.multiplyAndAdd(r,x[colIndex]);
383  }
384  }
385 
386  const Matrix& mII = getMatrix(rowIndex,rowIndex);
387 #ifndef FVM_PARALLEL
388  x.syncGather(rowIndex);
389 #endif
390  mII.reverseGS(x[rowIndex],r,r);
391 #ifndef FVM_PARALLEL
392  x.syncScatter(rowIndex);
393 #endif
394  }
395  }
396 
397  x.sync();
398 
399 }
400 
401 void
403  IContainer& rB) const
404 {
405  const MultiField& x = dynamic_cast<const MultiField&>(xB);
406  const MultiField& b = dynamic_cast<const MultiField&>(bB);
407  MultiField& r = dynamic_cast<MultiField&>(rB);
408 
409  const int xLen = x.getLength();
410 
411  //#pragma omp parallel for
412  for(int i=0; i<xLen; i++)
413  {
414  const Index rowIndex = x.getArrayIndex(i);
415  if (hasMatrix(rowIndex,rowIndex))
416  {
417  const ArrayBase& bI = b[rowIndex];
418  const StorageSite& rowSite = *rowIndex.second;
419  ArrayBase& rI = r[rowIndex];
420  rI.copyPartial(bI,0,rowSite.getSelfCount());
421  rI.zeroPartial(rowSite.getSelfCount(),rowSite.getCount());
422 
423  for(int j=0; j<xLen; j++)
424  {
425  const Index colIndex = x.getArrayIndex(j);
426  if (hasMatrix(rowIndex,colIndex))
427  {
428  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
429  mIJ.multiplyAndAdd(rI,x[colIndex]);
430  }
431  }
432  }
433  }
434 #ifdef FVM_PARALLEL
435  //r.sync();
436 #endif
437 }
438 
439 void
441 {
442  EntryIndex e(row,col);
443 
444  _matrices.erase(e);
445 }
446 
447 
448 void
450  const int groupSize,
451  const double weightRatioThreshold)
452 {
453 
454  const int xLen = coarseIndex.getLength();
455 
456 
457  //#pragma omp parallel for
458  for(int i=0; i<xLen; i++)
459  {
460  const Index rowIndex = coarseIndex.getArrayIndex(i);
461  if (hasMatrix(rowIndex,rowIndex))
462  {
463  Matrix& mII = getMatrix(rowIndex,rowIndex);
464  // cout << " proc_id = " << MPI::COMM_WORLD.Get_rank() << " coarse size = " <<
465  // mII.createCoarsening(coarseIndex[rowIndex], groupSize,weightRatioThreshold) <<endl;
466  _coarseSizes[rowIndex] =
467  mII.createCoarsening(coarseIndex[rowIndex],
468  groupSize,weightRatioThreshold);
469  }
470  }
471 }
472 
473 
474 
475 void
477 {
478  const int xLen = coarseIndexField.getLength();
479 
480  //#pragma omp parallel for
481  for(int i=0; i<xLen; i++)
482  {
483  const Index rowIndex = coarseIndexField.getArrayIndex(i);
484 
485  Array<int>& coarseIndex = dynamic_cast<Array<int>& >(coarseIndexField[rowIndex]);
486 
487 
488  int coarseGhostSize=0;
489  const int coarseSize = _coarseSizes.find(rowIndex)->second;
490 
491  const StorageSite& site = *rowIndex.second;
492 
493  const StorageSite::GatherMap& gatherMap = site.getGatherMap();
494  const StorageSite::GatherMap& gatherMapLevel1 = site.getGatherMapLevel1();
495 
496  // collect all the toIndices arrays for each storage site from
497  // both gatherMap and gatherMapLevel1
498 
499  typedef map<const StorageSite*, vector<const Array<int>* > > IndicesMap;
500  IndicesMap toIndicesMap;
501 
502  foreach(const StorageSite::GatherMap::value_type pos, gatherMap)
503  {
504  const StorageSite& oSite = *pos.first;
505  const Array<int>& toIndices = *pos.second;
506 
507  toIndicesMap[&oSite].push_back(&toIndices);
508  }
509 
510  foreach(const StorageSite::GatherMap::value_type pos, gatherMapLevel1)
511  {
512  const StorageSite& oSite = *pos.first;
513  const Array<int>& toIndices = *pos.second;
514 
515  toIndicesMap[&oSite].push_back(&toIndices);
516  }
517 
518  foreach(IndicesMap::value_type pos, toIndicesMap)
519  {
520  const StorageSite& oSite = *pos.first;
521  const vector<const Array<int>* > toIndicesArrays = pos.second;
522 
523 
524  map<int,int> otherToMyMapping;
525  UnorderedSet gatherSet;
526 
527  foreach(const Array<int>* toIndicesPtr, toIndicesArrays)
528  {
529  const Array<int>& toIndices = *toIndicesPtr;
530  const int nGhostRows = toIndices.getLength();
531  for(int ng=0; ng<nGhostRows; ng++)
532  {
533  const int fineIndex = toIndices[ng];
534  const int coarseOtherIndex = coarseIndex[fineIndex];
535 
536  if (coarseOtherIndex < 0)
537  continue;
538 
539  if (otherToMyMapping.find(coarseOtherIndex) !=
540  otherToMyMapping.end())
541  {
542  coarseIndex[fineIndex] = otherToMyMapping[coarseOtherIndex];
543  }
544  else
545  {
546  coarseIndex[fineIndex] = coarseGhostSize+coarseSize;
547  otherToMyMapping[coarseOtherIndex] = coarseIndex[fineIndex];
548  gatherSet.insert( coarseIndex[fineIndex] );
549  coarseGhostSize++;
550  }
551  }
552  }
553 
554  const int coarseMappersSize = otherToMyMapping.size();
555 
556  shared_ptr<Array<int> > coarseToIndices(new Array<int>(coarseMappersSize));
557 
558  for(int n = 0; n < gatherSet.size(); n++)
559  {
560  (*coarseToIndices)[n] = gatherSet.getData().at(n);
561  }
562 
563  SSPair sskey(&site,&oSite);
564  _coarseGatherMaps [sskey] = coarseToIndices;
565 
566  }
567 
568  const StorageSite::ScatterMap& scatterMap = site.getScatterMap();
569  const StorageSite::ScatterMap& scatterMapLevel1 = site.getScatterMapLevel1();
570 
571  IndicesMap fromIndicesMap;
572 
573  foreach(const StorageSite::GatherMap::value_type pos, scatterMap)
574  {
575  const StorageSite& oSite = *pos.first;
576  const Array<int>& fromIndices = *pos.second;
577 
578  fromIndicesMap[&oSite].push_back(&fromIndices);
579  }
580 
581  foreach(const StorageSite::GatherMap::value_type pos, scatterMapLevel1)
582  {
583  const StorageSite& oSite = *pos.first;
584  const Array<int>& fromIndices = *pos.second;
585 
586  fromIndicesMap[&oSite].push_back(&fromIndices);
587  }
588 
589  foreach(IndicesMap::value_type pos, fromIndicesMap)
590  {
591  const StorageSite& oSite = *pos.first;
592  const vector<const Array<int>* > fromIndicesArrays = pos.second;
593 
594  UnorderedSet scatterSet;
595 
596  foreach(const Array<int>* fromIndicesPtr, fromIndicesArrays)
597  {
598  const Array<int>& fromIndices = *fromIndicesPtr;
599  const int nGhostRows = fromIndices.getLength();
600  for(int ng=0; ng<nGhostRows; ng++)
601  {
602  const int fineIndex = fromIndices[ng];
603  const int coarseOtherIndex = coarseIndex[fineIndex];
604  if (coarseOtherIndex >= 0)
605  scatterSet.insert( coarseOtherIndex );
606  }
607 
608  }
609 
610  const int coarseMappersSize = scatterSet.size();
611 
612  shared_ptr<Array<int> > coarseFromIndices(new Array<int>(coarseMappersSize));
613 
614  for(int n = 0; n < scatterSet.size(); n++ ) {
615  (*coarseFromIndices)[n] = scatterSet.getData().at(n);
616  }
617 
618  SSPair sskey(&site,&oSite);
619  _coarseScatterMaps[sskey] = coarseFromIndices;
620 
621  }
622  _coarseGhostSizes[rowIndex]=coarseGhostSize;
623  }
624 }
625 
626 void
628 {
629 
630  const int xLen = coarseIndexField.getLength();
631  //#pragma omp parallel for
632  for(int i=0; i<xLen; i++)
633  {
634  const Index rowIndex = coarseIndexField.getArrayIndex(i);
635 
636  const StorageSite& fineSite = *rowIndex.second;
637 
638  const StorageSite& coarseSite = *_coarseSites[rowIndex];
639 
640  const int nFineRows = fineSite.getCountLevel1();
641 
642 
643  const Array<int>& coarseIndex =
644  dynamic_cast<const Array<int>& >(coarseIndexField[rowIndex]);
645 
646  shared_ptr<CRConnectivity> coarseToFine(new CRConnectivity(coarseSite,fineSite));
647 
648  coarseToFine->initCount();
649 
650 
651 
652  for(int nr=0; nr<nFineRows; nr++){
653  if (coarseIndex[nr]>=0)
654  coarseToFine->addCount(coarseIndex[nr],1);
655  }
656 
657 
658  coarseToFine->finishCount();
659 
660  for(int nr=0; nr<nFineRows; nr++)
661  if (coarseIndex[nr]>=0)
662  coarseToFine->add(coarseIndex[nr],nr);
663 
664  coarseToFine->finishAdd();
665  _coarseToFineMappings[rowIndex]=coarseToFine;
666  }
667 }
668 
669 void
671 {
672 
673  const int xLen = coarseIndex.getLength();
674 
675  //#pragma omp parallel for
676  for(int i=0; i<xLen; i++)
677  {
678  const Index rowIndex = coarseIndex.getArrayIndex(i);
679 
680  const StorageSite& coarseRowSite = *_coarseSites[rowIndex];
681 
682  const CRConnectivity& coarseToFine = *_coarseToFineMappings[rowIndex];
683 
684  for(int j=0; j<xLen; j++)
685  {
686  const Index colIndex = coarseIndex.getArrayIndex(j);
687  if (hasMatrix(rowIndex,colIndex))
688  {
689  Matrix& mIJ = getMatrix(rowIndex,colIndex);
690 
691  const StorageSite& coarseColSite = *_coarseSites[colIndex];
692 
693  shared_ptr<CRConnectivity> coarseConnectivity
694  (mIJ.createCoarseConnectivity(coarseIndex[rowIndex],
695  coarseToFine,
696  coarseRowSite,coarseColSite));
697  EntryIndex e(rowIndex,colIndex);
698  _coarseConnectivities[e]=coarseConnectivity;
699  }
700  }
701  }
702 }
703 
704 void
706 {
707  const int xLen = coarseIndex.getLength();
708  //#pragma omp parallel for
709  for(int i=0; i<xLen; i++)
710  {
711  const Index rowIndex = coarseIndex.getArrayIndex(i);
712 
713  const CRConnectivity& coarseToFine = *_coarseToFineMappings[rowIndex];
714 
715  for(int j=0; j<xLen; j++)
716  {
717  const Index colIndex = coarseIndex.getArrayIndex(j);
718  if (hasMatrix(rowIndex,colIndex))
719  {
720  Matrix& mIJ = getMatrix(rowIndex,colIndex);
721  EntryIndex e(rowIndex,colIndex);
722 
723  const CRConnectivity& coarseConnectivity = *_coarseConnectivities[e];
724 
725  shared_ptr<Matrix> coarseMatrix
726  (mIJ.createCoarseMatrix(coarseIndex[rowIndex],
727  coarseToFine,
728  coarseConnectivity));
729  _coarseMatrices[e]=coarseMatrix;
730  }
731  }
732  }
733 }
734 
735 
736 void
738  const MultiField& fineResidualField,
739  MultiField& coarseBField)
740 {
741  const int xLen = fineResidualField.getLength();
742 
743  //#pragma omp parallel for
744  for(int i=0; i<xLen; i++)
745  {
746  const Index rowIndex = fineResidualField.getArrayIndex(i);
747 
748  const StorageSite& coarseRowSite = *_coarseSites[rowIndex];
749 
750  const Index coarseRowIndex(rowIndex.first,&coarseRowSite);
751 
752  const ArrayBase& fineResidual =
753  dynamic_cast<const ArrayBase&>(fineResidualField[rowIndex]);
754 
755  const ArrayBase& fineToCoarse =
756  dynamic_cast<const ArrayBase&>(coarseIndex[rowIndex]);
757 
758  ArrayBase& coarseB = dynamic_cast<ArrayBase&>(coarseBField[coarseRowIndex]);
759 
760  fineResidual.inject(coarseB,fineToCoarse,rowIndex.second->getSelfCount());
761  }
762 }
763 
764 void
766  MultiField& fineSolutionField,
767  MFRPtr scaleField,
768  const MultiField& coarseSolutionField)
769 {
770  const int xLen = fineSolutionField.getLength();
771 
772  //#pragma omp parallel for
773  for(int i=0; i<xLen; i++)
774  {
775  const Index rowIndex = fineSolutionField.getArrayIndex(i);
776 
777  const StorageSite& coarseRowSite = *_coarseSites[rowIndex];
778 
779  const Index coarseRowIndex(rowIndex.first,&coarseRowSite);
780  ArrayBase* scale(0);
781  if (scaleField)
782  scale = &((*scaleField)[*(coarseRowIndex.first)]);
783 
784  ArrayBase& fineSolution = dynamic_cast<ArrayBase&>(fineSolutionField[rowIndex]);
785  fineSolution.correct(coarseSolutionField[coarseRowIndex],
786  coarseIndex[rowIndex],
787  scale,
788  rowIndex.second->getSelfCount());
789  }
790 }
791 
792 #ifdef FVM_PARALLEL
793 
794 int
795 MultiFieldMatrix::getMinSize( const MPI::Intracomm& comm ) const
796 {
797  int size=0;
798  foreach(const MatrixMap::value_type& pos, _matrices)
799  {
800  EntryIndex k = pos.first;
801 
802  if (k.first == k.second)
803  {
804  size += k.first.second->getCount();
805  }
806  }
807 
808 #ifdef FVM_PARALLEL
809  int count = 1;
810  comm.Allreduce(MPI::IN_PLACE, &size, count, MPI::INT, MPI::MIN);
811 
812 #endif
813 
814  return size;
815 
816 }
817 
818 int
819 MultiFieldMatrix::getMergeSize( const MPI::Intracomm& comm ) const
820 {
821  int size=0;
822  foreach(const MatrixMap::value_type& pos, _matrices)
823  {
824  EntryIndex k = pos.first;
825 
826  if (k.first == k.second)
827  {
828  size += k.first.second->getCount();
829  }
830  }
831 
832 #ifdef FVM_PARALLEL
833  int count = 1;
834  comm.Allreduce(MPI::IN_PLACE, &size, count, MPI::INT, MPI::SUM);
835 
836 
837 #endif
838 
839  return size;
840 
841 }
842 #endif
843 
844 int
846 {
847  int size=0;
848  foreach(const MatrixMap::value_type& pos, _matrices)
849  {
850  EntryIndex k = pos.first;
851 
852  if (k.first == k.second)
853  {
854  size += k.first.second->getCount();
855  }
856  }
857 
858 #ifdef FVM_PARALLEL
859  int count = 1;
860  MPI::COMM_WORLD.Allreduce(MPI::IN_PLACE, &size, count, MPI::INT, MPI::MIN);
861 
862 #endif
863 
864  return size;
865 
866 }
867 
868 
869 int
871 {
872  int size=0;
873  foreach(const MatrixMap::value_type& pos, _matrices)
874  {
875  EntryIndex k = pos.first;
876 
877  if (k.first == k.second)
878  {
879  size += k.first.second->getCount();
880  }
881  }
882 
883  return size;
884 
885 }
886 
887 MFRPtr
889 {
890  const int xLen = x.getLength();
891 
892  MultiField *p = new MultiField();
893  for(int i=0; i<xLen; i++)
894  {
895  const Index rowIndex = x.getArrayIndex(i);
896  for(int j=0; j<xLen; j++)
897  {
898  const Index colIndex = x.getArrayIndex(j);
899  if (hasMatrix(rowIndex,colIndex))
900  {
901  const Matrix& mIJ = getMatrix(rowIndex,colIndex);
902  p->addArray(rowIndex,
903  mIJ.quadProduct(x[colIndex]));
904  }
905  }
906  }
907 
908  MFRPtr r = p->reduceSum();
909  delete p;
910  return r;
911 }
MatrixSizeMap _coarseGhostSizes
Matrix & getMatrix(const Index &rowIndex, const Index &colIndex)
virtual ~MultiFieldMatrix()
int getSelfCount() const
Definition: StorageSite.h:40
virtual void iluSolve(IContainer &xB, const IContainer &bB, IContainer &tempB) const
void createCoarseToFineMapping(const MultiField &coarseIndexField)
void correctSolution(const MultiField &coarseIndex, MultiField &fineSolutionField, MFRPtr scaleField, const MultiField &coarseSolutionField)
virtual void forwardGS(IContainer &xB, const IContainer &bB, IContainer &temp) const
void createCoarseConnectivity(MultiField &coarseIndex)
virtual shared_ptr< CRConnectivity > createCoarseConnectivity(const IContainer &coarseIndex, const CRConnectivity &coarseToFine, const StorageSite &coarseRowSite, const StorageSite &coarseColSite)
Definition: Matrix.cpp:23
bool hasMatrix(const Index &rowIndex, const Index &colIndex) const
const GatherMap & getGatherMapLevel1() const
Definition: StorageSite.h:74
virtual void copyPartial(const IContainer &oc, const int iBeg, const int iEnd)=0
const ScatterMap & getScatterMapLevel1() const
Definition: StorageSite.h:73
void createCoarsening(MultiField &coarseIndex, const int groupSize, const double weightRatioThreshold)
virtual void correct(const IContainer &coarseI, const IContainer &coarseIndexI, const IContainer *scaleI, const int length)=0
void syncGather(const ArrayIndex &i)
Definition: MultiField.cpp:436
CoarseToFineMappingMap _coarseToFineMappings
void insert(int x)
#define logCtor()
Definition: RLogInterface.h:26
StorageSiteMap _coarseSites
virtual void multiplyAndAdd(IContainer &yB, const IContainer &xB) const
int getLocalSize() const
virtual void multiplyAndAdd(IContainer &yB, const IContainer &xB) const
Definition: Matrix.cpp:46
virtual void zeroPartial(const int iBeg, const int iEnd)=0
virtual void iluSolve(IContainer &xB, const IContainer &bB, const IContainer &residual) const
Definition: Matrix.cpp:69
virtual void spikeSolve(IContainer &xB, const IContainer &bB, const IContainer &residual, const SpikeStorage &spike_storage) const
Definition: Matrix.cpp:74
shared_ptr< MultiFieldReduction > reduceSum() const
Definition: MultiField.cpp:249
virtual void Jacobi(IContainer &xnew, const IContainer &xold, const IContainer &b) const
Definition: Matrix.cpp:63
virtual shared_ptr< Matrix > createCoarseMatrix(const IContainer &coarseIndex, const CRConnectivity &coarseToFine, const CRConnectivity &coarseConnectivity)
Definition: Matrix.cpp:32
virtual void spikeSolve(IContainer &xB, const IContainer &bB, IContainer &tempB, const SpikeStorage &spike_storage) const
MultiField::ArrayIndex Index
virtual void reverseGS(IContainer &xB, const IContainer &bB, IContainer &temp) const
MatrixMap _coarseMatrices
virtual void computeResidual(const IContainer &xB, const IContainer &bB, IContainer &rB) const
int size() const
Definition: Matrix.h:16
virtual void Jacobi(IContainer &xB, const IContainer &bB, IContainer &tempB) const
int getLength() const
Definition: MultiField.h:54
void createCoarseMatrices(MultiField &coarseIndex)
#define logDtor()
Definition: RLogInterface.h:33
int getCountLevel1() const
Definition: StorageSite.h:72
void removeMatrix(const Index &rowIndex, const Index &colIndex)
CoarseConnectivitiesMap _coarseConnectivities
const ScatterMap & getScatterMap() const
Definition: StorageSite.h:58
MatrixMappersMap _coarseGatherMaps
map< const StorageSite *, shared_ptr< Array< int > > > ScatterMap
Definition: StorageSite.h:23
const vector< int > & getData() const
map< EntryIndex, shared_ptr< Matrix > > MatrixMap
virtual void forwardGS(IContainer &xB, IContainer &bB, IContainer &residual) const
Definition: Matrix.cpp:51
MatrixMappersMap _coarseScatterMaps
const GatherMap & getGatherMap() const
Definition: StorageSite.h:59
virtual void reverseGS(IContainer &xB, IContainer &bB, IContainer &residual) const
Definition: Matrix.cpp:57
int getCount() const
Definition: StorageSite.h:39
shared_ptr< MultiFieldReduction > MFRPtr
map< const StorageSite *, shared_ptr< Array< int > > > GatherMap
Definition: StorageSite.h:24
void addArray(const ArrayIndex &aIndex, shared_ptr< ArrayBase > a)
Definition: MultiField.cpp:270
void syncScatter(const ArrayIndex &i)
Definition: MultiField.cpp:325
pair< Index, Index > EntryIndex
virtual void solveBoundary(IContainer &xB, IContainer &bB, IContainer &residual) const
Definition: Matrix.cpp:81
virtual void multiply(IContainer &yB, const IContainer &xB) const
virtual void zero()=0
const ArrayIndex getArrayIndex(const int i) const
Definition: MultiField.h:55
void syncGhostCoarsening(MultiField &coarseIndexField)
virtual int createCoarsening(IContainer &coarseIndex, const int groupSize, const double weighRatioThreshold)
Definition: Matrix.cpp:16
virtual void copyFrom(const IContainer &a)=0
MatrixSizeMap _coarseSizes
void sync()
Definition: MultiField.cpp:489
pair< const StorageSite *, const StorageSite * > SSPair
void injectResidual(const MultiField &coarseIndex, const MultiField &fineResidualField, MultiField &coarseBField)
virtual shared_ptr< IContainer > newClone() const
Definition: MultiField.cpp:81
virtual void inject(IContainer &coarseI, const IContainer &coarseIndexI, const int length) const =0
virtual void solveBoundary(IContainer &xB, const IContainer &bB, IContainer &temp) const
MFRPtr quadProduct(const MultiField &x) const
int getLength() const
Definition: Array.h:87
virtual shared_ptr< ArrayBase > quadProduct(const IContainer &xB) const
Definition: Matrix.h:28