polyMeshAdder.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-2016 OpenFOAM Foundation
9  Copyright (C) 2019-2021 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 "polyMeshAdder.H"
30 #include "mapAddedPolyMesh.H"
31 #include "IOobject.H"
32 #include "faceCoupleInfo.H"
33 #include "processorPolyPatch.H"
34 #include "SortableList.H"
35 #include "Time.H"
36 #include "globalMeshData.H"
37 #include "mergePoints.H"
38 #include "polyModifyFace.H"
39 #include "polyRemovePoint.H"
40 #include "polyTopoChange.H"
41 #include "globalIndex.H"
42 
43 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
44 
45 // Get index of patch in new set of patchnames/types
46 Foam::label Foam::polyMeshAdder::patchIndex
47 (
48  const polyPatch& p,
49  DynamicList<word>& allPatchNames,
50  DynamicList<word>& allPatchTypes
51 )
52 {
53  // Find the patch name on the list. If the patch is already there
54  // and patch types match, return index
55  const word& pType = p.type();
56  const word& pName = p.name();
57 
58  const label patchi = allPatchNames.find(pName);
59 
60  if (patchi == -1)
61  {
62  // Patch not found. Append to the list
63  allPatchNames.append(pName);
64  allPatchTypes.append(pType);
65 
66  return allPatchNames.size() - 1;
67  }
68  else if (allPatchTypes[patchi] == pType)
69  {
70  // Found name and types match
71  return patchi;
72  }
73  else
74  {
75  // Found the name, but type is different
76 
77  // Duplicate name is not allowed. Create a composite name from the
78  // patch name and case name
79  const word& caseName = p.boundaryMesh().mesh().time().caseName();
80 
81  allPatchNames.append(pName + "_" + caseName);
82  allPatchTypes.append(pType);
83 
84  Pout<< "label patchIndex(const polyPatch& p) : "
85  << "Patch " << p.index() << " named "
86  << pName << " in mesh " << caseName
87  << " already exists, but patch types"
88  << " do not match.\nCreating a composite name as "
89  << allPatchNames.last() << endl;
90 
91  return allPatchNames.size() - 1;
92  }
93 }
94 
95 
96 // Get index of zone in new set of zone names
97 Foam::label Foam::polyMeshAdder::zoneIndex
98 (
99  const word& curName,
100  DynamicList<word>& names
101 )
102 {
103  const label zoneI = names.find(curName);
104 
105  if (zoneI != -1)
106  {
107  return zoneI;
108  }
109  else
110  {
111  // Not found. Add new name to the list
112  names.append(curName);
113 
114  return names.size() - 1;
115  }
116 }
117 
118 
119 void Foam::polyMeshAdder::mergePatchNames
120 (
121  const polyBoundaryMesh& patches0,
122  const polyBoundaryMesh& patches1,
123 
124  DynamicList<word>& allPatchNames,
125  DynamicList<word>& allPatchTypes,
126 
127  labelList& from1ToAllPatches,
128  labelList& fromAllTo1Patches
129 )
130 {
131  // Insert the mesh0 patches and zones
132  allPatchNames.append(patches0.names());
133  allPatchTypes.append(patches0.types());
134 
135 
136  // Patches
137  // ~~~~~~~
138  // Patches from 0 are taken over as is; those from 1 get either merged
139  // (if they share name and type) or appended.
140  // Empty patches are filtered out much much later on.
141 
142  // Add mesh1 patches and build map both ways.
143  from1ToAllPatches.setSize(patches1.size());
144 
145  forAll(patches1, patchi)
146  {
147  from1ToAllPatches[patchi] = patchIndex
148  (
149  patches1[patchi],
150  allPatchNames,
151  allPatchTypes
152  );
153  }
154  allPatchTypes.shrink();
155  allPatchNames.shrink();
156 
157  // Invert 1 to all patch map
158  fromAllTo1Patches.setSize(allPatchNames.size());
159  fromAllTo1Patches = -1;
160 
161  forAll(from1ToAllPatches, i)
162  {
163  fromAllTo1Patches[from1ToAllPatches[i]] = i;
164  }
165 }
166 
167 
168 Foam::labelList Foam::polyMeshAdder::getPatchStarts
169 (
170  const polyBoundaryMesh& patches
171 )
172 {
173  labelList patchStarts(patches.size());
174  forAll(patches, patchi)
175  {
176  patchStarts[patchi] = patches[patchi].start();
177  }
178  return patchStarts;
179 }
180 
181 
182 Foam::labelList Foam::polyMeshAdder::getPatchSizes
183 (
184  const polyBoundaryMesh& patches
185 )
186 {
187  labelList patchSizes(patches.size());
188  forAll(patches, patchi)
189  {
190  patchSizes[patchi] = patches[patchi].size();
191  }
192  return patchSizes;
193 }
194 
195 
196 Foam::List<Foam::polyPatch*> Foam::polyMeshAdder::combinePatches
197 (
198  const polyMesh& mesh0,
199  const polyMesh& mesh1,
200  const polyBoundaryMesh& allBoundaryMesh,
201  const label nAllPatches,
202  const labelList& fromAllTo1Patches,
203 
204  const label nInternalFaces,
205  const labelList& nFaces,
206 
207  labelList& from0ToAllPatches,
208  labelList& from1ToAllPatches
209 )
210 {
211  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
212  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
213 
214 
215  // Compacted new patch list.
216  DynamicList<polyPatch*> allPatches(nAllPatches);
217 
218 
219  // Map from 0 to all patches (since gets compacted)
220  from0ToAllPatches.setSize(patches0.size());
221  from0ToAllPatches = -1;
222 
223  label startFacei = nInternalFaces;
224 
225  // Copy patches0 with new sizes. First patches always come from
226  // mesh0 and will always be present.
227  forAll(patches0, patchi)
228  {
229  // Originates from mesh0. Clone with new size & filter out empty
230  // patch.
231  label filteredPatchi;
232 
233  if (nFaces[patchi] == 0 && isA<processorPolyPatch>(patches0[patchi]))
234  {
235  //Pout<< "Removing zero sized mesh0 patch "
236  // << patches0[patchi].name() << endl;
237  filteredPatchi = -1;
238  }
239  else
240  {
241  filteredPatchi = allPatches.size();
242 
243  allPatches.append
244  (
245  patches0[patchi].clone
246  (
247  allBoundaryMesh,
248  filteredPatchi,
249  nFaces[patchi],
250  startFacei
251  ).ptr()
252  );
253  startFacei += nFaces[patchi];
254  }
255 
256  // Record new index in allPatches
257  from0ToAllPatches[patchi] = filteredPatchi;
258 
259  // Check if patch was also in mesh1 and update its addressing if so.
260  if (fromAllTo1Patches[patchi] != -1)
261  {
262  from1ToAllPatches[fromAllTo1Patches[patchi]] = filteredPatchi;
263  }
264  }
265 
266  // Copy unique patches of mesh1.
267  forAll(from1ToAllPatches, patchi)
268  {
269  label allPatchi = from1ToAllPatches[patchi];
270 
271  if (allPatchi >= patches0.size())
272  {
273  // Patch has not been merged with any mesh0 patch.
274 
275  label filteredPatchi;
276 
277  if
278  (
279  nFaces[allPatchi] == 0
280  && isA<processorPolyPatch>(patches1[patchi])
281  )
282  {
283  //Pout<< "Removing zero sized mesh1 patch "
284  // << patches1[patchi].name() << endl;
285  filteredPatchi = -1;
286  }
287  else
288  {
289  filteredPatchi = allPatches.size();
290 
291  allPatches.append
292  (
293  patches1[patchi].clone
294  (
295  allBoundaryMesh,
296  filteredPatchi,
297  nFaces[allPatchi],
298  startFacei
299  ).ptr()
300  );
301  startFacei += nFaces[allPatchi];
302  }
303 
304  from1ToAllPatches[patchi] = filteredPatchi;
305  }
306  }
307 
308  allPatches.shrink();
309 
310  return allPatches;
311 }
312 
313 
314 Foam::labelList Foam::polyMeshAdder::getFaceOrder
315 (
316  const cellList& cells,
317  const label nInternalFaces,
318  const labelList& owner,
319  const labelList& neighbour
320 )
321 {
322  labelList oldToNew(owner.size(), -1);
323 
324  // Leave boundary faces in order
325  for (label facei = nInternalFaces; facei < owner.size(); ++facei)
326  {
327  oldToNew[facei] = facei;
328  }
329 
330  // First unassigned face
331  label newFacei = 0;
332 
333  forAll(cells, celli)
334  {
335  const labelList& cFaces = cells[celli];
336 
337  SortableList<label> nbr(cFaces.size());
338 
339  forAll(cFaces, i)
340  {
341  const label facei = cFaces[i];
342 
343  label nbrCelli = neighbour[facei];
344 
345  if (nbrCelli != -1)
346  {
347  // Internal face. Get cell on other side.
348  if (nbrCelli == celli)
349  {
350  nbrCelli = owner[facei];
351  }
352 
353  if (celli < nbrCelli)
354  {
355  // Celli is master
356  nbr[i] = nbrCelli;
357  }
358  else
359  {
360  // nbrCell is master. Let it handle this face.
361  nbr[i] = -1;
362  }
363  }
364  else
365  {
366  // External face. Do later.
367  nbr[i] = -1;
368  }
369  }
370 
371  nbr.sort();
372 
373  forAll(nbr, i)
374  {
375  if (nbr[i] != -1)
376  {
377  oldToNew[cFaces[nbr.indices()[i]]] = newFacei++;
378  }
379  }
380  }
381 
382 
383  // Check done all faces.
384  forAll(oldToNew, facei)
385  {
386  if (oldToNew[facei] == -1)
387  {
389  << "Did not determine new position"
390  << " for face " << facei
391  << abort(FatalError);
392  }
393  }
394 
395  return oldToNew;
396 }
397 
398 
399 // Extends face f with split points. cutEdgeToPoints gives for every
400 // edge the points introduced inbetween the endpoints.
401 void Foam::polyMeshAdder::insertVertices
402 (
403  const edgeLookup& cutEdgeToPoints,
404  const Map<label>& meshToMaster,
405  const labelList& masterToCutPoints,
406  const face& masterF,
407 
408  DynamicList<label>& workFace,
409  face& allF
410 )
411 {
412  workFace.clear();
413 
414  // Check any edge for being cut (check on the cut so takes account
415  // for any point merging on the cut)
416 
417  forAll(masterF, fp)
418  {
419  label v0 = masterF[fp];
420  label v1 = masterF.nextLabel(fp);
421 
422  // Copy existing face point
423  workFace.append(allF[fp]);
424 
425  // See if any edge between v0,v1
426 
427  const auto v0Fnd = meshToMaster.cfind(v0);
428  if (v0Fnd.found())
429  {
430  const auto v1Fnd = meshToMaster.cfind(v1);
431  if (v1Fnd.found())
432  {
433  // Get edge in cutPoint numbering
434  edge cutEdge
435  (
436  masterToCutPoints[v0Fnd()],
437  masterToCutPoints[v1Fnd()]
438  );
439 
440  const auto iter = cutEdgeToPoints.cfind(cutEdge);
441 
442  if (iter.found())
443  {
444  const edge& e = iter.key();
445  const labelList& addedPoints = iter.val();
446 
447  // cutPoints first in allPoints so no need for renumbering
448  if (e[0] == cutEdge[0])
449  {
450  forAll(addedPoints, i)
451  {
452  workFace.append(addedPoints[i]);
453  }
454  }
455  else
456  {
457  forAllReverse(addedPoints, i)
458  {
459  workFace.append(addedPoints[i]);
460  }
461  }
462  }
463  }
464  }
465  }
466 
467  if (workFace.size() != allF.size())
468  {
469  allF.transfer(workFace);
470  }
471 }
472 
473 
474 // Adds primitives (cells, faces, points)
475 // Cells:
476 // - all of mesh0
477 // - all of mesh1
478 // Faces:
479 // - all uncoupled of mesh0
480 // - all coupled faces
481 // - all uncoupled of mesh1
482 // Points:
483 // - all coupled
484 // - all uncoupled of mesh0
485 // - all uncoupled of mesh1
486 void Foam::polyMeshAdder::mergePrimitives
487 (
488  const polyMesh& mesh0,
489  const polyMesh& mesh1,
490  const faceCoupleInfo& coupleInfo,
491 
492  const label nAllPatches, // number of patches in the new mesh
493  const labelList& fromAllTo1Patches,
494  const labelList& from1ToAllPatches,
495 
497  labelList& from0ToAllPoints,
498  labelList& from1ToAllPoints,
499 
500  faceList& allFaces,
501  labelList& allOwner,
502  labelList& allNeighbour,
503  label& nInternalFaces,
504  labelList& nFacesPerPatch,
505  label& nCells,
506 
507  labelList& from0ToAllFaces,
508  labelList& from1ToAllFaces,
509  labelList& from1ToAllCells
510 )
511 {
512  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
513  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
514 
515  const primitiveFacePatch& cutFaces = coupleInfo.cutFaces();
516  const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
517  const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
518 
519 
520  // Points
521  // ~~~~~~
522 
523  // Storage for new points
524  allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
525  label allPointi = 0;
526 
527  from0ToAllPoints.setSize(mesh0.nPoints());
528  from0ToAllPoints = -1;
529  from1ToAllPoints.setSize(mesh1.nPoints());
530  from1ToAllPoints = -1;
531 
532  // Copy coupled points (on cut)
533  {
534  const pointField& cutPoints = coupleInfo.cutPoints();
535 
536  //const labelListList& cutToMasterPoints =
537  // coupleInfo.cutToMasterPoints();
538  labelListList cutToMasterPoints
539  (
541  (
542  cutPoints.size(),
543  coupleInfo.masterToCutPoints()
544  )
545  );
546 
547  //const labelListList& cutToSlavePoints =
548  // coupleInfo.cutToSlavePoints();
549  labelListList cutToSlavePoints
550  (
552  (
553  cutPoints.size(),
554  coupleInfo.slaveToCutPoints()
555  )
556  );
557 
558  forAll(cutPoints, i)
559  {
560  allPoints[allPointi] = cutPoints[i];
561 
562  // Mark all master and slave points referring to this point.
563 
564  const labelList& masterPoints = cutToMasterPoints[i];
565 
566  forAll(masterPoints, j)
567  {
568  label mesh0Pointi = masterPatch.meshPoints()[masterPoints[j]];
569  from0ToAllPoints[mesh0Pointi] = allPointi;
570  }
571 
572  const labelList& slavePoints = cutToSlavePoints[i];
573 
574  forAll(slavePoints, j)
575  {
576  label mesh1Pointi = slavePatch.meshPoints()[slavePoints[j]];
577  from1ToAllPoints[mesh1Pointi] = allPointi;
578  }
579  allPointi++;
580  }
581  }
582 
583  // Add uncoupled mesh0 points
584  forAll(mesh0.points(), pointi)
585  {
586  if (from0ToAllPoints[pointi] == -1)
587  {
588  allPoints[allPointi] = mesh0.points()[pointi];
589  from0ToAllPoints[pointi] = allPointi;
590  allPointi++;
591  }
592  }
593 
594  // Add uncoupled mesh1 points
595  forAll(mesh1.points(), pointi)
596  {
597  if (from1ToAllPoints[pointi] == -1)
598  {
599  allPoints[allPointi] = mesh1.points()[pointi];
600  from1ToAllPoints[pointi] = allPointi;
601  allPointi++;
602  }
603  }
604 
605  allPoints.setSize(allPointi);
606 
607 
608  // Faces
609  // ~~~~~
610 
611  // Sizes per patch
612  nFacesPerPatch.setSize(nAllPatches);
613  nFacesPerPatch = 0;
614 
615  // Storage for faces and owner/neighbour
616  allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
617  allOwner.setSize(allFaces.size());
618  allOwner = -1;
619  allNeighbour.setSize(allFaces.size());
620  allNeighbour = -1;
621  label allFacei = 0;
622 
623  from0ToAllFaces.setSize(mesh0.nFaces());
624  from0ToAllFaces = -1;
625  from1ToAllFaces.setSize(mesh1.nFaces());
626  from1ToAllFaces = -1;
627 
628  // Copy mesh0 internal faces (always uncoupled)
629  for (label facei = 0; facei < mesh0.nInternalFaces(); facei++)
630  {
631  allFaces[allFacei] = renumber(from0ToAllPoints, mesh0.faces()[facei]);
632  allOwner[allFacei] = mesh0.faceOwner()[facei];
633  allNeighbour[allFacei] = mesh0.faceNeighbour()[facei];
634  from0ToAllFaces[facei] = allFacei++;
635  }
636 
637  // Copy coupled faces. Every coupled face has an equivalent master and
638  // slave. Also uncount as boundary faces all the newly coupled faces.
639  const labelList& cutToMasterFaces = coupleInfo.cutToMasterFaces();
640  const labelList& cutToSlaveFaces = coupleInfo.cutToSlaveFaces();
641 
642  forAll(cutFaces, i)
643  {
644  label masterFacei = cutToMasterFaces[i];
645 
646  label mesh0Facei = masterPatch.addressing()[masterFacei];
647 
648  if (from0ToAllFaces[mesh0Facei] == -1)
649  {
650  // First occurrence of face
651  from0ToAllFaces[mesh0Facei] = allFacei;
652 
653  // External face becomes internal so uncount
654  label patch0 = patches0.whichPatch(mesh0Facei);
655  nFacesPerPatch[patch0]--;
656  }
657 
658  label slaveFacei = cutToSlaveFaces[i];
659 
660  label mesh1Facei = slavePatch.addressing()[slaveFacei];
661 
662  if (from1ToAllFaces[mesh1Facei] == -1)
663  {
664  from1ToAllFaces[mesh1Facei] = allFacei;
665 
666  label patch1 = patches1.whichPatch(mesh1Facei);
667  nFacesPerPatch[from1ToAllPatches[patch1]]--;
668  }
669 
670  // Copy cut face (since cutPoints are copied first no renumbering
671  // necessary)
672  allFaces[allFacei] = cutFaces[i];
673  allOwner[allFacei] = mesh0.faceOwner()[mesh0Facei];
674  allNeighbour[allFacei] = mesh1.faceOwner()[mesh1Facei] + mesh0.nCells();
675 
676  allFacei++;
677  }
678 
679  // Copy mesh1 internal faces (always uncoupled)
680  for (label facei = 0; facei < mesh1.nInternalFaces(); facei++)
681  {
682  allFaces[allFacei] = renumber(from1ToAllPoints, mesh1.faces()[facei]);
683  allOwner[allFacei] = mesh1.faceOwner()[facei] + mesh0.nCells();
684  allNeighbour[allFacei] = mesh1.faceNeighbour()[facei] + mesh0.nCells();
685  from1ToAllFaces[facei] = allFacei++;
686  }
687 
688  nInternalFaces = allFacei;
689 
690  // Copy (unmarked/uncoupled) external faces in new order.
691  for (label allPatchi = 0; allPatchi < nAllPatches; allPatchi++)
692  {
693  if (allPatchi < patches0.size())
694  {
695  // Patch is present in mesh0
696  const polyPatch& pp = patches0[allPatchi];
697 
698  nFacesPerPatch[allPatchi] += pp.size();
699 
700  label facei = pp.start();
701 
702  forAll(pp, i)
703  {
704  if (from0ToAllFaces[facei] == -1)
705  {
706  // Is uncoupled face since has not yet been dealt with
707  allFaces[allFacei] = renumber
708  (
709  from0ToAllPoints,
710  mesh0.faces()[facei]
711  );
712  allOwner[allFacei] = mesh0.faceOwner()[facei];
713  allNeighbour[allFacei] = -1;
714 
715  from0ToAllFaces[facei] = allFacei++;
716  }
717  facei++;
718  }
719  }
720  if (fromAllTo1Patches[allPatchi] != -1)
721  {
722  // Patch is present in mesh1
723  const polyPatch& pp = patches1[fromAllTo1Patches[allPatchi]];
724 
725  nFacesPerPatch[allPatchi] += pp.size();
726 
727  label facei = pp.start();
728 
729  forAll(pp, i)
730  {
731  if (from1ToAllFaces[facei] == -1)
732  {
733  // Is uncoupled face
734  allFaces[allFacei] = renumber
735  (
736  from1ToAllPoints,
737  mesh1.faces()[facei]
738  );
739  allOwner[allFacei] =
740  mesh1.faceOwner()[facei]
741  + mesh0.nCells();
742  allNeighbour[allFacei] = -1;
743 
744  from1ToAllFaces[facei] = allFacei++;
745  }
746  facei++;
747  }
748  }
749  }
750  allFaces.setSize(allFacei);
751  allOwner.setSize(allFacei);
752  allNeighbour.setSize(allFacei);
753 
754 
755  // So now we have all ok for one-to-one mapping.
756  // For split slace faces:
757  // - mesh consistent with slave side
758  // - mesh not consistent with owner side. It is not zipped up, the
759  // original faces need edges split.
760 
761  // Use brute force to prevent having to calculate addressing:
762  // - get map from master edge to split edges.
763  // - check all faces to find any edge that is split.
764  {
765  // From two cut-points to labels of cut-points inbetween.
766  // (in order: from e[0] to e[1]
767  const edgeLookup& cutEdgeToPoints = coupleInfo.cutEdgeToPoints();
768 
769  // Get map of master face (in mesh labels) that are in cut. These faces
770  // do not need to be renumbered.
771  labelHashSet masterCutFaces(cutToMasterFaces.size());
772  forAll(cutToMasterFaces, i)
773  {
774  label meshFacei = masterPatch.addressing()[cutToMasterFaces[i]];
775 
776  masterCutFaces.insert(meshFacei);
777  }
778 
779  DynamicList<label> workFace(100);
780 
781  forAll(from0ToAllFaces, face0)
782  {
783  if (!masterCutFaces.found(face0))
784  {
785  label allFacei = from0ToAllFaces[face0];
786 
787  insertVertices
788  (
789  cutEdgeToPoints,
790  masterPatch.meshPointMap(),
791  coupleInfo.masterToCutPoints(),
792  mesh0.faces()[face0],
793 
794  workFace,
795  allFaces[allFacei]
796  );
797  }
798  }
799 
800  // Same for slave face
801 
802  labelHashSet slaveCutFaces(cutToSlaveFaces.size());
803  forAll(cutToSlaveFaces, i)
804  {
805  label meshFacei = slavePatch.addressing()[cutToSlaveFaces[i]];
806 
807  slaveCutFaces.insert(meshFacei);
808  }
809 
810  forAll(from1ToAllFaces, face1)
811  {
812  if (!slaveCutFaces.found(face1))
813  {
814  label allFacei = from1ToAllFaces[face1];
815 
816  insertVertices
817  (
818  cutEdgeToPoints,
819  slavePatch.meshPointMap(),
820  coupleInfo.slaveToCutPoints(),
821  mesh1.faces()[face1],
822 
823  workFace,
824  allFaces[allFacei]
825  );
826  }
827  }
828  }
829 
830  // Now we have a full facelist and owner/neighbour addressing.
831 
832 
833  // Cells
834  // ~~~~~
835 
836  from1ToAllCells.setSize(mesh1.nCells());
837  from1ToAllCells = -1;
838 
839  forAll(mesh1.cells(), i)
840  {
841  from1ToAllCells[i] = i + mesh0.nCells();
842  }
843 
844  // Make cells (= cell-face addressing)
845  nCells = mesh0.nCells() + mesh1.nCells();
846  cellList allCells(nCells);
847  primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
848 
849  // Reorder faces for upper-triangular order.
850  labelList oldToNew
851  (
852  getFaceOrder
853  (
854  allCells,
855  nInternalFaces,
856  allOwner,
857  allNeighbour
858  )
859  );
860 
861  inplaceReorder(oldToNew, allFaces);
862  inplaceReorder(oldToNew, allOwner);
863  inplaceReorder(oldToNew, allNeighbour);
864  inplaceRenumber(oldToNew, from0ToAllFaces);
865  inplaceRenumber(oldToNew, from1ToAllFaces);
866 }
867 
868 
869 void Foam::polyMeshAdder::mergePointZones
870 (
871  const label nAllPoints,
872  const pointZoneMesh& pz0,
873  const pointZoneMesh& pz1,
874  const labelList& from0ToAllPoints,
875  const labelList& from1ToAllPoints,
876 
877  DynamicList<word>& zoneNames,
878  labelList& from1ToAll,
879  List<DynamicList<label>>& pzPoints
880 )
881 {
882  zoneNames.setCapacity(pz0.size() + pz1.size());
883  zoneNames.append(pz0.names());
884 
885  from1ToAll.setSize(pz1.size());
886 
887  forAll(pz1, zoneI)
888  {
889  from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
890  }
891  zoneNames.shrink();
892 
893 
894 
895  // Zone(s) per point. Two levels: if only one zone
896  // stored in pointToZone. Any extra stored in additionalPointToZones.
897  // This is so we only allocate labelLists per point if absolutely
898  // necessary.
899  labelList pointToZone(nAllPoints, -1);
900  labelListList addPointToZones(nAllPoints);
901 
902  // mesh0 zones kept
903  forAll(pz0, zoneI)
904  {
905  const pointZone& pz = pz0[zoneI];
906 
907  forAll(pz, i)
908  {
909  label point0 = pz[i];
910  label allPointi = from0ToAllPoints[point0];
911 
912  if (pointToZone[allPointi] == -1)
913  {
914  pointToZone[allPointi] = zoneI;
915  }
916  else if (pointToZone[allPointi] != zoneI)
917  {
918  labelList& pZones = addPointToZones[allPointi];
919  pZones.appendUniq(zoneI);
920  }
921  }
922  }
923 
924  // mesh1 zones renumbered
925  forAll(pz1, zoneI)
926  {
927  const pointZone& pz = pz1[zoneI];
928  const label allZoneI = from1ToAll[zoneI];
929 
930  forAll(pz, i)
931  {
932  label point1 = pz[i];
933  label allPointi = from1ToAllPoints[point1];
934 
935  if (pointToZone[allPointi] == -1)
936  {
937  pointToZone[allPointi] = allZoneI;
938  }
939  else if (pointToZone[allPointi] != allZoneI)
940  {
941  labelList& pZones = addPointToZones[allPointi];
942  pZones.appendUniq(allZoneI);
943  }
944  }
945  }
946 
947  // Extract back into zones
948 
949  // 1. Count
950  labelList nPoints(zoneNames.size(), Zero);
951  forAll(pointToZone, allPointi)
952  {
953  label zoneI = pointToZone[allPointi];
954  if (zoneI != -1)
955  {
956  nPoints[zoneI]++;
957  }
958  }
959  forAll(addPointToZones, allPointi)
960  {
961  const labelList& pZones = addPointToZones[allPointi];
962  forAll(pZones, i)
963  {
964  nPoints[pZones[i]]++;
965  }
966  }
967 
968  // 2. Fill
969  pzPoints.setSize(zoneNames.size());
970  forAll(pzPoints, zoneI)
971  {
972  pzPoints[zoneI].setCapacity(nPoints[zoneI]);
973  }
974  forAll(pointToZone, allPointi)
975  {
976  label zoneI = pointToZone[allPointi];
977  if (zoneI != -1)
978  {
979  pzPoints[zoneI].append(allPointi);
980  }
981  }
982  forAll(addPointToZones, allPointi)
983  {
984  const labelList& pZones = addPointToZones[allPointi];
985  forAll(pZones, i)
986  {
987  pzPoints[pZones[i]].append(allPointi);
988  }
989  }
990  forAll(pzPoints, i)
991  {
992  pzPoints[i].shrink();
993  stableSort(pzPoints[i]);
994  }
995 }
996 
997 
998 void Foam::polyMeshAdder::mergeFaceZones
999 (
1000  const labelList& allOwner,
1001 
1002  const polyMesh& mesh0,
1003  const polyMesh& mesh1,
1004 
1005  const labelList& from0ToAllFaces,
1006  const labelList& from1ToAllFaces,
1007 
1008  const labelList& from1ToAllCells,
1009 
1010  DynamicList<word>& zoneNames,
1011  labelList& from1ToAll,
1012  List<DynamicList<label>>& fzFaces,
1013  List<DynamicList<bool>>& fzFlips
1014 )
1015 {
1016  const faceZoneMesh& fz0 = mesh0.faceZones();
1017  const labelList& owner0 = mesh0.faceOwner();
1018  const faceZoneMesh& fz1 = mesh1.faceZones();
1019  const labelList& owner1 = mesh1.faceOwner();
1020 
1021 
1022  zoneNames.setCapacity(fz0.size() + fz1.size());
1023  zoneNames.append(fz0.names());
1024 
1025  from1ToAll.setSize(fz1.size());
1026 
1027  forAll(fz1, zoneI)
1028  {
1029  from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
1030  }
1031  zoneNames.shrink();
1032 
1033 
1034  // Zone(s) per face
1035  labelList faceToZone(allOwner.size(), -1);
1036  labelListList addFaceToZones(allOwner.size());
1037  boolList faceToFlip(allOwner.size(), false);
1038  boolListList addFaceToFlips(allOwner.size());
1039 
1040  // mesh0 zones kept
1041  forAll(fz0, zoneI)
1042  {
1043  const labelList& addressing = fz0[zoneI];
1044  const boolList& flipMap = fz0[zoneI].flipMap();
1045 
1046  forAll(addressing, i)
1047  {
1048  label face0 = addressing[i];
1049  bool flip0 = flipMap[i];
1050 
1051  label allFacei = from0ToAllFaces[face0];
1052  if (allFacei != -1)
1053  {
1054  // Check if orientation same
1055  label allCell0 = owner0[face0];
1056  if (allOwner[allFacei] != allCell0)
1057  {
1058  flip0 = !flip0;
1059  }
1060 
1061  if (faceToZone[allFacei] == -1)
1062  {
1063  faceToZone[allFacei] = zoneI;
1064  faceToFlip[allFacei] = flip0;
1065  }
1066  else if (faceToZone[allFacei] != zoneI)
1067  {
1068  labelList& fZones = addFaceToZones[allFacei];
1069  boolList& flipZones = addFaceToFlips[allFacei];
1070 
1071  if (fZones.appendUniq(zoneI))
1072  {
1073  flipZones.append(flip0);
1074  }
1075  }
1076  }
1077  }
1078  }
1079 
1080  // mesh1 zones renumbered
1081  forAll(fz1, zoneI)
1082  {
1083  const labelList& addressing = fz1[zoneI];
1084  const boolList& flipMap = fz1[zoneI].flipMap();
1085 
1086  const label allZoneI = from1ToAll[zoneI];
1087 
1088  forAll(addressing, i)
1089  {
1090  label face1 = addressing[i];
1091  bool flip1 = flipMap[i];
1092 
1093  label allFacei = from1ToAllFaces[face1];
1094  if (allFacei != -1)
1095  {
1096  // Check if orientation same
1097  label allCell1 = from1ToAllCells[owner1[face1]];
1098  if (allOwner[allFacei] != allCell1)
1099  {
1100  flip1 = !flip1;
1101  }
1102 
1103  if (faceToZone[allFacei] == -1)
1104  {
1105  faceToZone[allFacei] = allZoneI;
1106  faceToFlip[allFacei] = flip1;
1107  }
1108  else if (faceToZone[allFacei] != allZoneI)
1109  {
1110  labelList& fZones = addFaceToZones[allFacei];
1111  boolList& flipZones = addFaceToFlips[allFacei];
1112 
1113  if (fZones.appendUniq(allZoneI))
1114  {
1115  flipZones.append(flip1);
1116  }
1117  }
1118  }
1119  }
1120  }
1121 
1122 
1123  // Extract back into zones
1124 
1125  // 1. Count
1126  labelList nFaces(zoneNames.size(), Zero);
1127  forAll(faceToZone, allFacei)
1128  {
1129  label zoneI = faceToZone[allFacei];
1130  if (zoneI != -1)
1131  {
1132  nFaces[zoneI]++;
1133  }
1134  }
1135  forAll(addFaceToZones, allFacei)
1136  {
1137  const labelList& fZones = addFaceToZones[allFacei];
1138  forAll(fZones, i)
1139  {
1140  nFaces[fZones[i]]++;
1141  }
1142  }
1143 
1144  // 2. Fill
1145  fzFaces.setSize(zoneNames.size());
1146  fzFlips.setSize(zoneNames.size());
1147  forAll(fzFaces, zoneI)
1148  {
1149  fzFaces[zoneI].setCapacity(nFaces[zoneI]);
1150  fzFlips[zoneI].setCapacity(nFaces[zoneI]);
1151  }
1152  forAll(faceToZone, allFacei)
1153  {
1154  label zoneI = faceToZone[allFacei];
1155  bool flip = faceToFlip[allFacei];
1156  if (zoneI != -1)
1157  {
1158  fzFaces[zoneI].append(allFacei);
1159  fzFlips[zoneI].append(flip);
1160  }
1161  }
1162  forAll(addFaceToZones, allFacei)
1163  {
1164  const labelList& fZones = addFaceToZones[allFacei];
1165  const boolList& flipZones = addFaceToFlips[allFacei];
1166 
1167  forAll(fZones, i)
1168  {
1169  label zoneI = fZones[i];
1170  fzFaces[zoneI].append(allFacei);
1171  fzFlips[zoneI].append(flipZones[i]);
1172  }
1173  }
1174 
1175  forAll(fzFaces, i)
1176  {
1177  fzFaces[i].shrink();
1178  fzFlips[i].shrink();
1179 
1180  labelList order(sortedOrder(fzFaces[i]));
1181 
1182  fzFaces[i] = labelUIndList(fzFaces[i], order)();
1183  fzFlips[i] = boolUIndList(fzFlips[i], order)();
1184  }
1185 }
1186 
1187 
1188 void Foam::polyMeshAdder::mergeCellZones
1189 (
1190  const label nAllCells,
1191 
1192  const cellZoneMesh& cz0,
1193  const cellZoneMesh& cz1,
1194  const labelList& from1ToAllCells,
1195 
1196  DynamicList<word>& zoneNames,
1197  labelList& from1ToAll,
1198  List<DynamicList<label>>& czCells
1199 )
1200 {
1201  zoneNames.setCapacity(cz0.size() + cz1.size());
1202  zoneNames.append(cz0.names());
1203 
1204  from1ToAll.setSize(cz1.size());
1205  forAll(cz1, zoneI)
1206  {
1207  from1ToAll[zoneI] = zoneIndex(cz1[zoneI].name(), zoneNames);
1208  }
1209  zoneNames.shrink();
1210 
1211 
1212  // Zone(s) per cell. Two levels: if only one zone
1213  // stored in cellToZone. Any extra stored in additionalCellToZones.
1214  // This is so we only allocate labelLists per cell if absolutely
1215  // necessary.
1216  labelList cellToZone(nAllCells, -1);
1217  labelListList addCellToZones(nAllCells);
1218 
1219  // mesh0 zones kept
1220  forAll(cz0, zoneI)
1221  {
1222  const cellZone& cz = cz0[zoneI];
1223  forAll(cz, i)
1224  {
1225  label cell0 = cz[i];
1226 
1227  if (cellToZone[cell0] == -1)
1228  {
1229  cellToZone[cell0] = zoneI;
1230  }
1231  else if (cellToZone[cell0] != zoneI)
1232  {
1233  labelList& cZones = addCellToZones[cell0];
1234  cZones.appendUniq(zoneI);
1235  }
1236  }
1237  }
1238 
1239  // mesh1 zones renumbered
1240  forAll(cz1, zoneI)
1241  {
1242  const cellZone& cz = cz1[zoneI];
1243  const label allZoneI = from1ToAll[zoneI];
1244  forAll(cz, i)
1245  {
1246  label cell1 = cz[i];
1247  label allCelli = from1ToAllCells[cell1];
1248 
1249  if (cellToZone[allCelli] == -1)
1250  {
1251  cellToZone[allCelli] = allZoneI;
1252  }
1253  else if (cellToZone[allCelli] != allZoneI)
1254  {
1255  labelList& cZones = addCellToZones[allCelli];
1256  cZones.appendUniq(allZoneI);
1257  }
1258  }
1259  }
1260 
1261  // Extract back into zones
1262 
1263  // 1. Count
1264  labelList nCells(zoneNames.size(), Zero);
1265  forAll(cellToZone, allCelli)
1266  {
1267  label zoneI = cellToZone[allCelli];
1268  if (zoneI != -1)
1269  {
1270  nCells[zoneI]++;
1271  }
1272  }
1273  forAll(addCellToZones, allCelli)
1274  {
1275  const labelList& cZones = addCellToZones[allCelli];
1276  forAll(cZones, i)
1277  {
1278  nCells[cZones[i]]++;
1279  }
1280  }
1281 
1282  // 2. Fill
1283  czCells.setSize(zoneNames.size());
1284  forAll(czCells, zoneI)
1285  {
1286  czCells[zoneI].setCapacity(nCells[zoneI]);
1287  }
1288  forAll(cellToZone, allCelli)
1289  {
1290  label zoneI = cellToZone[allCelli];
1291  if (zoneI != -1)
1292  {
1293  czCells[zoneI].append(allCelli);
1294  }
1295  }
1296  forAll(addCellToZones, allCelli)
1297  {
1298  const labelList& cZones = addCellToZones[allCelli];
1299  forAll(cZones, i)
1300  {
1301  czCells[cZones[i]].append(allCelli);
1302  }
1303  }
1304  forAll(czCells, i)
1305  {
1306  czCells[i].shrink();
1307  stableSort(czCells[i]);
1308  }
1309 }
1310 
1311 
1312 void Foam::polyMeshAdder::mergeZones
1313 (
1314  const label nAllPoints,
1315  const labelList& allOwner,
1316  const label nAllCells,
1317 
1318  const polyMesh& mesh0,
1319  const polyMesh& mesh1,
1320  const labelList& from0ToAllPoints,
1321  const labelList& from0ToAllFaces,
1322 
1323  const labelList& from1ToAllPoints,
1324  const labelList& from1ToAllFaces,
1325  const labelList& from1ToAllCells,
1326 
1327  DynamicList<word>& pointZoneNames,
1328  List<DynamicList<label>>& pzPoints,
1329 
1330  DynamicList<word>& faceZoneNames,
1331  List<DynamicList<label>>& fzFaces,
1332  List<DynamicList<bool>>& fzFlips,
1333 
1334  DynamicList<word>& cellZoneNames,
1335  List<DynamicList<label>>& czCells
1336 )
1337 {
1338  labelList from1ToAllPZones;
1339  mergePointZones
1340  (
1341  nAllPoints,
1342  mesh0.pointZones(),
1343  mesh1.pointZones(),
1344  from0ToAllPoints,
1345  from1ToAllPoints,
1346 
1347  pointZoneNames,
1348  from1ToAllPZones,
1349  pzPoints
1350  );
1351 
1352  labelList from1ToAllFZones;
1353  mergeFaceZones
1354  (
1355  allOwner,
1356  mesh0,
1357  mesh1,
1358  from0ToAllFaces,
1359  from1ToAllFaces,
1360  from1ToAllCells,
1361 
1362  faceZoneNames,
1363  from1ToAllFZones,
1364  fzFaces,
1365  fzFlips
1366  );
1367 
1368  labelList from1ToAllCZones;
1369  mergeCellZones
1370  (
1371  nAllCells,
1372  mesh0.cellZones(),
1373  mesh1.cellZones(),
1374  from1ToAllCells,
1375 
1376  cellZoneNames,
1377  from1ToAllCZones,
1378  czCells
1379  );
1380 }
1381 
1382 
1383 void Foam::polyMeshAdder::addZones
1384 (
1385  const DynamicList<word>& pointZoneNames,
1386  const List<DynamicList<label>>& pzPoints,
1387 
1388  const DynamicList<word>& faceZoneNames,
1389  const List<DynamicList<label>>& fzFaces,
1390  const List<DynamicList<bool>>& fzFlips,
1391 
1392  const DynamicList<word>& cellZoneNames,
1393  const List<DynamicList<label>>& czCells,
1394 
1395  polyMesh& mesh
1396 )
1397 {
1398  List<pointZone*> pZones(pzPoints.size());
1399  forAll(pZones, i)
1400  {
1401  pZones[i] = new pointZone
1402  (
1403  pointZoneNames[i],
1404  pzPoints[i],
1405  i,
1406  mesh.pointZones()
1407  );
1408  }
1409 
1410  List<faceZone*> fZones(fzFaces.size());
1411  forAll(fZones, i)
1412  {
1413  fZones[i] = new faceZone
1414  (
1415  faceZoneNames[i],
1416  fzFaces[i],
1417  fzFlips[i],
1418  i,
1419  mesh.faceZones()
1420  );
1421  }
1422 
1423  List<cellZone*> cZones(czCells.size());
1424  forAll(cZones, i)
1425  {
1426  cZones[i] = new cellZone
1427  (
1428  cellZoneNames[i],
1429  czCells[i],
1430  i,
1431  mesh.cellZones()
1432  );
1433  }
1434 
1435  mesh.addZones
1436  (
1437  pZones,
1438  fZones,
1439  cZones
1440  );
1441 }
1442 
1443 
1444 
1445 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1446 
1447 // Returns new mesh and sets
1448 // - map from new cell/face/point/patch to either mesh0 or mesh1
1449 //
1450 // mesh0Faces/mesh1Faces: corresponding faces on both meshes.
1452 (
1453  const IOobject& io,
1454  const polyMesh& mesh0,
1455  const polyMesh& mesh1,
1456  const faceCoupleInfo& coupleInfo,
1458 )
1459 {
1460  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1461  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1462 
1463 
1464  DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1465  DynamicList<word> allPatchTypes(allPatchNames.size());
1466 
1467  // Patch maps
1468  labelList from1ToAllPatches(patches1.size());
1469  labelList fromAllTo1Patches(allPatchNames.size(), -1);
1470 
1471  mergePatchNames
1472  (
1473  patches0,
1474  patches1,
1475  allPatchNames,
1476  allPatchTypes,
1477  from1ToAllPatches,
1478  fromAllTo1Patches
1479  );
1480 
1481 
1482  // New points
1484 
1485  // Map from mesh0/1 points to allPoints.
1486  labelList from0ToAllPoints(mesh0.nPoints(), -1);
1487  labelList from1ToAllPoints(mesh1.nPoints(), -1);
1488 
1489  // New faces
1490  faceList allFaces;
1491  label nInternalFaces;
1492 
1493  // New cells
1494  labelList allOwner;
1495  labelList allNeighbour;
1496  label nCells;
1497 
1498  // Sizes per patch
1499  labelList nFaces(allPatchNames.size(), Zero);
1500 
1501  // Maps
1502  labelList from0ToAllFaces(mesh0.nFaces(), -1);
1503  labelList from1ToAllFaces(mesh1.nFaces(), -1);
1504 
1505  // Map
1506  labelList from1ToAllCells(mesh1.nCells(), -1);
1507 
1508  mergePrimitives
1509  (
1510  mesh0,
1511  mesh1,
1512  coupleInfo,
1513 
1514  allPatchNames.size(),
1515  fromAllTo1Patches,
1516  from1ToAllPatches,
1517 
1518  allPoints,
1519  from0ToAllPoints,
1520  from1ToAllPoints,
1521 
1522  allFaces,
1523  allOwner,
1524  allNeighbour,
1525  nInternalFaces,
1526  nFaces,
1527  nCells,
1528 
1529  from0ToAllFaces,
1530  from1ToAllFaces,
1531  from1ToAllCells
1532  );
1533 
1534 
1535  // Zones
1536  // ~~~~~
1537 
1538  DynamicList<word> pointZoneNames;
1539  List<DynamicList<label>> pzPoints;
1540 
1541  DynamicList<word> faceZoneNames;
1542  List<DynamicList<label>> fzFaces;
1543  List<DynamicList<bool>> fzFlips;
1544 
1545  DynamicList<word> cellZoneNames;
1546  List<DynamicList<label>> czCells;
1547 
1548  mergeZones
1549  (
1550  allPoints.size(),
1551  allOwner,
1552  nCells,
1553 
1554  mesh0,
1555  mesh1,
1556 
1557  from0ToAllPoints,
1558  from0ToAllFaces,
1559 
1560  from1ToAllPoints,
1561  from1ToAllFaces,
1562  from1ToAllCells,
1563 
1564  pointZoneNames,
1565  pzPoints,
1566 
1567  faceZoneNames,
1568  fzFaces,
1569  fzFlips,
1570 
1571  cellZoneNames,
1572  czCells
1573  );
1574 
1575 
1576  // Patches
1577  // ~~~~~~~
1578 
1579  // Map from 0 to all patches (since gets compacted)
1580  labelList from0ToAllPatches(patches0.size(), -1);
1581 
1582  List<polyPatch*> allPatches
1583  (
1584  combinePatches
1585  (
1586  mesh0,
1587  mesh1,
1588  patches0, // Should be boundaryMesh() on new mesh.
1589  allPatchNames.size(),
1590  fromAllTo1Patches,
1591  mesh0.nInternalFaces()
1592  + mesh1.nInternalFaces()
1593  + coupleInfo.cutFaces().size(),
1594  nFaces,
1595 
1596  from0ToAllPatches,
1597  from1ToAllPatches
1598  )
1599  );
1600 
1601 
1602  // Map information
1603  // ~~~~~~~~~~~~~~~
1604 
1605  mapPtr.reset
1606  (
1607  new mapAddedPolyMesh
1608  (
1609  mesh0.nPoints(),
1610  mesh0.nFaces(),
1611  mesh0.nCells(),
1612 
1613  mesh1.nPoints(),
1614  mesh1.nFaces(),
1615  mesh1.nCells(),
1616 
1617  from0ToAllPoints,
1618  from0ToAllFaces,
1619  identity(mesh0.nCells()),
1620 
1621  from1ToAllPoints,
1622  from1ToAllFaces,
1623  from1ToAllCells,
1624 
1625  from0ToAllPatches,
1626  from1ToAllPatches,
1627  getPatchSizes(patches0),
1628  getPatchStarts(patches0)
1629  )
1630  );
1631 
1632 
1633 
1634  // Now we have extracted all information from all meshes.
1635  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1636 
1637  // Construct mesh
1639  (
1640  io,
1641  std::move(allPoints),
1642  std::move(allFaces),
1643  std::move(allOwner),
1644  std::move(allNeighbour)
1645  );
1646  polyMesh& mesh = *meshPtr;
1647 
1648  // Add zones to new mesh.
1649  addZones
1650  (
1651  pointZoneNames,
1652  pzPoints,
1653 
1654  faceZoneNames,
1655  fzFaces,
1656  fzFlips,
1657 
1658  cellZoneNames,
1659  czCells,
1660  mesh
1661  );
1662 
1663  // Add patches to new mesh
1664  mesh.addPatches(allPatches);
1666  return meshPtr;
1667 }
1668 
1669 
1670 // Inplace add mesh1 to mesh0
1672 (
1673  polyMesh& mesh0,
1674  const polyMesh& mesh1,
1675  const faceCoupleInfo& coupleInfo,
1676  const bool validBoundary
1677 )
1678 {
1679  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1680  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1681 
1682  DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1683  DynamicList<word> allPatchTypes(allPatchNames.size());
1684 
1685  // Patch maps
1686  labelList from1ToAllPatches(patches1.size());
1687  labelList fromAllTo1Patches(allPatchNames.size(), -1);
1688 
1689  mergePatchNames
1690  (
1691  patches0,
1692  patches1,
1693  allPatchNames,
1694  allPatchTypes,
1695  from1ToAllPatches,
1696  fromAllTo1Patches
1697  );
1698 
1699 
1700  // New points
1702 
1703  // Map from mesh0/1 points to allPoints.
1704  labelList from0ToAllPoints(mesh0.nPoints(), -1);
1705  labelList from1ToAllPoints(mesh1.nPoints(), -1);
1706 
1707  // New faces
1708  faceList allFaces;
1709  labelList allOwner;
1710  labelList allNeighbour;
1711  label nInternalFaces;
1712  // Sizes per patch
1713  labelList nFaces(allPatchNames.size(), Zero);
1714  label nCells;
1715 
1716  // Maps
1717  labelList from0ToAllFaces(mesh0.nFaces(), -1);
1718  labelList from1ToAllFaces(mesh1.nFaces(), -1);
1719  // Map
1720  labelList from1ToAllCells(mesh1.nCells(), -1);
1721 
1722  mergePrimitives
1723  (
1724  mesh0,
1725  mesh1,
1726  coupleInfo,
1727 
1728  allPatchNames.size(),
1729  fromAllTo1Patches,
1730  from1ToAllPatches,
1731 
1732  allPoints,
1733  from0ToAllPoints,
1734  from1ToAllPoints,
1735 
1736  allFaces,
1737  allOwner,
1738  allNeighbour,
1739  nInternalFaces,
1740  nFaces,
1741  nCells,
1742 
1743  from0ToAllFaces,
1744  from1ToAllFaces,
1745  from1ToAllCells
1746  );
1747 
1748 
1749  // Zones
1750  // ~~~~~
1751 
1752  DynamicList<word> pointZoneNames;
1753  List<DynamicList<label>> pzPoints;
1754 
1755  DynamicList<word> faceZoneNames;
1756  List<DynamicList<label>> fzFaces;
1757  List<DynamicList<bool>> fzFlips;
1758 
1759  DynamicList<word> cellZoneNames;
1760  List<DynamicList<label>> czCells;
1761 
1762  mergeZones
1763  (
1764  allPoints.size(),
1765  allOwner,
1766  nCells,
1767 
1768  mesh0,
1769  mesh1,
1770 
1771  from0ToAllPoints,
1772  from0ToAllFaces,
1773 
1774  from1ToAllPoints,
1775  from1ToAllFaces,
1776  from1ToAllCells,
1777 
1778  pointZoneNames,
1779  pzPoints,
1780 
1781  faceZoneNames,
1782  fzFaces,
1783  fzFlips,
1784 
1785  cellZoneNames,
1786  czCells
1787  );
1788 
1789 
1790  // Patches
1791  // ~~~~~~~
1792 
1793 
1794  // Store mesh0 patch info before modifying patches0.
1795  labelList mesh0PatchSizes(getPatchSizes(patches0));
1796  labelList mesh0PatchStarts(getPatchStarts(patches0));
1797 
1798  // Map from 0 to all patches (since gets compacted)
1799  labelList from0ToAllPatches(patches0.size(), -1);
1800 
1801  // Inplace extend mesh0 patches (note that patches0.size() now also
1802  // has changed)
1803  polyBoundaryMesh& allPatches =
1804  const_cast<polyBoundaryMesh&>(mesh0.boundaryMesh());
1805  allPatches.setSize(allPatchNames.size());
1806  labelList patchSizes(allPatches.size());
1807  labelList patchStarts(allPatches.size());
1808 
1809  label startFacei = nInternalFaces;
1810 
1811  // Copy patches0 with new sizes. First patches always come from
1812  // mesh0 and will always be present.
1813  label allPatchi = 0;
1814 
1815  forAll(from0ToAllPatches, patch0)
1816  {
1817  // Originates from mesh0. Clone with new size & filter out empty
1818  // patch.
1819 
1820  if (nFaces[patch0] == 0 && isA<processorPolyPatch>(allPatches[patch0]))
1821  {
1822  //Pout<< "Removing zero sized mesh0 patch " << allPatchNames[patch0]
1823  // << endl;
1824  from0ToAllPatches[patch0] = -1;
1825  // Check if patch was also in mesh1 and update its addressing if so.
1826  if (fromAllTo1Patches[patch0] != -1)
1827  {
1828  from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
1829  }
1830  }
1831  else
1832  {
1833  // Clone. Note dummy size and start. Gets overwritten later in
1834  // resetPrimitives. This avoids getting temporarily illegal
1835  // SubList construction in polyPatch.
1836  allPatches.set
1837  (
1838  allPatchi,
1839  allPatches[patch0].clone
1840  (
1841  allPatches,
1842  allPatchi,
1843  0, // dummy size
1844  0 // dummy start
1845  )
1846  );
1847  patchSizes[allPatchi] = nFaces[patch0];
1848  patchStarts[allPatchi] = startFacei;
1849 
1850  // Record new index in allPatches
1851  from0ToAllPatches[patch0] = allPatchi;
1852 
1853  // Check if patch was also in mesh1 and update its addressing if so.
1854  if (fromAllTo1Patches[patch0] != -1)
1855  {
1856  from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchi;
1857  }
1858 
1859  startFacei += nFaces[patch0];
1860 
1861  allPatchi++;
1862  }
1863  }
1864 
1865  // Copy unique patches of mesh1.
1866  forAll(from1ToAllPatches, patch1)
1867  {
1868  label uncompactAllPatchi = from1ToAllPatches[patch1];
1869 
1870  if (uncompactAllPatchi >= from0ToAllPatches.size())
1871  {
1872  // Patch has not been merged with any mesh0 patch.
1873 
1874  if
1875  (
1876  nFaces[uncompactAllPatchi] == 0
1877  && isA<processorPolyPatch>(patches1[patch1])
1878  )
1879  {
1880  //Pout<< "Removing zero sized mesh1 patch "
1881  // << allPatchNames[uncompactAllPatchi] << endl;
1882  from1ToAllPatches[patch1] = -1;
1883  }
1884  else
1885  {
1886  // Clone.
1887  allPatches.set
1888  (
1889  allPatchi,
1890  patches1[patch1].clone
1891  (
1892  allPatches,
1893  allPatchi,
1894  0, // dummy size
1895  0 // dummy start
1896  )
1897  );
1898  patchSizes[allPatchi] = nFaces[uncompactAllPatchi];
1899  patchStarts[allPatchi] = startFacei;
1900 
1901  // Record new index in allPatches
1902  from1ToAllPatches[patch1] = allPatchi;
1903 
1904  startFacei += nFaces[uncompactAllPatchi];
1905 
1906  allPatchi++;
1907  }
1908  }
1909  }
1910 
1911  allPatches.setSize(allPatchi);
1912  patchSizes.setSize(allPatchi);
1913  patchStarts.setSize(allPatchi);
1914 
1915 
1916  // Construct map information before changing mesh0 primitives
1917  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1918 
1919  autoPtr<mapAddedPolyMesh> mapPtr
1920  (
1921  new mapAddedPolyMesh
1922  (
1923  mesh0.nPoints(),
1924  mesh0.nFaces(),
1925  mesh0.nCells(),
1926 
1927  mesh1.nPoints(),
1928  mesh1.nFaces(),
1929  mesh1.nCells(),
1930 
1931  from0ToAllPoints,
1932  from0ToAllFaces,
1933  identity(mesh0.nCells()),
1934 
1935  from1ToAllPoints,
1936  from1ToAllFaces,
1937  from1ToAllCells,
1938 
1939  from0ToAllPatches,
1940  from1ToAllPatches,
1941 
1942  mesh0PatchSizes,
1943  mesh0PatchStarts
1944  )
1945  );
1946 
1947 
1948 
1949  // Now we have extracted all information from all meshes.
1950  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1951 
1952  mesh0.resetMotion(); // delete any oldPoints.
1953  mesh0.resetPrimitives
1954  (
1955  autoPtr<pointField>::New(std::move(allPoints)),
1956  autoPtr<faceList>::New(std::move(allFaces)),
1957  autoPtr<labelList>::New(std::move(allOwner)),
1958  autoPtr<labelList>::New(std::move(allNeighbour)),
1959  patchSizes, // size
1960  patchStarts, // patchstarts
1961  validBoundary // boundary valid?
1962  );
1963 
1964  // Add zones to new mesh.
1965  mesh0.pointZones().clear();
1966  mesh0.faceZones().clear();
1967  mesh0.cellZones().clear();
1968  addZones
1969  (
1970  pointZoneNames,
1971  pzPoints,
1972 
1973  faceZoneNames,
1974  fzFaces,
1975  fzFlips,
1976 
1977  cellZoneNames,
1978  czCells,
1979  mesh0
1980  );
1981 
1982  return mapPtr;
1983 }
1984 
1985 
1987 (
1988  const polyMesh& mesh,
1989  const scalar mergeDist
1990 )
1991 {
1992  const labelList& sharedPointLabels = mesh.globalData().sharedPointLabels();
1993  const labelList& sharedPointAddr = mesh.globalData().sharedPointAddr();
1994 
1995  // Because of adding the missing pieces e.g. when redistributing a mesh
1996  // it can be that there are multiple points on the same processor that
1997  // refer to the same shared point.
1998 
1999  // Invert point-to-shared addressing
2000  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2001 
2002  Map<labelList> sharedToMesh(sharedPointLabels.size());
2003 
2004  label nMultiple = 0;
2005 
2006  forAll(sharedPointLabels, i)
2007  {
2008  label pointi = sharedPointLabels[i];
2009 
2010  label sharedI = sharedPointAddr[i];
2011 
2012  auto iter = sharedToMesh.find(sharedI);
2013 
2014  if (iter.found())
2015  {
2016  // sharedI already used by other point. Add this one.
2017 
2018  nMultiple++;
2019 
2020  labelList& connectedPointLabels = iter.val();
2021 
2022  label sz = connectedPointLabels.size();
2023 
2024  // Check just to make sure.
2025  if (connectedPointLabels.found(pointi))
2026  {
2028  << "Duplicate point in sharedPoint addressing." << endl
2029  << "When trying to add point " << pointi << " on shared "
2030  << sharedI << " with connected points "
2031  << connectedPointLabels
2032  << abort(FatalError);
2033  }
2034 
2035  connectedPointLabels.setSize(sz+1);
2036  connectedPointLabels[sz] = pointi;
2037  }
2038  else
2039  {
2040  sharedToMesh.insert(sharedI, labelList(1, pointi));
2041  }
2042  }
2043 
2044 
2045  // Assign single master for every shared with multiple geometric points
2046  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2047 
2048  Map<label> pointToMaster(nMultiple);
2049 
2050  forAllConstIters(sharedToMesh, iter)
2051  {
2052  const labelList& connectedPointLabels = iter.val();
2053 
2054  //Pout<< "For shared:" << iter.key()
2055  // << " found points:" << connectedPointLabels
2056  // << " at coords:"
2057  // << pointField(mesh.points(), connectedPointLabels) << endl;
2058 
2059  if (connectedPointLabels.size() > 1)
2060  {
2061  const pointField connectedPoints
2062  (
2063  mesh.points(),
2064  connectedPointLabels
2065  );
2066 
2067  labelList toMergedPoints;
2068  label nUnique = Foam::mergePoints
2069  (
2070  connectedPoints,
2071  mergeDist,
2072  false,
2073  toMergedPoints
2074  );
2075 
2076  if (nUnique < connectedPoints.size())
2077  {
2078  // Invert toMergedPoints
2079  const labelListList mergeSets
2080  (
2082  (
2083  nUnique,
2084  toMergedPoints
2085  )
2086  );
2087 
2088  // Find master for valid merges
2089  forAll(mergeSets, setI)
2090  {
2091  const labelList& mergeSet = mergeSets[setI];
2092 
2093  if (mergeSet.size() > 1)
2094  {
2095  // Pick lowest numbered point
2096  label masterPointi = labelMax;
2097 
2098  forAll(mergeSet, i)
2099  {
2100  label pointi = connectedPointLabels[mergeSet[i]];
2101 
2102  masterPointi = min(masterPointi, pointi);
2103  }
2104 
2105  forAll(mergeSet, i)
2106  {
2107  label pointi = connectedPointLabels[mergeSet[i]];
2108 
2109  //Pout<< "Merging point " << pointi
2110  // << " at " << mesh.points()[pointi]
2111  // << " into master point " << masterPointi
2112  // << " at " << mesh.points()[masterPointi]
2113  // << endl;
2114 
2115  pointToMaster.insert(pointi, masterPointi);
2116  }
2117  }
2118  }
2119  }
2120  }
2121  }
2122 
2123  //- Old: geometric merging. Causes problems for two close shared points.
2124  //labelList sharedToMerged;
2125  //label nUnique = Foam::mergePoints
2126  //(
2127  // UIndirectList<point>(mesh.points(), sharedPointLabels),
2128  // mergeDist,
2129  // false,
2130  // sharedToMerged
2131  //);
2132  //
2135  //
2136  //Map<label> pointToMaster(10*sharedToMerged.size());
2137  //
2138  //if (nUnique < sharedPointLabels.size())
2139  //{
2140  // labelListList mergeSets
2141  // (
2142  // invertOneToMany
2143  // (
2144  // sharedToMerged.size(),
2145  // sharedToMerged
2146  // )
2147  // );
2148  //
2149  // label nMergeSets = 0;
2150  //
2151  // forAll(mergeSets, setI)
2152  // {
2153  // const labelList& mergeSet = mergeSets[setI];
2154  //
2155  // if (mergeSet.size() > 1)
2156  // {
2157  // // Take as master the shared point with the lowest mesh
2158  // // point label. (rather arbitrarily - could use max or
2159  // // any other one of the points)
2160  //
2161  // nMergeSets++;
2162  //
2163  // label masterI = labelMax;
2164  //
2165  // forAll(mergeSet, i)
2166  // {
2167  // label sharedI = mergeSet[i];
2168  //
2169  // masterI = min(masterI, sharedPointLabels[sharedI]);
2170  // }
2171  //
2172  // forAll(mergeSet, i)
2173  // {
2174  // label sharedI = mergeSet[i];
2175  //
2176  // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
2177  // }
2178  // }
2179  // }
2180  //
2181  // //if (debug)
2182  // //{
2183  // // Pout<< "polyMeshAdder : merging:"
2184  // // << pointToMaster.size() << " into " << nMergeSets
2185  // // << " sets." << endl;
2186  // //}
2187  //}
2188 
2189  return pointToMaster;
2191 
2192 
2194 (
2195  const polyMesh& mesh,
2196  const Map<label>& pointToMaster,
2197  polyTopoChange& meshMod
2198 )
2199 {
2200  // Remove all non-master points.
2201  forAll(mesh.points(), pointi)
2202  {
2203  const auto iter = pointToMaster.cfind(pointi);
2204 
2205  if (iter.found())
2206  {
2207  if (iter.val() != pointi)
2208  {
2209  meshMod.removePoint(pointi, iter.val());
2210  }
2211  }
2212  }
2213 
2214  // Modify faces for points. Note: could use pointFaces here but want to
2215  // avoid addressing calculation.
2216  const faceList& faces = mesh.faces();
2217 
2218  forAll(faces, facei)
2219  {
2220  const face& f = faces[facei];
2221 
2222  bool hasMerged = false;
2223 
2224  forAll(f, fp)
2225  {
2226  label pointi = f[fp];
2227 
2228  const auto iter = pointToMaster.cfind(pointi);
2229 
2230  if (iter.found())
2231  {
2232  if (iter.val() != pointi)
2233  {
2234  hasMerged = true;
2235  break;
2236  }
2237  }
2238  }
2239 
2240  if (hasMerged)
2241  {
2242  face newF(f);
2243 
2244  forAll(f, fp)
2245  {
2246  label pointi = f[fp];
2247 
2248  const auto iter = pointToMaster.cfind(pointi);
2249 
2250  if (iter.found())
2251  {
2252  newF[fp] = iter.val();
2253  }
2254  }
2255 
2256  label patchID = mesh.boundaryMesh().whichPatch(facei);
2257  label nei = (patchID == -1 ? mesh.faceNeighbour()[facei] : -1);
2258  label zoneID = mesh.faceZones().whichZone(facei);
2259  bool zoneFlip = false;
2260 
2261  if (zoneID >= 0)
2262  {
2263  const faceZone& fZone = mesh.faceZones()[zoneID];
2264  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
2265  }
2266 
2267  meshMod.setAction
2268  (
2269  polyModifyFace
2270  (
2271  newF, // modified face
2272  facei, // label of face
2273  mesh.faceOwner()[facei], // owner
2274  nei, // neighbour
2275  false, // face flip
2276  patchID, // patch for face
2277  false, // remove from zone
2278  zoneID, // zone for face
2279  zoneFlip // face flip in zone
2280  )
2281  );
2282  }
2283  }
2284 }
2285 
2286 
2287 Foam::label Foam::polyMeshAdder::procPatchIndex
2288 (
2289  const polyBoundaryMesh& pbm,
2290  const label nbrProci,
2291  const label n
2292 )
2293 {
2294  // Find n'th processor patch going to nbrProci. Usually n=0 but in some
2295  // cases (e.g. processorCyclic, implicit cht) there can be more than one
2296  // processor patch between two processors.
2297 
2298  label index = n;
2299 
2300  for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++)
2301  {
2302  const processorPolyPatch& pp =
2303  refCast<const processorPolyPatch>(pbm[patchi]);
2304  if (pp.neighbProcNo() == nbrProci)
2305  {
2306  if (index == 0)
2307  {
2308  return patchi;
2309  }
2310  else
2311  {
2312  --index;
2313  }
2314  }
2315  }
2316 
2317  FatalErrorInFunction << "no patch found to processor " << nbrProci
2318  << ". Current patches:" << pbm.names() << exit(FatalError);
2319  return -1;
2321 
2322 
2324 (
2325  const UPtrList<polyMesh>& meshes,
2326  List<DynamicList<label>>& localPatch,
2327  List<DynamicList<label>>& remoteProc,
2328  List<DynamicList<label>>& remotePatch
2329  //List<labelListList>& remotePatchFace,
2330  //List<labelListList>& remotePatchFaceStart
2331 )
2332 {
2333  // Determine pairs of processor patches:
2334  // - remote processor
2335  // - patch on remote processor
2336  // - face on remote patch
2337  // - starting index on remote face
2338  localPatch.setSize(meshes.size());
2339  remoteProc.setSize(meshes.size());
2340  remotePatch.setSize(meshes.size());
2341  //remotePatchFace.setSize(meshes.size());
2342  //remotePatchFaceStart.setSize(meshes.size());
2343 
2344 
2345  // Check that all processors have the same globalPatches
2346  {
2347  const polyBoundaryMesh& pbm = meshes[0].boundaryMesh();
2348  const wordList names0(SubList<word>(pbm.names(), pbm.nNonProcessor()));
2349  for (label proci = 1; proci < meshes.size(); proci++)
2350  {
2351  const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2352  const wordList names(pbm.names());
2353 
2354  if (SubList<word>(names, pbm.nNonProcessor()) != names0)
2355  {
2357  << "Patch names should be identical on all processors."
2358  << " Processor 0 has " << names0
2359  << ". Processor " << proci
2360  << " has " << names
2361  << exit(FatalError);
2362  }
2363  }
2364  }
2365 
2366 
2367  // Work array
2368  labelList nNeighbourProcs(meshes.size());
2369 
2370  forAll(meshes, proci)
2371  {
2372  const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2373 
2374  // Running count of number of patches communicating with same nbr
2375  // (usually 0)
2376  nNeighbourProcs = 0;
2377 
2378  for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++)
2379  {
2380  const processorPolyPatch& pp =
2381  refCast<const processorPolyPatch>(pbm[patchi]);
2382  if (pp.owner())
2383  {
2384  const label nbrProci = pp.neighbProcNo();
2385  const label nbrPatchi = procPatchIndex
2386  (
2387  meshes[nbrProci].boundaryMesh(),
2388  proci,
2389  nNeighbourProcs[nbrProci]
2390  );
2391 
2392  const auto& nbrPbm = meshes[nbrProci].boundaryMesh();
2393  const auto& nbrPp = nbrPbm[nbrPatchi];
2394  if (pp.size() != nbrPp.size())
2395  {
2397  << "at proc:" << proci
2398  << " processor patch "
2399  << pp.name() << " is not same size " << pp.size()
2400  << " as coupled patch " << nbrPp.name()
2401  << " on proc:" << nbrProci
2402  << " size:" << nbrPp.size()
2403  << exit(FatalError);
2404  }
2405 
2406  localPatch[proci].append(patchi);
2407  remoteProc[proci].append(nbrProci);
2408  remotePatch[proci].append(nbrPatchi);
2409 
2410  localPatch[nbrProci].append(nbrPatchi);
2411  remoteProc[nbrProci].append(proci);
2412  remotePatch[nbrProci].append(patchi);
2413 
2414  nNeighbourProcs[nbrProci]++;
2415  }
2416  }
2417  }
2418 
2420  //forAll(meshes, proci)
2421  //{
2422  // const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2423  //
2424  // const DynamicList<label>& localPatches = localPatch[proci];
2425  //
2426  // labelListList& rpf = remotePatchFace[proci];
2427  // rpf.setSize(localPatches.size());
2428  //
2429  // labelListList& rps = remotePatchFaceStart[proci];
2430  // rps.setSize(localPatches.size());
2431  //
2432  // forAll(localPatches, i)
2433  // {
2434  // const auto& pp = pbm[localPatches[i]];
2435  // rpf[i] = identity(pp.size());
2436  // rps[i].setSize(pp.size(), 0);
2437  // }
2438  //}
2439 
2440  return meshes[0].boundaryMesh().nNonProcessor();
2442 
2443 
2445 (
2446  const UPtrList<polyMesh>& meshes,
2447  const List<DynamicList<label>>& localPatch,
2448  const List<DynamicList<label>>& remoteMesh,
2449  const List<DynamicList<label>>& remotePatch,
2450  labelListList& localBoundaryFace,
2451  labelListList& remoteFaceMesh,
2452  labelListList& remoteBoundaryFace
2453 )
2454 {
2455  // Calculates pairs of matching (boundary) faces. Returns
2456  // localBoundaryFace[meshi] : index of local face (in boundary face
2457  // indexing!)
2458  // remoteMesh[meshi] : index of remote mesh
2459  // remoteBoundaryFace[meshi] : index of remote face (in boundary face
2460  // indexing!)
2461  localBoundaryFace.setSize(meshes.size());
2462  remoteFaceMesh.setSize(meshes.size());
2463  remoteBoundaryFace.setSize(meshes.size());
2464 
2465  forAll(meshes, meshi)
2466  {
2467  const auto& mesh = meshes[meshi];
2468  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2469  const DynamicList<label>& procPatches = localPatch[meshi];
2470  const DynamicList<label>& procNbrs = remoteMesh[meshi];
2471  const DynamicList<label>& procNbrPatches = remotePatch[meshi];
2472 
2473 
2474  // Count number of processor faces
2475  label nFaces = 0;
2476  for (const label patchi : procPatches)
2477  {
2478  nFaces += pbm[patchi].size();
2479  }
2480 
2481  labelList& procFaces = localBoundaryFace[meshi];
2482  labelList& remoteMeshes = remoteFaceMesh[meshi];
2483  labelList& remoteFaces = remoteBoundaryFace[meshi];
2484 
2485  procFaces.setSize(nFaces);
2486  remoteMeshes.setSize(nFaces);
2487  remoteFaces.setSize(nFaces);
2488 
2489  nFaces = 0;
2490 
2491  forAll(procPatches, i)
2492  {
2493  const label patchi = procPatches[i];
2494  const label nbrMeshi = procNbrs[i];
2495  const label nbrPatchi = procNbrPatches[i];
2496 
2497  const auto& pp = pbm[patchi];
2498  const label offset = pp.start()-mesh.nInternalFaces();
2499 
2500  const auto& nbrMesh = meshes[nbrMeshi];
2501  const auto& nbrPp = nbrMesh.boundaryMesh()[nbrPatchi];
2502  const label nbrOffset = nbrPp.start()-nbrMesh.nInternalFaces();
2503 
2504  forAll(pp, patchFacei)
2505  {
2506  procFaces[nFaces] = offset+patchFacei;
2507  remoteMeshes[nFaces] = nbrMeshi;
2508  remoteFaces[nFaces] = nbrOffset+patchFacei;
2509  nFaces++;
2510  }
2511  }
2512  }
2513 }
2514 
2515 
2516 void Foam::polyMeshAdder::compactPoints
2517 (
2518  const UPtrList<polyMesh>& meshes,
2519  const labelListList& localBoundaryFace,
2520  const labelListList& remoteFaceMesh,
2521  const labelListList& remoteBoundaryFace,
2522  const labelListList& remoteFaceStart,
2523  const globalIndex& globalPoints,
2524 
2525  labelListList& pointProcAddressing,
2526  labelListList& localPoints
2527 )
2528 {
2529  // Determines 'master' points for shared points. Returns
2530  // pointProcAddressing[meshi] : global point for every mesh point
2531  // localPoints[meshi] : indices of local points that are unique
2532 
2533  // Choose minimum point for shared ones. Iterate minimising global points
2534  // until nothing changes
2535  while (true)
2536  {
2537  label nChanged = 0;
2538  forAll(meshes, meshi)
2539  {
2540  if (meshes.set(meshi))
2541  {
2542  const polyMesh& mesh = meshes[meshi];
2543  const faceList& faces = mesh.faces();
2544 
2545  labelList& pAddressing = pointProcAddressing[meshi];
2546 
2547  const labelList& localBFaces = localBoundaryFace[meshi];
2548  const labelList& procNbrs = remoteFaceMesh[meshi];
2549  const labelList& procNbrBFaces = remoteBoundaryFace[meshi];
2550  const labelList& procNbrIndex = remoteFaceStart[meshi];
2551 
2552  forAll(localBFaces, i)
2553  {
2554  const label bFacei = localBFaces[i];
2555  const label nbrMeshi = procNbrs[i];
2556  const label nbrBFacei = procNbrBFaces[i];
2557 
2558  // Local mesh face
2559  const label facei = mesh.nInternalFaces()+bFacei;
2560  const face& f = faces[facei];
2561 
2562  // Matched (remote) face
2563  const auto& nbrMesh = meshes[nbrMeshi];
2564  const label nbrFacei = nbrMesh.nInternalFaces()+nbrBFacei;
2565  const face& nbrF = nbrMesh.faces()[nbrFacei];
2566 
2567 
2568  labelList& nbrAddressing = pointProcAddressing[nbrMeshi];
2569 
2570  // Starting index is indexed wrt matched, not original
2571  // face. Check!
2572  label nbrFp = procNbrIndex[i];
2573 
2574  forAll(f, fp)
2575  {
2576  label& ppPointi = pAddressing[f[fp]];
2577  label& nbrPointi = nbrAddressing[nbrF[nbrFp]];
2578 
2579  //const point& pt = mesh.points()[f[fp]];
2580  //const point& nbrPt = nbrMesh.points()[nbrF[nbrFp]];
2581  //if (mag(pt-nbrPt) > SMALL)
2582  //{
2583  // FatalErrorInFunction
2584  // << "Merging differing points :"
2585  // << " pt:" << pt
2586  // << " nbrPt:" << nbrPt
2587  // << exit(FatalError);
2588  //}
2589 
2590  if (ppPointi < nbrPointi)
2591  {
2592  //Pout<< "on proc:" << nbrMeshi
2593  // << " point:" << nbrF[nbrFp]
2594  // << " changing from:" << nbrPointi
2595  // << " to:" << ppPointi << endl;
2596  nbrPointi = ppPointi;
2597  nChanged++;
2598  }
2599  else if (nbrPointi < ppPointi)
2600  {
2601  //Pout<< "on proc:" << meshi
2602  // << " point:" << f[fp]
2603  // << " changing from:" << ppPointi
2604  // << " to:" << nbrPointi << endl;
2605  ppPointi = nbrPointi;
2606  nChanged++;
2607  }
2608 
2609  nbrFp = nbrF.rcIndex(nbrFp);
2610  }
2611  }
2612  }
2613  }
2614 
2615  if (nChanged == 0)
2616  {
2617  break;
2618  }
2619  }
2620 
2621 
2622 
2623  // Compact out unused points
2624  localPoints.setSize(meshes.size());
2625  labelList globalToCompact(globalPoints.totalSize(), -1);
2626  label nGlobal = 0;
2627  forAll(meshes, meshi)
2628  {
2629  if (meshes.set(meshi))
2630  {
2631  const polyMesh& mesh = meshes[meshi];
2632 
2633  labelList& compactPoints = localPoints[meshi];
2634  compactPoints.setSize(mesh.nPoints());
2635  label nCompact = 0;
2636 
2637  const labelList& pAddressing = pointProcAddressing[meshi];
2638  forAll(pAddressing, pointi)
2639  {
2640  //Pout<< "proc:" << meshi
2641  // << " localpoint:" << pointi
2642  // << " globalpoint:"
2643  // << globalPoints.toGlobal(meshi, pointi)
2644  // << " merged:" << pAddressing[pointi]
2645  // << endl;
2646 
2647  const label globali = globalPoints.toGlobal(meshi, pointi);
2648 
2649  if (pAddressing[pointi] == globali)
2650  {
2651  // Unchanged address
2652  globalToCompact[globali] = nGlobal++;
2653  compactPoints[nCompact++] = pointi;
2654  }
2655  }
2656  compactPoints.setSize(nCompact);
2657  }
2658  }
2659 
2660  forAll(meshes, meshi)
2661  {
2662  labelList& pAddressing = pointProcAddressing[meshi];
2663  pAddressing = UIndirectList<label>(globalToCompact, pAddressing);
2664  }
2666 
2667 
2669 (
2670  const UPtrList<polyMesh>& meshes,
2671  const UList<labelList>& patchMap,
2672 
2673  const labelListList& localBoundaryFace,
2674  const labelListList& remoteFaceMesh,
2675  const labelListList& remoteBoundaryFace,
2676  const labelListList& remoteFaceStart,
2677 
2678  const UList<labelList>& pointZoneMap,
2679  const UList<labelList>& faceZoneMap,
2680  const UList<labelList>& cellZoneMap,
2681 
2682  polyTopoChange& meshMod,
2683  labelListList& cellProcAddressing,
2684  labelListList& faceProcAddressing,
2685  labelListList& pointProcAddressing
2686  //labelListList& boundaryProcAddressing
2687 )
2688 {
2689  cellProcAddressing.setSize(meshes.size());
2690  faceProcAddressing.setSize(meshes.size());
2691  pointProcAddressing.setSize(meshes.size());
2692  //boundaryProcAddressing.setSize(meshes.size());
2693  forAll(cellProcAddressing, meshi)
2694  {
2695  cellProcAddressing[meshi].clear();
2696  faceProcAddressing[meshi].clear();
2697  pointProcAddressing[meshi].clear();
2698  }
2699 
2700  // Start off with points allocated in processor order.
2701  labelList offsets(meshes.size()+1);
2702  offsets[0] = 0;
2703  forAll(meshes, meshi)
2704  {
2705  label nPoints = 0;
2706  if (meshes.set(meshi))
2707  {
2708  const polyMesh& mesh = meshes[meshi];
2709  nPoints = mesh.nPoints();
2710  }
2711  pointProcAddressing[meshi] = identity(nPoints, offsets[meshi]);
2712  offsets[meshi+1] = offsets[meshi]+nPoints;
2713  }
2714  const globalIndex globalPoints(std::move(offsets));
2715 
2716  labelListList uniquePoints(meshes.size());
2717  compactPoints
2718  (
2719  meshes,
2720 
2721  localBoundaryFace,
2722  remoteFaceMesh,
2723  remoteBoundaryFace,
2724  remoteFaceStart,
2725 
2726  globalPoints,
2727 
2728  pointProcAddressing, // per proc, per point the compact,global point
2729  uniquePoints // per proc indices of local preserved points
2730  );
2731 
2732 
2733  // Add cells
2734  // ~~~~~~~~~
2735  // These are used by face adding later on
2736 
2737  forAll(meshes, meshi)
2738  {
2739  if (meshes.set(meshi))
2740  {
2741  const polyMesh& mesh = meshes[meshi];
2742  const cellZoneMesh& cellZones = mesh.cellZones();
2743 
2744  // Precalc offset zones
2745  labelList newZoneID(mesh.nCells(), -1);
2746 
2747  forAll(cellZones, zonei)
2748  {
2749  const labelList& cellLabels = cellZones[zonei];
2750 
2751  for (const label celli : cellLabels)
2752  {
2753  if (newZoneID[celli] != -1)
2754  {
2756  << "Cell:" << celli
2757  << " centre:" << mesh.cellCentres()[celli]
2758  << " is in two zones:"
2759  << cellZones[newZoneID[celli]].name()
2760  << " and " << cellZones[zonei].name() << endl
2761  << " This is not supported."
2762  << " Continuing with first zone only." << endl;
2763  }
2764  else
2765  {
2766  newZoneID[celli] = cellZoneMap[meshi][zonei];
2767  }
2768  }
2769  }
2770 
2771  // Add cells in mesh order
2772  cellProcAddressing[meshi].setSize(mesh.nCells());
2773  for (label celli = 0; celli < mesh.nCells(); celli++)
2774  {
2775  // Add cell from cell
2776  cellProcAddressing[meshi][celli] = meshMod.addCell
2777  (
2778  -1,
2779  -1,
2780  -1,
2781  celli,
2782  newZoneID[celli]
2783  );
2784  }
2785  }
2786  }
2787 
2788 
2789  // Add points
2790  // ~~~~~~~~~~
2791  // These are used by face adding later on
2792 
2793  forAll(meshes, meshi)
2794  {
2795  if (meshes.set(meshi))
2796  {
2797  const polyMesh& mesh = meshes[meshi];
2798  const pointField& points = mesh.points();
2799  const pointZoneMesh& pointZones = mesh.pointZones();
2800 
2801  // Precalc offset zones
2802  labelList newZoneID(points.size(), -1);
2803 
2804  forAll(pointZones, zonei)
2805  {
2806  const labelList& pointLabels = pointZones[zonei];
2807 
2808  for (const label pointi : pointLabels)
2809  {
2810  newZoneID[pointi] = pointZoneMap[meshi][zonei];
2811  }
2812  }
2813 
2814  // Add points in mesh order
2815  const labelList& myUniquePoints = uniquePoints[meshi];
2816  for (const label pointi : myUniquePoints)
2817  {
2818  // Rewrite the addressing (should already be compact) just in
2819  // case the polyTopoChange does some special ordering
2820  pointProcAddressing[meshi][pointi] = meshMod.addPoint
2821  (
2822  points[pointi],
2823  pointi,
2824  newZoneID[pointi],
2825  true
2826  );
2827  }
2828  }
2829  }
2830 
2831 
2832 
2833  // Add faces
2834  // ~~~~~~~~~
2835 
2836  forAll(meshes, meshi)
2837  {
2838  if (meshes.set(meshi))
2839  {
2840  const polyMesh& mesh = meshes[meshi];
2841  faceProcAddressing[meshi].setSize(mesh.nFaces());
2842  faceProcAddressing[meshi] = -1;
2843  //boundaryProcAddressing[meshi].setSize(mesh.boundaryMesh().size());
2844  //boundaryProcAddressing[meshi] = -1;
2845  }
2846  }
2847 
2848  forAll(meshes, meshi)
2849  {
2850  if (meshes.set(meshi))
2851  {
2852  const polyMesh& mesh = meshes[meshi];
2853  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2854  const faceList& faces = mesh.faces();
2855  const labelList& faceOwner = mesh.faceOwner();
2856  const labelList& faceNeighbour = mesh.faceNeighbour();
2857  const faceZoneMesh& faceZones = mesh.faceZones();
2858 
2859  // Precalc offset zones
2860  labelList newZoneID(faces.size(), -1);
2861  boolList zoneFlip(faces.size(), false);
2862 
2863  forAll(faceZones, zonei)
2864  {
2865  const labelList& faceLabels = faceZones[zonei];
2866  const boolList& flipMap = faceZones[zonei].flipMap();
2867 
2868  forAll(faceLabels, facei)
2869  {
2870  newZoneID[faceLabels[facei]] = faceZoneMap[meshi][zonei];
2871  zoneFlip[faceLabels[facei]] = flipMap[facei];
2872  }
2873  }
2874 
2875  // Add faces in mesh order
2876 
2877  // 1. Internal faces
2878 
2879  face newFace;
2880  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
2881  {
2882  const face& f = faces[facei];
2883 
2884  label newOwn = cellProcAddressing[meshi][faceOwner[facei]];
2885  label newNei = cellProcAddressing[meshi][faceNeighbour[facei]];
2886 
2887  newFace.setSize(f.size());
2888  forAll(f, fp)
2889  {
2890  newFace[fp] = pointProcAddressing[meshi][f[fp]];
2891  }
2892  bool flipFaceFlux = false;
2893  bool flip = zoneFlip[facei];
2894  if (newNei < newOwn)
2895  {
2896  Swap(newOwn, newNei);
2897  newFace = newFace.reverseFace();
2898  flipFaceFlux = !flipFaceFlux;
2899  flip = !flip;
2900  }
2901 
2902  const label newFacei = meshMod.addFace
2903  (
2904  newFace,
2905  newOwn,
2906  newNei,
2907  -1, // masterPointID
2908  -1, // masterEdgeID
2909  facei, // masterFaceID
2910  flipFaceFlux, // flipFaceFlux
2911  -1, // patchID
2912  newZoneID[facei], // zoneID
2913  flip // zoneFlip
2914  );
2915 
2916  faceProcAddressing[meshi][facei] = newFacei;
2917  }
2918 
2919  // 1b. Owner side of coupled faces (since owner side cells are
2920  // smallest)
2921 
2922  const labelList& localBFaces = localBoundaryFace[meshi];
2923  const labelList& procNbrs = remoteFaceMesh[meshi];
2924  const labelList& procNbrBFaces = remoteBoundaryFace[meshi];
2925 
2926  forAll(localBFaces, i)
2927  {
2928  const label bFacei = localBFaces[i];
2929  const label nbrMeshi = procNbrs[i];
2930  const label nbrBFacei = procNbrBFaces[i];
2931 
2932  // Local mesh face
2933  const label facei = mesh.nInternalFaces()+bFacei;
2934  const face& f = mesh.faces()[facei];
2935  const label newOwn =
2936  cellProcAddressing[meshi][faceOwner[facei]];
2937 
2938  // Neighbour mesh face
2939  const auto& nbrMesh = meshes[nbrMeshi];
2940  const label nbrFacei = nbrMesh.nInternalFaces()+nbrBFacei;
2941  const label nbrOwn = nbrMesh.faceOwner()[nbrFacei];
2942  const label newNei = cellProcAddressing[nbrMeshi][nbrOwn];
2943 
2944  //Pout<< "** connection between face:" << facei
2945  // << " at:" << mesh.faceCentres()[facei]
2946  // << " and nbrMesh:" << nbrMeshi
2947  // << " nbrFacei:" << nbrMesh.faceCentres()[nbrFacei]
2948  // << endl;
2949 
2950  if (newOwn < newNei)
2951  {
2952  newFace.setSize(f.size());
2953  forAll(f, fp)
2954  {
2955  newFace[fp] = pointProcAddressing[meshi][f[fp]];
2956  }
2957  const bool flipFaceFlux = false;
2958  const bool flip = zoneFlip[facei];
2959  const label newFacei = meshMod.addFace
2960  (
2961  newFace,
2962  newOwn,
2963  newNei, // neighbour
2964  -1, // masterPointID
2965  -1, // masterEdgeID
2966  facei, // masterFaceID
2967  flipFaceFlux, // flipFaceFlux
2968  -1, // patchID
2969  newZoneID[facei], // zoneID
2970  flip // zoneFlip
2971  );
2972 
2973  faceProcAddressing[meshi][facei] = newFacei;
2974  faceProcAddressing[nbrMeshi][nbrFacei] = newFacei;
2975  }
2976  }
2977 
2978 
2979  // 2. Remaining patch faces
2980 
2981  forAll(pbm, patchi)
2982  {
2983  const auto& pp = pbm[patchi];
2984 
2985  if (patchi < patchMap[meshi].size())
2986  {
2987  const label newPatchi = patchMap[meshi][patchi];
2988 
2989  //boundaryProcAddressing[meshi][patchi] = newPatchi;
2990 
2991  forAll(pp, patchFacei)
2992  {
2993  const label facei = pp.start() + patchFacei;
2994  if (faceProcAddressing[meshi][facei] == -1)
2995  {
2996  const face& f = faces[facei];
2997 
2998  const label newOwn =
2999  cellProcAddressing[meshi][faceOwner[facei]];
3000  newFace.setSize(f.size());
3001  forAll(f, fp)
3002  {
3003  newFace[fp] = pointProcAddressing[meshi][f[fp]];
3004  }
3005 
3006  const label newFacei = meshMod.addFace
3007  (
3008  newFace,
3009  newOwn,
3010  -1, // neighbour
3011  -1, // masterPointID
3012  -1, // masterEdgeID
3013  facei, // masterFaceID
3014  false, // flipFaceFlux
3015  newPatchi, // patchID
3016  newZoneID[facei], // zoneID
3017  zoneFlip[facei] // zoneFlip
3018  );
3019 
3020  faceProcAddressing[meshi][facei] = newFacei;
3021  }
3022  }
3023  }
3024  }
3025  }
3026  }
3027 }
3028 
3029 
3030 // ************************************************************************* //
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:584
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:51
reference val() const
Const access to referenced object (value)
Definition: HashTable.H:1139
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
labelList pointLabels(nPoints, -1)
label nPoints() const noexcept
Number of mesh points.
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
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:491
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
Definition: UList.C:204
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1110
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
List< face > faceList
A List of faces.
Definition: faceListFwd.H:41
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
label appendUniq(const T &val)
Append an element if not already in the list.
Definition: List.H:526
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:255
Class containing mesh-to-mesh mapping information after a mesh addition where we add a mesh (&#39;added m...
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:348
const primitiveFacePatch & cutFaces() const
Addressing engine for combined set of faces.
label nFaces() const noexcept
Number of mesh faces.
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field...
label addCell(const label masterPointID, const label masterEdgeID, const label masterFaceID, const label masterCellID, const label zoneID)
Add cell. Return new cell label.
Container for information needed to couple to meshes. When constructed from two meshes and a geometri...
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1066
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
label mergePoints(const PointList &points, labelList &pointToUnique, labelList &uniquePoints, const scalar mergeTol=SMALL, const bool verbose=false)
Calculate merge mapping, preserving the original point order. All points closer/equal mergeTol are to...
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:173
List< List< bool > > boolListList
A List of boolList.
Definition: boolList.H:42
A List obtained as a section of another List.
Definition: SubList.H:50
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:289
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
const cellShapeList & cells
label addFace(const face &f, const label own, const label nei, const label masterPointID, const label masterEdgeID, const label masterFaceID, const bool flipFaceFlux, const label patchID, const label zoneID, const bool zoneFlip)
Add face to cells. Return new face label.
const pointField & points
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
labelListList invertOneToMany(const label len, const labelUList &map)
Invert one-to-many map. Unmapped elements will be size 0.
Definition: ListOps.C:107
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:134
labelList identity(const label len, label start=0)
Return an identity map of the given length with (map[i] == i)
Definition: labelList.C:31
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:109
label nPoints
wordList names() const
Return a list of patch names.
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:99
void addZones(PtrList< pointZone > &&pz, PtrList< faceZone > &&fz, PtrList< cellZone > &&cz)
Add mesh zones.
Definition: polyMesh.C:997
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1104
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1293
label nInternalFaces() const noexcept
Number of internal faces.
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1091
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
const vectorField & cellCentres() const
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: HashTable.H:100
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
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:99
static label procPatchPairs(const UPtrList< polyMesh > &meshes, List< DynamicList< label >> &localPatch, List< DynamicList< label >> &remoteMesh, List< DynamicList< label >> &remotePatch)
Helper: find pairs of processor patches. Return number of non-processor patches.
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:646
Geometric merging of points. See below.
labelList f(nPoints)
void setSize(const label newLen)
Same as resize()
Definition: PtrList.H:183
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:276
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition: polyMesh.H:638
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: IndirectList.H:65
static void patchFacePairs(const UPtrList< polyMesh > &meshes, const List< DynamicList< label >> &localPatch, const List< DynamicList< label >> &remoteMesh, const List< DynamicList< label >> &remotePatch, labelListList &localBoundaryFace, labelListList &remoteFaceMesh, labelListList &remoteBoundaryFace)
Helper: expand list of coupled patches into pairs of coupled faces.
#define WarningInFunction
Report a warning using Foam::Warning.
label nCells() const noexcept
Number of mesh cells.
void removePoint(const label pointi, const label mergePointi)
Remove/merge point.
Direct mesh changes based on v1.3 polyTopoChange syntax.
label whichPatch(const label faceIndex) const
Return patch index for a given mesh face index.
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:441
const polyBoundaryMesh & patches
void Swap(DynamicList< T, SizeMinA > &a, DynamicList< T, SizeMinB > &b)
Definition: DynamicList.H:647
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:654
constexpr label labelMax
Definition: label.H:55
label n
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
HashTable< labelList, edge, Hash< edge > > edgeLookup
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:73
label addPoint(const point &pt, const label masterPointID, const label zoneID, const bool inCell)
Add point. Return new point label.
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:429
List< label > labelList
A List of labels.
Definition: List.H:62
volScalarField & p
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
label nNonProcessor() const
The number of patches before the first processor patch.
void addPatches(polyPatchList &plist, const bool validBoundary=true)
Add boundary patches.
Definition: polyMesh.C:959
static autoPtr< polyMesh > add(const IOobject &io, const polyMesh &mesh0, const polyMesh &mesh1, const faceCoupleInfo &coupleInfo, autoPtr< mapAddedPolyMesh > &mapPtr)
Add two polyMeshes. Returns new polyMesh and map construct.
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:41
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
static Map< label > findSharedPoints(const polyMesh &, const scalar mergeTol)
Find topologically and geometrically shared points.
UIndirectList< bool > boolUIndList
UIndirectList of bools.
Definition: IndirectList.H:61
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
IOporosityModelList pZones(mesh)
A HashTable to objects of type <T> with a label key.
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157