lduPrimitiveMesh.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) 2013-2017 OpenFOAM Foundation
9  Copyright (C) 2019,2022 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 "lduPrimitiveMesh.H"
30 #include "processorLduInterface.H"
31 #include "edgeHashes.H"
32 #include "labelPair.H"
33 #include "processorGAMGInterface.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
40 }
41 
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
46 (
47  const label size,
48  const labelUList& l,
49  const labelUList& u
50 )
51 {
52  forAll(l, facei)
53  {
54  if (u[facei] < l[facei])
55  {
57  << "Reversed face. Problem at face " << facei
58  << " l:" << l[facei] << " u:" << u[facei]
59  << abort(FatalError);
60  }
61  if (l[facei] < 0 || u[facei] < 0 || u[facei] >= size)
62  {
64  << "Illegal cell label. Problem at face " << facei
65  << " l:" << l[facei] << " u:" << u[facei]
66  << abort(FatalError);
67  }
68  }
69 
70  for (label facei=1; facei < l.size(); ++facei)
71  {
72  if (l[facei-1] > l[facei])
73  {
75  << "Lower not in incremental cell order."
76  << " Problem at face " << facei
77  << " l:" << l[facei] << " u:" << u[facei]
78  << " previous l:" << l[facei-1]
79  << abort(FatalError);
80  }
81  else if (l[facei-1] == l[facei])
82  {
83  // Same cell.
84  if (u[facei-1] > u[facei])
85  {
87  << "Upper not in incremental cell order."
88  << " Problem at face " << facei
89  << " l:" << l[facei] << " u:" << u[facei]
90  << " previous u:" << u[facei-1]
91  << abort(FatalError);
92  }
93  }
94  }
95 }
96 
97 
99 (
100  const lduMesh& mesh,
101  const globalIndex& globalNumbering
102 )
103 {
104  const lduAddressing& addr = mesh.lduAddr();
105  lduInterfacePtrsList interfaces = mesh.interfaces();
106 
107  const labelList globalIndices
108  (
109  identity
110  (
111  addr.size(),
112  globalNumbering.localStart(UPstream::myProcNo(mesh.comm()))
113  )
114  );
115 
116  // Get the interface cells
117  PtrList<labelList> nbrGlobalCells(interfaces.size());
118  {
119  // Initialise transfer of restrict addressing on the interface
120  forAll(interfaces, inti)
121  {
122  if (interfaces.set(inti))
123  {
124  interfaces[inti].initInternalFieldTransfer
125  (
127  globalIndices
128  );
129  }
130  }
131 
132  // Wait for all
134 
135  forAll(interfaces, inti)
136  {
137  if (interfaces.set(inti))
138  {
139  nbrGlobalCells.set
140  (
141  inti,
142  new labelList
143  (
144  interfaces[inti].internalFieldTransfer
145  (
147  globalIndices
148  )
149  )
150  );
151  }
152  }
153  }
154 
155 
156  // Scan the neighbour list to find out how many times the cell
157  // appears as a neighbour of the face. Done this way to avoid guessing
158  // and resizing list
159  labelList nNbrs(addr.size(), Zero);
160 
161  const labelUList& nbr = addr.upperAddr();
162  const labelUList& own = addr.lowerAddr();
163 
164  {
165  forAll(nbr, facei)
166  {
167  nNbrs[nbr[facei]]++;
168  nNbrs[own[facei]]++;
169  }
170 
171  forAll(interfaces, inti)
172  {
173  if (interfaces.set(inti))
174  {
175  for (const label celli : interfaces[inti].faceCells())
176  {
177  nNbrs[celli]++;
178  }
179  }
180  }
181  }
182 
183 
184  // Create cell-cells addressing
185  labelListList cellCells(addr.size());
186 
187  forAll(cellCells, celli)
188  {
189  cellCells[celli].setSize(nNbrs[celli], -1);
190  }
191 
192  // Reset the list of number of neighbours to zero
193  nNbrs = 0;
194 
195  // Scatter the neighbour faces
196  forAll(nbr, facei)
197  {
198  const label c0 = own[facei];
199  const label c1 = nbr[facei];
200 
201  cellCells[c0][nNbrs[c0]++] = globalIndices[c1];
202  cellCells[c1][nNbrs[c1]++] = globalIndices[c0];
203  }
204  forAll(interfaces, inti)
205  {
206  if (interfaces.set(inti))
207  {
208  const labelUList& faceCells = interfaces[inti].faceCells();
209 
210  forAll(faceCells, facei)
211  {
212  const label c0 = faceCells[facei];
213  cellCells[c0][nNbrs[c0]++] = nbrGlobalCells[inti][facei];
214  }
215  }
216  }
217 
218  return cellCells;
219 }
220 
221 
222 Foam::label Foam::lduPrimitiveMesh::totalSize
223 (
224  const PtrList<lduPrimitiveMesh>& meshes
225 )
226 {
227  label size = 0;
228 
229  for (const lduPrimitiveMesh& msh : meshes)
230  {
231  size += msh.lduAddr().size();
232  }
233  return size;
234 }
235 
236 
238 (
239  const label nCells,
240  const labelUList& lower,
241  const labelUList& upper
242 )
243 {
244  labelList nNbrs(nCells, Zero);
245 
246  // Count number of upper neighbours
247  forAll(lower, facei)
248  {
249  if (upper[facei] < lower[facei])
250  {
252  << "Problem at face:" << facei
253  << " lower:" << lower[facei]
254  << " upper:" << upper[facei]
255  << exit(FatalError);
256  }
257  nNbrs[lower[facei]]++;
258  }
259 
260  // Construct cell-upper cell addressing
261  labelList offsets(nCells+1);
262  offsets[0] = 0;
263  forAll(nNbrs, celli)
264  {
265  offsets[celli+1] = offsets[celli]+nNbrs[celli];
266  }
267 
268  nNbrs = offsets;
269 
270  labelList cellToFaces(offsets.last());
271  forAll(upper, facei)
272  {
273  const label celli = lower[facei];
274  cellToFaces[nNbrs[celli]++] = facei;
275  }
276 
277  // Sort
278 
279  labelList oldToNew(lower.size());
280 
281  DynamicList<label> order;
282  DynamicList<label> nbr;
283 
284  label newFacei = 0;
285 
286  for (label celli = 0; celli < nCells; ++celli)
287  {
288  const label startOfCell = offsets[celli];
289  const label nNbr = offsets[celli+1] - startOfCell;
290 
291  nbr.resize(nNbr);
292  order.resize(nNbr);
293 
294  forAll(nbr, i)
295  {
296  nbr[i] = upper[cellToFaces[offsets[celli]+i]];
297  }
298  sortedOrder(nbr, order);
299 
300  for (const label index : order)
301  {
302  oldToNew[cellToFaces[startOfCell + index]] = newFacei++;
303  }
304  }
305 
306  return oldToNew;
307 }
308 
309 
310 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
311 
312 Foam::lduPrimitiveMesh::lduPrimitiveMesh
313 (
314  const label nCells,
315  labelList& l,
316  labelList& u,
317  const label comm,
318  bool reuse
319 )
320 :
321  lduAddressing(nCells),
322  lowerAddr_(l, reuse),
323  upperAddr_(u, reuse),
324  comm_(comm)
325 {
326  if (debug && lowerAddr_.size())
327  {
328  if (max(lowerAddr_) >= nCells || min(lowerAddr_) < 0)
329  {
330  FatalErrorInFunction << "Illegal lower addressing."
331  << " nCells:" << nCells
332  << " max(lower):" << max(lowerAddr_)
333  << " min(lower):" << min(lowerAddr_)
334  << exit(FatalError);
335  }
336  }
337  if (debug && upperAddr_.size())
338  {
339  if (max(upperAddr_) >= nCells || min(upperAddr_) < 0)
340  {
341  FatalErrorInFunction << "Illegal upper addressing."
342  << " nCells:" << nCells
343  << " max(upper):" << max(upperAddr_)
344  << " min(upper):" << min(upperAddr_)
346  }
347  }
348 }
349 
350 
352 (
353  lduInterfacePtrsList& interfaces,
354  const lduSchedule& ps
355 )
356 {
357  interfaces_ = interfaces;
358  patchSchedule_ = ps;
359 
360  // Create interfaces
361  primitiveInterfaces_.setSize(interfaces_.size());
362  forAll(interfaces_, i)
363  {
364  if (interfaces_.set(i))
365  {
366  primitiveInterfaces_.set(i, &interfaces_[i]);
367  }
368  }
369 }
370 
371 
372 Foam::lduPrimitiveMesh::lduPrimitiveMesh
373 (
374  const label nCells
375 )
376 :
377  lduAddressing(nCells),
378  comm_(0)
379 {}
380 
381 
382 Foam::lduPrimitiveMesh::lduPrimitiveMesh
383 (
384  const label nCells,
385  labelList& l,
386  labelList& u,
387  PtrList<const lduInterface>& primitiveInterfaces,
388  const lduSchedule& ps,
389  const label comm
390 )
391 :
392  lduAddressing(nCells),
393  lowerAddr_(l, true),
394  upperAddr_(u, true),
395  primitiveInterfaces_(),
396  patchSchedule_(ps),
397  comm_(comm)
398 {
399  if (debug && lowerAddr_.size())
400  {
401  if (max(lowerAddr_) >= nCells || min(lowerAddr_) < 0)
402  {
403  FatalErrorInFunction << "Illegal lower addressing."
404  << " nCells:" << nCells
405  << " max(lower):" << max(lowerAddr_)
406  << " min(lower):" << min(lowerAddr_)
407  << exit(FatalError);
408  }
409  }
410  if (debug && upperAddr_.size())
411  {
412  if (max(upperAddr_) >= nCells || min(upperAddr_) < 0)
413  {
414  FatalErrorInFunction << "Illegal upper addressing."
415  << " nCells:" << nCells
416  << " max(upper):" << max(upperAddr_)
417  << " min(upper):" << min(upperAddr_)
418  << exit(FatalError);
419  }
420  }
421 
422 
423  primitiveInterfaces_.transfer(primitiveInterfaces);
424 
425  // Create interfaces
426  interfaces_.setSize(primitiveInterfaces_.size());
427  forAll(primitiveInterfaces_, i)
428  {
429  if (primitiveInterfaces_.set(i))
430  {
431  interfaces_.set(i, &primitiveInterfaces_[i]);
432  }
433  }
434 }
435 
436 
437 Foam::lduPrimitiveMesh::lduPrimitiveMesh
438 (
439  const label comm,
440  const labelList& procAgglomMap,
441 
442  const labelList& procIDs,
443  const lduMesh& myMesh,
444  const PtrList<lduPrimitiveMesh>& otherMeshes,
445 
446  labelList& cellOffsets,
447  labelList& faceOffsets,
449  labelListList& boundaryMap,
450  labelListListList& boundaryFaceMap
451 )
452 :
453  lduAddressing(myMesh.lduAddr().size() + totalSize(otherMeshes)),
454  comm_(comm)
455 {
456  const label currentComm = myMesh.comm();
457 
458  forAll(otherMeshes, i)
459  {
460  if (otherMeshes[i].comm() != currentComm)
461  {
463  << "Communicator " << otherMeshes[i].comm()
464  << " at index " << i
465  << " differs from that of predecessor "
466  << currentComm
467  << endl; //exit(FatalError);
468  }
469  }
470 
471  const label nMeshes = otherMeshes.size()+1;
472 
473  const label myAgglom = procAgglomMap[UPstream::myProcNo(currentComm)];
474 
476  {
477  Pout<< "I am " << UPstream::myProcNo(currentComm)
478  << " agglomerating into " << myAgglom
479  << " as are " << findIndices(procAgglomMap, myAgglom)
480  << endl;
481  }
482 
483 
484  forAll(procIDs, i)
485  {
486  if (procAgglomMap[procIDs[i]] != procAgglomMap[procIDs[0]])
487  {
489  << "Processor " << procIDs[i]
490  << " agglomerates to " << procAgglomMap[procIDs[i]]
491  << " whereas other processors " << procIDs
492  << " agglomerate to "
493  << labelUIndList(procAgglomMap, procIDs)
494  << exit(FatalError);
495  }
496  }
497 
498 
499  // Cells get added in order.
500  cellOffsets.setSize(nMeshes+1);
501  cellOffsets[0] = 0;
502  for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
503  {
504  const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
505 
506  cellOffsets[procMeshI+1] =
507  cellOffsets[procMeshI]
508  + procMesh.lduAddr().size();
509  }
510 
511 
512  // Faces initially get added in order, sorted later
513  labelList internalFaceOffsets(nMeshes+1);
514  internalFaceOffsets[0] = 0;
515  for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
516  {
517  const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
518 
519  internalFaceOffsets[procMeshI+1] =
520  internalFaceOffsets[procMeshI]
521  + procMesh.lduAddr().lowerAddr().size();
522  }
523 
524  // Count how faces get added. Interfaces inbetween get merged.
525 
526  // Merged interfaces: map from two coarse processors back to
527  // - procMeshes
528  // - interface in procMesh
529  // (estimate size from number of patches of mesh0)
530  EdgeMap<labelPairList> mergedMap(2*myMesh.interfaces().size());
531 
532  // Unmerged interfaces: map from two coarse processors back to
533  // - procMeshes
534  // - interface in procMesh
535  EdgeMap<labelPairList> unmergedMap(mergedMap.size());
536 
537  boundaryMap.setSize(nMeshes);
538  boundaryFaceMap.setSize(nMeshes);
539 
540 
541  label nOtherInterfaces = 0;
542  labelList nCoupledFaces(nMeshes, Zero);
543 
544  for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
545  {
547  mesh(myMesh, otherMeshes, procMeshI).interfaces();
548 
549  // Initialise all boundaries as merged
550  boundaryMap[procMeshI].setSize(interfaces.size(), -1);
551  boundaryFaceMap[procMeshI].setSize(interfaces.size());
552 
553  // Get sorted order of processors
554  forAll(interfaces, intI)
555  {
556  if (interfaces.set(intI))
557  {
558  const lduInterface& ldui = interfaces[intI];
559 
560  if (isA<processorLduInterface>(ldui))
561  {
562  const processorLduInterface& pldui =
563  refCast<const processorLduInterface>(ldui);
564 
565  label agglom0 = procAgglomMap[pldui.myProcNo()];
566  label agglom1 = procAgglomMap[pldui.neighbProcNo()];
567 
568  const edge procEdge(agglom0, agglom1);
569 
570  if (agglom0 != myAgglom && agglom1 != myAgglom)
571  {
573  << "At mesh from processor " << procIDs[procMeshI]
574  << " have interface " << intI
575  << " with myProcNo:" << pldui.myProcNo()
576  << " with neighbProcNo:" << pldui.neighbProcNo()
577  << exit(FatalError);
578  }
579  else if (agglom0 == myAgglom && agglom1 == myAgglom)
580  {
581  // Merged interface
582  if (debug)
583  {
584  Pout<< "merged interface: myProcNo:"
585  << pldui.myProcNo()
586  << " nbr:" << pldui.neighbProcNo()
587  << " size:" << ldui.faceCells().size()
588  << endl;
589  }
590 
591  const label nbrProcMeshI =
592  procIDs.find(pldui.neighbProcNo());
593 
594  if (procMeshI < nbrProcMeshI)
595  {
596  // I am 'master' since get lowest numbered cells
597  nCoupledFaces[procMeshI] += ldui.faceCells().size();
598  }
599 
600  mergedMap(procEdge).append
601  (
602  labelPair(procMeshI, intI)
603  );
604  }
605  else
606  {
607  if (debug)
608  {
609  Pout<< "external interface: myProcNo:"
610  << pldui.myProcNo()
611  << " nbr:" << pldui.neighbProcNo()
612  << " size:" << ldui.faceCells().size()
613  << endl;
614  }
615 
616  unmergedMap(procEdge).append
617  (
618  labelPair(procMeshI, intI)
619  );
620  }
621  }
622  else
623  {
624  // Still external (non proc) interface
626  << "At mesh from processor " << procIDs[procMeshI]
627  << " have interface " << intI
628  << " of unhandled type " << interfaces[intI].type()
629  << exit(FatalError);
630 
631  ++nOtherInterfaces;
632  }
633  }
634  }
635  }
636 
637 
638 
639  if (debug)
640  {
641  Pout<< "Remaining interfaces:" << endl;
642  forAllConstIters(unmergedMap, iter)
643  {
644  Pout<< " agglom procEdge:" << iter.key() << endl;
645  const labelPairList& elems = iter.val();
646  forAll(elems, i)
647  {
648  label procMeshI = elems[i][0];
649  label interfacei = elems[i][1];
651  mesh(myMesh, otherMeshes, procMeshI).interfaces();
652 
653  const processorLduInterface& pldui =
654  refCast<const processorLduInterface>
655  (
656  interfaces[interfacei]
657  );
658 
659  Pout<< " proc:" << procIDs[procMeshI]
660  << " interfacei:" << interfacei
661  << " between:" << pldui.myProcNo()
662  << " and:" << pldui.neighbProcNo()
663  << endl;
664  }
665  Pout<< endl;
666  }
667  }
668  if (debug)
669  {
670  Pout<< "Merged interfaces:" << endl;
671  forAllConstIters(mergedMap, iter)
672  {
673  Pout<< " agglom procEdge:" << iter.key() << endl;
674  const labelPairList& elems = iter.val();
675 
676  forAll(elems, i)
677  {
678  label procMeshI = elems[i][0];
679  label interfacei = elems[i][1];
681  mesh(myMesh, otherMeshes, procMeshI).interfaces();
682  const processorLduInterface& pldui =
683  refCast<const processorLduInterface>
684  (
685  interfaces[interfacei]
686  );
687 
688  Pout<< " proc:" << procIDs[procMeshI]
689  << " interfacei:" << interfacei
690  << " between:" << pldui.myProcNo()
691  << " and:" << pldui.neighbProcNo()
692  << endl;
693  }
694  Pout<< endl;
695  }
696  }
697 
698 
699  // Adapt faceOffsets for internal interfaces
700  faceOffsets.setSize(nMeshes+1);
701  faceOffsets[0] = 0;
702  faceMap.setSize(nMeshes);
703  for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
704  {
705  const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
706  label nInternal = procMesh.lduAddr().lowerAddr().size();
707 
708  faceOffsets[procMeshI+1] =
709  faceOffsets[procMeshI]
710  + nInternal
711  + nCoupledFaces[procMeshI];
712 
713  labelList& map = faceMap[procMeshI];
714  map.setSize(nInternal);
715  forAll(map, i)
716  {
717  map[i] = faceOffsets[procMeshI] + i;
718  }
719  }
720 
721 
722  // Combine upper and lower
723  lowerAddr_.setSize(faceOffsets.last(), -1);
724  upperAddr_.setSize(lowerAddr_.size(), -1);
725 
726 
727  // Old internal faces and resolved coupled interfaces
728  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
729 
730  for (label procMeshI = 0; procMeshI < nMeshes; ++procMeshI)
731  {
732  const lduMesh& procMesh = mesh(myMesh, otherMeshes, procMeshI);
733 
734  const labelUList& l = procMesh.lduAddr().lowerAddr();
735  const labelUList& u = procMesh.lduAddr().upperAddr();
736 
737  // Add internal faces
738  label allFacei = faceOffsets[procMeshI];
739 
740  forAll(l, facei)
741  {
742  lowerAddr_[allFacei] = cellOffsets[procMeshI]+l[facei];
743  upperAddr_[allFacei] = cellOffsets[procMeshI]+u[facei];
744  allFacei++;
745  }
746 
747 
748  // Add merged interfaces
749  const lduInterfacePtrsList interfaces = procMesh.interfaces();
750 
751  forAll(interfaces, intI)
752  {
753  if (interfaces.set(intI))
754  {
755  const lduInterface& ldui = interfaces[intI];
756 
757  if (isA<processorLduInterface>(ldui))
758  {
759  const processorLduInterface& pldui =
760  refCast<const processorLduInterface>(ldui);
761 
762  // Look up corresponding interfaces
763  label myP = pldui.myProcNo();
764  label nbrP = pldui.neighbProcNo();
765  label nbrProcMeshI = procIDs.find(nbrP);
766 
767  if (procMeshI < nbrProcMeshI)
768  {
769  // I am 'master' since my cell numbers will be lower
770  // since cells get added in procMeshI order.
771 
772  const label agglom0 = procAgglomMap[myP];
773  const label agglom1 = procAgglomMap[nbrP];
774 
775  const auto fnd =
776  mergedMap.cfind(edge(agglom0, agglom1));
777 
778  if (fnd.found())
779  {
780  const labelPairList& elems = fnd();
781 
782  // Find nbrP in elems
783  label nbrIntI = -1;
784  forAll(elems, i)
785  {
786  label proci = elems[i][0];
787  label interfacei = elems[i][1];
789  mesh
790  (
791  myMesh,
792  otherMeshes,
793  proci
794  ).interfaces();
795  const processorLduInterface& pldui =
796  refCast<const processorLduInterface>
797  (
798  interfaces[interfacei]
799  );
800 
801  if
802  (
803  elems[i][0] == nbrProcMeshI
804  && pldui.neighbProcNo() == procIDs[procMeshI]
805  )
806  {
807  nbrIntI = elems[i][1];
808  break;
809  }
810  }
811 
812 
813  if (nbrIntI == -1)
814  {
816  << "elems:" << elems << abort(FatalError);
817  }
818 
819 
820  const lduInterfacePtrsList nbrInterfaces = mesh
821  (
822  myMesh,
823  otherMeshes,
824  nbrProcMeshI
825  ).interfaces();
826 
827 
828  const labelUList& faceCells =
829  ldui.faceCells();
830  const labelUList& nbrFaceCells =
831  nbrInterfaces[nbrIntI].faceCells();
832 
833  if (faceCells.size() != nbrFaceCells.size())
834  {
836  << "faceCells:" << faceCells
837  << " nbrFaceCells:" << nbrFaceCells
838  << abort(FatalError);
839  }
840 
841 
842  labelList& bfMap =
843  boundaryFaceMap[procMeshI][intI];
844  labelList& nbrBfMap =
845  boundaryFaceMap[nbrProcMeshI][nbrIntI];
846 
847  bfMap.setSize(faceCells.size());
848  nbrBfMap.setSize(faceCells.size());
849 
850  forAll(faceCells, pfI)
851  {
852  lowerAddr_[allFacei] =
853  cellOffsets[procMeshI]+faceCells[pfI];
854  bfMap[pfI] = allFacei;
855  upperAddr_[allFacei] =
856  cellOffsets[nbrProcMeshI]+nbrFaceCells[pfI];
857  nbrBfMap[pfI] = (-allFacei-1);
858  allFacei++;
859  }
860  }
861  }
862  }
863  }
864  }
865  }
866 
867 
868  // Sort upper-tri order
869  {
870  labelList oldToNew
871  (
873  (
874  cellOffsets.last(), //nCells
875  lowerAddr_,
876  upperAddr_
877  )
878  );
879 
880  forAll(faceMap, procMeshI)
881  {
882  labelList& map = faceMap[procMeshI];
883  forAll(map, i)
884  {
885  if (map[i] >= 0)
886  {
887  map[i] = oldToNew[map[i]];
888  }
889  else
890  {
891  label allFacei = -map[i]-1;
892  map[i] = -oldToNew[allFacei]-1;
893  }
894  }
895  }
896 
897 
898  inplaceReorder(oldToNew, lowerAddr_);
899  inplaceReorder(oldToNew, upperAddr_);
900 
901  forAll(boundaryFaceMap, proci)
902  {
903  const labelList& bMap = boundaryMap[proci];
904  forAll(bMap, intI)
905  {
906  if (bMap[intI] == -1)
907  {
908  // Merged interface
909  labelList& bfMap = boundaryFaceMap[proci][intI];
910 
911  forAll(bfMap, i)
912  {
913  if (bfMap[i] >= 0)
914  {
915  bfMap[i] = oldToNew[bfMap[i]];
916  }
917  else
918  {
919  label allFacei = -bfMap[i]-1;
920  bfMap[i] = (-oldToNew[allFacei]-1);
921  }
922  }
923  }
924  }
925  }
926  }
927 
928 
929  // Kept interfaces
930  // ~~~~~~~~~~~~~~~
931 
932  interfaces_.setSize(unmergedMap.size() + nOtherInterfaces);
933  primitiveInterfaces_.setSize(interfaces_.size());
934 
935  label allInterfacei = 0;
936 
937  forAllConstIters(unmergedMap, iter)
938  {
939  const labelPairList& elems = iter.val();
940 
941  // Sort processors in increasing order so both sides walk through in
942  // same order.
943  labelPairList procPairs(elems.size());
944  forAll(elems, i)
945  {
946  const labelPair& elem = elems[i];
947  label procMeshI = elem[0];
948  label interfacei = elem[1];
950  (
951  myMesh,
952  otherMeshes,
953  procMeshI
954  ).interfaces();
955 
956  const processorLduInterface& pldui =
957  refCast<const processorLduInterface>
958  (
959  interfaces[interfacei]
960  );
961  label myProcNo = pldui.myProcNo();
962  label nbrProcNo = pldui.neighbProcNo();
963  procPairs[i] = labelPair
964  (
965  min(myProcNo, nbrProcNo),
966  max(myProcNo, nbrProcNo)
967  );
968  }
969 
970  labelList order(sortedOrder(procPairs));
971 
972  // Count
973  label n = 0;
974 
975  forAll(order, i)
976  {
977  const labelPair& elem = elems[order[i]];
978  label procMeshI = elem[0];
979  label interfacei = elem[1];
981  (
982  myMesh,
983  otherMeshes,
984  procMeshI
985  ).interfaces();
986 
987  n += interfaces[interfacei].faceCells().size();
988  }
989 
990  // Size
991  labelField allFaceCells(n);
992  labelField allFaceRestrictAddressing(n);
993  n = 0;
994 
995  // Fill
996  forAll(order, i)
997  {
998  const labelPair& elem = elems[order[i]];
999  label procMeshI = elem[0];
1000  label interfacei = elem[1];
1002  (
1003  myMesh,
1004  otherMeshes,
1005  procMeshI
1006  ).interfaces();
1007 
1008  boundaryMap[procMeshI][interfacei] = allInterfacei;
1009  labelList& bfMap = boundaryFaceMap[procMeshI][interfacei];
1010 
1011  const labelUList& l = interfaces[interfacei].faceCells();
1012  bfMap.setSize(l.size());
1013 
1014  forAll(l, facei)
1015  {
1016  allFaceCells[n] = cellOffsets[procMeshI]+l[facei];
1017  allFaceRestrictAddressing[n] = n;
1018  bfMap[facei] = n;
1019  n++;
1020  }
1021  }
1022 
1023 
1024  // Find out local and remote processor in new communicator
1025 
1026  label neighbProcNo = -1;
1027 
1028  // See what the two processors map onto
1029 
1030  if (iter.key()[0] == myAgglom)
1031  {
1032  if (iter.key()[1] == myAgglom)
1033  {
1035  << "problem procEdge:" << iter.key()
1036  << exit(FatalError);
1037  }
1038 
1039  neighbProcNo = iter.key()[1];
1040  }
1041  else
1042  {
1043  if (iter.key()[1] != myAgglom)
1044  {
1046  << "problem procEdge:" << iter.key()
1047  << exit(FatalError);
1048  }
1049 
1050  neighbProcNo = iter.key()[0];
1051  }
1052 
1053  primitiveInterfaces_.set
1054  (
1055  allInterfacei,
1056  new processorGAMGInterface
1057  (
1058  allInterfacei,
1059  interfaces_,
1060  allFaceCells,
1061  allFaceRestrictAddressing,
1062  comm_,
1063  myAgglom,
1064  neighbProcNo,
1065  tensorField(), // forwardT
1066  Pstream::msgType() // tag
1067  )
1068  );
1069  interfaces_.set(allInterfacei, &primitiveInterfaces_[allInterfacei]);
1070 
1071  if (debug)
1072  {
1073  Pout<< "Created " << interfaces_[allInterfacei].type()
1074  << " interface at " << allInterfacei
1075  << " comm:" << comm_
1076  << " myProcNo:" << myAgglom
1077  << " neighbProcNo:" << neighbProcNo
1078  << " nFaces:" << allFaceCells.size()
1079  << endl;
1080  }
1081 
1082 
1083  allInterfacei++;
1084  }
1085 
1086 
1087  patchSchedule_ = nonBlockingSchedule<processorGAMGInterface>(interfaces_);
1088 
1089  if (debug)
1090  {
1091  checkUpperTriangular(cellOffsets.last(), lowerAddr_, upperAddr_);
1092  }
1093 }
1094 
1095 
1096 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1097 
1099 (
1100  const lduMesh& myMesh,
1101  const PtrList<lduPrimitiveMesh>& otherMeshes,
1102  const label meshI
1104 {
1105  return (meshI == 0 ? myMesh : otherMeshes[meshI-1]);
1106 }
1107 
1108 
1110 (
1111  const label comm,
1112  const lduMesh& mesh,
1113  const labelList& procIDs,
1114  PtrList<lduPrimitiveMesh>& otherMeshes
1115 )
1116 {
1117  // Force calculation of schedule (since does parallel comms)
1118  (void)mesh.lduAddr().patchSchedule();
1119 
1120  if (Pstream::myProcNo(comm) == procIDs[0])
1121  {
1122  // Master.
1123  otherMeshes.setSize(procIDs.size()-1);
1124 
1125  for (label i = 1; i < procIDs.size(); ++i)
1126  {
1127  //Pout<< "on master :"
1128  // << " receiving from proc " << procIDs[i] << endl;
1129 
1130  IPstream fromProc
1131  (
1133  procIDs[i],
1134  0, // bufSize
1135  Pstream::msgType(),
1136  comm
1137  );
1138 
1139  label nCells = readLabel(fromProc);
1140  labelList lowerAddr(fromProc);
1141  labelList upperAddr(fromProc);
1142  boolList validInterface(fromProc);
1143 
1144 
1145  // Construct mesh without interfaces
1146  otherMeshes.set
1147  (
1148  i-1,
1149  new lduPrimitiveMesh
1150  (
1151  nCells,
1152  lowerAddr,
1153  upperAddr,
1154  comm,
1155  true // reuse
1156  )
1157  );
1158 
1159  // Construct GAMGInterfaces
1160  lduInterfacePtrsList newInterfaces(validInterface.size());
1161  forAll(validInterface, intI)
1162  {
1163  if (validInterface[intI])
1164  {
1165  word coupleType(fromProc);
1166 
1167  newInterfaces.set
1168  (
1169  intI,
1171  (
1172  coupleType,
1173  intI,
1174  otherMeshes[i-1].rawInterfaces(),
1175  fromProc
1176  ).ptr()
1177  );
1178  }
1179  }
1180 
1181  otherMeshes[i-1].addInterfaces
1182  (
1183  newInterfaces,
1184  nonBlockingSchedule<processorGAMGInterface>
1185  (
1186  newInterfaces
1187  )
1188  );
1189  }
1190  }
1191  else if (procIDs.found(Pstream::myProcNo(comm)))
1192  {
1193  // Send to master
1194 
1195  const lduAddressing& addressing = mesh.lduAddr();
1196  lduInterfacePtrsList interfaces(mesh.interfaces());
1197  boolList validInterface(interfaces.size());
1198  forAll(interfaces, intI)
1199  {
1200  validInterface[intI] = interfaces.set(intI);
1201  }
1202 
1203  OPstream toMaster
1204  (
1206  procIDs[0],
1207  0,
1208  Pstream::msgType(),
1209  comm
1210  );
1211 
1212  toMaster
1213  << addressing.size()
1214  << addressing.lowerAddr()
1215  << addressing.upperAddr()
1216  << validInterface;
1217 
1218  forAll(interfaces, intI)
1219  {
1220  if (interfaces.set(intI))
1221  {
1222  const GAMGInterface& interface = refCast<const GAMGInterface>
1223  (
1224  interfaces[intI]
1225  );
1226 
1227  toMaster << interface.type();
1228  interface.write(toMaster);
1229  }
1230  }
1231  }
1232 }
1233 
1234 
1235 // ************************************************************************* //
virtual lduInterfacePtrsList interfaces() const =0
Return a list of pointers for each patch with only those pointing to interfaces being set...
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:51
Field< label > labelField
Specialisation of Field<T> for label.
Definition: labelField.H:48
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
static autoPtr< GAMGInterface > New(const label index, const lduInterfacePtrsList &coarseInterfaces, const lduInterface &fineInterface, const labelField &localRestrictAddressing, const labelField &neighbourRestrictAddressing, const label fineLevelIndex, const label coarseComm)
Return a pointer to a new interface created on freestore given.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void addInterfaces(lduInterfacePtrsList &interfaces, const lduSchedule &ps)
Add interfaces to a mesh constructed without.
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
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:578
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
Type & refCast(U &obj)
A dynamic_cast (for references) that generates FatalError on failed casts, uses the virtual type() me...
Definition: typeInfo.H:151
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
bool found(const T &val, label pos=0) const
True if the value if found in the list.
Definition: UListI.H:258
Abstract base class for meshes which provide LDU addressing for the construction of lduMatrix and LDU...
Definition: lduMesh.H:53
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1187
PtrList< const lduInterface > & primitiveInterfaces()
Return a non-const list of primitive interfaces.
labelList findIndices(const ListType &input, typename ListType::const_reference val, label start=0)
Linear search to find all occurrences of given element.
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:806
interfaceProperties interface(alpha1, U, thermo->transportPropertiesDict())
List< lduScheduleEntry > lduSchedule
A List of lduSchedule entries.
Definition: lduSchedule.H:46
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:688
UList< label > labelUList
A UList of labels.
Definition: UList.H:80
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: UPtrListI.H:134
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
Input inter-processor communications stream.
Definition: IPstream.H:49
virtual label comm() const
Return communicator used for parallel communication.
Definition: fvMesh.H:413
void setSize(const label n)
Alias for resize()
Definition: List.H:289
dynamicFvMesh & mesh
"scheduled" : (MPI_Send, MPI_Recv)
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:31
A class for handling words, derived from Foam::string.
Definition: word.H:63
virtual const lduAddressing & lduAddr() const
Return ldu addressing.
Definition: fvMesh.C:711
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:99
virtual label comm() const
Return communicator used for parallel communication.
UPtrList< const lduInterface > lduInterfacePtrsList
Store lists of lduInterface as a UPtrList.
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
Simplest concrete lduMesh that stores the addressing needed by lduMatrix.
List< labelPair > labelPairList
List of labelPairs.
Definition: labelPair.H:61
static const lduMesh & mesh(const lduMesh &mesh0, const PtrList< lduPrimitiveMesh > &otherMeshes, const label meshI)
Select either mesh0 (meshI is 0) or otherMeshes[meshI-1].
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: PtrList.H:163
int debug
Static debugging option.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:50
defineTypeNameAndDebug(combustionModel, 0)
void setSize(const label newLen)
Same as resize()
Definition: PtrList.H:183
static void waitRequests(const label start=0)
Wait until all requests (from start onwards) have finished.
Definition: UPstream.C:93
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: IndirectList.H:65
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1171
#define WarningInFunction
Report a warning using Foam::Warning.
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch.
Definition: fvMesh.C:728
static void checkUpperTriangular(const label size, const labelUList &l, const labelUList &u)
Check if in upper-triangular ordering.
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
List< labelListList > labelListListList
A List of labelListList.
Definition: labelList.H:52
static labelListList globalCellCells(const lduMesh &mesh, const globalIndex &globalNumbering)
Calculate global cell-cells.
const dimensionedScalar c1
First radiation constant: default SI units: [W/m2].
"nonBlocking" : (MPI_Isend, MPI_Irecv)
label n
static void gather(const label comm, const lduMesh &mesh, const labelList &procIDs, PtrList< lduPrimitiveMesh > &otherMeshes)
Gather meshes from other processors onto procIDs[0].
The class contains the addressing required by the lduMatrix: upper, lower and losort.
List< label > labelList
A List of labels.
Definition: List.H:62
void setSize(const label n)
Alias for resize()
Definition: UPtrList.H:337
virtual lduInterfacePtrsList interfaces() const
Return a list of pointers for each patch with only those pointing to interfaces being set...
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
static labelList upperTriOrder(const label nCells, const labelUList &lower, const labelUList &upper)
Calculate upper-triangular order.
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
label size() const
Return number of equations.
virtual const lduSchedule & patchSchedule() const =0
Return patch field evaluation schedule.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157