GAMGSolverAgglomerateMatrix.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2023-2024 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "GAMGSolver.H"
30 #include "GAMGInterfaceField.H"
33 
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 
36 void Foam::GAMGSolver::agglomerateMatrix
37 (
38  const label fineLevelIndex,
39  const lduMesh& coarseMesh,
40  const lduInterfacePtrsList& coarseMeshInterfaces
41 )
42 {
43  // Get fine matrix
44  const lduMatrix& fineMatrix = matrixLevel(fineLevelIndex);
45 
46  if (UPstream::myProcNo(fineMatrix.mesh().comm()) != -1)
47  {
48  const label nCoarseFaces = agglomeration_.nFaces(fineLevelIndex);
49  const label nCoarseCells = agglomeration_.nCells(fineLevelIndex);
50 
51  // Set the coarse level matrix
52  matrixLevels_.set
53  (
54  fineLevelIndex,
55  new lduMatrix(coarseMesh)
56  );
57  lduMatrix& coarseMatrix = matrixLevels_[fineLevelIndex];
58 
59 
60  // Coarse matrix diagonal initialised by restricting the finer mesh
61  // diagonal. Note that we size with the cached coarse nCells and not
62  // the actual coarseMesh size since this might be dummy when processor
63  // agglomerating.
64  scalarField& coarseDiag = coarseMatrix.diag(nCoarseCells);
65 
66  agglomeration_.restrictField
67  (
68  coarseDiag,
69  fineMatrix.diag(),
70  fineLevelIndex,
71  false // no processor agglomeration
72  );
73 
74  // Get reference to fine-level interfaces
75  const lduInterfaceFieldPtrsList& fineInterfaces =
76  interfaceLevel(fineLevelIndex);
77 
78  // Create coarse-level interfaces
79  primitiveInterfaceLevels_.set
80  (
81  fineLevelIndex,
82  new PtrList<lduInterfaceField>(fineInterfaces.size())
83  );
84 
85  PtrList<lduInterfaceField>& coarsePrimInterfaces =
86  primitiveInterfaceLevels_[fineLevelIndex];
87 
88  interfaceLevels_.set
89  (
90  fineLevelIndex,
91  new lduInterfaceFieldPtrsList(fineInterfaces.size())
92  );
93 
94  lduInterfaceFieldPtrsList& coarseInterfaces =
95  interfaceLevels_[fineLevelIndex];
96 
97  // Set coarse-level boundary coefficients
98  interfaceLevelsBouCoeffs_.set
99  (
100  fineLevelIndex,
101  new FieldField<Field, scalar>(fineInterfaces.size())
102  );
103  FieldField<Field, scalar>& coarseInterfaceBouCoeffs =
104  interfaceLevelsBouCoeffs_[fineLevelIndex];
105 
106  // Set coarse-level internal coefficients
107  interfaceLevelsIntCoeffs_.set
108  (
109  fineLevelIndex,
110  new FieldField<Field, scalar>(fineInterfaces.size())
111  );
112  FieldField<Field, scalar>& coarseInterfaceIntCoeffs =
113  interfaceLevelsIntCoeffs_[fineLevelIndex];
114 
115  // Add the coarse level
116  agglomerateInterfaceCoefficients
117  (
118  fineLevelIndex,
119  coarseMeshInterfaces,
120  coarsePrimInterfaces,
121  coarseInterfaces,
122  coarseInterfaceBouCoeffs,
123  coarseInterfaceIntCoeffs
124  );
125 
126 
127  // Get face restriction map for current level
128  const labelList& faceRestrictAddr =
129  agglomeration_.faceRestrictAddressing(fineLevelIndex);
130  const boolList& faceFlipMap =
131  agglomeration_.faceFlipMap(fineLevelIndex);
132 
133  // Check if matrix is asymmetric and if so agglomerate both upper
134  // and lower coefficients ...
135  if (fineMatrix.hasLower())
136  {
137  // Get off-diagonal matrix coefficients
138  const scalarField& fineUpper = fineMatrix.upper();
139  const scalarField& fineLower = fineMatrix.lower();
140 
141  // Coarse matrix upper coefficients. Note passed in size
142  scalarField& coarseUpper = coarseMatrix.upper(nCoarseFaces);
143  scalarField& coarseLower = coarseMatrix.lower(nCoarseFaces);
144 
145  forAll(faceRestrictAddr, fineFacei)
146  {
147  label cFace = faceRestrictAddr[fineFacei];
148 
149  if (cFace >= 0)
150  {
151  // Check the orientation of the fine-face relative to the
152  // coarse face it is being agglomerated into
153  if (!faceFlipMap[fineFacei])
154  {
155  coarseUpper[cFace] += fineUpper[fineFacei];
156  coarseLower[cFace] += fineLower[fineFacei];
157  }
158  else
159  {
160  coarseUpper[cFace] += fineLower[fineFacei];
161  coarseLower[cFace] += fineUpper[fineFacei];
162  }
163  }
164  else
165  {
166  // Add the fine face coefficients into the diagonal.
167  coarseDiag[-1 - cFace] +=
168  fineUpper[fineFacei] + fineLower[fineFacei];
169  }
170  }
171  }
172  else // ... Otherwise it is symmetric so agglomerate just the upper
173  {
174  // Get off-diagonal matrix coefficients
175  const scalarField& fineUpper = fineMatrix.upper();
176 
177  // Coarse matrix upper coefficients
178  scalarField& coarseUpper = coarseMatrix.upper(nCoarseFaces);
179 
180  forAll(faceRestrictAddr, fineFacei)
181  {
182  label cFace = faceRestrictAddr[fineFacei];
183 
184  if (cFace >= 0)
185  {
186  coarseUpper[cFace] += fineUpper[fineFacei];
187  }
188  else
189  {
190  // Add the fine face coefficient into the diagonal.
191  coarseDiag[-1 - cFace] += 2*fineUpper[fineFacei];
192  }
193  }
194  }
195  }
196 }
197 
198 
199 void Foam::GAMGSolver::agglomerateInterfaceCoefficients
200 (
201  const label fineLevelIndex,
202  const lduInterfacePtrsList& coarseMeshInterfaces,
203  PtrList<lduInterfaceField>& coarsePrimInterfaces,
204  lduInterfaceFieldPtrsList& coarseInterfaces,
205  FieldField<Field, scalar>& coarseInterfaceBouCoeffs,
206  FieldField<Field, scalar>& coarseInterfaceIntCoeffs
207 ) const
208 {
209  // Get reference to fine-level interfaces
210  const lduInterfaceFieldPtrsList& fineInterfaces =
211  interfaceLevel(fineLevelIndex);
212 
213  // Get reference to fine-level boundary coefficients
214  const FieldField<Field, scalar>& fineInterfaceBouCoeffs =
215  interfaceBouCoeffsLevel(fineLevelIndex);
216 
217  // Get reference to fine-level internal coefficients
218  const FieldField<Field, scalar>& fineInterfaceIntCoeffs =
219  interfaceIntCoeffsLevel(fineLevelIndex);
220 
221  const labelListList& patchFineToCoarse =
222  agglomeration_.patchFaceRestrictAddressing(fineLevelIndex);
223 
224  const labelList& nPatchFaces =
225  agglomeration_.nPatchFaces(fineLevelIndex);
226 
227 
228  // Add the coarse level
229  forAll(fineInterfaces, inti)
230  {
231  if (fineInterfaces.set(inti))
232  {
233  const GAMGInterface& coarseInterface =
234  refCast<const GAMGInterface>
235  (
236  coarseMeshInterfaces[inti]
237  );
238 
239  coarsePrimInterfaces.set
240  (
241  inti,
243  (
244  coarseInterface,
245  fineInterfaces[inti]
246  ).ptr()
247  );
248  coarseInterfaces.set
249  (
250  inti,
251  &coarsePrimInterfaces[inti]
252  );
253 
254  const labelList& faceRestrictAddressing = patchFineToCoarse[inti];
255 
256  coarseInterfaceBouCoeffs.set
257  (
258  inti,
259  new scalarField(nPatchFaces[inti], Zero)
260  );
261  agglomeration_.restrictField
262  (
263  coarseInterfaceBouCoeffs[inti],
264  fineInterfaceBouCoeffs[inti],
265  faceRestrictAddressing
266  );
267 
268  coarseInterfaceIntCoeffs.set
269  (
270  inti,
271  new scalarField(nPatchFaces[inti], Zero)
272  );
273  agglomeration_.restrictField
274  (
275  coarseInterfaceIntCoeffs[inti],
276  fineInterfaceIntCoeffs[inti],
277  faceRestrictAddressing
278  );
279  }
280  }
281 }
282 
283 
284 void Foam::GAMGSolver::gatherMatrices
285 (
286  const label destLevel,
287  const label comm,
288 
289  // Local matrix
290  const lduMatrix& mat,
291  const FieldField<Field, scalar>& interfaceBouCoeffs,
292  const FieldField<Field, scalar>& interfaceIntCoeffs,
293  const lduInterfaceFieldPtrsList& interfaces,
294 
295  // Remote matrices
296  PtrList<lduMatrix>& otherMats,
297  PtrList<FieldField<Field, scalar>>& otherBouCoeffs,
298  PtrList<FieldField<Field, scalar>>& otherIntCoeffs,
299  PtrList<PtrList<lduInterfaceField>>& otherInterfaces
300 ) const
301 {
302  if (debug & 2)
303  {
304  const auto& procIDs = UPstream::procID(comm);
305 
306  Pout<< "GAMGSolver::gatherMatrices :"
307  << " collecting matrices from procs:" << procIDs
308  << " using comm:" << comm << endl;
309  }
310 
311  const auto& boundaryMap = agglomeration_.boundaryMap(destLevel);
312 
313  PstreamBuffers pBufs(comm);
314 
315  // Send to master
316  if (!UPstream::master(comm))
317  {
318  // Mark valid interfaces
319  // -1 : not set
320  // >= 0 : coupled interface (might also be unmerged processor boundary)
321  //
322  // Note: most processor interfaces will disappear. Originally
323  // we did not know which ones were kept but this is now stored
324  // on the boundaryMap (even on the slave processors). So we can
325  // already filter here and avoid sending across typeNames etc.
326 
327  const label proci = UPstream::myProcNo(comm);
328 
329  // All interfaceBouCoeffs need to be sent across
330  bitSet validCoeffs(interfaces.size());
331  forAll(interfaceBouCoeffs, intI)
332  {
333  if (interfaceBouCoeffs.set(intI))
334  {
335  validCoeffs.set(intI);
336  }
337  }
338 
339  // Only preserved interfaces need to be sent across
340  bitSet validInterface(interfaces.size());
341  forAll(interfaces, intI)
342  {
343  const label allIntI = boundaryMap[proci][intI];
344  if (interfaces.set(intI) && allIntI != -1)
345  {
346  validInterface.set(intI);
347  }
348  }
349 
350  UOPstream toMaster(UPstream::masterNo(), pBufs);
351 
352  toMaster
353  << mat
354  << token::SPACE << validCoeffs
355  << token::SPACE << validInterface;
356 
357  for (const label intI : validCoeffs)
358  {
359  toMaster
360  << interfaceBouCoeffs[intI]
361  << interfaceIntCoeffs[intI];
362  }
363  for (const label intI : validInterface)
364  {
365  const auto& interface = refCast<const GAMGInterfaceField>
366  (
367  interfaces[intI]
368  );
369 
370  toMaster << interface.type();
371  interface.write(toMaster);
372  }
373  }
374 
375  // Wait for finish
376  pBufs.finishedGathers();
377 
378  // Consume
379  if (UPstream::master(comm))
380  {
381  const label nProcs = UPstream::nProcs(comm);
382 
383  const lduMesh& destMesh = agglomeration_.meshLevel(destLevel);
384  lduInterfacePtrsList destInterfaces = destMesh.interfaces();
385 
386  // Master.
387  otherMats.resize(nProcs-1);
388  otherBouCoeffs.resize(nProcs-1);
389  otherIntCoeffs.resize(nProcs-1);
390  otherInterfaces.resize(nProcs-1);
391 
392  for (const int proci : UPstream::subProcs(comm))
393  {
394  const label otherI = proci-1;
395 
396  UIPstream fromProc(proci, pBufs);
397 
398  otherMats.set(otherI, new lduMatrix(destMesh, fromProc));
399 
400  // Receive bit-sets of valid interfaceCoeffs/interfaces
401  const bitSet validCoeffs(fromProc);
402  const bitSet validInterface(fromProc);
403 
404  otherBouCoeffs.emplace_set(otherI, validCoeffs.size());
405  otherIntCoeffs.emplace_set(otherI, validCoeffs.size());
406  otherInterfaces.emplace_set(otherI, validInterface.size());
407 
408  // Receive individual interface contributions
409  for (const label intI : validCoeffs)
410  {
411  otherBouCoeffs[otherI].emplace_set(intI, fromProc);
412  otherIntCoeffs[otherI].emplace_set(intI, fromProc);
413  }
414 
415  // Receive individual interface contributions
416  for (const label intI : validInterface)
417  {
418  const word coupleType(fromProc);
419 
420  const label allIntI = boundaryMap[proci][intI];
421 
422  otherInterfaces[otherI].set
423  (
424  intI,
426  (
427  coupleType,
428  refCast<const GAMGInterface>
429  (
430  destInterfaces[allIntI]
431  ),
432  fromProc
433  ).release()
434  );
435  }
436  }
437  }
438 }
439 
440 
441 void Foam::GAMGSolver::procAgglomerateMatrix
442 (
443  // Agglomeration information
444  const labelList& procAgglomMap,
445  const List<label>& agglomProcIDs,
446 
447  const label levelI,
448 
449  // Resulting matrix
450  autoPtr<lduMatrix>& allMatrixPtr,
451  FieldField<Field, scalar>& allInterfaceBouCoeffs,
452  FieldField<Field, scalar>& allInterfaceIntCoeffs,
453  PtrList<lduInterfaceField>& allPrimitiveInterfaces,
454  lduInterfaceFieldPtrsList& allInterfaces
455 ) const
456 {
457  const lduMatrix& coarsestMatrix = matrixLevels_[levelI];
458  const lduInterfaceFieldPtrsList& coarsestInterfaces =
459  interfaceLevels_[levelI];
460  const FieldField<Field, scalar>& coarsestBouCoeffs =
461  interfaceLevelsBouCoeffs_[levelI];
462  const FieldField<Field, scalar>& coarsestIntCoeffs =
463  interfaceLevelsIntCoeffs_[levelI];
464 
465  // Communicator containing all processors to combine (=agglomProcIDs).
466  // Result will be on master of communicator.
467  const label agglomComm = agglomeration_.agglomCommunicator(levelI+1);
468 
469 
470  // Gather all matrix coefficients onto agglomProcIDs[0]
471  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
472 
473  PtrList<lduMatrix> otherMats;
474  PtrList<FieldField<Field, scalar>> otherBouCoeffs;
475  PtrList<FieldField<Field, scalar>> otherIntCoeffs;
476  PtrList<PtrList<lduInterfaceField>> otherInterfaces;
477  gatherMatrices
478  (
479  levelI+1, // allMesh level (only on master)
480  agglomComm,
481 
482  coarsestMatrix, // master before gathering
483  coarsestBouCoeffs, // master before gathering
484  coarsestIntCoeffs, // master before gathering
485  coarsestInterfaces, // master before gathering
486 
487  otherMats, // slave info
488  otherBouCoeffs, // slave info
489  otherIntCoeffs, // slave info
490  otherInterfaces // slave info
491  );
492 
493 
494  if (UPstream::master(agglomComm))
495  {
496  // Agglomerate all matrix
497  // ~~~~~~~~~~~~~~~~~~~~~~
498 
499  const lduMesh& allMesh = agglomeration_.meshLevel(levelI+1);
500  const labelList& cellOffsets = agglomeration_.cellOffsets(levelI+1);
501  const labelListList& faceMap = agglomeration_.faceMap(levelI+1);
502  const labelListList& boundaryMap = agglomeration_.boundaryMap(levelI+1);
503  const labelListListList& boundaryFaceMap =
504  agglomeration_.boundaryFaceMap(levelI+1);
505 
506  allMatrixPtr.reset(new lduMatrix(allMesh));
507  lduMatrix& allMatrix = allMatrixPtr();
508 
509  if (coarsestMatrix.hasDiag())
510  {
511  scalarField& allDiag = allMatrix.diag();
512 
513  SubList<scalar>
514  (
515  allDiag,
516  coarsestMatrix.diag().size()
517  ) = coarsestMatrix.diag();
518 
519  forAll(otherMats, i)
520  {
521  SubList<scalar>
522  (
523  allDiag,
524  otherMats[i].diag().size(),
525  cellOffsets[i+1]
526  ) = otherMats[i].diag();
527  }
528  }
529  if (coarsestMatrix.hasLower())
530  {
531  scalarField& allLower = allMatrix.lower();
532  UIndirectList<scalar>
533  (
534  allLower,
535  faceMap[0]
536  ) = coarsestMatrix.lower();
537  forAll(otherMats, i)
538  {
539  UIndirectList<scalar>
540  (
541  allLower,
542  faceMap[i+1]
543  ) = otherMats[i].lower();
544  }
545  }
546  if (coarsestMatrix.hasUpper())
547  {
548  scalarField& allUpper = allMatrix.upper();
549  UIndirectList<scalar>
550  (
551  allUpper,
552  faceMap[0]
553  ) = coarsestMatrix.upper();
554  forAll(otherMats, i)
555  {
556  UIndirectList<scalar>
557  (
558  allUpper,
559  faceMap[i+1]
560  ) = otherMats[i].upper();
561  }
562  }
563 
564 
565  // Agglomerate interface fields and coefficients
566  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
567 
568  lduInterfacePtrsList allMeshInterfaces = allMesh.interfaces();
569 
570  allInterfaceBouCoeffs.setSize(allMeshInterfaces.size());
571  allInterfaceIntCoeffs.setSize(allMeshInterfaces.size());
572  allPrimitiveInterfaces.setSize(allMeshInterfaces.size());
573  allInterfaces.setSize(allMeshInterfaces.size());
574 
575  forAll(allMeshInterfaces, intI)
576  {
577  const lduInterface& patch = allMeshInterfaces[intI];
578  label size = patch.faceCells().size();
579 
580  allInterfaceBouCoeffs.set(intI, new scalarField(size));
581  allInterfaceIntCoeffs.set(intI, new scalarField(size));
582  }
583 
584  UPtrList<lduInterfaceField> otherFlds(0);
585 
586  forAll(boundaryMap, proci)
587  {
588  const FieldField<Field, scalar>& procBouCoeffs
589  (
590  (proci == 0)
591  ? coarsestBouCoeffs
592  : otherBouCoeffs[proci-1]
593  );
594  const FieldField<Field, scalar>& procIntCoeffs
595  (
596  (proci == 0)
597  ? coarsestIntCoeffs
598  : otherIntCoeffs[proci-1]
599  );
600 
601 
602  const labelList& bMap = boundaryMap[proci];
603  forAll(bMap, procIntI)
604  {
605  label allIntI = bMap[procIntI];
606 
607  if (allIntI != -1)
608  {
609  // So this boundary has been preserved. Copy
610  // data across.
611 
612  if (!allInterfaces.set(allIntI))
613  {
614  const GAMGInterface& intf = refCast<const GAMGInterface>
615  (
616  allMeshInterfaces[allIntI]
617  );
618 
619  if (proci == 0)
620  {
621  // Clone my local interfaceField. Since it is from
622  // this processor it will already exist, even if it
623  // is a processor one.
624 
625  const auto& ffld =
626  refCast<const GAMGInterfaceField>
627  (
628  coarsestInterfaces[procIntI]
629  );
630 
631  allPrimitiveInterfaces.set
632  (
633  allIntI,
634  ffld.clone
635  (
636  intf,
637  otherFlds
638  ).release()
639  );
640  }
641  else
642  {
643  // Recreate a remote interfaceField
644  if (otherInterfaces[proci-1].set(procIntI))
645  {
646  const auto& ffld =
647  refCast<const GAMGInterfaceField>
648  (
649  otherInterfaces[proci-1][procIntI]
650  );
651 
652  allPrimitiveInterfaces.set
653  (
654  allIntI,
655  ffld.clone
656  (
657  intf,
658  otherFlds
659  ).release()
660  );
661  }
662  else
663  {
664  // Recreate a default interfaceField with
665  // sensible defaults.
666  // Should not occur since all unmerged
667  // processor interfaces get transferred.
668  allPrimitiveInterfaces.set
669  (
670  allIntI,
672  (
673  intf,
674  false, //doTransform,
675  0 //rank
676  ).ptr()
677  );
678  }
679  }
680  allInterfaces.set
681  (
682  allIntI,
683  allPrimitiveInterfaces.get(allIntI)
684  );
685  }
686 
687 
688  // Map data from processor to complete mesh
689 
690  scalarField& allBou = allInterfaceBouCoeffs[allIntI];
691  scalarField& allInt = allInterfaceIntCoeffs[allIntI];
692 
693  const labelList& map = boundaryFaceMap[proci][procIntI];
694 
695  const scalarField& procBou = procBouCoeffs[procIntI];
696  const scalarField& procInt = procIntCoeffs[procIntI];
697 
698  forAll(map, i)
699  {
700  label allFacei = map[i];
701  if (allFacei < 0)
702  {
704  << "problem." << abort(FatalError);
705  }
706  allBou[allFacei] = procBou[i];
707  allInt[allFacei] = procInt[i];
708  }
709  }
710  else if (procBouCoeffs.set(procIntI))
711  {
712  // Boundary has become internal face
713 
714  const labelList& map = boundaryFaceMap[proci][procIntI];
715  const scalarField& procBou = procBouCoeffs[procIntI];
716  const scalarField& procInt = procIntCoeffs[procIntI];
717 
718  forAll(map, i)
719  {
720  if (map[i] >= 0)
721  {
722  label allFacei = map[i];
723 
724  if (coarsestMatrix.hasUpper())
725  {
726  allMatrix.upper()[allFacei] = -procBou[i];
727  }
728  if (coarsestMatrix.hasLower())
729  {
730  allMatrix.lower()[allFacei] = -procInt[i];
731  }
732  }
733  else
734  {
735  label allFacei = -map[i]-1;
736 
737  if (coarsestMatrix.hasUpper())
738  {
739  allMatrix.upper()[allFacei] = -procInt[i];
740  }
741  if (coarsestMatrix.hasLower())
742  {
743  allMatrix.lower()[allFacei] = -procBou[i];
744  }
745  }
746  }
747  }
748  }
749  }
750 
751 
752  //Pout<< "** Assembled allMatrix:" << allMatrix.info() << endl;
753  //
754  //forAll(allInterfaces, intI)
755  //{
756  // if (allInterfaces.set(intI))
757  // {
758  // Pout<< " patch:" << intI
759  // << " type:" << allInterfaces[intI].type()
760  // << " size:"
761  // << allInterfaces[intI].interface().faceCells().size()
762  // << endl;
763  //
764  // const scalarField& bouCoeffs = allInterfaceBouCoeffs[intI];
765  // const scalarField& intCoeffs = allInterfaceIntCoeffs[intI];
766  // forAll(bouCoeffs, facei)
767  // {
768  // Pout<< " " << facei
769  // << "\tbou:" << bouCoeffs[facei]
770  // << "\tint:" << intCoeffs[facei]
771  // << endl;
772  // }
773  // }
774  //}
775  }
776 }
777 
778 
779 void Foam::GAMGSolver::procAgglomerateMatrix
780 (
781  const labelList& procAgglomMap,
782  const List<label>& agglomProcIDs,
783 
784  const label levelI
785 )
786 {
787  autoPtr<lduMatrix> allMatrixPtr;
788  autoPtr<FieldField<Field, scalar>> allInterfaceBouCoeffs
789  (
790  new FieldField<Field, scalar>(0)
791  );
792  autoPtr<FieldField<Field, scalar>> allInterfaceIntCoeffs
793  (
794  new FieldField<Field, scalar>(0)
795  );
796  autoPtr<PtrList<lduInterfaceField>> allPrimitiveInterfaces
797  (
798  new PtrList<lduInterfaceField>(0)
799  );
800  autoPtr<lduInterfaceFieldPtrsList> allInterfaces
801  (
803  );
804 
805  procAgglomerateMatrix
806  (
807  // Agglomeration information
808  procAgglomMap,
809  agglomProcIDs,
810 
811  levelI,
812 
813  // Resulting matrix
814  allMatrixPtr,
815  allInterfaceBouCoeffs(),
816  allInterfaceIntCoeffs(),
817  allPrimitiveInterfaces(),
818  allInterfaces()
819  );
820 
821  matrixLevels_.set(levelI, allMatrixPtr);
822  interfaceLevelsBouCoeffs_.set(levelI, allInterfaceBouCoeffs);
823  interfaceLevelsIntCoeffs_.set(levelI, allInterfaceIntCoeffs);
824  primitiveInterfaceLevels_.set(levelI, allPrimitiveInterfaces);
825  interfaceLevels_.set(levelI, allInterfaces);
826 }
827 
828 
829 // ************************************************************************* //
UPtrList< const lduInterfaceField > lduInterfaceFieldPtrsList
List of coupled interface fields to be used in coupling.
const labelList & faceRestrictAddressing(const label leveli) const
Return face restrict addressing of given level.
void restrictField(Field< Type > &cf, const Field< Type > &ff, const label fineLevelIndex, const bool procAgglom) const
Restrict (integrate by summation) cell field.
const boolList & faceFlipMap(const label leveli) const
Return face flip map of given level.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:493
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition: typeInfo.H:172
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1187
interfaceProperties interface(alpha1, U, thermo->transportPropertiesDict())
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1086
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1077
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
static constexpr int masterNo() noexcept
Relative rank for the master process - is always 0.
Definition: UPstream.H:1071
Space [isspace].
Definition: token.H:131
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
void resize(const label newLen)
Change the size of the list. Any new entries are nullptr.
Definition: UPtrListI.H:251
List< labelListList > labelListListList
List of labelListList.
Definition: labelList.H:41
errorManip< error > abort(error &err)
Definition: errorManip.H:139
int debug
Static debugging option.
label nFaces(const label leveli) const
Return number of coarse faces (before processor agglomeration)
static autoPtr< GAMGInterfaceField > New(const GAMGInterface &GAMGCp, const lduInterfaceField &fineInterface)
Return a pointer to a new interface created on freestore given.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1171
static List< int > & procID(const label communicator)
The list of ranks within a given communicator.
Definition: UPstream.H:1142
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1094
const std::string patch
OpenFOAM patch number as a std::string.
static rangeType subProcs(const label communicator=worldComm)
Range of process indices for sub-processes.
Definition: UPstream.H:1197
List< label > labelList
A List of labels.
Definition: List.H:62
void setSize(const label n)
Alias for resize()
Definition: UPtrList.H:840
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
label nCells(const label leveli) const
Return number of coarse cells (before processor agglomeration)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127