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.
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);
1665 
1666  return meshPtr;
1667 }
1668 
1669 
1670 // Inplace add mesh1 to mesh0
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 
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 
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  // pointField
2128  // (
2129  // mesh.points(),
2130  // sharedPointLabels
2131  // ),
2132  // mergeDist,
2133  // false,
2134  // sharedToMerged
2135  //);
2136  //
2139  //
2140  //Map<label> pointToMaster(10*sharedToMerged.size());
2141  //
2142  //if (nUnique < sharedPointLabels.size())
2143  //{
2144  // labelListList mergeSets
2145  // (
2146  // invertOneToMany
2147  // (
2148  // sharedToMerged.size(),
2149  // sharedToMerged
2150  // )
2151  // );
2152  //
2153  // label nMergeSets = 0;
2154  //
2155  // forAll(mergeSets, setI)
2156  // {
2157  // const labelList& mergeSet = mergeSets[setI];
2158  //
2159  // if (mergeSet.size() > 1)
2160  // {
2161  // // Take as master the shared point with the lowest mesh
2162  // // point label. (rather arbitrarily - could use max or
2163  // // any other one of the points)
2164  //
2165  // nMergeSets++;
2166  //
2167  // label masterI = labelMax;
2168  //
2169  // forAll(mergeSet, i)
2170  // {
2171  // label sharedI = mergeSet[i];
2172  //
2173  // masterI = min(masterI, sharedPointLabels[sharedI]);
2174  // }
2175  //
2176  // forAll(mergeSet, i)
2177  // {
2178  // label sharedI = mergeSet[i];
2179  //
2180  // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
2181  // }
2182  // }
2183  // }
2184  //
2185  // //if (debug)
2186  // //{
2187  // // Pout<< "polyMeshAdder : merging:"
2188  // // << pointToMaster.size() << " into " << nMergeSets
2189  // // << " sets." << endl;
2190  // //}
2191  //}
2192 
2193  return pointToMaster;
2194 }
2195 
2196 
2199  const polyMesh& mesh,
2200  const Map<label>& pointToMaster,
2201  polyTopoChange& meshMod
2202 )
2203 {
2204  // Remove all non-master points.
2205  forAll(mesh.points(), pointi)
2206  {
2207  const auto iter = pointToMaster.cfind(pointi);
2208 
2209  if (iter.found())
2210  {
2211  if (iter.val() != pointi)
2212  {
2213  meshMod.removePoint(pointi, iter.val());
2214  }
2215  }
2216  }
2217 
2218  // Modify faces for points. Note: could use pointFaces here but want to
2219  // avoid addressing calculation.
2220  const faceList& faces = mesh.faces();
2221 
2222  forAll(faces, facei)
2223  {
2224  const face& f = faces[facei];
2225 
2226  bool hasMerged = false;
2227 
2228  forAll(f, fp)
2229  {
2230  label pointi = f[fp];
2231 
2232  const auto iter = pointToMaster.cfind(pointi);
2233 
2234  if (iter.found())
2235  {
2236  if (iter.val() != pointi)
2237  {
2238  hasMerged = true;
2239  break;
2240  }
2241  }
2242  }
2243 
2244  if (hasMerged)
2245  {
2246  face newF(f);
2247 
2248  forAll(f, fp)
2249  {
2250  label pointi = f[fp];
2251 
2252  const auto iter = pointToMaster.cfind(pointi);
2253 
2254  if (iter.found())
2255  {
2256  newF[fp] = iter.val();
2257  }
2258  }
2259 
2260  label patchID = mesh.boundaryMesh().whichPatch(facei);
2261  label nei = (patchID == -1 ? mesh.faceNeighbour()[facei] : -1);
2262  label zoneID = mesh.faceZones().whichZone(facei);
2263  bool zoneFlip = false;
2264 
2265  if (zoneID >= 0)
2266  {
2267  const faceZone& fZone = mesh.faceZones()[zoneID];
2268  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
2269  }
2270 
2271  meshMod.setAction
2272  (
2274  (
2275  newF, // modified face
2276  facei, // label of face
2277  mesh.faceOwner()[facei], // owner
2278  nei, // neighbour
2279  false, // face flip
2280  patchID, // patch for face
2281  false, // remove from zone
2282  zoneID, // zone for face
2283  zoneFlip // face flip in zone
2284  )
2285  );
2286  }
2287  }
2288 }
2289 
2290 
2291 Foam::label Foam::polyMeshAdder::procPatchIndex
2292 (
2293  const polyBoundaryMesh& pbm,
2294  const label nbrProci,
2295  const label n
2296 )
2297 {
2298  // Find n'th processor patch going to nbrProci. Usually n=0 but in some
2299  // cases (e.g. processorCyclic, implicit cht) there can be more than one
2300  // processor patch between two processors.
2301 
2302  label index = n;
2303 
2304  for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++)
2305  {
2306  const processorPolyPatch& pp =
2307  refCast<const processorPolyPatch>(pbm[patchi]);
2308  if (pp.neighbProcNo() == nbrProci)
2309  {
2310  if (index == 0)
2311  {
2312  return patchi;
2313  }
2314  else
2315  {
2316  --index;
2317  }
2318  }
2319  }
2320 
2321  FatalErrorInFunction << "no patch found to processor " << nbrProci
2322  << ". Current patches:" << pbm.names() << exit(FatalError);
2323  return -1;
2324 }
2325 
2326 
2329  const UPtrList<polyMesh>& meshes,
2330  List<DynamicList<label>>& localPatch,
2331  List<DynamicList<label>>& remoteProc,
2332  List<DynamicList<label>>& remotePatch
2333  //List<labelListList>& remotePatchFace,
2334  //List<labelListList>& remotePatchFaceStart
2335 )
2336 {
2337  // Determine pairs of processor patches:
2338  // - remote processor
2339  // - patch on remote processor
2340  // - face on remote patch
2341  // - starting index on remote face
2342  localPatch.setSize(meshes.size());
2343  remoteProc.setSize(meshes.size());
2344  remotePatch.setSize(meshes.size());
2345  //remotePatchFace.setSize(meshes.size());
2346  //remotePatchFaceStart.setSize(meshes.size());
2347 
2348 
2349  // Check that all processors have the same globalPatches
2350  {
2351  const polyBoundaryMesh& pbm = meshes[0].boundaryMesh();
2352  const wordList names0(SubList<word>(pbm.names(), pbm.nNonProcessor()));
2353  for (label proci = 1; proci < meshes.size(); proci++)
2354  {
2355  const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2356  const wordList names(pbm.names());
2357 
2358  if (SubList<word>(names, pbm.nNonProcessor()) != names0)
2359  {
2361  << "Patch names should be identical on all processors."
2362  << " Processor 0 has " << names0
2363  << ". Processor " << proci
2364  << " has " << names
2365  << exit(FatalError);
2366  }
2367  }
2368  }
2369 
2370 
2371  // Work array
2372  labelList nNeighbourProcs(meshes.size());
2373 
2374  forAll(meshes, proci)
2375  {
2376  const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2377 
2378  // Running count of number of patches communicating with same nbr
2379  // (usually 0)
2380  nNeighbourProcs = 0;
2381 
2382  for (label patchi = pbm.nNonProcessor(); patchi < pbm.size(); patchi++)
2383  {
2384  const processorPolyPatch& pp =
2385  refCast<const processorPolyPatch>(pbm[patchi]);
2386  if (pp.owner())
2387  {
2388  const label nbrProci = pp.neighbProcNo();
2389  const label nbrPatchi = procPatchIndex
2390  (
2391  meshes[nbrProci].boundaryMesh(),
2392  proci,
2393  nNeighbourProcs[nbrProci]
2394  );
2395 
2396  const auto& nbrPbm = meshes[nbrProci].boundaryMesh();
2397  const auto& nbrPp = nbrPbm[nbrPatchi];
2398  if (pp.size() != nbrPp.size())
2399  {
2401  << "at proc:" << proci
2402  << " processor patch "
2403  << pp.name() << " is not same size " << pp.size()
2404  << " as coupled patch " << nbrPp.name()
2405  << " on proc:" << nbrProci
2406  << " size:" << nbrPp.size()
2407  << exit(FatalError);
2408  }
2409 
2410  localPatch[proci].append(patchi);
2411  remoteProc[proci].append(nbrProci);
2412  remotePatch[proci].append(nbrPatchi);
2413 
2414  localPatch[nbrProci].append(nbrPatchi);
2415  remoteProc[nbrProci].append(proci);
2416  remotePatch[nbrProci].append(patchi);
2417 
2418  nNeighbourProcs[nbrProci]++;
2419  }
2420  }
2421  }
2422 
2424  //forAll(meshes, proci)
2425  //{
2426  // const polyBoundaryMesh& pbm = meshes[proci].boundaryMesh();
2427  //
2428  // const DynamicList<label>& localPatches = localPatch[proci];
2429  //
2430  // labelListList& rpf = remotePatchFace[proci];
2431  // rpf.setSize(localPatches.size());
2432  //
2433  // labelListList& rps = remotePatchFaceStart[proci];
2434  // rps.setSize(localPatches.size());
2435  //
2436  // forAll(localPatches, i)
2437  // {
2438  // const auto& pp = pbm[localPatches[i]];
2439  // rpf[i] = identity(pp.size());
2440  // rps[i].setSize(pp.size(), 0);
2441  // }
2442  //}
2443 
2444  return meshes[0].boundaryMesh().nNonProcessor();
2445 }
2446 
2447 
2450  const UPtrList<polyMesh>& meshes,
2451  const List<DynamicList<label>>& localPatch,
2452  const List<DynamicList<label>>& remoteMesh,
2453  const List<DynamicList<label>>& remotePatch,
2454  labelListList& localBoundaryFace,
2455  labelListList& remoteFaceMesh,
2456  labelListList& remoteBoundaryFace
2457 )
2458 {
2459  // Calculates pairs of matching (boundary) faces. Returns
2460  // localBoundaryFace[meshi] : index of local face (in boundary face
2461  // indexing!)
2462  // remoteMesh[meshi] : index of remote mesh
2463  // remoteBoundaryFace[meshi] : index of remote face (in boundary face
2464  // indexing!)
2465  localBoundaryFace.setSize(meshes.size());
2466  remoteFaceMesh.setSize(meshes.size());
2467  remoteBoundaryFace.setSize(meshes.size());
2468 
2469  forAll(meshes, meshi)
2470  {
2471  const auto& mesh = meshes[meshi];
2472  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2473  const DynamicList<label>& procPatches = localPatch[meshi];
2474  const DynamicList<label>& procNbrs = remoteMesh[meshi];
2475  const DynamicList<label>& procNbrPatches = remotePatch[meshi];
2476 
2477 
2478  // Count number of processor faces
2479  label nFaces = 0;
2480  for (const label patchi : procPatches)
2481  {
2482  nFaces += pbm[patchi].size();
2483  }
2484 
2485  labelList& procFaces = localBoundaryFace[meshi];
2486  labelList& remoteMeshes = remoteFaceMesh[meshi];
2487  labelList& remoteFaces = remoteBoundaryFace[meshi];
2488 
2489  procFaces.setSize(nFaces);
2490  remoteMeshes.setSize(nFaces);
2491  remoteFaces.setSize(nFaces);
2492 
2493  nFaces = 0;
2494 
2495  forAll(procPatches, i)
2496  {
2497  const label patchi = procPatches[i];
2498  const label nbrMeshi = procNbrs[i];
2499  const label nbrPatchi = procNbrPatches[i];
2500 
2501  const auto& pp = pbm[patchi];
2502  const label offset = pp.start()-mesh.nInternalFaces();
2503 
2504  const auto& nbrMesh = meshes[nbrMeshi];
2505  const auto& nbrPp = nbrMesh.boundaryMesh()[nbrPatchi];
2506  const label nbrOffset = nbrPp.start()-nbrMesh.nInternalFaces();
2507 
2508  forAll(pp, patchFacei)
2509  {
2510  procFaces[nFaces] = offset+patchFacei;
2511  remoteMeshes[nFaces] = nbrMeshi;
2512  remoteFaces[nFaces] = nbrOffset+patchFacei;
2513  nFaces++;
2514  }
2515  }
2516  }
2517 }
2518 
2519 
2520 void Foam::polyMeshAdder::compactPoints
2521 (
2522  const UPtrList<polyMesh>& meshes,
2523  const labelListList& localBoundaryFace,
2524  const labelListList& remoteFaceMesh,
2525  const labelListList& remoteBoundaryFace,
2526  const labelListList& remoteFaceStart,
2527  const globalIndex& globalPoints,
2528 
2529  labelListList& pointProcAddressing,
2530  labelListList& localPoints
2531 )
2532 {
2533  // Determines 'master' points for shared points. Returns
2534  // pointProcAddressing[meshi] : global point for every mesh point
2535  // localPoints[meshi] : indices of local points that are unique
2536 
2537  // Choose minimum point for shared ones. Iterate minimising global points
2538  // until nothing changes
2539  while (true)
2540  {
2541  label nChanged = 0;
2542  forAll(meshes, meshi)
2543  {
2544  if (meshes.set(meshi))
2545  {
2546  const polyMesh& mesh = meshes[meshi];
2547  const faceList& faces = mesh.faces();
2548 
2549  labelList& pAddressing = pointProcAddressing[meshi];
2550 
2551  const labelList& localBFaces = localBoundaryFace[meshi];
2552  const labelList& procNbrs = remoteFaceMesh[meshi];
2553  const labelList& procNbrBFaces = remoteBoundaryFace[meshi];
2554  const labelList& procNbrIndex = remoteFaceStart[meshi];
2555 
2556  forAll(localBFaces, i)
2557  {
2558  const label bFacei = localBFaces[i];
2559  const label nbrMeshi = procNbrs[i];
2560  const label nbrBFacei = procNbrBFaces[i];
2561 
2562  // Local mesh face
2563  const label facei = mesh.nInternalFaces()+bFacei;
2564  const face& f = faces[facei];
2565 
2566  // Matched (remote) face
2567  const auto& nbrMesh = meshes[nbrMeshi];
2568  const label nbrFacei = nbrMesh.nInternalFaces()+nbrBFacei;
2569  const face& nbrF = nbrMesh.faces()[nbrFacei];
2570 
2571 
2572  labelList& nbrAddressing = pointProcAddressing[nbrMeshi];
2573 
2574  // Starting index is indexed wrt matched, not original
2575  // face. Check!
2576  label nbrFp = procNbrIndex[i];
2577 
2578  forAll(f, fp)
2579  {
2580  label& ppPointi = pAddressing[f[fp]];
2581  label& nbrPointi = nbrAddressing[nbrF[nbrFp]];
2582 
2583  //const point& pt = mesh.points()[f[fp]];
2584  //const point& nbrPt = nbrMesh.points()[nbrF[nbrFp]];
2585  //if (mag(pt-nbrPt) > SMALL)
2586  //{
2587  // FatalErrorInFunction
2588  // << "Merging differing points :"
2589  // << " pt:" << pt
2590  // << " nbrPt:" << nbrPt
2591  // << exit(FatalError);
2592  //}
2593 
2594  if (ppPointi < nbrPointi)
2595  {
2596  //Pout<< "on proc:" << nbrMeshi
2597  // << " point:" << nbrF[nbrFp]
2598  // << " changing from:" << nbrPointi
2599  // << " to:" << ppPointi << endl;
2600  nbrPointi = ppPointi;
2601  nChanged++;
2602  }
2603  else if (nbrPointi < ppPointi)
2604  {
2605  //Pout<< "on proc:" << meshi
2606  // << " point:" << f[fp]
2607  // << " changing from:" << ppPointi
2608  // << " to:" << nbrPointi << endl;
2609  ppPointi = nbrPointi;
2610  nChanged++;
2611  }
2612 
2613  nbrFp = nbrF.rcIndex(nbrFp);
2614  }
2615  }
2616  }
2617  }
2618 
2619  if (nChanged == 0)
2620  {
2621  break;
2622  }
2623  }
2624 
2625 
2626 
2627  // Compact out unused points
2628  localPoints.setSize(meshes.size());
2629  labelList globalToCompact(globalPoints.size(), -1);
2630  label nGlobal = 0;
2631  forAll(meshes, meshi)
2632  {
2633  if (meshes.set(meshi))
2634  {
2635  const polyMesh& mesh = meshes[meshi];
2636 
2637  labelList& compactPoints = localPoints[meshi];
2638  compactPoints.setSize(mesh.nPoints());
2639  label nCompact = 0;
2640 
2641  const labelList& pAddressing = pointProcAddressing[meshi];
2642  forAll(pAddressing, pointi)
2643  {
2644  //Pout<< "proc:" << meshi
2645  // << " localpoint:" << pointi
2646  // << " globalpoint:"
2647  // << globalPoints.toGlobal(meshi, pointi)
2648  // << " merged:" << pAddressing[pointi]
2649  // << endl;
2650 
2651  const label globali = globalPoints.toGlobal(meshi, pointi);
2652 
2653  if (pAddressing[pointi] == globali)
2654  {
2655  // Unchanged address
2656  globalToCompact[globali] = nGlobal++;
2657  compactPoints[nCompact++] = pointi;
2658  }
2659  }
2660  compactPoints.setSize(nCompact);
2661  }
2662  }
2663 
2664  forAll(meshes, meshi)
2665  {
2666  labelList& pAddressing = pointProcAddressing[meshi];
2667  pAddressing = UIndirectList<label>(globalToCompact, pAddressing);
2668  }
2669 }
2670 
2671 
2674  const UPtrList<polyMesh>& meshes,
2675  const UList<labelList>& patchMap,
2676 
2677  const labelListList& localBoundaryFace,
2678  const labelListList& remoteFaceMesh,
2679  const labelListList& remoteBoundaryFace,
2680  const labelListList& remoteFaceStart,
2681 
2682  const UList<labelList>& pointZoneMap,
2683  const UList<labelList>& faceZoneMap,
2684  const UList<labelList>& cellZoneMap,
2685 
2686  polyTopoChange& meshMod,
2687  labelListList& cellProcAddressing,
2689  labelListList& pointProcAddressing
2690  //labelListList& boundaryProcAddressing
2691 )
2692 {
2693  cellProcAddressing.setSize(meshes.size());
2694  faceProcAddressing.setSize(meshes.size());
2695  pointProcAddressing.setSize(meshes.size());
2696  //boundaryProcAddressing.setSize(meshes.size());
2697  forAll(cellProcAddressing, meshi)
2698  {
2699  cellProcAddressing[meshi].clear();
2700  faceProcAddressing[meshi].clear();
2701  pointProcAddressing[meshi].clear();
2702  }
2703 
2704  // Start off with points allocated in processor order.
2705  labelList offsets(meshes.size()+1);
2706  offsets[0] = 0;
2707  forAll(meshes, meshi)
2708  {
2709  label nPoints = 0;
2710  if (meshes.set(meshi))
2711  {
2712  const polyMesh& mesh = meshes[meshi];
2713  nPoints = mesh.nPoints();
2714  }
2715  pointProcAddressing[meshi] = identity(nPoints, offsets[meshi]);
2716  offsets[meshi+1] = offsets[meshi]+nPoints;
2717  }
2718  const globalIndex globalPoints(std::move(offsets));
2719 
2720  labelListList uniquePoints(meshes.size());
2721  compactPoints
2722  (
2723  meshes,
2724 
2725  localBoundaryFace,
2726  remoteFaceMesh,
2727  remoteBoundaryFace,
2728  remoteFaceStart,
2729 
2730  globalPoints,
2731 
2732  pointProcAddressing, // per proc, per point the compact,global point
2733  uniquePoints // per proc indices of local preserved points
2734  );
2735 
2736 
2737  // Add cells
2738  // ~~~~~~~~~
2739  // These are used by face adding later on
2740 
2741  forAll(meshes, meshi)
2742  {
2743  if (meshes.set(meshi))
2744  {
2745  const polyMesh& mesh = meshes[meshi];
2746  const cellZoneMesh& cellZones = mesh.cellZones();
2747 
2748  // Precalc offset zones
2749  labelList newZoneID(mesh.nCells(), -1);
2750 
2751  forAll(cellZones, zonei)
2752  {
2753  const labelList& cellLabels = cellZones[zonei];
2754 
2755  for (const label celli : cellLabels)
2756  {
2757  if (newZoneID[celli] != -1)
2758  {
2760  << "Cell:" << celli
2761  << " centre:" << mesh.cellCentres()[celli]
2762  << " is in two zones:"
2763  << cellZones[newZoneID[celli]].name()
2764  << " and " << cellZones[zonei].name() << endl
2765  << " This is not supported."
2766  << " Continuing with first zone only." << endl;
2767  }
2768  else
2769  {
2770  newZoneID[celli] = cellZoneMap[meshi][zonei];
2771  }
2772  }
2773  }
2774 
2775  // Add cells in mesh order
2776  cellProcAddressing[meshi].setSize(mesh.nCells());
2777  for (label celli = 0; celli < mesh.nCells(); celli++)
2778  {
2779  // Add cell from cell
2780  cellProcAddressing[meshi][celli] = meshMod.addCell
2781  (
2782  -1,
2783  -1,
2784  -1,
2785  celli,
2786  newZoneID[celli]
2787  );
2788  }
2789  }
2790  }
2791 
2792 
2793  // Add points
2794  // ~~~~~~~~~~
2795  // These are used by face adding later on
2796 
2797  forAll(meshes, meshi)
2798  {
2799  if (meshes.set(meshi))
2800  {
2801  const polyMesh& mesh = meshes[meshi];
2802  const pointField& points = mesh.points();
2803  const pointZoneMesh& pointZones = mesh.pointZones();
2804 
2805  // Precalc offset zones
2806  labelList newZoneID(points.size(), -1);
2807 
2808  forAll(pointZones, zonei)
2809  {
2810  const labelList& pointLabels = pointZones[zonei];
2811 
2812  for (const label pointi : pointLabels)
2813  {
2814  newZoneID[pointi] = pointZoneMap[meshi][zonei];
2815  }
2816  }
2817 
2818  // Add points in mesh order
2819  const labelList& myUniquePoints = uniquePoints[meshi];
2820  for (const label pointi : myUniquePoints)
2821  {
2822  // Rewrite the addressing (should already be compact) just in
2823  // case the polyTopoChange does some special ordering
2824  pointProcAddressing[meshi][pointi] = meshMod.addPoint
2825  (
2826  points[pointi],
2827  pointi,
2828  newZoneID[pointi],
2829  true
2830  );
2831  }
2832  }
2833  }
2834 
2835 
2836 
2837  // Add faces
2838  // ~~~~~~~~~
2839 
2840  forAll(meshes, meshi)
2841  {
2842  if (meshes.set(meshi))
2843  {
2844  const polyMesh& mesh = meshes[meshi];
2845  faceProcAddressing[meshi].setSize(mesh.nFaces());
2846  faceProcAddressing[meshi] = -1;
2847  //boundaryProcAddressing[meshi].setSize(mesh.boundaryMesh().size());
2848  //boundaryProcAddressing[meshi] = -1;
2849  }
2850  }
2851 
2852  forAll(meshes, meshi)
2853  {
2854  if (meshes.set(meshi))
2855  {
2856  const polyMesh& mesh = meshes[meshi];
2857  const polyBoundaryMesh& pbm = mesh.boundaryMesh();
2858  const faceList& faces = mesh.faces();
2859  const labelList& faceOwner = mesh.faceOwner();
2860  const labelList& faceNeighbour = mesh.faceNeighbour();
2861  const faceZoneMesh& faceZones = mesh.faceZones();
2862 
2863  // Precalc offset zones
2864  labelList newZoneID(faces.size(), -1);
2865  boolList zoneFlip(faces.size(), false);
2866 
2867  forAll(faceZones, zonei)
2868  {
2869  const labelList& faceLabels = faceZones[zonei];
2870  const boolList& flipMap = faceZones[zonei].flipMap();
2871 
2872  forAll(faceLabels, facei)
2873  {
2874  newZoneID[faceLabels[facei]] = faceZoneMap[meshi][zonei];
2875  zoneFlip[faceLabels[facei]] = flipMap[facei];
2876  }
2877  }
2878 
2879  // Add faces in mesh order
2880 
2881  // 1. Internal faces
2882 
2883  face newFace;
2884  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
2885  {
2886  const face& f = faces[facei];
2887 
2888  label newOwn = cellProcAddressing[meshi][faceOwner[facei]];
2889  label newNei = cellProcAddressing[meshi][faceNeighbour[facei]];
2890 
2891  newFace.setSize(f.size());
2892  forAll(f, fp)
2893  {
2894  newFace[fp] = pointProcAddressing[meshi][f[fp]];
2895  }
2896  bool flipFaceFlux = false;
2897  bool flip = zoneFlip[facei];
2898  if (newNei < newOwn)
2899  {
2900  Swap(newOwn, newNei);
2901  newFace = newFace.reverseFace();
2902  flipFaceFlux = !flipFaceFlux;
2903  flip = !flip;
2904  }
2905 
2906  const label newFacei = meshMod.addFace
2907  (
2908  newFace,
2909  newOwn,
2910  newNei,
2911  -1, // masterPointID
2912  -1, // masterEdgeID
2913  facei, // masterFaceID
2914  flipFaceFlux, // flipFaceFlux
2915  -1, // patchID
2916  newZoneID[facei], // zoneID
2917  flip // zoneFlip
2918  );
2919 
2920  faceProcAddressing[meshi][facei] = newFacei;
2921  }
2922 
2923  // 1b. Owner side of coupled faces (since owner side cells are
2924  // smallest)
2925 
2926  const labelList& localBFaces = localBoundaryFace[meshi];
2927  const labelList& procNbrs = remoteFaceMesh[meshi];
2928  const labelList& procNbrBFaces = remoteBoundaryFace[meshi];
2929 
2930  forAll(localBFaces, i)
2931  {
2932  const label bFacei = localBFaces[i];
2933  const label nbrMeshi = procNbrs[i];
2934  const label nbrBFacei = procNbrBFaces[i];
2935 
2936  // Local mesh face
2937  const label facei = mesh.nInternalFaces()+bFacei;
2938  const face& f = mesh.faces()[facei];
2939  const label newOwn =
2940  cellProcAddressing[meshi][faceOwner[facei]];
2941 
2942  // Neighbour mesh face
2943  const auto& nbrMesh = meshes[nbrMeshi];
2944  const label nbrFacei = nbrMesh.nInternalFaces()+nbrBFacei;
2945  const label nbrOwn = nbrMesh.faceOwner()[nbrFacei];
2946  const label newNei = cellProcAddressing[nbrMeshi][nbrOwn];
2947 
2948  //Pout<< "** connection between face:" << facei
2949  // << " at:" << mesh.faceCentres()[facei]
2950  // << " and nbrMesh:" << nbrMeshi
2951  // << " nbrFacei:" << nbrMesh.faceCentres()[nbrFacei]
2952  // << endl;
2953 
2954  if (newOwn < newNei)
2955  {
2956  newFace.setSize(f.size());
2957  forAll(f, fp)
2958  {
2959  newFace[fp] = pointProcAddressing[meshi][f[fp]];
2960  }
2961  const bool flipFaceFlux = false;
2962  const bool flip = zoneFlip[facei];
2963  const label newFacei = meshMod.addFace
2964  (
2965  newFace,
2966  newOwn,
2967  newNei, // neighbour
2968  -1, // masterPointID
2969  -1, // masterEdgeID
2970  facei, // masterFaceID
2971  flipFaceFlux, // flipFaceFlux
2972  -1, // patchID
2973  newZoneID[facei], // zoneID
2974  flip // zoneFlip
2975  );
2976 
2977  faceProcAddressing[meshi][facei] = newFacei;
2978  faceProcAddressing[nbrMeshi][nbrFacei] = newFacei;
2979  }
2980  }
2981 
2982 
2983  // 2. Remaining patch faces
2984 
2985  forAll(pbm, patchi)
2986  {
2987  const auto& pp = pbm[patchi];
2988 
2989  if (patchi < patchMap[meshi].size())
2990  {
2991  const label newPatchi = patchMap[meshi][patchi];
2992 
2993  //boundaryProcAddressing[meshi][patchi] = newPatchi;
2994 
2995  forAll(pp, patchFacei)
2996  {
2997  const label facei = pp.start() + patchFacei;
2998  if (faceProcAddressing[meshi][facei] == -1)
2999  {
3000  const face& f = faces[facei];
3001 
3002  const label newOwn =
3003  cellProcAddressing[meshi][faceOwner[facei]];
3004  newFace.setSize(f.size());
3005  forAll(f, fp)
3006  {
3007  newFace[fp] = pointProcAddressing[meshi][f[fp]];
3008  }
3009 
3010  const label newFacei = meshMod.addFace
3011  (
3012  newFace,
3013  newOwn,
3014  -1, // neighbour
3015  -1, // masterPointID
3016  -1, // masterEdgeID
3017  facei, // masterFaceID
3018  false, // flipFaceFlux
3019  newPatchi, // patchID
3020  newZoneID[facei], // zoneID
3021  zoneFlip[facei] // zoneFlip
3022  );
3023 
3024  faceProcAddressing[meshi][facei] = newFacei;
3025  }
3026  }
3027  }
3028  }
3029  }
3030  }
3031 }
3032 
3033 
3034 // ************************************************************************* //
Foam::polyMesh::addPatches
void addPatches(PtrList< polyPatch > &plist, const bool validBoundary=true)
Add boundary patches.
Definition: polyMesh.C:961
Foam::polyTopoChange::addCell
label addCell(const label masterPointID, const label masterEdgeID, const label masterFaceID, const label masterCellID, const label zoneID)
Add cell. Return new cell label.
Definition: polyTopoChange.C:2895
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:67
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::face::reverseFace
face reverseFace() const
Return face with reverse direction.
Definition: face.C:636
faceProcAddressing
PtrList< labelIOList > & faceProcAddressing
Definition: checkFaceAddressingComp.H:9
meshPtr
Foam::autoPtr< Foam::fvMesh > meshPtr(nullptr)
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::Swap
void Swap(DynamicList< T, SizeMinA > &a, DynamicList< T, SizeMinB > &b)
Definition: DynamicList.H:429
Foam::globalPoints
Calculates points shared by more than two processor patches or cyclic patches.
Definition: globalPoints.H:102
Foam::boolListList
List< List< bool > > boolListList
A List of boolList.
Definition: boolList.H:48
polyRemovePoint.H
Foam::labelMax
constexpr label labelMax
Definition: label.H:61
Foam::faceZone::flipMap
const boolList & flipMap() const noexcept
Return face flip map.
Definition: faceZone.H:272
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::primitiveFacePatch
PrimitivePatch< List< face >, const pointField & > primitiveFacePatch
A PrimitivePatch with List storage for the faces, const reference for the point field.
Definition: primitiveFacePatch.H:51
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList< word >
Foam::polyTopoChange::removePoint
void removePoint(const label pointi, const label mergePointi)
Remove/merge point.
Definition: polyTopoChange.C:2699
globalMeshData.H
Foam::SubList
A List obtained as a section of another List.
Definition: SubList.H:54
globalIndex.H
Foam::polyTopoChange::addFace
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.
Definition: polyTopoChange.C:2747
polyTopoChange.H
Foam::polyTopoChange::addPoint
label addPoint(const point &pt, const label masterPointID, const label zoneID, const bool inCell)
Add point. Return new point label.
Definition: polyTopoChange.C:2610
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:99
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: lumpedPointController.H:69
Foam::processorPolyPatch::neighbProcNo
int neighbProcNo() const
Return neighbour processor number.
Definition: processorPolyPatch.H:274
Foam::boolList
List< bool > boolList
A List of bools.
Definition: List.H:65
Foam::List::append
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Foam::polyModifyFace
Class describing modification of a face.
Definition: polyModifyFace.H:50
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::PtrList::set
const T * set(const label i) const
Return const pointer to element (can be nullptr),.
Definition: PtrList.H:138
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::cellZoneMesh
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
Definition: cellZoneMeshFwd.H:44
Foam::edgeLookup
HashTable< labelList, edge, Hash< edge > > edgeLookup
Definition: faceCoupleInfo.H:147
Foam::pointZoneMesh
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
Definition: pointZoneMeshFwd.H:44
Foam::polyBoundaryMesh::start
label start() const
The start label of the boundary faces in the polyMesh face list.
Definition: polyBoundaryMesh.C:611
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::inplaceRenumber
void inplaceRenumber(const labelUList &oldToNew, IntListType &input)
Inplace renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:61
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::polyBoundaryMesh::names
wordList names() const
Return a list of patch names.
Definition: polyBoundaryMesh.C:555
Foam::primitiveMesh::nPoints
label nPoints() const noexcept
Number of mesh points.
Definition: primitiveMeshI.H:37
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::stableSort
void stableSort(UList< T > &a)
Definition: UList.C:275
pZones
IOporosityModelList pZones(mesh)
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::faceZoneMesh
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
Definition: faceZoneMeshFwd.H:44
n
label n
Definition: TABSMDCalcMethod2.H:31
SortableList.H
Foam::primitiveMesh::nCells
label nCells() const noexcept
Number of mesh cells.
Definition: primitiveMeshI.H:96
Foam::boolUIndList
UIndirectList< bool > boolUIndList
UIndirectList of bools.
Definition: UIndirectList.H:54
Foam::Field< vector >
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::polyMesh::cellZones
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:492
Foam::List::setSize
void setSize(const label n)
Alias for resize()
Definition: List.H:222
meshes
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
patchID
label patchID
Definition: boundaryProcessorFaPatchPoints.H:5
Foam::polyMesh::faceOwner
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1107
Foam::cellList
List< cell > cellList
A List of cells.
Definition: cellListFwd.H:47
Foam::PtrList::setSize
void setSize(const label newLen)
Same as resize()
Definition: PtrList.H:151
Foam::ZoneMesh< cellZone, polyMesh >
Foam::UPtrList
A list of pointers to objects of type <T>, without allocation/deallocation management of the pointers...
Definition: UPtrList.H:62
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
Foam::polyBoundaryMesh::whichPatch
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
Definition: polyBoundaryMesh.C:812
Foam::processorPolyPatch
Neighbour processor patch.
Definition: processorPolyPatch.H:58
mapAddedPolyMesh.H
Foam::List::appendUniq
label appendUniq(const T &val)
Append an element if not already in the list.
Definition: ListI.H:232
faceCoupleInfo.H
Foam::ZoneMesh::whichZone
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:289
Foam::processorPolyPatch::owner
virtual bool owner() const
Does the processor own the patch ?
Definition: processorPolyPatch.H:280
IOobject.H
Foam::FatalError
error FatalError
processorPolyPatch.H
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
zoneID
const labelIOList & zoneID
Definition: interpolatedFaces.H:22
Foam::faceZone::whichFace
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:372
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::globalIndex
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:68
polyMeshAdder.H
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:361
Foam::polyMeshAdder::findSharedPoints
static Map< label > findSharedPoints(const polyMesh &, const scalar mergeTol)
Find topologically and geometrically shared points.
Definition: polyMeshAdder.C:1987
polyModifyFace.H
Foam::mergePoints
label mergePoints(const PointList &points, const scalar mergeTol, const bool verbose, labelList &pointMap, typename PointList::const_reference origin=PointList::value_type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::indirectPrimitivePatch
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
A PrimitivePatch with an IndirectList for the faces, const reference for the point field.
Definition: indirectPrimitivePatch.H:49
Foam::polyBoundaryMesh::nNonProcessor
label nNonProcessor() const
The number of patches before the first processor patch.
Definition: polyBoundaryMesh.C:535
Foam::polyMeshAdder::procPatchPairs
static label procPatchPairs(const UPtrList< polyMesh > &meshes, List< DynamicList< label >> &localPatch, List< DynamicList< label >> &remoteMesh, List< DynamicList< label >> &remotePatch)
Definition: polyMeshAdder.C:2328
Foam::autoPtr::reset
void reset(autoPtr< T > &&other) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:117
Time.H
Foam::autoPtr< Foam::polyMesh >
Foam::labelListList
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
Foam::renumber
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values (not the indices) of a list.
Definition: ListOpsTemplates.C:37
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:84
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::polyTopoChange::setAction
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
Definition: polyTopoChange.C:2481
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
f
labelList f(nPoints)
Foam::globalIndex::size
label size() const
Global sum of localSizes.
Definition: globalIndexI.H:151
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::primitiveMesh::nInternalFaces
label nInternalFaces() const noexcept
Number of internal faces.
Definition: primitiveMeshI.H:78
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::UList
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:103
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::identity
labelList identity(const label len, label start=0)
Create identity map of the given length with (map[i] == i)
Definition: labelList.C:38
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
Foam::polyMesh::pointZones
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition: polyMesh.H:480
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::polyMeshAdder::add
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.
Definition: polyMeshAdder.C:1452
Foam::faceCoupleInfo
Container for information needed to couple to meshes. When constructed from two meshes and a geometri...
Definition: faceCoupleInfo.H:160
Foam::autoPtr::clear
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:176
mergePoints.H
Merge points. See below.
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:309
Foam::globalMeshData::sharedPointLabels
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
Definition: globalMeshData.C:1996
Foam::boundaryMesh
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
Definition: boundaryMesh.H:62
Foam::globalMeshData::sharedPointAddr
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points.
Definition: globalMeshData.C:2006
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
Foam::primitiveMesh::nFaces
label nFaces() const noexcept
Number of mesh faces.
Definition: primitiveMeshI.H:90
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::DelaunayMeshTools::allPoints
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
Foam::patchIdentifier::name
const word & name() const noexcept
The patch name.
Definition: patchIdentifier.H:135
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
Foam::polyMeshAdder::patchFacePairs
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)
Definition: polyMeshAdder.C:2449
Foam::polyMesh::globalData
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1295
Foam::mapAddedPolyMesh
Class containing mesh-to-mesh mapping information after a mesh addition where we add a mesh ('added m...
Definition: mapAddedPolyMesh.H:58
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
Foam::faceCoupleInfo::cutFaces
const primitiveFacePatch & cutFaces() const
Addressing engine for combined set of faces.
Definition: faceCoupleInfo.H:467
Foam::invertOneToMany
labelListList invertOneToMany(const label len, const labelUList &map)
Invert one-to-many map. Unmapped elements will be size 0.
Definition: ListOps.C:114
Foam::PtrListOps::names
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::polyMesh::addZones
void addZones(const List< pointZone * > &pz, const List< faceZone * > &fz, const List< cellZone * > &cz)
Add mesh zones.
Definition: polyMesh.C:999
pointLabels
labelList pointLabels(nPoints, -1)
Foam::polyMeshAdder::mergePoints
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
Definition: polyMeshAdder.C:2198
Foam::polyMesh::faceNeighbour
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1113
Foam::globalIndex::toGlobal
label toGlobal(const label i) const
From local to global index.
Definition: globalIndexI.H:240
Foam::labelUIndList
UIndirectList< label > labelUIndList
UIndirectList of labels.
Definition: UIndirectList.H:58