Memosa-FVM  0.2
CRMatrix.h
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 #ifndef _CRMATRIX_H_
6 #define _CRMATRIX_H_
7 
8 #ifdef FVM_PARALLEL
9 #include <mpi.h>
10 #endif
11 
12 #include "Matrix.h"
13 #include "CRConnectivity.h"
14 #include "Array.h"
15 #include "StorageSite.h"
16 #include "LinearSystemMerger.h"
17 #include "SpikeStorage.h"
18 #include "SpikeMatrix.h"
19 #include <set>
20 
21 // used to handle cases where OffDiag and Diag are not the same type
22 // and we need to assign the latter to the former. Specialized as
23 // required in DiagonalTensor etc.
24 template<class X>
25 X DiagToOffDiag(const X& x)
26 {
27  return x;
28 }
29 
30 // helper function to set coefficients of a flattened matrix
31 // corresponding to a given CRMatrix. The default version is not
32 // implemented but we do define the versions we need i.e. for a scalar
33 // matrix and for a SquareTensor one (see SquareTensor.h). This function gets used
34 // to create the matrix for use in the DirectSolver.
35 
36 template<class T_Diag, class T_OffDiag>
37 void setFlatCoeffs(Array<double>& flatCoeffs,
38  const CRConnectivity& flatConnectivity,
39  const Array<T_Diag>& diag,
40  const Array<T_OffDiag>& offDiag,
41  const CRConnectivity& connectivity)
42 {
43  throw CException("not implemented");
44 }
45 
46 
47 void setFlatCoeffs(Array<double>& flatCoeffs,
48  const CRConnectivity& flatConnectivity,
49  Array<double>& diag,
50  Array<double>& offDiag,
51  const CRConnectivity& connectivity)
52 {
53  const Array<int>& myRow = connectivity.getRow();
54  const Array<int>& myCol = connectivity.getCol();
55  const int rowDim = connectivity.getRowDim();
56 
57  for(int i=0; i<rowDim; i++)
58  {
59  const int fp = flatConnectivity.getCoeffPosition(i,i);
60  flatCoeffs[fp] = diag[i];
61 
62  for(int jp=myRow[i]; jp<myRow[i+1]; jp++)
63  {
64  const int j = myCol[jp];
65 
66  // the flat matrix uses compressed col format so swap i,j
67  const int fp = flatConnectivity.getCoeffPosition(j,i);
68  flatCoeffs[fp] = offDiag[jp];
69  }
70  }
71 }
72 
86 template<class T_Diag, class T_OffDiag, class X>
87 class CRMatrix : public Matrix
88 {
89 public:
90 
91  //friend class LinearSystemMerger;
92 
93  typedef T_Diag Diag;
94  typedef T_OffDiag OffDiag;
97 
99  typedef Array<X> XArray;
100  typedef shared_ptr< Array<int> > IntArrayPtr;
101  typedef shared_ptr< Array<Diag> > DiagArrayPtr;
102 
103  typedef shared_ptr< Array<double> > ArrayDblePtr;
105 
106  typedef pair<const StorageSite*, const StorageSite*> EntryIndex;
107  typedef map<EntryIndex, shared_ptr<ArrayBase> > GhostArrayMap;
108 
118  {
119  public:
121  const Array<Vector<int,2> >& pairToCol) :
122  _coeffs(coeffs),
123  _pairToCol(pairToCol)
124  {}
125 
126  OffDiag& getCoeff01(const int np)
127  {
128  return _coeffs[_pairToCol[np][0]];
129  }
130 
131  OffDiag& getCoeff10(const int np)
132  {
133  return _coeffs[_pairToCol[np][1]];
134  }
135 
136  void addCoeffsSymmetric(const int np, const OffDiag& c)
137  {
138  _coeffs[_pairToCol[np][0]] += c;
139  _coeffs[_pairToCol[np][1]] += c;
140  }
141 
142  void addCoeffs(const int np, const OffDiag& c01, const OffDiag& c10)
143  {
144  _coeffs[_pairToCol[np][0]] += c01;
145  _coeffs[_pairToCol[np][1]] += c10;
146  }
147 
148  void addCoeff01(const int np, const OffDiag& c01)
149  {
150  _coeffs[_pairToCol[np][0]] += c01;
151  }
152 
153  void addCoeff10(const int np, const OffDiag& c10)
154  {
155  _coeffs[_pairToCol[np][1]] += c10;
156  }
157  private:
160  };
161 
162  typedef map<const CRConnectivity*,PairWiseAssembler*> PairWiseAssemblerMap;
163 
164 
165  CRMatrix(const CRConnectivity& conn) :
166  Matrix(),
167  _conn(conn),
168  _row(_conn.getRow()),
169  _col(_conn.getCol()),
170  _diag(_conn.getRowDim()),
171  _offDiag(_col.getLength()),
173  _isBoundary(_conn.getRowDim()),
174  _spikeMtrx()
175  {
176 
177  logCtor();
178  _isBoundary = false;
179  }
180 
181 
182  DEFINE_TYPENAME("CRMatrix<"
186  +">");
187 
188  virtual void initAssembly()
189  {
190  _diag.zero();
191  _offDiag.zero();
192  _isBoundary = false;
193  }
194 
200  virtual void multiply(IContainer& yB, const IContainer& xB) const
201  {
202  XArray& y = dynamic_cast<XArray&>(yB);
203  const XArray& x = dynamic_cast<const XArray&>(xB);
204 
205  const int nRows = _conn.getRowSite().getCount();
206  for(int nr=0; nr<nRows; nr++)
207  {
208  y[nr] = _diag[nr]*x[nr];
209  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
210  {
211  const int j = _col[nb];
212  y[nr] += _offDiag[nb]*x[j];
213  }
214 
215  }
216  }
217 
223  virtual void multiplyAndAdd(IContainer& yB, const IContainer& xB) const
224  {
225  XArray& y = dynamic_cast<XArray&>(yB);
226  const XArray& x = dynamic_cast<const XArray&>(xB);
227 
228  const int nRows = _conn.getRowSite().getCount();
229  for(int nr=0; nr<nRows; nr++)
230  {
231  y[nr] += _diag[nr]*x[nr];
232  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
233  {
234  const int j = _col[nb];
235  y[nr] += _offDiag[nb]*x[j];
236  }
237  }
238 
239  }
240 
241  virtual void transpose()
242  {
243  const int nRows = _conn.getRowSite().getCount();
244  for(int i=0; i<nRows; i++)
245  {
246  for (int nb = _row[i]; nb<_row[i+1]; nb++)
247  {
248  const int j = _col[nb];
249  bool found = false;
250 
251  for (int nb2 = _row[j]; nb2<_row[j+1]; nb2++)
252  {
253  if (_col[nb2] == i)
254  {
255  const OffDiag coeffIJ = _offDiag[nb];
256  _offDiag[nb] = _offDiag[nb2];
257  _offDiag[nb2] = coeffIJ;
258 
259  found = true;
260  }
261  }
262  if (!found)
263  throw CException("invalid connectivity for transpose");
264  }
265  }
266  }
267 
273  virtual shared_ptr<ArrayBase>
274  quadProduct(const IContainer& xB) const
275  {
276 
277  X sum( NumTypeTraits<X>::getZero());
278  const XArray& x = dynamic_cast<const XArray&>(xB);
279 
280  const int nRows = _conn.getRowSite().getSelfCount();
281  for(int nr=0; nr<nRows; nr++)
282  {
283  X sum_n = _diag[nr]*x[nr];
284  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
285  {
286  const int j = _col[nb];
287  sum_n += _offDiag[nb]*x[j];
288  }
289 
290  sum += sum_n*x[nr];
291  }
292 
293  XArray *p = new XArray(1);
294  (*p)[0] = sum;
295  return shared_ptr<ArrayBase>(p);
296  }
297 
303  virtual void forwardGS(IContainer& xB, IContainer& bB, IContainer&) const
304  {
305  XArray& x = dynamic_cast<XArray&>(xB);
306  const XArray& b = dynamic_cast<const XArray&>(bB);
307 
308  const int nRows = _conn.getRowSite().getSelfCount();
309 
310  X sum;
311  for(int nr=0; nr<nRows; nr++)
312  {
313  sum = b[nr];
314  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
315  {
316  const int j = _col[nb];
317  sum += _offDiag[nb]*x[j];
318  }
319  x[nr] = -sum/_diag[nr];
320  }
321  }
322 
328  virtual void reverseGS(IContainer& xB, IContainer& bB, IContainer&) const
329  {
330  XArray& x = dynamic_cast<XArray&>(xB);
331  const XArray& b = dynamic_cast<const XArray&>(bB);
332 
333  const int nRows = _conn.getRowSite().getSelfCount();
334 
335  X sum;
336  for(int nr=nRows-1; nr>=0; nr--)
337  {
338  sum = b[nr];
339  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
340  {
341  const int j = _col[nb];
342  sum += _offDiag[nb]*x[j];
343  }
344  x[nr] = -sum/_diag[nr];
345  }
346  }
347 
353  virtual void Jacobi(IContainer& xnewB, const IContainer& xoldB,
354  const IContainer& bB) const
355  {
356  XArray& xnew = dynamic_cast<XArray&>(xnewB);
357  const XArray& xold = dynamic_cast<const XArray&>(xoldB);
358  const XArray& b = dynamic_cast<const XArray&>(bB);
359 
360  const int nRows = _conn.getRowSite().getSelfCount();
361 
362  X sum;
363  for(int nr=0; nr<nRows; nr++)
364  {
365  sum = b[nr];
366  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
367  {
368  const int j = _col[nb];
369  sum += _offDiag[nb]*xold[j];
370  }
371  xnew[nr] = -sum/_diag[nr];
372  }
373 
374  }
375 
376  virtual void iluSolve(IContainer& xB, const IContainer& bB, const IContainer&) const
377  {
378  XArray& x = dynamic_cast<XArray&>(xB);
379  shared_ptr<XArray> y = dynamic_pointer_cast<XArray>(x.newClone());
380  const XArray& b = dynamic_cast<const XArray&>(bB);
381 
382  if (!_iluConnPtr)
383  compute_ILU0();
384 
385  lowerSolve(*y,b);
386  upperSolve(x,*y);
387  }
388 
389  virtual void spikeSolve(IContainer& xB, const IContainer& bB, const IContainer&, const SpikeStorage& spike_storage) const
390  {
391  if (!_spikeMtrx)
392  _spikeMtrx = shared_ptr<T_SpikeMtrx>(new T_SpikeMtrx(_conn, _diag, _offDiag, spike_storage));
393 
394  XArray& x = dynamic_cast<XArray&>(xB);
395  shared_ptr<XArray> y = dynamic_pointer_cast<XArray>(x.newClone());
396  const XArray& b = dynamic_cast<const XArray&>(bB);
397  _spikeMtrx->solve( b, x);
398 
399  }
400 
401 
407  virtual void computeResidual(const IContainer& xB, const IContainer& bB,
408  IContainer& rB) const
409  {
410  const XArray& x = dynamic_cast<const XArray&>(xB);
411  const XArray& b = dynamic_cast<const XArray&>(bB);
412  XArray& r = dynamic_cast<XArray&>(rB);
413 
414  const int nRows = _conn.getRowSite().getSelfCount();
415 
416  for(int nr=0; nr<nRows; nr++)
417  {
418 
419  r[nr] = b[nr] + _diag[nr]*x[nr];
420  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
421  {
422  const int j = _col[nb];
423  r[nr] += _offDiag[nb]*x[j];
424  }
425  }
426  }
427 
433  virtual void solveBoundary(IContainer& xB, IContainer& bB, IContainer&) const
434  {
435 
436  XArray& x = dynamic_cast<XArray&>(xB);
437  const XArray& b = dynamic_cast<const XArray&>(bB);
438 
439  const int nRowsInterior = _conn.getRowSite().getSelfCount();
440  const int nRowsExtra = _conn.getRowSite().getCount();
441 
442  X sum;
443  for(int nr=nRowsInterior; nr<nRowsExtra; nr++)
444  if (_isBoundary[nr])
445  {
446  sum = b[nr];
447  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
448  {
449  const int j = _col[nb];
450  sum += _offDiag[nb]*x[j];
451  }
452  x[nr] = -sum/_diag[nr];
453  }
454  }
455 
468  virtual int createCoarsening(IContainer& gCoarseIndex, const int groupSize,
469  const double weightRatioThreshold)
470  {
471  Array<int>& coarseIndex = dynamic_cast<Array<int>& >(gCoarseIndex);
472 
473  const int nRows = _conn.getRowSite().getSelfCount();
474 
475  coarseIndex = -1;
476 
477  // the number of rows in the coarse level matrix
478  int nCoarseRows=0;
479 
480  // temp storage to keep track of how many in each coarse group
481  Array<int> coarseCount(nRows);
482 
483  coarseCount = 0;
484 
485  for(int nr=0; nr<nRows; nr++)
486  if (coarseIndex[nr] == -1 && !_isBoundary[nr])
487  {
488  // the row that we are going to go through looking for
489  // neighbours to group with; it starts off being the current
490  // row but for group sizes greater than 2 it will be reset
491  // to the ones that we group this one with
492 
493  int current = nr;
494 
495  int colMaxGrouped=-1; // columnn with largest coeff among grouped ones
496  int colMaxUngrouped=-1; // columnn with largest coeff among ungrouped ones
497 
498  int nGrouped;
499 
500  // assign current row to a new coarse row
501 
502  coarseIndex[current] = nCoarseRows;
503 
504  for(nGrouped=1; nGrouped<groupSize; nGrouped++)
505  {
506  // find largest coeff among both grouped and ungrouped columns
507 
508  double maxWeightUngrouped = 0;
509  double maxWeightGrouped = 0;
510  colMaxGrouped = -1;
511  colMaxUngrouped = -1;
512 
513  for(int nb=_row[current]; nb<_row[current+1]; nb++)
514  {
515  const int nc = _col[nb];
516 
517  //skip ghost and boundaries
518  if (nc < nRows && !_isBoundary[nc])
519  {
520  double diagMeasure0 =
522  double diagMeasure1 =
524  double coeffMeasure =
526 
527  double thisWeight = fabs(coeffMeasure /
528  max(diagMeasure0,diagMeasure1));
529 
530  if (coarseIndex[nc] == -1)
531  {
532  if (colMaxUngrouped == -1 || (thisWeight > maxWeightUngrouped))
533  {
534  colMaxUngrouped = nc;
535  maxWeightUngrouped = thisWeight;
536  }
537  }
538  else if (coarseIndex[nc] != coarseIndex[nr])
539  {
540  if (colMaxGrouped == -1 || (thisWeight > maxWeightGrouped))
541  {
542  colMaxGrouped = nc;
543  maxWeightGrouped = thisWeight;
544  }
545  }
546  }
547  }
548 
549  // if we found at least one ungrouped row, group it
550  // with the current one as long as it is large
551  // enough compared to already grouped ones
552 
553  if ( (colMaxUngrouped != -1) &&
554  (colMaxGrouped == -1 ||
555  (maxWeightUngrouped > weightRatioThreshold*maxWeightGrouped)))
556  {
557  coarseIndex[colMaxUngrouped] = coarseIndex[current];
558  coarseCount[coarseIndex[current]]++;
559  // next we will look at neighbours of this row
560  current = colMaxUngrouped;
561  }
562  else
563  // no point trying to find more for the current coarse group
564  break;
565  }
566 
567  // if we managed to find at least one ungrouped
568  // neighbour to group the current row with or if there
569  // is no already grouped neighbour that is too crowded
570  // then accept the new group
571  if (nGrouped > 1 || colMaxGrouped == -1 ||
572  coarseCount[coarseIndex[colMaxGrouped]] > groupSize+2)
573  {
574  coarseCount[coarseIndex[nr]]++;
575  nCoarseRows++;
576  }
577  else
578  {
579  // put the current row in an existing group
580  coarseIndex[nr] = coarseIndex[colMaxGrouped];
581  coarseCount[coarseIndex[colMaxGrouped]]++;
582  }
583  }
584 
585  return nCoarseRows;
586  }
587 
588 
597  shared_ptr<CRConnectivity>
599  const CRConnectivity& coarseToFine,
600  const StorageSite& coarseRowSite,
601  const StorageSite& coarseColSite)
602  {
603  const Array<int>& coarseIndex = dynamic_cast<const Array<int>& >(gCoarseIndex);
604 
605  const int nCoarseRows = coarseRowSite.getCountLevel1();
606 
607  shared_ptr<CRConnectivity> coarseCR(new CRConnectivity(coarseRowSite,coarseColSite));
608 
609 
610  coarseCR->initCount();
611 
612  Array<bool> coarseCounted(nCoarseRows);
613 
614  coarseCounted = false;
615 
616  for(int nrCoarse=0; nrCoarse<nCoarseRows; nrCoarse++)
617  {
618  const int nFine = coarseToFine.getCount(nrCoarse);
619  for(int nfr=0; nfr<nFine; nfr++)
620  {
621  const int nrFine = coarseToFine(nrCoarse,nfr);
622  for (int nb = _row[nrFine]; nb<_row[nrFine+1]; nb++)
623  {
624  const int nc = _col[nb];
625  const int ncCoarse = coarseIndex[nc];
626 
627 
628  if (ncCoarse>=0 && nrCoarse!=ncCoarse && !coarseCounted[ncCoarse])
629  {
630  coarseCounted[ncCoarse] = true;
631  coarseCR->addCount(nrCoarse,1);
632  }
633  }
634  }
635 
636  // reset counted
637  for(int nfr=0; nfr<nFine; nfr++)
638  {
639  const int nrFine = coarseToFine(nrCoarse,nfr);
640 
641  for (int nb = _row[nrFine]; nb<_row[nrFine+1]; nb++)
642  {
643  const int nc = _col[nb];
644  const int ncCoarse = coarseIndex[nc];
645  if (ncCoarse>=0)
646  coarseCounted[ncCoarse] = false;
647  }
648  }
649  }
650 
651  coarseCR->finishCount();
652 
653  for(int nrCoarse=0; nrCoarse<nCoarseRows; nrCoarse++)
654  {
655  const int nFine = coarseToFine.getCount(nrCoarse);
656  for(int nfr=0; nfr<nFine; nfr++)
657  {
658  const int nrFine = coarseToFine(nrCoarse,nfr);
659 
660  for (int nb = _row[nrFine]; nb<_row[nrFine+1]; nb++)
661  {
662  const int nc = _col[nb];
663  const int ncCoarse = coarseIndex[nc];
664  if (ncCoarse>=0 && nrCoarse!=ncCoarse && !coarseCounted[ncCoarse])
665  {
666  coarseCounted[ncCoarse] = true;
667  coarseCR->add(nrCoarse,ncCoarse);
668  }
669  }
670  }
671 
672  // reset counted
673  for(int nfr=0; nfr<nFine; nfr++)
674  {
675  const int nrFine = coarseToFine(nrCoarse,nfr);
676 
677  for (int nb = _row[nrFine]; nb<_row[nrFine+1]; nb++)
678  {
679  const int nc = _col[nb];
680  const int ncCoarse = coarseIndex[nc];
681  if (ncCoarse>=0)
682  coarseCounted[ncCoarse] = false;
683  }
684  }
685  }
686 
687 
688  coarseCR->finishAdd();
689 
690  return coarseCR;
691  }
692 
699  shared_ptr<Matrix>
700  createCoarseMatrix(const IContainer& gCoarseIndex,
701  const CRConnectivity& coarseToFine,
702  const CRConnectivity& coarseConnectivity)
703  {
704  const Array<int>& coarseIndex = dynamic_cast<const Array<int>& >(gCoarseIndex);
705  const int nCoarseRows = coarseConnectivity.getRowDim();
706 
707  shared_ptr<CRMatrix> coarseMatrix(new CRMatrix(coarseConnectivity));
708 
709  Array<Diag>& coarseDiag = coarseMatrix->getDiag();
710  Array<OffDiag>& coarseOffDiag = coarseMatrix->getOffDiag();
711 
712  const Array<int>& coarseConnRow = coarseConnectivity.getRow();
713  const Array<int>& coarseConnCol = coarseConnectivity.getCol();
714 
715  coarseDiag.zero();
716  coarseOffDiag.zero();
717 
718  //used to avoid searches when inserting coeffs
719  Array<int> coarseCoeffPos(nCoarseRows);
720 
721 
722  for(int nrCoarse=0; nrCoarse<nCoarseRows; nrCoarse++)
723  {
724  // for easy indexing when inserting coefficients set col
725  // positions into the coarse connectivity
726  for(int nb=coarseConnRow[nrCoarse]; nb<coarseConnRow[nrCoarse+1]; nb++)
727  coarseCoeffPos[coarseConnCol[nb]] = nb;
728 
729  // loop over the fine rows that make up this coarse row
730  const int nFine = coarseToFine.getCount(nrCoarse);
731  for(int nfr=0; nfr<nFine; nfr++)
732  {
733  const int nrFine = coarseToFine(nrCoarse,nfr);
734 
735  coarseDiag[nrCoarse] += _diag[nrFine];
736 
737  for (int nb = _row[nrFine]; nb<_row[nrFine+1]; nb++)
738  {
739  const int nc = _col[nb];
740  const int ncCoarse = coarseIndex[nc];
741 
742  if (ncCoarse<0) continue;
743 
744  if (nrCoarse!=ncCoarse)
745  {
746  const int pos = coarseCoeffPos[ncCoarse];
747  coarseOffDiag[pos] += _offDiag[nb];
748  }
749  else
750  {
751  coarseDiag[nrCoarse] += _offDiag[nb];
752  }
753  }
754  }
755  }
756 
757  return coarseMatrix;
758  }
759 
760 #ifdef FVM_PARALLEL
761 
762 shared_ptr<Matrix>
763 createMergeMatrix( const LinearSystemMerger& mergeLS )
764 {
765  const CRConnectivity& conn = mergeLS.getConnectivity();
766 
767  const map<int,IntArrayPtr>& localToGlobalMap = mergeLS.getLocalToGlobal();
768 
769  const Array<int>& selfCounts = mergeLS.getSelfCounts();
770 
771  const map< int, IntArrayPtr >& rowMap = mergeLS.getLocalConnRow();
772  const map< int, IntArrayPtr >& colMap = mergeLS.getLocalConnCol();
773  const vector< map<int,int> >& gatherIDsLocalToGlobal = mergeLS.getGatherIDsLocalToGlobal(); //[proc][localid] = globalID
774 
775  const map<int, ArrayDblePtr> & diagMap = mergeLS.getDiag();
776  const map<int, ArrayDblePtr> & offDiagMap = mergeLS.getOffDiag();
777 
778  const set<int>& group = mergeLS.getGroup();
779 
780  shared_ptr<CRMatrix> mergeMatrix( new CRMatrix(conn) );
781  mergeMatrix->initAssembly();
782 
783  Array<Diag>& mergeDiag = mergeMatrix->getDiag();
784  Array<OffDiag>& mergeOffDiag = mergeMatrix->getOffDiag();
785  const Array<int>& mergeRow = conn.getRow();
786  const Array<int>& mergeCol = conn.getCol();
787  foreach ( const set<int>::value_type proc_id, group ){
788  const Array<double>& diag = *diagMap.find(proc_id)->second;
789  const Array<double>& offDiag = *offDiagMap.find(proc_id)->second;
790 
791  const Array<int>& localToGlobal = *localToGlobalMap.find(proc_id)->second;
792  const map<int,int>& gatherIDsMap = gatherIDsLocalToGlobal[proc_id];
793 
794  const Array<int>& row = *rowMap.find(proc_id)->second;
795  const Array<int>& col = *colMap.find(proc_id)->second;
796 
797  for ( int i = 0; i < selfCounts[proc_id]; i++ ){
798  int glbl_indx = localToGlobal[i];
799  mergeDiag[glbl_indx] = diag[i];
800  }
801 
802  for ( int i = 0; i < selfCounts[proc_id]; i++ ){
803  int global_indx = localToGlobal[i];
804  for ( int np = row[i]; np < row[i+1]; np++ ){
805  int local_j = col[np];
806 
807  //if -1 means boundary skip it
808  if ( local_j >= 0 ){
809  int global_j = -1;
810  if ( local_j < selfCounts[proc_id] )
811  global_j = localToGlobal[ local_j ];
812  else //ghost
813  global_j = gatherIDsMap.find(local_j)->second;
814 
815 
816  for ( int npg = mergeRow[global_indx]; npg < mergeRow[global_indx+1]; npg++ ){
817  if ( mergeCol[npg] == global_j ){
818  mergeOffDiag[npg] = offDiag[np];
819  }
820  }
821  }
822  }
823  }
824 
825  }
826 
827 
828  return mergeMatrix;
829 
830 }
831 
832 #endif
833 
834  virtual const CRConnectivity& getConnectivity() const {return _conn;}
835 
836  OffDiag& getCoeff(const int i, const int j)
837  {
838  for (int nnb = _row[i]; nnb<_row[i+1]; nnb++)
839  {
840  if (_col[nnb] == j)
841  return _offDiag[nnb];
842  }
843  throw CException("invalid indices");
844  }
845 
846  bool hasCoeff(const int i, const int j)
847  {
848  for (int nnb = _row[i]; nnb<_row[i+1]; nnb++)
849  {
850  if (_col[nnb] == j)
851  return true;
852  }
853  return false;
854  }
855 
856  Array<Diag>& getDiag() {return _diag;}
858 
859  const Array<Diag>& getDiag() const {return _diag;}
860  const Array<OffDiag>& getOffDiag() const {return _offDiag;}
861 
862  void *getDiagData() const { return _diag.getData(); }
863  void *getOffDiagData() const { return _offDiag.getData(); }
864  int getDiagDataSize() const { return _diag.getDataSize(); }
865  int getOffDiagDataSize() const { return _offDiag.getDataSize(); }
866 
868  {
869  if (_pairWiseAssemblers.find(&pairs) == _pairWiseAssemblers.end())
870  {
871  _pairWiseAssemblers[&pairs] =
873  _conn.getPairToColMapping(pairs));
874  }
875  return *_pairWiseAssemblers[&pairs];
876  }
877 
878  virtual ~CRMatrix()
879  {
880  for (typename PairWiseAssemblerMap::iterator pos = _pairWiseAssemblers.begin();
881  pos != _pairWiseAssemblers.end();
882  ++pos)
883  delete pos->second;
884  logDtor();
885  }
886 
887  void setDirichlet(const int nr)
888  {
889  for (int nb = _row[nr]; nb<_row[nr+1]; nb++)
892  _isBoundary[nr] = true;
893  }
894 
895  // eliminate row j from the linear system. This only works for
896  // boundary rows because of the special connectivity pattern. We
897  // also assume that the connectivity is symmetric. The rhs b is required.
898 
899  void eliminateRow(const int j, Array<X>& b )
900  {
901  // in case of problems with an immersed boundary, we might call
902  // this function also for interior rows that are marked as
903  // Dirichlet but in that case we don't need to do anything since
904  // the off diagonal entries are all zero
905  const int nRowsInterior = _conn.getRowSite().getSelfCount();
906  const bool isInterior = (j<nRowsInterior);
907 
908  if (isInterior) return;
909 
910  const Diag& a_jj = _diag[j];
911  // loop over neighbours of j to determine the rows that will change
912  for (int nb = _row[j]; nb<_row[j+1]; nb++)
913  {
914  const int i = _col[nb];
915  OffDiag& a_ij = getCoeff(i,j);
916 
917  // for the ith row we need to find the indices k for which the
918  // entries will change. we do this by again going through
919  // neighbors of j
920 
921  for (int nb2 = _row[j]; nb2<_row[j+1]; nb2++)
922  {
923  const int k = _col[nb2];
924  const OffDiag& a_jk = _offDiag[nb2];
925 
926  if (i!=k)
927  {
928  if (hasCoeff(i,k))
929  {
930  OffDiag& a_ik = getCoeff(i,k);
931  a_ik -= DiagToOffDiag(a_ij*(a_jk/a_jj));
932  }
933  }
934  else
935  _diag[i] -= a_ij*(a_jk/a_jj);
936  }
937 
938  b[i] -= a_ij*(b[j]/a_jj);
940 
941  }
942 
943 
944  }
945 
946  // eliminate row j from the linear system. This only works for
947  // boundary rows because of the special connectivity pattern. We
948  // also assume that the connectivity is symmetric. The rhs b is required.
949  //this addition elimination is necessary if you have ghost cells which is
950  //real boundary on the other partition or mesh
951 
953  {
954 
955  const StorageSite& site = _conn.getRowSite();
956  const int nRowsInterior = site.getSelfCount();
957  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
958  //looping gathermap indices
959  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
960  const StorageSite& oSite = *mpos.first;
961  EntryIndex e(&oSite,&site);
962  const Array<int>& recv_counts = dynamic_cast< const Array<int>& > (*_recvCounts [e]);
963  const Array<int>& recv_indices = dynamic_cast< const Array<int>& > (*_recvIndices [e]);
964  const Array<OffDiag>& recv_values_crmtrx = dynamic_cast< const Array<OffDiag>& > (*_recvValuesCRMtrx[e]);
965  const Array<X>& recv_values_b = dynamic_cast< const Array<X>& > (*_recvValuesB[e]);
966 
967  //row and col
968  Array<int> row( recv_counts.getLength()+1);
969  row[0] = 0;
970  for ( int i = 1; i < recv_counts.getLength()+1; i++ ){
971  row[i] = row[i-1] + recv_counts[i-1] - 1;
972  }
973 
974  Array<int> boundaryPtr( recv_counts.getLength());
975  boundaryPtr[0] = 0;
976  for ( int i = 1; i < recv_counts.getLength(); i++ ){
977  boundaryPtr[i] = boundaryPtr[i-1] + recv_counts[i-1];
978  }
979  //col and offDiag
980  Array<int> col( row[recv_counts.getLength()] );
981  Array<OffDiag> offDiag( row[recv_counts.getLength()] );
982  int indx = 0;
983  int jj = 0;
984  for ( int i=0; i<recv_counts.getLength(); i++ ){
985  indx++; //skip first
986  for ( int j=1; j<recv_counts[i]; j++ ){
987  col[jj] = recv_indices[indx];
988  offDiag[jj] = recv_values_crmtrx[indx];
989  jj++; indx++;
990  }
991  }
992 
993  //over boundary cells on ghost
994  for ( int rc = 0; rc < recv_counts.getLength(); rc++ ){
995  const int pIndx = boundaryPtr[rc]; //point where the boundary location in recv_indices or recv_values_crmtrx
996  const int j = recv_indices[pIndx];
997  const OffDiag& a_jj = recv_values_crmtrx[pIndx];
998  // loop over neighbours of j to determine the rows that will change
999  for (int nb = row[rc]; nb<row[rc+1]; nb++)
1000  {
1001  const int i = col[nb];
1002  if ( i < nRowsInterior ){
1003  OffDiag& a_ij = getCoeff(i,j);
1004  // for the ith row we need to find the indices k for which the
1005  // entries will change. we do this by again going through
1006  // neighbors of j
1007  for (int nb2 = row[rc]; nb2<row[rc+1]; nb2++)
1008  {
1009  const int k = col[nb2];
1010  const OffDiag& a_jk = offDiag[nb2];
1011 
1012  if (i!=k)
1013  {
1014  OffDiag& a_ik = getCoeff(i,k);
1015  a_ik -= a_ij*(a_jk/a_jj);
1016  }
1017  else
1018  _diag[i] -= a_ij*(a_jk/a_jj);
1019  }
1020  b[i] -= a_ij*(recv_values_b[rc]/a_jj);
1022  }
1023  }
1024  }
1025  }
1026  }
1027 
1028  virtual void printRow(const int i) const
1029  {
1030  cout << "coeff (" << i << "," << i << ") = " << _diag[i] << endl;
1031 
1032  for (int nb = _row[i]; nb<_row[i+1]; nb++)
1033  {
1034  const int j = _col[nb];
1035  cout << "coeff (" << i << "," << j << ") = " << _offDiag[nb] << endl;
1036  }
1037  }
1038 
1039  // eliminate a_ij coefficients because of a dirichlet row j, the rhs
1040  // b as well as the delta_j values are required
1041  void eliminateDirichlet(const int j, Array<X>& b, const X& delta_j,
1042  const bool explicitMode=false)
1043  {
1044  for (int nb = _row[j]; nb<_row[j+1]; nb++)
1045  {
1046  const int i = _col[nb];
1047  OffDiag& a_ij = getCoeff(i,j);
1048 
1049  b[i] += a_ij*delta_j;
1050 
1051  if (!explicitMode)
1053  }
1054  }
1055 
1056  void setBoundary(const int nr)
1057  {
1058  _isBoundary[nr] = true;
1059  }
1060 
1061  // eliminate the boundary equations from the interior ones. This is
1062  // called by initSolve() of LinearSystem. Subsequent linear solver
1063  // methods operate only on the interior equations.
1065  {
1066  XArray& b = dynamic_cast<XArray&>(bB);
1067  const int nRowsInterior = _conn.getRowSite().getSelfCount();
1068  const int nRowsExtra = _conn.getRowSite().getCount();
1069 
1070  for(int nr=nRowsInterior; nr<nRowsExtra; nr++)
1071  if (_isBoundary[nr])
1072  eliminateRow(nr,b);
1073 
1074  //syncing coefficients from other processors (or other mesh) to eliminate equations
1075  //const StorageSite& site = _conn.getRowSite();
1076  //if (b.getLength() == site.getCountLevel1() && site.getCountLevel1() != site.getCount() ){
1077 #ifdef FVM_PARALLEL
1078  //skip nprocs == 1
1079  if ( _conn.getConnType() == CRConnectivity::CELLCELL2 && MPI::COMM_WORLD.Get_size() > 1 ){
1080  syncBndryCoeffs(b);
1081  eliminateRowGhost(b);
1082  }
1083 
1084 #endif
1085  }
1086 
1087  virtual void setFlatMatrix(Matrix& fmg) const
1088  {
1092  }
1093 
1094 private:
1095 
1096  void syncBndryCoeffs( const Array<X>& b )
1097  {
1098  //create recvCounts buffer
1100  //syn counts
1101  syncCounts();
1102  //create recvindices buffer
1104  //sync indices
1105  syncIndices();
1106  //create crmtrx buffer
1108  //sync values crmtrx
1109  syncValuesCRMtrx();
1110  //create b buffer
1112  //sync values b
1113  syncValuesB();
1114  }
1115 
1116  //fill countArray (both mesh and partition) and only gatherArray for mesh
1118  {
1119  //SENDING allocation and filling
1120  const StorageSite& site = _conn.getRowSite();
1121  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1122  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1123  const StorageSite& oSite = *mpos.first;
1124  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1125  const Array<int>& scatterArray = *mpos.second;
1126  int boundaryCount = 0;
1127  vector<int> cellCellsCount;
1128  for (int i = 0; i < scatterArray.getLength(); i++){
1129  const int cellID = scatterArray[i];
1130  if ( _isBoundary[cellID] ){
1131  boundaryCount++;
1132  cellCellsCount.push_back( _conn.getCount( scatterArray[i] )+1 ); //adding itself
1133  }
1134  }
1135 
1136  //key site
1137  EntryIndex e(&site,&oSite);
1138  //allocate array
1139  _sendCounts[e] = shared_ptr< Array<int> > ( new Array<int> (boundaryCount) );
1140  //fill send array
1141  Array<int>& sendArray = dynamic_cast< Array<int>& > ( *_sendCounts[e] );
1142  for( int i = 0; i < boundaryCount; i++ ){
1143  sendArray[i] = cellCellsCount[i];
1144  }
1145  }
1146  //RECIEVING allocation (filling will be done by MPI Communication)
1147  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1148  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1149  const StorageSite& oSite = *mpos.first;
1150  EntryIndex e(&oSite,&site);
1151  //mesh interface can be done know
1152  if (oSite.getGatherProcID() == - 1) {
1153  *_recvCounts[e] = *_sendCounts[e];
1154  }
1155  }
1156  }
1157 
1158  void syncCounts()
1159  {
1160 #ifdef FVM_PARALLEL
1161  //SENDING
1162  const int request_size = get_request_size();
1163  MPI::Request request_send[ request_size ];
1164  MPI::Request request_recv[ request_size ];
1165  int indxSend = 0;
1166  int indxRecv = 0;
1167  const StorageSite& site = _conn.getRowSite();
1168  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1169  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1170  const StorageSite& oSite = *mpos.first;
1171  EntryIndex e(&site,&oSite);
1172  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1173  ArrayBase& sendArray = *_sendCounts[e];
1174  //loop over surround indices and itself
1175  int to_where = oSite.getGatherProcID();
1176  //many interior partiton is not going to have any boundary in cellCell2 so no need to send the data
1177  if ( to_where != -1 ){
1178  int mpi_tag = oSite.getTag();
1179  request_send[indxSend++] =
1180  MPI::COMM_WORLD.Isend( sendArray.getData(), sendArray.getDataSize(), MPI::BYTE, to_where, mpi_tag );
1181  }
1182  }
1183  //RECIEVING
1184  //getting values from other meshes to fill g
1185  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1186  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1187  const StorageSite& oSite = *mpos.first;
1188  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1189  EntryIndex e(&oSite,&site);
1190  int from_where = oSite.getGatherProcID();
1191  if ( from_where != -1 ){
1192  int mpi_tag = oSite.getTag();
1193  MPI::Status recv_status;
1194  while ( !(recv_status.Get_source() == from_where && recv_status.Get_tag() == mpi_tag) ){
1195  if ( MPI::COMM_WORLD.Iprobe(from_where, mpi_tag, recv_status) ){
1196  const int recv_count = recv_status.Get_count( MPI::INT );
1197  _recvCounts[e] = shared_ptr< Array<int> > ( new Array<int> (recv_count) );
1198  ArrayBase& recvArray = *_recvCounts[e];
1199  request_recv[indxRecv++] =
1200  MPI::COMM_WORLD.Irecv( recvArray.getData(), recvArray.getDataSize(), MPI::BYTE, from_where, mpi_tag );
1201  }
1202  }
1203  }
1204  }
1205 
1206  int count = get_request_size();
1207  MPI::Request::Waitall( count, request_recv );
1208  MPI::Request::Waitall( count, request_send );
1209 #endif
1210 
1211  }
1212 
1213  //fill scatterArray (both mesh and partition) and only gatherArray for mesh
1215  {
1216  //SENDING allocation and filling
1217  const StorageSite& site = _conn.getRowSite();
1218  const Array<int>& localToGlobal = _conn.getLocalToGlobalMap();
1219  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1220  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1221  const StorageSite& oSite = *mpos.first;
1222  const Array<int>& scatterArray = *mpos.second;
1223  //loop over surround indices and itself for sizing
1224  EntryIndex e(&site,&oSite);
1225  const Array<int>& send_counts = dynamic_cast< const Array<int>& > (*_sendCounts[e]);
1226  //allocate array
1227  int sendSize = 0;
1228  for ( int i = 0; i < send_counts.getLength(); i++ ){
1229  sendSize += send_counts[i];
1230  }
1231  _sendIndices[e] = shared_ptr< Array<int> > ( new Array<int> (sendSize) );
1232  //fill send array
1233  Array<int>& sendArray = dynamic_cast< Array<int>& > ( *_sendIndices[e] );
1234  int indx = 0;
1235  for( int i = 0; i < scatterArray.getLength(); i++ ){
1236  const int cellID = scatterArray[i];
1237  if ( _isBoundary[cellID] ){
1238  sendArray[indx++] = localToGlobal[cellID];
1239  for ( int j = 0; j < _conn.getCount(cellID); j++ ){
1240  sendArray[indx] = localToGlobal[ _conn(cellID,j) ];
1241  indx++;
1242  }
1243  }
1244  }
1245  }
1246  //RECIEVING allocation (filling will be done by MPI Communication)
1247  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1248  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1249  const StorageSite& oSite = *mpos.first;
1250  EntryIndex e(&oSite,&site);
1251  const Array<int>& recvCounts = dynamic_cast< const Array<int>& > (*_recvCounts[e]);
1252  int recvSize = 0;
1253  for ( int i = 0; i < recvCounts.getLength(); i++ ){
1254  recvSize += recvCounts[i];
1255  }
1256  //allocate array
1257  _recvIndices[e] = shared_ptr< Array<int> > ( new Array<int> (recvSize) );
1258  //mesh interface can be done know
1259  if ( oSite.getGatherProcID() == - 1) {
1260  *_recvIndices[e] = *_sendIndices[e];
1261  }
1262  }
1263 
1264  }
1265 
1266 
1268  {
1269 
1270 #ifdef FVM_PARALLEL
1271  //SENDING
1272  const int request_size = get_request_size();
1273  MPI::Request request_send[ request_size ];
1274  MPI::Request request_recv[ request_size ];
1275  int indxSend = 0;
1276  int indxRecv = 0;
1277  const StorageSite& site = _conn.getRowSite();
1278  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1279  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1280  const StorageSite& oSite = *mpos.first;
1281  EntryIndex e(&site,&oSite);
1282  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1283  ArrayBase& sendArray = *_sendIndices[e];
1284  //loop over surround indices and itself
1285  int to_where = oSite.getGatherProcID();
1286  if ( to_where != -1 ){
1287  int mpi_tag = oSite.getTag();
1288  request_send[indxSend++] =
1289  MPI::COMM_WORLD.Isend( sendArray.getData(), sendArray.getDataSize(), MPI::BYTE, to_where, mpi_tag );
1290  }
1291  }
1292  //RECIEVING
1293  //getting values from other meshes to fill g
1294  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1295  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1296  const StorageSite& oSite = *mpos.first;
1297  EntryIndex e(&oSite,&site);
1298  ArrayBase& recvArray = *_recvIndices[e];
1299  int from_where = oSite.getGatherProcID();
1300  if ( from_where != -1 ){
1301  int mpi_tag = oSite.getTag();
1302  request_recv[indxRecv++] =
1303  MPI::COMM_WORLD.Irecv( recvArray.getData(), recvArray.getDataSize(), MPI::BYTE, from_where, mpi_tag );
1304  }
1305  }
1306 
1307  int count = get_request_size();
1308  MPI::Request::Waitall( count, request_recv );
1309  MPI::Request::Waitall( count, request_send );
1310 #endif
1311 
1312 #ifndef FVM_PARALLEL
1313  const StorageSite& site = _conn.getRowSite();
1314  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1315 #endif
1316  //globaltolocal
1317  const map<int,int>& globalToLocal = _conn. getGlobalToLocalMapper();
1318  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1319  const StorageSite& oSite = *mpos.first;
1320  EntryIndex e(&oSite,&site);
1321  Array<int>& recv_indices = dynamic_cast< Array<int>& > (*_recvIndices[e]);
1322  for( int i=0; i < recv_indices.getLength(); i++ ){
1323  const int localID = globalToLocal.find( recv_indices[i] )->second;
1324  recv_indices[i] = localID;
1325  }
1326  }
1327 
1328  }
1329 
1330  //fill scatterArray (both mesh and partition) and only gatherArray for mesh
1332  {
1333  //SENDING allocation and filling
1334  const StorageSite& site = _conn.getRowSite();
1335  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1336  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1337  const StorageSite& oSite = *mpos.first;
1338  const Array<int>& scatterArray = *mpos.second;
1339  //loop over surround indices and itself for sizing
1340  EntryIndex e(&site,&oSite);
1341  //decide allocation size
1342  const Array<int>& send_counts = dynamic_cast< const Array<int>& > (*_sendCounts[e]);
1343  int sendSize = 0;
1344  for ( int i = 0; i < send_counts.getLength(); i++ ){
1345  sendSize += send_counts[i];
1346  }
1347  //allocate array
1348  _sendValuesCRMtrx[e] = shared_ptr< Array<OffDiag> > ( new Array<OffDiag> (sendSize) );
1349  //fill send array
1350  Array<OffDiag>& valueArray = dynamic_cast< Array<OffDiag>& > ( *_sendValuesCRMtrx[e] );
1351  int indx = 0;
1352  for( int i = 0; i < scatterArray.getLength(); i++ ){
1353  const int ii = scatterArray[i];
1354  if ( _isBoundary[ii] ){
1355  valueArray[indx++] = DiagToOffDiag(_diag[ii]);
1356  for ( int j = 0; j < _conn.getCount(ii); j++ ){
1357  const int jj = _conn(ii,j);
1358  valueArray[indx] = getCoeff(ii,jj);
1359  indx++;
1360  }
1361  }
1362  }
1363  }
1364  //RECIEVING allocation (filling will be done by MPI Communication)
1365  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1366  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1367  const StorageSite& oSite = *mpos.first;
1368  EntryIndex e(&oSite,&site);
1369  //get recvSize
1370  const Array<int>& recvCounts = dynamic_cast< const Array<int>& > (*_recvCounts[e]);
1371  int recvSize = 0;
1372  for ( int i = 0; i < recvCounts.getLength(); i++ ){
1373  recvSize += recvCounts[i];
1374  }
1375  //allocate array
1376  _recvValuesCRMtrx[e] = shared_ptr< Array<OffDiag> > ( new Array<OffDiag> (recvSize) );
1377  //mesh interface can be done know
1378  if ( oSite.getGatherProcID() == - 1) {
1380  }
1381  }
1382 
1383  }
1384 
1385  //sending values
1387  {
1388  #ifdef FVM_PARALLEL
1389  //SENDING
1390  const int request_size = get_request_size();
1391  MPI::Request request_send[ request_size ];
1392  MPI::Request request_recv[ request_size ];
1393  int indxSend = 0;
1394  int indxRecv = 0;
1395  const StorageSite& site = _conn.getRowSite();
1396  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1397  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1398  const StorageSite& oSite = *mpos.first;
1399  EntryIndex e(&site,&oSite);
1400  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1401  ArrayBase& sendArray = *_sendValuesCRMtrx[e];
1402  //loop over surround indices and itself
1403  int to_where = oSite.getGatherProcID();
1404  if ( to_where != -1 ){
1405  int mpi_tag = oSite.getTag();
1406  request_send[indxSend++] =
1407  MPI::COMM_WORLD.Isend( sendArray.getData(), sendArray.getDataSize(), MPI::BYTE, to_where, mpi_tag );
1408  }
1409  }
1410  //RECIEVING
1411  //getting values from other meshes to fill g
1412  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1413  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1414  const StorageSite& oSite = *mpos.first;
1415  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1416  EntryIndex e(&oSite,&site);
1417  ArrayBase& recvArray = *_recvValuesCRMtrx[e];
1418  int from_where = oSite.getGatherProcID();
1419  if ( from_where != -1 ){
1420  int mpi_tag = oSite.getTag();
1421  request_recv[indxRecv++] =
1422  MPI::COMM_WORLD.Irecv( recvArray.getData(), recvArray.getDataSize(), MPI::BYTE, from_where, mpi_tag );
1423  }
1424  }
1425 
1426  int count = get_request_size();
1427  MPI::Request::Waitall( count, request_recv );
1428  MPI::Request::Waitall( count, request_send );
1429 #endif
1430 
1431  }
1432 
1433  //fill scatterArray (both mesh and partition) and only gatherArray for mesh
1435  {
1436  //SENDING allocation and filling
1437  const StorageSite& site = _conn.getRowSite();
1438  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1439  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1440  const StorageSite& oSite = *mpos.first;
1441  const Array<int>& scatterArray = *mpos.second;
1442  //loop over surround indices and itself for sizing
1443  EntryIndex e(&site,&oSite);
1444  //decide allocation size
1445  const Array<int>& send_counts = dynamic_cast< const Array<int>& > (*_sendCounts[e]);
1446  int sendSize = send_counts.getLength();
1447  //allocate array
1448  _sendValuesB[e] = shared_ptr< Array<X> > ( new Array<X> (sendSize) );
1449  //fill send array
1450  XArray& bArray = dynamic_cast< Array<X>& > ( *_sendValuesB[e] );
1451  int indx = 0;
1452  for( int i = 0; i < scatterArray.getLength(); i++ ){
1453  const int ii = scatterArray[i];
1454  if ( _isBoundary[ii] ){
1455  bArray[indx++] = B[ii];
1456  }
1457  }
1458  }
1459  //RECIEVING allocation (filling will be done by MPI Communication)
1460  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1461  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1462  const StorageSite& oSite = *mpos.first;
1463  EntryIndex e(&oSite,&site);
1464  //get recvSize
1465  const Array<int>& recvCounts = dynamic_cast< const Array<int>& > (*_recvCounts[e]);
1466  int recvSize = recvCounts.getLength();
1467  //allocate array
1468  _recvValuesB[e] = shared_ptr< Array<X> > ( new Array<X> (recvSize) );
1469  //mesh interface can be done know
1470  if ( oSite.getGatherProcID() == - 1) {
1471  *_recvValuesB[e] = *_sendValuesB[e];
1472  }
1473  }
1474 
1475  }
1476 
1477  //sending values
1479  {
1480  #ifdef FVM_PARALLEL
1481  //SENDING
1482  const int request_size = get_request_size();
1483  MPI::Request request_send[ request_size ];
1484  MPI::Request request_recv[ request_size ];
1485  int indxSend = 0;
1486  int indxRecv = 0;
1487  const StorageSite& site = _conn.getRowSite();
1488  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1489  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1490  const StorageSite& oSite = *mpos.first;
1491  EntryIndex e(&site,&oSite);
1492  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1493  ArrayBase& sendArray = *_sendValuesB[e];
1494  //loop over surround indices and itself
1495  int to_where = oSite.getGatherProcID();
1496  if ( to_where != -1 ){
1497  int mpi_tag = oSite.getTag();
1498  request_send[indxSend++] =
1499  MPI::COMM_WORLD.Isend( sendArray.getData(), sendArray.getDataSize(), MPI::BYTE, to_where, mpi_tag );
1500  }
1501  }
1502  //RECIEVING
1503  //getting values from other meshes to fill g
1504  const StorageSite::GatherMap& gatherMap = site.getGatherMapLevel1();
1505  foreach(const StorageSite::GatherMap::value_type& mpos, gatherMap){
1506  const StorageSite& oSite = *mpos.first;
1507  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1508  EntryIndex e(&oSite,&site);
1509  ArrayBase& recvArray = *_recvValuesB[e];
1510  int from_where = oSite.getGatherProcID();
1511  if ( from_where != -1 ){
1512  int mpi_tag = oSite.getTag();
1513  request_recv[indxRecv++] =
1514  MPI::COMM_WORLD.Irecv( recvArray.getData(), recvArray.getDataSize(), MPI::BYTE, from_where, mpi_tag );
1515  }
1516  }
1517 
1518  int count = get_request_size();
1519  MPI::Request::Waitall( count, request_recv );
1520  MPI::Request::Waitall( count, request_send );
1521 #endif
1522 
1523  }
1524 
1526  {
1527  int indx = 0;
1528  const StorageSite& site = _conn.getRowSite();
1529  const StorageSite::ScatterMap& scatterMap = site.getScatterMapLevel1();
1530  foreach(const StorageSite::ScatterMap::value_type& mpos, scatterMap){
1531  const StorageSite& oSite = *mpos.first;
1532  //checking if storage site is only site or ghost site, we only communicate ghost site ( oSite.getCount() == -1 )
1533  if ( oSite.getGatherProcID() != -1 )
1534  indx++;
1535  }
1536  return indx;
1537  }
1538 
1539 
1540 
1541 
1542 
1543 
1544  // computes the level 0 (i.e. with no additional non zero entries)
1545  // incomplete LU factorization
1546  void compute_ILU0() const
1547  {
1548  const int nRows = _conn.getRowSite().getSelfCount();
1549 
1550  // create connectivity matrix for the ILU factored matrix; for ILU
1551  // 0 the only difference from this CRMatrix's connectivity is that
1552  // the diagonal is explicitly included
1553  //
1554 
1555  _iluConnPtr = shared_ptr<CRConnectivity>
1557  CRConnectivity& iluConn = *_iluConnPtr;
1558 
1559  iluConn.initCount();
1560 
1561  for(int nr=0; nr<nRows; nr++)
1562  {
1563  // add one for diagonal
1564  iluConn.addCount(nr,1);
1565  for(int nb=_row[nr]; nb<_row[nr+1]; nb++)
1566  {
1567  // only include neighbours in this matrix
1568  if (_col[nb] < nRows)
1569  iluConn.addCount(nr,1);
1570  }
1571  }
1572 
1573  iluConn.finishCount();
1574 
1575  const int nnz = iluConn.getCol().getLength();
1576  _iluCoeffsPtr = DiagArrayPtr(new DiagArray(nnz));
1577  _iluDiagIndexPtr = IntArrayPtr(new IntArray(nRows));
1578 
1579  DiagArray& iluCoeffs = *_iluCoeffsPtr;
1580  IntArray& iluDiagIndex = *_iluDiagIndexPtr;
1581 
1582  // now we can fill the iluCoeffs with this matrix's coeffs
1583  for(int nr=0; nr<nRows; nr++)
1584  {
1585  // lower coeffs first
1586  for(int nb=_row[nr]; nb<_row[nr+1]; nb++)
1587  {
1588  const int j = _col[nb];
1589  if (j < nRows && j < nr)
1590  {
1591  const int pos = iluConn.add(nr,j);
1592  iluCoeffs[pos] = _offDiag[nb];
1593  }
1594 
1595  }
1596 
1597  // add diagonal next
1598  const int pos = iluConn.add(nr,nr);
1599  iluCoeffs[pos] = _diag[nr];
1600  iluDiagIndex[nr] = pos;
1601 
1602  // finally the upper coeffs
1603  for(int nb=_row[nr]; nb<_row[nr+1]; nb++)
1604  {
1605  const int j = _col[nb];
1606  if (j < nRows && j > nr)
1607  {
1608  const int pos = iluConn.add(nr,j);
1609  iluCoeffs[pos] = _offDiag[nb];
1610  }
1611 
1612  }
1613  }
1614 
1615  // finalize the iluConnectivity
1616  iluConn.finishAdd();
1617 
1618  // ilu decomposition
1619 
1620  const IntArray& iluRow = iluConn.getRow();
1621  const IntArray& iluCol = iluConn.getCol();
1622 
1623 
1624  //work array iw(n) and diagonal pointer uptr
1625  Array<int> iw(nRows);
1626  Array<int> uptr(nRows);
1627  iw = 0;
1628  uptr = 0;
1629 
1630  const Diag unity(NumTypeTraits<Diag>::getUnity());
1631 
1632  //main loop
1633  for (int k = 0; k < nRows; k++ )
1634  {
1635  const int j1 = iluRow[k];
1636  const int j2 = iluRow[k+1];
1637  for (int j = j1; j <j2; j++ )
1638  iw[ iluCol[j] ] = j;
1639 
1640  int j = j1;
1641  do
1642  {
1643  int jrow = iluCol[j];
1644  if ( jrow < k )
1645  {
1646  const Diag t1 = iluCoeffs[j] * iluCoeffs[ uptr[jrow] ];
1647  iluCoeffs[j] = t1;
1648  //perform linear combination
1649  for (int jj = uptr[jrow]+1; jj < iluRow[jrow+1]; jj++ )
1650  {
1651  int jw = iw[ iluCol[jj] ];
1652  if ( jw != 0 )
1653  iluCoeffs[jw] -= t1 * iluCoeffs[jj];
1654  }
1655  j++;
1656  }
1657  else
1658  {
1659  uptr[k] = j;
1660  break;
1661  }
1662  }
1663  while( j < j2 );
1664 
1665  //inverting diagonal
1666  iluCoeffs[j] = unity / iluCoeffs[j];
1667  //zeroing iw
1668  for ( int i = j1; i < j2; i++ )
1669  iw[ iluCol[i] ] = 0;
1670  }
1671  }
1672 
1673 
1674  //Solve L y = b. This assumes that the factorization has already
1675  //been performed
1676  void lowerSolve( XArray& y, const XArray& b) const
1677  {
1678  const IntArray& iluRow = _iluConnPtr->getRow();
1679  const IntArray& iluCol = _iluConnPtr->getCol();
1680  const IntArray& iluDiagIndex = *_iluDiagIndexPtr;
1681  const DiagArray& iluCoeffs = *_iluCoeffsPtr;
1682 
1683  const int nRows = _conn.getRowSite().getSelfCount();
1684 
1685  for (int j = 0; j < nRows; j++)
1686  {
1687  X yj = -b[j];
1688  for ( int k = iluRow[j]; k < iluDiagIndex[j]; k++ )
1689  {
1690  yj -= iluCoeffs[k] * y[ iluCol[k] ];
1691  }
1692  y[j] = yj;
1693  }
1694  }
1695 
1696  //solve U x = y
1697  void upperSolve( XArray& x, const XArray& y ) const
1698  {
1699  const IntArray& iluRow = _iluConnPtr->getRow();
1700  const IntArray& iluCol = _iluConnPtr->getCol();
1701  const IntArray& iluDiagIndex = *_iluDiagIndexPtr;
1702  const DiagArray& iluCoeffs = *_iluCoeffsPtr;
1703 
1704  const int nRows = _conn.getRowSite().getSelfCount();
1705 
1706  for ( int j = nRows-1; j >= 0; j-- )
1707  {
1708  X xj = y[j];
1709  for ( int k = iluDiagIndex[j]+1; k <iluRow[j+1]; k++ )
1710  {
1711  xj -= iluCoeffs[k] * x[ iluCol[k] ];
1712  }
1713  x[j] = iluCoeffs[ iluDiagIndex[j] ]*xj;
1714  }
1715  }
1716 
1717 
1725 
1726  // connectivity for the ILU factorization. This connectivity
1727  // explicitly includes diagonal and is also ordered such that for a
1728  // particular row the lower triangle entries are first, followed by
1729  // the diagonal and then the upper triangle entries. The _iluDiagIndexPtr
1730  // array is used to keep the index of the diagonal location
1731  mutable shared_ptr<CRConnectivity> _iluConnPtr;
1732 
1734 
1735  // ilu coeffs
1737 
1738  mutable shared_ptr<T_SpikeMtrx> _spikeMtrx;
1739 
1748  map<int,int> _ghostCellBoundayMap;
1749 
1750 
1751 };
1752 
1753 
1754 #include "Vector.h"
1755 #include "DiagonalTensor.h"
1756 
1757 template<class T>
1759 {
1761 };
1762 
1763 template<class T, int N>
1765 {
1769 };
1770 
1771 #endif
void * getOffDiagData() const
Definition: CRMatrix.h:863
const Array< int > & getCol() const
pair< const StorageSite *, const StorageSite * > EntryIndex
Definition: CRMatrix.h:106
void syncCounts()
Definition: CRMatrix.h:1158
int getCount(const int i) const
virtual void zero()
Definition: Array.h:281
GhostArrayMap _sendCounts
Definition: CRMatrix.h:1740
X DiagToOffDiag(const X &x)
Definition: CRMatrix.h:25
DEFINE_TYPENAME("CRMatrix<"+NumTypeTraits< Diag >::getTypeName()+","+NumTypeTraits< OffDiag >::getTypeName()+","+NumTypeTraits< X >::getTypeName()+">")
virtual int getDataSize() const =0
const Array< int > & getRow() const
int getSelfCount() const
Definition: StorageSite.h:40
CRMatrix< T, T, T > T_Matrix
Definition: CRMatrix.h:1760
virtual void Jacobi(IContainer &xnewB, const IContainer &xoldB, const IContainer &bB) const
Definition: CRMatrix.h:353
void createScatterGatherIndicesBuffer()
Definition: CRMatrix.h:1214
shared_ptr< T_SpikeMtrx > _spikeMtrx
Definition: CRMatrix.h:1738
virtual void initAssembly()
Definition: CRMatrix.h:188
shared_ptr< Array< int > > IntArrayPtr
Definition: CRMatrix.h:100
void upperSolve(XArray &x, const XArray &y) const
Definition: CRMatrix.h:1697
Array< int > IntArray
Definition: CRMatrix.h:96
virtual shared_ptr< ArrayBase > quadProduct(const IContainer &xB) const
Definition: CRMatrix.h:274
const Array< int > & _col
Definition: CRMatrix.h:1720
PairWiseAssembler(Array< OffDiag > &coeffs, const Array< Vector< int, 2 > > &pairToCol)
Definition: CRMatrix.h:120
void syncBndryCoeffs(const Array< X > &b)
Definition: CRMatrix.h:1096
CRMatrix< T_DiagTensor, T_DiagTensor, T_Vector > T_Matrix
Definition: CRMatrix.h:1768
virtual void eliminateBoundaryEquations(IContainer &bB)
Definition: CRMatrix.h:1064
const GatherMap & getGatherMapLevel1() const
Definition: StorageSite.h:74
OffDiag & getCoeff(const int i, const int j)
Definition: CRMatrix.h:836
shared_ptr< Array< Diag > > DiagArrayPtr
Definition: CRMatrix.h:101
GhostArrayMap _sendIndices
Definition: CRMatrix.h:1742
Array< bool > _isBoundary
Definition: CRMatrix.h:1724
const ScatterMap & getScatterMapLevel1() const
Definition: StorageSite.h:73
bool hasCoeff(const int i, const int j)
Definition: CRMatrix.h:846
void compute_ILU0() const
Definition: CRMatrix.h:1546
double max(double x, double y)
Definition: Octree.cpp:18
OffDiag & getCoeff10(const int np)
Definition: CRMatrix.h:131
Array< X > XArray
Definition: CRMatrix.h:99
void addCoeff10(const int np, const OffDiag &c10)
Definition: CRMatrix.h:153
void eliminateRow(const int j, Array< X > &b)
Definition: CRMatrix.h:899
const Array< OffDiag > & getOffDiag() const
Definition: CRMatrix.h:860
Array< Diag > & getDiag()
Definition: CRMatrix.h:856
void addCoeffsSymmetric(const int np, const OffDiag &c)
Definition: CRMatrix.h:136
#define logCtor()
Definition: RLogInterface.h:26
virtual int createCoarsening(IContainer &gCoarseIndex, const int groupSize, const double weightRatioThreshold)
Definition: CRMatrix.h:468
CRMatrix(const CRConnectivity &conn)
Definition: CRMatrix.h:165
void addCoeffs(const int np, const OffDiag &c01, const OffDiag &c10)
Definition: CRMatrix.h:142
GhostArrayMap _recvCounts
Definition: CRMatrix.h:1741
Array< Diag > DiagArray
Definition: CRMatrix.h:95
Array< OffDiag > _offDiag
Definition: CRMatrix.h:1722
virtual const CRConnectivity & getConnectivity() const
Definition: CRMatrix.h:834
Array< OffDiag > OffDiagArray
Definition: CRMatrix.h:98
void syncIndices()
Definition: CRMatrix.h:1267
T_Diag Diag
Definition: CRMatrix.h:93
GhostArrayMap _sendValuesCRMtrx
Definition: CRMatrix.h:1744
int getCoeffPosition(const int i, const int j) const
virtual void transpose()
Definition: CRMatrix.h:241
GhostArrayMap _recvValuesB
Definition: CRMatrix.h:1747
Array< OffDiag > & getOffDiag()
Definition: CRMatrix.h:857
const Array< int > & getLocalToGlobalMap() const
virtual void printRow(const int i) const
Definition: CRMatrix.h:1028
void * getDiagData() const
Definition: CRMatrix.h:862
Array< Diag > _diag
Definition: CRMatrix.h:1721
virtual int getDataSize() const
Definition: Array.h:276
void eliminateRowGhost(Array< X > &b)
Definition: CRMatrix.h:952
const Array< Diag > & getDiag() const
Definition: CRMatrix.h:859
virtual ~CRMatrix()
Definition: CRMatrix.h:878
const Array< Vector< int, 2 > > & _pairToCol
Definition: CRMatrix.h:159
void syncValuesCRMtrx()
Definition: CRMatrix.h:1386
void syncValuesB()
Definition: CRMatrix.h:1478
virtual void * getData() const
Definition: Array.h:275
int getTag() const
Definition: StorageSite.h:84
shared_ptr< Matrix > createCoarseMatrix(const IContainer &gCoarseIndex, const CRConnectivity &coarseToFine, const CRConnectivity &coarseConnectivity)
Definition: CRMatrix.h:700
int getDiagDataSize() const
Definition: CRMatrix.h:864
int getGatherProcID() const
Definition: StorageSite.h:83
virtual void forwardGS(IContainer &xB, IContainer &bB, IContainer &) const
Definition: CRMatrix.h:303
map< EntryIndex, shared_ptr< ArrayBase > > GhostArrayMap
Definition: CRMatrix.h:107
virtual void solveBoundary(IContainer &xB, IContainer &bB, IContainer &) const
Definition: CRMatrix.h:433
const Array< int > & _row
Definition: CRMatrix.h:1719
GhostArrayMap _recvValuesCRMtrx
Definition: CRMatrix.h:1745
int getOffDiagDataSize() const
Definition: CRMatrix.h:865
void createScatterGatherValuesCRMtrxBuffer()
Definition: CRMatrix.h:1331
Definition: Matrix.h:16
const CRConnectivity & _conn
Definition: CRMatrix.h:1718
map< int, int > _ghostCellBoundayMap
Definition: CRMatrix.h:1748
int get_request_size()
Definition: CRMatrix.h:1525
GhostArrayMap _recvIndices
Definition: CRMatrix.h:1743
#define logDtor()
Definition: RLogInterface.h:33
virtual void iluSolve(IContainer &xB, const IContainer &bB, const IContainer &) const
Definition: CRMatrix.h:376
const StorageSite & getColSite() const
int getCountLevel1() const
Definition: StorageSite.h:72
OffDiag & getCoeff01(const int np)
Definition: CRMatrix.h:126
virtual shared_ptr< IContainer > newClone() const
Definition: Array.h:470
map< const StorageSite *, shared_ptr< Array< int > > > ScatterMap
Definition: StorageSite.h:23
IntArrayPtr _iluDiagIndexPtr
Definition: CRMatrix.h:1733
Tangent fabs(const Tangent &a)
Definition: Tangent.h:312
const CRTYPE & getConnType() const
void setBoundary(const int nr)
Definition: CRMatrix.h:1056
virtual void setFlatMatrix(Matrix &fmg) const
Definition: CRMatrix.h:1087
virtual void multiply(IContainer &yB, const IContainer &xB) const
Definition: CRMatrix.h:200
void setFlatCoeffs(Array< double > &flatCoeffs, const CRConnectivity &flatConnectivity, const Array< T_Diag > &diag, const Array< T_OffDiag > &offDiag, const CRConnectivity &connectivity)
Definition: CRMatrix.h:37
virtual void reverseGS(IContainer &xB, IContainer &bB, IContainer &) const
Definition: CRMatrix.h:328
int add(const int index, const int val)
shared_ptr< CRConnectivity > createCoarseConnectivity(const IContainer &gCoarseIndex, const CRConnectivity &coarseToFine, const StorageSite &coarseRowSite, const StorageSite &coarseColSite)
Definition: CRMatrix.h:598
virtual void * getData() const =0
virtual void spikeSolve(IContainer &xB, const IContainer &bB, const IContainer &, const SpikeStorage &spike_storage) const
Definition: CRMatrix.h:389
int getCount() const
Definition: StorageSite.h:39
PairWiseAssemblerMap _pairWiseAssemblers
Definition: CRMatrix.h:1723
map< const CRConnectivity *, PairWiseAssembler * > PairWiseAssemblerMap
Definition: CRMatrix.h:162
shared_ptr< Array< double > > ArrayDblePtr
Definition: CRMatrix.h:103
DiagonalTensor< T, N > T_DiagTensor
Definition: CRMatrix.h:1767
void createScatterGatherCountsBuffer()
Definition: CRMatrix.h:1117
shared_ptr< CRConnectivity > _iluConnPtr
Definition: CRMatrix.h:1731
map< const StorageSite *, shared_ptr< Array< int > > > GatherMap
Definition: StorageSite.h:24
void createScatterGatherValuesBBuffer(const XArray &B)
Definition: CRMatrix.h:1434
Array< OffDiag > & _coeffs
Definition: CRMatrix.h:158
virtual void computeResidual(const IContainer &xB, const IContainer &bB, IContainer &rB) const
Definition: CRMatrix.h:407
void setDirichlet(const int nr)
Definition: CRMatrix.h:887
virtual shared_ptr< Matrix > createMergeMatrix(const LinearSystemMerger &mergeLS)
Definition: Matrix.h:57
PairWiseAssembler & getPairWiseAssembler(const CRConnectivity &pairs)
Definition: CRMatrix.h:867
const StorageSite & getRowSite() const
virtual void multiplyAndAdd(IContainer &yB, const IContainer &xB) const
Definition: CRMatrix.h:223
GhostArrayMap _sendValuesB
Definition: CRMatrix.h:1746
void addCoeff01(const int np, const OffDiag &c01)
Definition: CRMatrix.h:148
int getRowDim() const
void addCount(const int index, const int count)
void eliminateDirichlet(const int j, Array< X > &b, const X &delta_j, const bool explicitMode=false)
Definition: CRMatrix.h:1041
SpikeMatrix< Diag, OffDiag, X > T_SpikeMtrx
Definition: CRMatrix.h:104
const PairToColMapping & getPairToColMapping(const CRConnectivity &pairs) const
T_OffDiag OffDiag
Definition: CRMatrix.h:94
int getLength() const
Definition: Array.h:87
DiagArrayPtr _iluCoeffsPtr
Definition: CRMatrix.h:1736
void lowerSolve(XArray &y, const XArray &b) const
Definition: CRMatrix.h:1676