faMeshDistributorNew.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) 2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "faMeshDistributor.H"
29 #include "globalIndex.H"
30 #include "BitOps.H"
31 #include "ListOps.H"
32 #include "mapDistributePolyMesh.H"
34 #include "labelPairHashes.H"
35 
36 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
37 
40 (
41  const faMesh& oldMesh,
42  const mapDistributePolyMesh& distMap,
43  const polyMesh& tgtPolyMesh,
44  autoPtr<faMesh>& newMeshPtr
45 )
46 {
47  newMeshPtr.reset(nullptr);
48 
49  const uindirectPrimitivePatch& oldAreaPatch = oldMesh.patch();
50 
51  // Original (patch) sizes before any changes
52  const label nOldPoints = oldAreaPatch.nPoints();
53  const label nOldEdges = oldAreaPatch.nEdges();
54  const label nOldFaces = oldAreaPatch.nFaces();
55 
56 
57  // ------------------------
58  // Step 1: The face mapping
59  // ------------------------
60  // Relatively straightforward.
61  // - a subset of face selections on the polyMesh faceMap
62 
63  mapDistributeBase faFaceMap(distMap.faceMap());
64 
65  {
66  // Retain faces needed for the faMesh - preserve original order
67 
68  // Note can use compactLocalData without problem since
69  // finiteArea is only defined on real boundary faces so there
70  // is no danger of sending an internal or processor face.
71 
72  labelList oldToNewSub;
73  labelList oldToNewConstruct;
74 
75  faFaceMap.compactLocalData
76  (
77  oldMesh.faceLabels(),
78  oldToNewSub,
79  oldToNewConstruct,
80  distMap.nOldFaces(),
82  );
83 
84 
85  // The receiving side:
86  // Mapped faces (>= 0) are the polyMesh face labels that define
87  // the faMesh. Since the compact order is implicitly sorted in
88  // ascending order, it tends to form contiguous ranges on the
89  // polyPatches, which serves our purpose nicely.
90 
91  labelList newFaceLabels
92  (
93  ListOps::findIndices(oldToNewConstruct, labelRange::ge0())
94  );
95 
96  // Set up to read-if-present
97  IOobject io(tgtPolyMesh);
99 
100  newMeshPtr.reset
101  (
102  new faMesh(tgtPolyMesh, std::move(newFaceLabels), io)
103  );
104  }
105 
106  // The face map is now complete.
107 
108  // The new faMesh and the corresponding primitive patch
109  auto& newMesh = newMeshPtr();
110  const uindirectPrimitivePatch& newAreaPatch = newMesh.patch();
111 
112 
113  // ------------------------
114  // Step 2: The edge mapping
115  // ------------------------
116  // Use globally unique addressing to identify both sides of the edges.
117 
118  // A local bookkeeping struct of (face0 face1 edge0 edge1)
119  // selected for a stable and unique sort
120 
121  struct faceEdgeTuple : public FixedList<label, 4>
122  {
123  // Inherit constructors
125 
126  // Default construct as 'invalid'
127  faceEdgeTuple() : FixedList<label, 4>(-1) {}
128 
129  // Is empty if face indices are negative
130  bool empty() const
131  {
132  return (face0() < 0 && face1() < 0);
133  }
134 
135  // Global face numbers are the first sort index
136  label face0() const { return (*this)[0]; }
137  label face1() const { return (*this)[1]; }
138 
139  // Additional sorting based on edges
140  label edge0() const { return (*this)[2]; }
141  label edge1() const { return (*this)[3]; }
142 
143  label getFace(int i) const { return (*this)[(i ? 1 : 0)]; }
144  label getEdge(int i) const { return (*this)[(i ? 3 : 2)]; }
145 
146  labelPair getFaces() const { return labelPair(face0(), face1()); }
147  labelPair getPair0() const { return labelPair(face0(), edge0()); }
148  // labelPair getPair1() const { return labelPair(face1(), edge1()); }
149 
150  // Canonically sorted order
151  void canonical()
152  {
153  if (face1() >= 0 && face0() >= face1())
154  {
155  std::swap((*this)[0], (*this)[1]);
156  std::swap((*this)[2], (*this)[3]);
157  }
158  }
159 
160  // Slot a face-edge pair into a free location in the tuple
161  void add(const labelPair& faceEdge)
162  {
163  if ((*this)[0] < 0) // face0
164  {
165  (*this)[0] = faceEdge.first(); // face
166  (*this)[2] = faceEdge.second(); // edge
167  }
168  else if ((*this)[1] < 0) // face1
169  {
170  (*this)[1] = faceEdge.first(); // face
171  (*this)[3] = faceEdge.second(); // edge
172  }
173  }
174 
175  // Combine operation
176  void combine(const faceEdgeTuple& y)
177  {
178  auto& x = *this;
179 
180  if (y.empty() || x == y)
181  {
182  // Nothing to do
183  }
184  else if (x.empty())
185  {
186  x = y;
187  }
188  else // Both non-empty, but non-identical (should not occur)
189  {
191  << "Unexpected edge matching: "
192  << x << " vs. " << y << endl
193  << exit(FatalError);
194  }
195  }
196 
197  // Combine operation
198  void operator()(faceEdgeTuple& x, const faceEdgeTuple& y) const
199  {
200  x.combine(y);
201  }
202  };
203 
204 
205  // ------------------------
206  // (Edge mapping)
207  // ------------------------
208  // 1.
209  // Create a list of destination edges for each face,
210  // appended by a unique face identifier.
211  // Using global face numbering from the *target* mesh.
212 
213  const globalIndex uniqFaceIndex(newAreaPatch.nFaces());
214 
215  labelListList dstFaceEdgeIds(newAreaPatch.nFaces());
216 
217  forAll(newAreaPatch.faceEdges(), facei)
218  {
219  const labelList& fEdges = newAreaPatch.faceEdges()[facei];
220  labelList& dstEdges = dstFaceEdgeIds[facei];
221 
222  dstEdges.resize(fEdges.size() + 1);
223 
224  // Leading entries are the destination (patch) edge indices
225  labelSubList(dstEdges, fEdges.size()) = fEdges;
226 
227  // Last entry is the face id
228  dstEdges.last() = uniqFaceIndex.toGlobal(facei);
229  }
230 
231  // Send back to the original mesh locations
232  faFaceMap.reverseDistribute(nOldFaces, dstFaceEdgeIds);
233 
234 
235  // 2.
236  // Walk all original faces and their edges to generate a edge lookup
237  // table with the destination face/edge information.
238  // Eg ((globFacei, localEdgei), (globFacei, localEdgei))
239 
240  // NB: currently no provision for face flips, which would potentially
241  // reverse the local edge order.
242 
243  List<faceEdgeTuple> halfEdgeLookup(nOldEdges, faceEdgeTuple());
244 
245  forAll(oldAreaPatch.faceEdges(), facei)
246  {
247  const labelList& fEdges = oldAreaPatch.faceEdges()[facei];
248 
249  // The corresponding destination edges (+ uniqFacei).
250  const labelList& dstFaceEdges = dstFaceEdgeIds[facei];
251 
252  // Last entry has the unique destination face id
253  const label uniqFacei = dstFaceEdges.last();
254 
255  forAll(fEdges, faceEdgei)
256  {
257  const label srcEdgei = fEdges[faceEdgei];
258  const label dstEdgei = dstFaceEdges[faceEdgei];
259 
260  halfEdgeLookup[srcEdgei].add(labelPair(uniqFacei, dstEdgei));
261  }
262  }
263 
264  // 3.
265  // Add patch indices - encoded as '-(patchId + 2)' for
266  // non-processor boundaries (will be needed later).
267 
268  // Also record which procs get patches from here [proc] -> [patches]
269  // Use for building patchMap
270  Map<labelHashSet> patchMapInfo;
271 
272  label nNonProcessor(0);
273  {
274  const faBoundaryMesh& oldBndMesh = oldMesh.boundary();
275 
276  forAll(oldBndMesh, patchi)
277  {
278  const faPatch& fap = oldBndMesh[patchi];
279  if (isA<processorFaPatch>(fap))
280  {
281  break;
282  }
283  ++nNonProcessor;
284 
285  // Encoded as -(patchId + 2)
286  const labelPair encodedPatchId(-(patchi+2), -(patchi+2));
287 
288  for (const label srcEdgei : fap.edgeLabels())
289  {
290  faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
291 
292  facePairings.add(encodedPatchId);
293 
294  label dstFacei = facePairings.face0();
295 
296  label proci = uniqFaceIndex.whichProcID(dstFacei);
297 
298  patchMapInfo(proci).insert(patchi);
299  }
300  }
301 
302  Pstream::broadcast(nNonProcessor);
303  }
304 
305  // Processor-processor connections
306  if (Pstream::parRun())
307  {
308  const label startOfRequests = UPstream::nRequests();
309 
310  const faBoundaryMesh& oldBndMesh = oldMesh.boundary();
311 
312  // Setup sends
313  for (const faPatch& fap : oldBndMesh)
314  {
315  const auto* fapp = isA<processorFaPatch>(fap);
316 
317  if (fapp)
318  {
319  // Send (dstFacei dstEdgei) per patch edge.
320  // Since we are walking a boundary edge, the first location
321  // from the previously established lookup provides
322  // our information.
323 
324  List<labelPair> edgeTuples(fap.edgeLabels().size());
325 
326  label edgeTuplei = 0;
327 
328  for (const label edgei : fap.edgeLabels())
329  {
330  edgeTuples[edgeTuplei] = halfEdgeLookup[edgei].getPair0();
331  ++edgeTuplei;
332  }
333 
334  fapp->send<labelPair>
335  (
337  edgeTuples
338  );
339  }
340  }
341 
342  // Wait for outstanding requests
343  // (commsType == UPstream::commsTypes::nonBlocking)
344  UPstream::waitRequests(startOfRequests);
345 
346  // Receive values
347  for (const faPatch& fap : oldBndMesh)
348  {
349  const auto* fapp = isA<processorFaPatch>(fap);
350 
351  if (fapp)
352  {
353  // Receive (dstFacei dstEdgei) per patch edge.
354  // - slot into the second location of the lookup
355 
356  List<labelPair> edgeTuples(fap.edgeLabels().size());
357 
358  fapp->receive<labelPair>
359  (
361  edgeTuples
362  );
363 
364  label edgeTuplei = 0;
365 
366  for (const label srcEdgei : fap.edgeLabels())
367  {
368  halfEdgeLookup[srcEdgei].add(edgeTuples[edgeTuplei]);
369  ++edgeTuplei;
370  }
371  }
372  }
373  }
374 
375  // Globally consistent order
376  for (auto& tuple : halfEdgeLookup)
377  {
378  tuple.canonical();
379  }
380 
381 
382  // Now ready to actually construct the edgeMap
383 
384  mapDistributeBase faEdgeMap
385  (
386  newAreaPatch.nEdges(), // constructSize
387  labelListList(), // subMap
388  labelListList(), // constructMap
389  false, // subHasFlip
390  false, // constructHasFlip
391  faFaceMap.comm()
392  );
393 
394  {
395  // Pass 1.
396  // Count the number of edges to be sent to each proc
397 
398  labelList nProcEdges(Pstream::nProcs(faFaceMap.comm()), Zero);
399 
400  forAll(halfEdgeLookup, srcEdgei)
401  {
402  const faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
403 
404  labelPair dstProcs(-1, -1);
405 
406  for (int sidei = 0; sidei < 2; ++sidei)
407  {
408  const label dstFacei = facePairings.getFace(sidei);
409  //const label dstEdgei = facePairings.getEdge(sidei);
410 
411  if (dstFacei < 0)
412  {
413  continue;
414  }
415 
416  label proci = uniqFaceIndex.whichProcID(dstFacei);
417  dstProcs[sidei] = proci;
418 
419  if (proci != -1 && dstProcs[0] != dstProcs[1])
420  {
421  ++nProcEdges[proci];
422  }
423  }
424  }
425 
426  auto& edgeSubMap = faEdgeMap.subMap();
427  auto& edgeCnstrMap = faEdgeMap.constructMap();
428 
429  edgeSubMap.resize(nProcEdges.size());
430  edgeCnstrMap.resize(nProcEdges.size());
431 
432  labelListList remoteEdges(nProcEdges.size());
433 
434  forAll(nProcEdges, proci)
435  {
436  edgeSubMap[proci].resize(nProcEdges[proci], -1);
437  remoteEdges[proci].resize(nProcEdges[proci], -1);
438  }
439 
440 
441  // Pass 2.
442  // Fill in the maps
443 
444  nProcEdges = Zero; // Reset counter
445 
446  forAll(halfEdgeLookup, srcEdgei)
447  {
448  const faceEdgeTuple& facePairings = halfEdgeLookup[srcEdgei];
449 
450  labelPair dstProcs(-1, -1);
451 
452  for (int sidei = 0; sidei < 2; ++sidei)
453  {
454  const label dstFacei = facePairings.getFace(sidei);
455  const label dstEdgei = facePairings.getEdge(sidei);
456 
457  if (dstFacei < 0)
458  {
459  continue;
460  }
461 
462  label proci = uniqFaceIndex.whichProcID(dstFacei);
463  dstProcs[sidei] = proci;
464 
465  if (proci != -1 && dstProcs[0] != dstProcs[1])
466  {
467  edgeSubMap[proci][nProcEdges[proci]] = srcEdgei;
468  remoteEdges[proci][nProcEdges[proci]] = dstEdgei;
469  ++nProcEdges[proci];
470  }
471  }
472  }
473 
474  // The remoteEdges are what we know locally about what will be
475  // received, but not what is actually received.
476  // So need an all-to-all exchange
477 
478  Pstream::exchange<labelList, label>
479  (
480  remoteEdges,
481  edgeCnstrMap,
483  faEdgeMap.comm()
484  );
485  }
486 
487  // The edge map is now complete [in PrimitivePatch edge order]
488 
489 
490  if (oldMesh.hasInternalEdgeLabels())
491  {
492  // If there are gaps in the edge numbering or the
493  // internal edge labels are out of sequence would
494  // have to use compactLocalData etc before sending
495  // But just issue an error for now
496 
498  << "Originating faMesh has gaps in the edge addressing"
499  << " this is currently unsupported"
500  << abort(FatalError);
501  }
502 
503 
504  // ------------------------
505  // Patch edge labels
506  // ------------------------
507 
508  faPatchList newFaPatches;
509 
510  // Distribute the edge lookups.
511  // Needs full version for the combine operation
512 
513  mapDistributeBase::distribute<faceEdgeTuple, faceEdgeTuple, identityOp>
514  (
517  faEdgeMap.constructSize(),
518 
519  faEdgeMap.subMap(),
520  faEdgeMap.subHasFlip(),
521 
522  faEdgeMap.constructMap(),
523  faEdgeMap.constructHasFlip(),
524 
525  halfEdgeLookup,
526  faceEdgeTuple(), // nullValue
527  faceEdgeTuple(), // CombineOp
528  identityOp(), // NegateOp
530  faEdgeMap.comm()
531  );
532 
533  {
534  // Pass 1.
535  // Count the number of edges for each patch type
536 
537  Map<label> nNonProcEdges(2*nNonProcessor);
538  LabelPairMap<label> nProcEdges(2*nNonProcessor);
539 
540  forAll(halfEdgeLookup, edgei)
541  {
542  const auto& tuple = halfEdgeLookup[edgei];
543 
544  labelPair target(tuple.getFaces());
545 
546  if (target[1] < -1)
547  {
548  // Neighbour face was patchId encoded value
549  label patchi = mag(target[1])-2;
550  ++nNonProcEdges(patchi);
551  }
552  else if (target[0] >= 0 && target[1] >= 0)
553  {
554  // From global face to proc id
555  target[0] = uniqFaceIndex.whichProcID(target[0]);
556  target[1] = uniqFaceIndex.whichProcID(target[1]);
557 
558  // A connection between different procs but involving
559  // myProc?
560  if
561  (
562  target[0] != target[1]
563  &&
564  (
565  target[0] == Pstream::myProcNo()
566  || target[1] == Pstream::myProcNo()
567  )
568  )
569  {
570  ++nProcEdges(target);
571  }
572  }
573  }
574 
575  label nPatches = (nNonProcessor + nProcEdges.size());
576 
577  newFaPatches.resize(nPatches);
578 
579  labelList nEdgeLabels(nPatches, Zero);
580  labelListList newEdgeLabels(nPatches);
581 
582  LabelPairMap<label> procPairToPatchId(2*nProcEdges.size());
583 
584  // Map processor-pair to index in patches
585  {
586  nPatches = nNonProcessor;
587 
588  for (const labelPair& twoProcs : nProcEdges.sortedToc())
589  {
590  procPairToPatchId.set(twoProcs, nPatches);
591  ++nPatches;
592  }
593  }
594 
595  // Presize edgeLabels arrays
596  {
597  nPatches = 0;
598 
599  for (label patchi = 0; patchi < nNonProcessor; ++patchi)
600  {
601  label nLabels = nNonProcEdges.lookup(nPatches, 0);
602 
603  nEdgeLabels[nPatches] = nLabels;
604 
605  newEdgeLabels[nPatches].resize(nLabels);
606 
607  ++nPatches;
608  }
609 
610  // Processor patches
611  for (const labelPair& twoProcs : nProcEdges.sortedToc())
612  {
613  label nLabels = nProcEdges.lookup(twoProcs, 0);
614 
615  nEdgeLabels[nPatches] = nLabels;
616 
617  newEdgeLabels[nPatches].resize(nLabels);
618 
619  ++nPatches;
620  }
621  }
622 
623  nEdgeLabels = Zero;
624 
625  // Populate edgeLabels arrays - walk in canonically sorted
626  // order to ensure that both sides of processor edges
627  // correspond.
628 
629  const labelList order(Foam::sortedOrder(halfEdgeLookup));
630 
631  for (const label edgei : order)
632  {
633  const auto& tuple = halfEdgeLookup[edgei];
634 
635  labelPair target(tuple.getFaces());
636 
637  label patchi = -1;
638 
639  if (target[1] < -1)
640  {
641  // Neighbour face was patchId encoded value
642  patchi = mag(target[1])-2;
643  }
644  else if (target[0] >= 0 && target[1] >= 0)
645  {
646  // From global face to proc id
647  target[0] = uniqFaceIndex.whichProcID(target[0]);
648  target[1] = uniqFaceIndex.whichProcID(target[1]);
649 
650  // A connection between different procs but involving
651  // myProc?
652  if
653  (
654  target[0] != target[1]
655  &&
656  (
657  target[0] == Pstream::myProcNo()
658  || target[1] == Pstream::myProcNo()
659  )
660  )
661  {
662  patchi = procPairToPatchId.lookup(target, -1);
663  }
664  }
665 
666  if (patchi >= 0)
667  {
668  const label idx = nEdgeLabels[patchi]++;
669  newEdgeLabels[patchi][idx] = edgei;
670  }
671  }
672 
673 
674  // Clone all non-processor patches
675 
676  nPatches = 0;
677  for (label patchi = 0; patchi < nNonProcessor; ++patchi)
678  {
679  newFaPatches.set
680  (
681  nPatches,
682  oldMesh.boundary()[patchi].clone
683  (
684  newMesh.boundary(),
685  newEdgeLabels[nPatches], // edgeLabels
686  nPatches,
687  oldMesh.boundary()[patchi].ngbPolyPatchIndex()
688  )
689  );
690  ++nPatches;
691  }
692 
693  // Any processor patches
694  for (const labelPair& twoProcs : nProcEdges.sortedToc())
695  {
696  label nbrProcNo =
697  (
698  twoProcs[1] == Pstream::myProcNo()
699  ? twoProcs[0] : twoProcs[1]
700  );
701 
702  newFaPatches.set
703  (
704  nPatches,
705  new processorFaPatch
706  (
707  newEdgeLabels[nPatches], // edgeLabels
708  nPatches,
709  newMesh.boundary(),
710  -1, // nbrPolyPatchi
712  nbrProcNo
713  )
714  );
715  ++nPatches;
716  }
717  }
718 
719 
720  newMesh.addFaPatches(newFaPatches);
721  newMesh.init(true);
722 
723 
724  // At this stage we now have a complete mapping overview in
725  // terms of the PrimitivePatch edge ordering which now must be
726  // changed into faMesh edge ordering.
727 
728  {
729  labelList oldToNewSub;
730  labelList oldToNewConstruct;
731 
732  // Assume we use all patch edges for the faMesh too.
733  oldToNewSub.resize(oldAreaPatch.nEdges(), -1);
734  oldToNewConstruct.resize(newAreaPatch.nEdges(), -1);
735 
736  // Remap old edges
737  label nEdges = 0;
738 
739  // Internal edgeLabels
740  for
741  (
742  label edgei = 0;
743  edgei < oldAreaPatch.nInternalEdges();
744  ++edgei
745  )
746  {
747  oldToNewSub[edgei] = nEdges++;
748  }
749 
750  // Boundary edgeLabels
751  for (const faPatch& fap : oldMesh.boundary())
752  {
753  for (const label edgei : fap.edgeLabels())
754  {
755  oldToNewSub[edgei] = nEdges++;
756  }
757  }
758 
759  // New edges
760  nEdges = 0;
761 
762  // Internal edgeLabels
763  for
764  (
765  label edgei = 0;
766  edgei < newAreaPatch.nInternalEdges();
767  ++edgei
768  )
769  {
770  oldToNewConstruct[edgei] = nEdges++;
771  }
772 
773  // Boundary edgeLabels
774  for (const faPatch& fap : newMesh.boundary())
775  {
776  for (const label edgei : fap.edgeLabels())
777  {
778  oldToNewConstruct[edgei] = nEdges++;
779  }
780  }
781 
783  (
784  faEdgeMap.subMap(),
785  oldToNewSub,
786  faEdgeMap.subHasFlip()
787  );
788 
790  (
791  faEdgeMap.constructMap(),
792  oldToNewConstruct,
793  faEdgeMap.constructHasFlip()
794  );
795  }
796 
797 
798  // ------------------------
799  // Patch mapping
800  // ------------------------
801 
802  mapDistributeBase faPatchMap
803  (
804  newMesh.boundary().size(), // constructSize
805  labelListList(), // subMap
806  labelListList(), // constructMap
807  false, // subHasFlip
808  false, // constructHasFlip
809  faFaceMap.comm()
810  );
811 
812  // For patch maps, would normally transcribe from patchMapInfo
813  // gathered earlier. However, existing practice (APR-2022) for
814  // faMesh decomposition is to map all non-processor patches
815 
816  {
817  // Map all non-processor patches
818  const label nProcs = UPstream::nProcs(faPatchMap.comm());
819 
820  faPatchMap.subMap().resize(nProcs, identity(nNonProcessor));
821  faPatchMap.constructMap().resize(nProcs, identity(nNonProcessor));
822  }
823 
853 
854 
855  // ------------------------
856  // Point mapping
857  // ------------------------
858 
859  mapDistributeBase faPointMap(distMap.pointMap());
860 
861  {
862  // Retain meshPoints needed for the faMesh - preserve original order
863  // Need both sides (local/remote) for correct compaction maps
864  // without dangling points.
865 
866  labelList oldToNewSub;
867  labelList oldToNewConstruct;
868 
869  faPointMap.compactData
870  (
871  oldAreaPatch.meshPoints(),
872  newAreaPatch.meshPoints(),
873  oldToNewSub,
874  oldToNewConstruct,
875  distMap.nOldPoints(),
877  );
878  }
879 
880 
881  return mapDistributePolyMesh
882  (
883  // Mesh before changes
884  nOldPoints,
885  nOldEdges, // area: nOldEdges (volume: nOldFaces)
886  nOldFaces, // area: nOldFaces (volume: nOldCells)
887 
888  labelList(oldMesh.boundary().patchStarts()),
889  labelList(), // oldPatchNMeshPoints [unused]
890 
891  mapDistribute(std::move(faPointMap)),
892  mapDistribute(std::move(faEdgeMap)), // area: edgeMap (volume: faceMap)
893  mapDistribute(std::move(faFaceMap)), // area: faceMap (volume: cellMap)
894  mapDistribute(std::move(faPatchMap))
895  );
896 }
897 
898 
901 (
902  const faMesh& oldMesh,
903  const mapDistributePolyMesh& distMap,
904  autoPtr<faMesh>& newMeshPtr
905 )
906 {
908  (
909  oldMesh,
910  distMap,
911  oldMesh.mesh(), // polyMesh
912  newMeshPtr
913  );
914 }
915 
916 
917 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:396
SubList< label > labelSubList
A SubList of labels.
Definition: SubList.H:55
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition: faMesh.H:87
const T & first() const noexcept
Access the first element.
Definition: Pair.H:137
label nPoints() const
Number of points supporting patch faces.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
labelList findIndices(const ListType &input, const UnaryPredicate &pred, label start=0)
Linear search to find all occurences of given element.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: HashTable.H:107
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:160
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:598
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
PtrList< T > clone(Args &&... args) const
Make a copy by cloning each of the list elements.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1049
label nInternalEdges() const
Number of internal edges.
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
static int & msgType() noexcept
Message tag of standard messages.
Definition: UPstream.H:1229
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:1074
static const List< T > & null()
Return a null List.
Definition: ListI.H:130
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
const labelList & edgeLabels() const noexcept
Return the list of edges.
Definition: faPatch.H:335
static const faMesh & mesh(const polyMesh &pMesh)
The single-region finite-area region on the polyMesh. Uses lookupObject semantics - Fatal if non-exis...
Definition: faMesh.C:74
static void waitRequests()
Wait for all requests to finish.
Definition: UPstream.H:1538
const labelList & meshPoints() const
Return labelList of mesh points in patch.
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
const uindirectPrimitivePatch & patch() const
Return constant reference to primitive patch.
Definition: faMeshI.H:109
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
bool insert(const label &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:152
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
scalar y
static label getEdge(List< DynamicList< label >> &pe, DynamicList< edge > &es, const label pointi, const label nextPointi)
A list of faces which address into the list of points.
label nOldPoints() const noexcept
Number of points in mesh before distribution.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:61
const mapDistribute & pointMap() const noexcept
Point distribute map.
AccessType combine(const UList< T > &lists, AccessOp aop=accessOp< T >())
Combines sub-lists into a single list.
Definition: ListListOps.C:62
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:1065
const labelList & faceLabels() const noexcept
Return the underlying polyMesh face labels.
Definition: faMeshI.H:103
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i), works like std::iota() but returning a...
Definition: labelLists.C:44
label nOldFaces() const noexcept
Number of faces in mesh before distribution.
bool hasInternalEdgeLabels() const noexcept
True if the internalEdges use an ordering that does not correspond 1-to-1 with the patch internalEdge...
Definition: faMeshI.H:155
Reading is optional [identical to LAZY_READ].
A HashTable similar to std::unordered_map.
Definition: HashTable.H:108
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:159
A HashTable to objects of type <T> with a labelPair key. The hashing is based on labelPair (FixedList...
Class containing processor-to-processor mapping information.
label nEdges() const
Number of edges in patch.
void add(FieldField< Field1, typename typeOfSum< Type1, Type2 >::type > &f, const FieldField< Field1, Type1 > &f1, const FieldField< Field2, Type2 > &f2)
A functor that returns its argument unchanged (cf. C++20 std::identity) Should never be specialized...
Definition: stdFoam.H:90
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
Finite area patch class. Used for 2-D non-Euclidian finite area method.
Definition: faPatch.H:72
const faBoundaryMesh & boundary() const noexcept
Return constant reference to boundary mesh.
Definition: faMeshI.H:31
T & last()
Access last element of the list, position [size()-1].
Definition: UList.H:867
void resize(const label newLen)
Adjust size of PtrList.
Definition: PtrList.C:95
Class containing processor-to-processor mapping information.
const T & lookup(const Key &key, const T &deflt) const
Return hashed entry if it exists, or return the given default.
Definition: HashTableI.H:222
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:139
Finite area boundary mesh.
"nonBlocking" : (MPI_Isend, MPI_Irecv)
const labelListList & faceEdges() const
Return face-edge addressing.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
List< label > labelList
A List of labels.
Definition: List.H:62
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
const T & second() const noexcept
Access the second element.
Definition: Pair.H:147
label nFaces() const noexcept
Number of faces in the patch.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
labelList patchStarts() const
Return a list of patch start indices.
const mapDistribute & faceMap() const noexcept
Face distribute map.
static mapDistributePolyMesh distribute(const faMesh &oldMesh, const mapDistributePolyMesh &distMap, const polyMesh &tgtPolyMesh, autoPtr< faMesh > &newMeshPtr)
Distribute mesh according to the given (volume) mesh distribution.
static label renumberMap(labelListList &mapElements, const labelUList &oldToNew, const bool hasFlip)
Helper for renumbering the (compacted) map elements using the supplied old-to-new mapping...
Processor patch.
A HashTable to objects of type <T> with a label key.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127