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 | Copyright (C) 2011-2016 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "polyMeshAdder.H"
27 #include "mapAddedPolyMesh.H"
28 #include "IOobject.H"
29 #include "faceCoupleInfo.H"
30 #include "processorPolyPatch.H"
31 #include "SortableList.H"
32 #include "Time.H"
33 #include "globalMeshData.H"
34 #include "mergePoints.H"
35 #include "polyModifyFace.H"
36 #include "polyRemovePoint.H"
37 #include "polyTopoChange.H"
38 
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 
41 // Get index of patch in new set of patchnames/types
42 Foam::label Foam::polyMeshAdder::patchIndex
43 (
44  const polyPatch& p,
45  DynamicList<word>& allPatchNames,
46  DynamicList<word>& allPatchTypes
47 )
48 {
49  // Find the patch name on the list. If the patch is already there
50  // and patch types match, return index
51  const word& pType = p.type();
52  const word& pName = p.name();
53 
54  label patchi = findIndex(allPatchNames, pName);
55 
56  if (patchi == -1)
57  {
58  // Patch not found. Append to the list
59  allPatchNames.append(pName);
60  allPatchTypes.append(pType);
61 
62  return allPatchNames.size() - 1;
63  }
64  else if (allPatchTypes[patchi] == pType)
65  {
66  // Found name and types match
67  return patchi;
68  }
69  else
70  {
71  // Found the name, but type is different
72 
73  // Duplicate name is not allowed. Create a composite name from the
74  // patch name and case name
75  const word& caseName = p.boundaryMesh().mesh().time().caseName();
76 
77  allPatchNames.append(pName + "_" + caseName);
78  allPatchTypes.append(pType);
79 
80  Pout<< "label patchIndex(const polyPatch& p) : "
81  << "Patch " << p.index() << " named "
82  << pName << " in mesh " << caseName
83  << " already exists, but patch types"
84  << " do not match.\nCreating a composite name as "
85  << allPatchNames.last() << endl;
86 
87  return allPatchNames.size() - 1;
88  }
89 }
90 
91 
92 // Get index of zone in new set of zone names
93 Foam::label Foam::polyMeshAdder::zoneIndex
94 (
95  const word& curName,
96  DynamicList<word>& names
97 )
98 {
99  label zoneI = findIndex(names, curName);
100 
101  if (zoneI != -1)
102  {
103  return zoneI;
104  }
105  else
106  {
107  // Not found. Add new name to the list
108  names.append(curName);
109 
110  return names.size() - 1;
111  }
112 }
113 
114 
115 void Foam::polyMeshAdder::mergePatchNames
116 (
117  const polyBoundaryMesh& patches0,
118  const polyBoundaryMesh& patches1,
119 
120  DynamicList<word>& allPatchNames,
121  DynamicList<word>& allPatchTypes,
122 
123  labelList& from1ToAllPatches,
124  labelList& fromAllTo1Patches
125 )
126 {
127  // Insert the mesh0 patches and zones
128  allPatchNames.append(patches0.names());
129  allPatchTypes.append(patches0.types());
130 
131 
132  // Patches
133  // ~~~~~~~
134  // Patches from 0 are taken over as is; those from 1 get either merged
135  // (if they share name and type) or appended.
136  // Empty patches are filtered out much much later on.
137 
138  // Add mesh1 patches and build map both ways.
139  from1ToAllPatches.setSize(patches1.size());
140 
141  forAll(patches1, patchi)
142  {
143  from1ToAllPatches[patchi] = patchIndex
144  (
145  patches1[patchi],
146  allPatchNames,
147  allPatchTypes
148  );
149  }
150  allPatchTypes.shrink();
151  allPatchNames.shrink();
152 
153  // Invert 1 to all patch map
154  fromAllTo1Patches.setSize(allPatchNames.size());
155  fromAllTo1Patches = -1;
156 
157  forAll(from1ToAllPatches, i)
158  {
159  fromAllTo1Patches[from1ToAllPatches[i]] = i;
160  }
161 }
162 
163 
164 Foam::labelList Foam::polyMeshAdder::getPatchStarts
165 (
166  const polyBoundaryMesh& patches
167 )
168 {
169  labelList patchStarts(patches.size());
170  forAll(patches, patchi)
171  {
172  patchStarts[patchi] = patches[patchi].start();
173  }
174  return patchStarts;
175 }
176 
177 
178 Foam::labelList Foam::polyMeshAdder::getPatchSizes
179 (
180  const polyBoundaryMesh& patches
181 )
182 {
183  labelList patchSizes(patches.size());
184  forAll(patches, patchi)
185  {
186  patchSizes[patchi] = patches[patchi].size();
187  }
188  return patchSizes;
189 }
190 
191 
192 Foam::List<Foam::polyPatch*> Foam::polyMeshAdder::combinePatches
193 (
194  const polyMesh& mesh0,
195  const polyMesh& mesh1,
196  const polyBoundaryMesh& allBoundaryMesh,
197  const label nAllPatches,
198  const labelList& fromAllTo1Patches,
199 
200  const label nInternalFaces,
201  const labelList& nFaces,
202 
203  labelList& from0ToAllPatches,
204  labelList& from1ToAllPatches
205 )
206 {
207  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
208  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
209 
210 
211  // Compacted new patch list.
212  DynamicList<polyPatch*> allPatches(nAllPatches);
213 
214 
215  // Map from 0 to all patches (since gets compacted)
216  from0ToAllPatches.setSize(patches0.size());
217  from0ToAllPatches = -1;
218 
219  label startFacei = nInternalFaces;
220 
221  // Copy patches0 with new sizes. First patches always come from
222  // mesh0 and will always be present.
223  forAll(patches0, patchi)
224  {
225  // Originates from mesh0. Clone with new size & filter out empty
226  // patch.
227  label filteredPatchi;
228 
229  if (nFaces[patchi] == 0 && isA<processorPolyPatch>(patches0[patchi]))
230  {
231  //Pout<< "Removing zero sized mesh0 patch "
232  // << patches0[patchi].name() << endl;
233  filteredPatchi = -1;
234  }
235  else
236  {
237  filteredPatchi = allPatches.size();
238 
239  allPatches.append
240  (
241  patches0[patchi].clone
242  (
243  allBoundaryMesh,
244  filteredPatchi,
245  nFaces[patchi],
246  startFacei
247  ).ptr()
248  );
249  startFacei += nFaces[patchi];
250  }
251 
252  // Record new index in allPatches
253  from0ToAllPatches[patchi] = filteredPatchi;
254 
255  // Check if patch was also in mesh1 and update its addressing if so.
256  if (fromAllTo1Patches[patchi] != -1)
257  {
258  from1ToAllPatches[fromAllTo1Patches[patchi]] = filteredPatchi;
259  }
260  }
261 
262  // Copy unique patches of mesh1.
263  forAll(from1ToAllPatches, patchi)
264  {
265  label allPatchi = from1ToAllPatches[patchi];
266 
267  if (allPatchi >= patches0.size())
268  {
269  // Patch has not been merged with any mesh0 patch.
270 
271  label filteredPatchi;
272 
273  if
274  (
275  nFaces[allPatchi] == 0
276  && isA<processorPolyPatch>(patches1[patchi])
277  )
278  {
279  //Pout<< "Removing zero sized mesh1 patch "
280  // << patches1[patchi].name() << endl;
281  filteredPatchi = -1;
282  }
283  else
284  {
285  filteredPatchi = allPatches.size();
286 
287  allPatches.append
288  (
289  patches1[patchi].clone
290  (
291  allBoundaryMesh,
292  filteredPatchi,
293  nFaces[allPatchi],
294  startFacei
295  ).ptr()
296  );
297  startFacei += nFaces[allPatchi];
298  }
299 
300  from1ToAllPatches[patchi] = filteredPatchi;
301  }
302  }
303 
304  allPatches.shrink();
305 
306  return allPatches;
307 }
308 
309 
310 Foam::labelList Foam::polyMeshAdder::getFaceOrder
311 (
312  const cellList& cells,
313  const label nInternalFaces,
314  const labelList& owner,
315  const labelList& neighbour
316 )
317 {
318  labelList oldToNew(owner.size(), -1);
319 
320  // Leave boundary faces in order
321  for (label facei = nInternalFaces; facei < owner.size(); ++facei)
322  {
323  oldToNew[facei] = facei;
324  }
325 
326  // First unassigned face
327  label newFacei = 0;
328 
329  forAll(cells, celli)
330  {
331  const labelList& cFaces = cells[celli];
332 
333  SortableList<label> nbr(cFaces.size());
334 
335  forAll(cFaces, i)
336  {
337  label facei = cFaces[i];
338 
339  label nbrCelli = neighbour[facei];
340 
341  if (nbrCelli != -1)
342  {
343  // Internal face. Get cell on other side.
344  if (nbrCelli == celli)
345  {
346  nbrCelli = owner[facei];
347  }
348 
349  if (celli < nbrCelli)
350  {
351  // Celli is master
352  nbr[i] = nbrCelli;
353  }
354  else
355  {
356  // nbrCell is master. Let it handle this face.
357  nbr[i] = -1;
358  }
359  }
360  else
361  {
362  // External face. Do later.
363  nbr[i] = -1;
364  }
365  }
366 
367  nbr.sort();
368 
369  forAll(nbr, i)
370  {
371  if (nbr[i] != -1)
372  {
373  oldToNew[cFaces[nbr.indices()[i]]] = newFacei++;
374  }
375  }
376  }
377 
378 
379  // Check done all faces.
380  forAll(oldToNew, facei)
381  {
382  if (oldToNew[facei] == -1)
383  {
385  << "Did not determine new position"
386  << " for face " << facei
387  << abort(FatalError);
388  }
389  }
390 
391  return oldToNew;
392 }
393 
394 
395 // Extends face f with split points. cutEdgeToPoints gives for every
396 // edge the points introduced inbetween the endpoints.
397 void Foam::polyMeshAdder::insertVertices
398 (
399  const edgeLookup& cutEdgeToPoints,
400  const Map<label>& meshToMaster,
401  const labelList& masterToCutPoints,
402  const face& masterF,
403 
404  DynamicList<label>& workFace,
405  face& allF
406 )
407 {
408  workFace.clear();
409 
410  // Check any edge for being cut (check on the cut so takes account
411  // for any point merging on the cut)
412 
413  forAll(masterF, fp)
414  {
415  label v0 = masterF[fp];
416  label v1 = masterF.nextLabel(fp);
417 
418  // Copy existing face point
419  workFace.append(allF[fp]);
420 
421  // See if any edge between v0,v1
422 
423  Map<label>::const_iterator v0Fnd = meshToMaster.find(v0);
424  if (v0Fnd != meshToMaster.end())
425  {
426  Map<label>::const_iterator v1Fnd = meshToMaster.find(v1);
427  if (v1Fnd != meshToMaster.end())
428  {
429  // Get edge in cutPoint numbering
430  edge cutEdge
431  (
432  masterToCutPoints[v0Fnd()],
433  masterToCutPoints[v1Fnd()]
434  );
435 
436  edgeLookup::const_iterator iter = cutEdgeToPoints.find(cutEdge);
437 
438  if (iter != cutEdgeToPoints.end())
439  {
440  const edge& e = iter.key();
441  const labelList& addedPoints = iter();
442 
443  // cutPoints first in allPoints so no need for renumbering
444  if (e[0] == cutEdge[0])
445  {
446  forAll(addedPoints, i)
447  {
448  workFace.append(addedPoints[i]);
449  }
450  }
451  else
452  {
453  forAllReverse(addedPoints, i)
454  {
455  workFace.append(addedPoints[i]);
456  }
457  }
458  }
459  }
460  }
461  }
462 
463  if (workFace.size() != allF.size())
464  {
465  allF.transfer(workFace);
466  }
467 }
468 
469 
470 // Adds primitives (cells, faces, points)
471 // Cells:
472 // - all of mesh0
473 // - all of mesh1
474 // Faces:
475 // - all uncoupled of mesh0
476 // - all coupled faces
477 // - all uncoupled of mesh1
478 // Points:
479 // - all coupled
480 // - all uncoupled of mesh0
481 // - all uncoupled of mesh1
482 void Foam::polyMeshAdder::mergePrimitives
483 (
484  const polyMesh& mesh0,
485  const polyMesh& mesh1,
486  const faceCoupleInfo& coupleInfo,
487 
488  const label nAllPatches, // number of patches in the new mesh
489  const labelList& fromAllTo1Patches,
490  const labelList& from1ToAllPatches,
491 
492  pointField& allPoints,
493  labelList& from0ToAllPoints,
494  labelList& from1ToAllPoints,
495 
496  faceList& allFaces,
497  labelList& allOwner,
498  labelList& allNeighbour,
499  label& nInternalFaces,
500  labelList& nFacesPerPatch,
501  label& nCells,
502 
503  labelList& from0ToAllFaces,
504  labelList& from1ToAllFaces,
505  labelList& from1ToAllCells
506 )
507 {
508  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
509  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
510 
511  const primitiveFacePatch& cutFaces = coupleInfo.cutFaces();
512  const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
513  const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
514 
515 
516  // Points
517  // ~~~~~~
518 
519  // Storage for new points
520  allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
521  label allPointi = 0;
522 
523  from0ToAllPoints.setSize(mesh0.nPoints());
524  from0ToAllPoints = -1;
525  from1ToAllPoints.setSize(mesh1.nPoints());
526  from1ToAllPoints = -1;
527 
528  // Copy coupled points (on cut)
529  {
530  const pointField& cutPoints = coupleInfo.cutPoints();
531 
532  //const labelListList& cutToMasterPoints =
533  // coupleInfo.cutToMasterPoints();
534  labelListList cutToMasterPoints
535  (
537  (
538  cutPoints.size(),
539  coupleInfo.masterToCutPoints()
540  )
541  );
542 
543  //const labelListList& cutToSlavePoints =
544  // coupleInfo.cutToSlavePoints();
545  labelListList cutToSlavePoints
546  (
548  (
549  cutPoints.size(),
550  coupleInfo.slaveToCutPoints()
551  )
552  );
553 
554  forAll(cutPoints, i)
555  {
556  allPoints[allPointi] = cutPoints[i];
557 
558  // Mark all master and slave points referring to this point.
559 
560  const labelList& masterPoints = cutToMasterPoints[i];
561 
562  forAll(masterPoints, j)
563  {
564  label mesh0Pointi = masterPatch.meshPoints()[masterPoints[j]];
565  from0ToAllPoints[mesh0Pointi] = allPointi;
566  }
567 
568  const labelList& slavePoints = cutToSlavePoints[i];
569 
570  forAll(slavePoints, j)
571  {
572  label mesh1Pointi = slavePatch.meshPoints()[slavePoints[j]];
573  from1ToAllPoints[mesh1Pointi] = allPointi;
574  }
575  allPointi++;
576  }
577  }
578 
579  // Add uncoupled mesh0 points
580  forAll(mesh0.points(), pointi)
581  {
582  if (from0ToAllPoints[pointi] == -1)
583  {
584  allPoints[allPointi] = mesh0.points()[pointi];
585  from0ToAllPoints[pointi] = allPointi;
586  allPointi++;
587  }
588  }
589 
590  // Add uncoupled mesh1 points
591  forAll(mesh1.points(), pointi)
592  {
593  if (from1ToAllPoints[pointi] == -1)
594  {
595  allPoints[allPointi] = mesh1.points()[pointi];
596  from1ToAllPoints[pointi] = allPointi;
597  allPointi++;
598  }
599  }
600 
601  allPoints.setSize(allPointi);
602 
603 
604  // Faces
605  // ~~~~~
606 
607  // Sizes per patch
608  nFacesPerPatch.setSize(nAllPatches);
609  nFacesPerPatch = 0;
610 
611  // Storage for faces and owner/neighbour
612  allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
613  allOwner.setSize(allFaces.size());
614  allOwner = -1;
615  allNeighbour.setSize(allFaces.size());
616  allNeighbour = -1;
617  label allFacei = 0;
618 
619  from0ToAllFaces.setSize(mesh0.nFaces());
620  from0ToAllFaces = -1;
621  from1ToAllFaces.setSize(mesh1.nFaces());
622  from1ToAllFaces = -1;
623 
624  // Copy mesh0 internal faces (always uncoupled)
625  for (label facei = 0; facei < mesh0.nInternalFaces(); facei++)
626  {
627  allFaces[allFacei] = renumber(from0ToAllPoints, mesh0.faces()[facei]);
628  allOwner[allFacei] = mesh0.faceOwner()[facei];
629  allNeighbour[allFacei] = mesh0.faceNeighbour()[facei];
630  from0ToAllFaces[facei] = allFacei++;
631  }
632 
633  // Copy coupled faces. Every coupled face has an equivalent master and
634  // slave. Also uncount as boundary faces all the newly coupled faces.
635  const labelList& cutToMasterFaces = coupleInfo.cutToMasterFaces();
636  const labelList& cutToSlaveFaces = coupleInfo.cutToSlaveFaces();
637 
638  forAll(cutFaces, i)
639  {
640  label masterFacei = cutToMasterFaces[i];
641 
642  label mesh0Facei = masterPatch.addressing()[masterFacei];
643 
644  if (from0ToAllFaces[mesh0Facei] == -1)
645  {
646  // First occurrence of face
647  from0ToAllFaces[mesh0Facei] = allFacei;
648 
649  // External face becomes internal so uncount
650  label patch0 = patches0.whichPatch(mesh0Facei);
651  nFacesPerPatch[patch0]--;
652  }
653 
654  label slaveFacei = cutToSlaveFaces[i];
655 
656  label mesh1Facei = slavePatch.addressing()[slaveFacei];
657 
658  if (from1ToAllFaces[mesh1Facei] == -1)
659  {
660  from1ToAllFaces[mesh1Facei] = allFacei;
661 
662  label patch1 = patches1.whichPatch(mesh1Facei);
663  nFacesPerPatch[from1ToAllPatches[patch1]]--;
664  }
665 
666  // Copy cut face (since cutPoints are copied first no renumbering
667  // necessary)
668  allFaces[allFacei] = cutFaces[i];
669  allOwner[allFacei] = mesh0.faceOwner()[mesh0Facei];
670  allNeighbour[allFacei] = mesh1.faceOwner()[mesh1Facei] + mesh0.nCells();
671 
672  allFacei++;
673  }
674 
675  // Copy mesh1 internal faces (always uncoupled)
676  for (label facei = 0; facei < mesh1.nInternalFaces(); facei++)
677  {
678  allFaces[allFacei] = renumber(from1ToAllPoints, mesh1.faces()[facei]);
679  allOwner[allFacei] = mesh1.faceOwner()[facei] + mesh0.nCells();
680  allNeighbour[allFacei] = mesh1.faceNeighbour()[facei] + mesh0.nCells();
681  from1ToAllFaces[facei] = allFacei++;
682  }
683 
684  nInternalFaces = allFacei;
685 
686  // Copy (unmarked/uncoupled) external faces in new order.
687  for (label allPatchi = 0; allPatchi < nAllPatches; allPatchi++)
688  {
689  if (allPatchi < patches0.size())
690  {
691  // Patch is present in mesh0
692  const polyPatch& pp = patches0[allPatchi];
693 
694  nFacesPerPatch[allPatchi] += pp.size();
695 
696  label facei = pp.start();
697 
698  forAll(pp, i)
699  {
700  if (from0ToAllFaces[facei] == -1)
701  {
702  // Is uncoupled face since has not yet been dealt with
703  allFaces[allFacei] = renumber
704  (
705  from0ToAllPoints,
706  mesh0.faces()[facei]
707  );
708  allOwner[allFacei] = mesh0.faceOwner()[facei];
709  allNeighbour[allFacei] = -1;
710 
711  from0ToAllFaces[facei] = allFacei++;
712  }
713  facei++;
714  }
715  }
716  if (fromAllTo1Patches[allPatchi] != -1)
717  {
718  // Patch is present in mesh1
719  const polyPatch& pp = patches1[fromAllTo1Patches[allPatchi]];
720 
721  nFacesPerPatch[allPatchi] += pp.size();
722 
723  label facei = pp.start();
724 
725  forAll(pp, i)
726  {
727  if (from1ToAllFaces[facei] == -1)
728  {
729  // Is uncoupled face
730  allFaces[allFacei] = renumber
731  (
732  from1ToAllPoints,
733  mesh1.faces()[facei]
734  );
735  allOwner[allFacei] =
736  mesh1.faceOwner()[facei]
737  + mesh0.nCells();
738  allNeighbour[allFacei] = -1;
739 
740  from1ToAllFaces[facei] = allFacei++;
741  }
742  facei++;
743  }
744  }
745  }
746  allFaces.setSize(allFacei);
747  allOwner.setSize(allFacei);
748  allNeighbour.setSize(allFacei);
749 
750 
751  // So now we have all ok for one-to-one mapping.
752  // For split slace faces:
753  // - mesh consistent with slave side
754  // - mesh not consistent with owner side. It is not zipped up, the
755  // original faces need edges split.
756 
757  // Use brute force to prevent having to calculate addressing:
758  // - get map from master edge to split edges.
759  // - check all faces to find any edge that is split.
760  {
761  // From two cut-points to labels of cut-points inbetween.
762  // (in order: from e[0] to e[1]
763  const edgeLookup& cutEdgeToPoints = coupleInfo.cutEdgeToPoints();
764 
765  // Get map of master face (in mesh labels) that are in cut. These faces
766  // do not need to be renumbered.
767  labelHashSet masterCutFaces(cutToMasterFaces.size());
768  forAll(cutToMasterFaces, i)
769  {
770  label meshFacei = masterPatch.addressing()[cutToMasterFaces[i]];
771 
772  masterCutFaces.insert(meshFacei);
773  }
774 
775  DynamicList<label> workFace(100);
776 
777  forAll(from0ToAllFaces, face0)
778  {
779  if (!masterCutFaces.found(face0))
780  {
781  label allFacei = from0ToAllFaces[face0];
782 
783  insertVertices
784  (
785  cutEdgeToPoints,
786  masterPatch.meshPointMap(),
787  coupleInfo.masterToCutPoints(),
788  mesh0.faces()[face0],
789 
790  workFace,
791  allFaces[allFacei]
792  );
793  }
794  }
795 
796  // Same for slave face
797 
798  labelHashSet slaveCutFaces(cutToSlaveFaces.size());
799  forAll(cutToSlaveFaces, i)
800  {
801  label meshFacei = slavePatch.addressing()[cutToSlaveFaces[i]];
802 
803  slaveCutFaces.insert(meshFacei);
804  }
805 
806  forAll(from1ToAllFaces, face1)
807  {
808  if (!slaveCutFaces.found(face1))
809  {
810  label allFacei = from1ToAllFaces[face1];
811 
812  insertVertices
813  (
814  cutEdgeToPoints,
815  slavePatch.meshPointMap(),
816  coupleInfo.slaveToCutPoints(),
817  mesh1.faces()[face1],
818 
819  workFace,
820  allFaces[allFacei]
821  );
822  }
823  }
824  }
825 
826  // Now we have a full facelist and owner/neighbour addressing.
827 
828 
829  // Cells
830  // ~~~~~
831 
832  from1ToAllCells.setSize(mesh1.nCells());
833  from1ToAllCells = -1;
834 
835  forAll(mesh1.cells(), i)
836  {
837  from1ToAllCells[i] = i + mesh0.nCells();
838  }
839 
840  // Make cells (= cell-face addressing)
841  nCells = mesh0.nCells() + mesh1.nCells();
842  cellList allCells(nCells);
843  primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
844 
845  // Reorder faces for upper-triangular order.
846  labelList oldToNew
847  (
848  getFaceOrder
849  (
850  allCells,
851  nInternalFaces,
852  allOwner,
853  allNeighbour
854  )
855  );
856 
857  inplaceReorder(oldToNew, allFaces);
858  inplaceReorder(oldToNew, allOwner);
859  inplaceReorder(oldToNew, allNeighbour);
860  inplaceRenumber(oldToNew, from0ToAllFaces);
861  inplaceRenumber(oldToNew, from1ToAllFaces);
862 }
863 
864 
865 void Foam::polyMeshAdder::mergePointZones
866 (
867  const label nAllPoints,
868  const pointZoneMesh& pz0,
869  const pointZoneMesh& pz1,
870  const labelList& from0ToAllPoints,
871  const labelList& from1ToAllPoints,
872 
873  DynamicList<word>& zoneNames,
874  labelList& from1ToAll,
875  List<DynamicList<label>>& pzPoints
876 )
877 {
878  zoneNames.setCapacity(pz0.size() + pz1.size());
879  zoneNames.append(pz0.names());
880 
881  from1ToAll.setSize(pz1.size());
882 
883  forAll(pz1, zoneI)
884  {
885  from1ToAll[zoneI] = zoneIndex(pz1[zoneI].name(), zoneNames);
886  }
887  zoneNames.shrink();
888 
889 
890 
891  // Zone(s) per point. Two levels: if only one zone
892  // stored in pointToZone. Any extra stored in additionalPointToZones.
893  // This is so we only allocate labelLists per point if absolutely
894  // necesary.
895  labelList pointToZone(nAllPoints, -1);
896  labelListList addPointToZones(nAllPoints);
897 
898  // mesh0 zones kept
899  forAll(pz0, zoneI)
900  {
901  const pointZone& pz = pz0[zoneI];
902 
903  forAll(pz, i)
904  {
905  label point0 = pz[i];
906  label allPointi = from0ToAllPoints[point0];
907 
908  if (pointToZone[allPointi] == -1)
909  {
910  pointToZone[allPointi] = zoneI;
911  }
912  else if (pointToZone[allPointi] != zoneI)
913  {
914  labelList& pZones = addPointToZones[allPointi];
915  if (findIndex(pZones, zoneI) == -1)
916  {
917  pZones.append(zoneI);
918  }
919  }
920  }
921  }
922 
923  // mesh1 zones renumbered
924  forAll(pz1, zoneI)
925  {
926  const pointZone& pz = pz1[zoneI];
927  const label allZoneI = from1ToAll[zoneI];
928 
929  forAll(pz, i)
930  {
931  label point1 = pz[i];
932  label allPointi = from1ToAllPoints[point1];
933 
934  if (pointToZone[allPointi] == -1)
935  {
936  pointToZone[allPointi] = allZoneI;
937  }
938  else if (pointToZone[allPointi] != allZoneI)
939  {
940  labelList& pZones = addPointToZones[allPointi];
941  if (findIndex(pZones, allZoneI) == -1)
942  {
943  pZones.append(allZoneI);
944  }
945  }
946  }
947  }
948 
949  // Extract back into zones
950 
951  // 1. Count
952  labelList nPoints(zoneNames.size(), 0);
953  forAll(pointToZone, allPointi)
954  {
955  label zoneI = pointToZone[allPointi];
956  if (zoneI != -1)
957  {
958  nPoints[zoneI]++;
959  }
960  }
961  forAll(addPointToZones, allPointi)
962  {
963  const labelList& pZones = addPointToZones[allPointi];
964  forAll(pZones, i)
965  {
966  nPoints[pZones[i]]++;
967  }
968  }
969 
970  // 2. Fill
971  pzPoints.setSize(zoneNames.size());
972  forAll(pzPoints, zoneI)
973  {
974  pzPoints[zoneI].setCapacity(nPoints[zoneI]);
975  }
976  forAll(pointToZone, allPointi)
977  {
978  label zoneI = pointToZone[allPointi];
979  if (zoneI != -1)
980  {
981  pzPoints[zoneI].append(allPointi);
982  }
983  }
984  forAll(addPointToZones, allPointi)
985  {
986  const labelList& pZones = addPointToZones[allPointi];
987  forAll(pZones, i)
988  {
989  pzPoints[pZones[i]].append(allPointi);
990  }
991  }
992  forAll(pzPoints, i)
993  {
994  pzPoints[i].shrink();
995  stableSort(pzPoints[i]);
996  }
997 }
998 
999 
1000 void Foam::polyMeshAdder::mergeFaceZones
1001 (
1002  const labelList& allOwner,
1003 
1004  const polyMesh& mesh0,
1005  const polyMesh& mesh1,
1006 
1007  const labelList& from0ToAllFaces,
1008  const labelList& from1ToAllFaces,
1009 
1010  const labelList& from1ToAllCells,
1011 
1012  DynamicList<word>& zoneNames,
1013  labelList& from1ToAll,
1014  List<DynamicList<label>>& fzFaces,
1015  List<DynamicList<bool>>& fzFlips
1016 )
1017 {
1018  const faceZoneMesh& fz0 = mesh0.faceZones();
1019  const labelList& owner0 = mesh0.faceOwner();
1020  const faceZoneMesh& fz1 = mesh1.faceZones();
1021  const labelList& owner1 = mesh1.faceOwner();
1022 
1023 
1024  zoneNames.setCapacity(fz0.size() + fz1.size());
1025  zoneNames.append(fz0.names());
1026 
1027  from1ToAll.setSize(fz1.size());
1028 
1029  forAll(fz1, zoneI)
1030  {
1031  from1ToAll[zoneI] = zoneIndex(fz1[zoneI].name(), zoneNames);
1032  }
1033  zoneNames.shrink();
1034 
1035 
1036  // Zone(s) per face
1037  labelList faceToZone(allOwner.size(), -1);
1038  labelListList addFaceToZones(allOwner.size());
1039  boolList faceToFlip(allOwner.size(), false);
1040  boolListList addFaceToFlips(allOwner.size());
1041 
1042  // mesh0 zones kept
1043  forAll(fz0, zoneI)
1044  {
1045  const labelList& addressing = fz0[zoneI];
1046  const boolList& flipMap = fz0[zoneI].flipMap();
1047 
1048  forAll(addressing, i)
1049  {
1050  label face0 = addressing[i];
1051  bool flip0 = flipMap[i];
1052 
1053  label allFacei = from0ToAllFaces[face0];
1054  if (allFacei != -1)
1055  {
1056  // Check if orientation same
1057  label allCell0 = owner0[face0];
1058  if (allOwner[allFacei] != allCell0)
1059  {
1060  flip0 = !flip0;
1061  }
1062 
1063  if (faceToZone[allFacei] == -1)
1064  {
1065  faceToZone[allFacei] = zoneI;
1066  faceToFlip[allFacei] = flip0;
1067  }
1068  else if (faceToZone[allFacei] != zoneI)
1069  {
1070  labelList& fZones = addFaceToZones[allFacei];
1071  boolList& flipZones = addFaceToFlips[allFacei];
1072 
1073  if (findIndex(fZones, zoneI) == -1)
1074  {
1075  fZones.append(zoneI);
1076  flipZones.append(flip0);
1077  }
1078  }
1079  }
1080  }
1081  }
1082 
1083  // mesh1 zones renumbered
1084  forAll(fz1, zoneI)
1085  {
1086  const labelList& addressing = fz1[zoneI];
1087  const boolList& flipMap = fz1[zoneI].flipMap();
1088 
1089  const label allZoneI = from1ToAll[zoneI];
1090 
1091  forAll(addressing, i)
1092  {
1093  label face1 = addressing[i];
1094  bool flip1 = flipMap[i];
1095 
1096  label allFacei = from1ToAllFaces[face1];
1097  if (allFacei != -1)
1098  {
1099  // Check if orientation same
1100  label allCell1 = from1ToAllCells[owner1[face1]];
1101  if (allOwner[allFacei] != allCell1)
1102  {
1103  flip1 = !flip1;
1104  }
1105 
1106  if (faceToZone[allFacei] == -1)
1107  {
1108  faceToZone[allFacei] = allZoneI;
1109  faceToFlip[allFacei] = flip1;
1110  }
1111  else if (faceToZone[allFacei] != allZoneI)
1112  {
1113  labelList& fZones = addFaceToZones[allFacei];
1114  boolList& flipZones = addFaceToFlips[allFacei];
1115 
1116  if (findIndex(fZones, allZoneI) == -1)
1117  {
1118  fZones.append(allZoneI);
1119  flipZones.append(flip1);
1120  }
1121  }
1122  }
1123  }
1124  }
1125 
1126 
1127  // Extract back into zones
1128 
1129  // 1. Count
1130  labelList nFaces(zoneNames.size(), 0);
1131  forAll(faceToZone, allFacei)
1132  {
1133  label zoneI = faceToZone[allFacei];
1134  if (zoneI != -1)
1135  {
1136  nFaces[zoneI]++;
1137  }
1138  }
1139  forAll(addFaceToZones, allFacei)
1140  {
1141  const labelList& fZones = addFaceToZones[allFacei];
1142  forAll(fZones, i)
1143  {
1144  nFaces[fZones[i]]++;
1145  }
1146  }
1147 
1148  // 2. Fill
1149  fzFaces.setSize(zoneNames.size());
1150  fzFlips.setSize(zoneNames.size());
1151  forAll(fzFaces, zoneI)
1152  {
1153  fzFaces[zoneI].setCapacity(nFaces[zoneI]);
1154  fzFlips[zoneI].setCapacity(nFaces[zoneI]);
1155  }
1156  forAll(faceToZone, allFacei)
1157  {
1158  label zoneI = faceToZone[allFacei];
1159  bool flip = faceToFlip[allFacei];
1160  if (zoneI != -1)
1161  {
1162  fzFaces[zoneI].append(allFacei);
1163  fzFlips[zoneI].append(flip);
1164  }
1165  }
1166  forAll(addFaceToZones, allFacei)
1167  {
1168  const labelList& fZones = addFaceToZones[allFacei];
1169  const boolList& flipZones = addFaceToFlips[allFacei];
1170 
1171  forAll(fZones, i)
1172  {
1173  label zoneI = fZones[i];
1174  fzFaces[zoneI].append(allFacei);
1175  fzFlips[zoneI].append(flipZones[i]);
1176  }
1177  }
1178 
1179  forAll(fzFaces, i)
1180  {
1181  fzFaces[i].shrink();
1182  fzFlips[i].shrink();
1183 
1184  labelList order;
1185  sortedOrder(fzFaces[i], order);
1186  fzFaces[i] = UIndirectList<label>(fzFaces[i], order)();
1187  fzFlips[i] = UIndirectList<bool>(fzFlips[i], order)();
1188  }
1189 }
1190 
1191 
1192 void Foam::polyMeshAdder::mergeCellZones
1193 (
1194  const label nAllCells,
1195 
1196  const cellZoneMesh& cz0,
1197  const cellZoneMesh& cz1,
1198  const labelList& from1ToAllCells,
1199 
1200  DynamicList<word>& zoneNames,
1201  labelList& from1ToAll,
1202  List<DynamicList<label>>& czCells
1203 )
1204 {
1205  zoneNames.setCapacity(cz0.size() + cz1.size());
1206  zoneNames.append(cz0.names());
1207 
1208  from1ToAll.setSize(cz1.size());
1209  forAll(cz1, zoneI)
1210  {
1211  from1ToAll[zoneI] = zoneIndex(cz1[zoneI].name(), zoneNames);
1212  }
1213  zoneNames.shrink();
1214 
1215 
1216  // Zone(s) per cell. Two levels: if only one zone
1217  // stored in cellToZone. Any extra stored in additionalCellToZones.
1218  // This is so we only allocate labelLists per cell if absolutely
1219  // necesary.
1220  labelList cellToZone(nAllCells, -1);
1221  labelListList addCellToZones(nAllCells);
1222 
1223  // mesh0 zones kept
1224  forAll(cz0, zoneI)
1225  {
1226  const cellZone& cz = cz0[zoneI];
1227  forAll(cz, i)
1228  {
1229  label cell0 = cz[i];
1230 
1231  if (cellToZone[cell0] == -1)
1232  {
1233  cellToZone[cell0] = zoneI;
1234  }
1235  else if (cellToZone[cell0] != zoneI)
1236  {
1237  labelList& cZones = addCellToZones[cell0];
1238  if (findIndex(cZones, zoneI) == -1)
1239  {
1240  cZones.append(zoneI);
1241  }
1242  }
1243  }
1244  }
1245 
1246  // mesh1 zones renumbered
1247  forAll(cz1, zoneI)
1248  {
1249  const cellZone& cz = cz1[zoneI];
1250  const label allZoneI = from1ToAll[zoneI];
1251  forAll(cz, i)
1252  {
1253  label cell1 = cz[i];
1254  label allCelli = from1ToAllCells[cell1];
1255 
1256  if (cellToZone[allCelli] == -1)
1257  {
1258  cellToZone[allCelli] = allZoneI;
1259  }
1260  else if (cellToZone[allCelli] != allZoneI)
1261  {
1262  labelList& cZones = addCellToZones[allCelli];
1263  if (findIndex(cZones, allZoneI) == -1)
1264  {
1265  cZones.append(allZoneI);
1266  }
1267  }
1268  }
1269  }
1270 
1271  // Extract back into zones
1272 
1273  // 1. Count
1274  labelList nCells(zoneNames.size(), 0);
1275  forAll(cellToZone, allCelli)
1276  {
1277  label zoneI = cellToZone[allCelli];
1278  if (zoneI != -1)
1279  {
1280  nCells[zoneI]++;
1281  }
1282  }
1283  forAll(addCellToZones, allCelli)
1284  {
1285  const labelList& cZones = addCellToZones[allCelli];
1286  forAll(cZones, i)
1287  {
1288  nCells[cZones[i]]++;
1289  }
1290  }
1291 
1292  // 2. Fill
1293  czCells.setSize(zoneNames.size());
1294  forAll(czCells, zoneI)
1295  {
1296  czCells[zoneI].setCapacity(nCells[zoneI]);
1297  }
1298  forAll(cellToZone, allCelli)
1299  {
1300  label zoneI = cellToZone[allCelli];
1301  if (zoneI != -1)
1302  {
1303  czCells[zoneI].append(allCelli);
1304  }
1305  }
1306  forAll(addCellToZones, allCelli)
1307  {
1308  const labelList& cZones = addCellToZones[allCelli];
1309  forAll(cZones, i)
1310  {
1311  czCells[cZones[i]].append(allCelli);
1312  }
1313  }
1314  forAll(czCells, i)
1315  {
1316  czCells[i].shrink();
1317  stableSort(czCells[i]);
1318  }
1319 }
1320 
1321 
1322 void Foam::polyMeshAdder::mergeZones
1323 (
1324  const label nAllPoints,
1325  const labelList& allOwner,
1326  const label nAllCells,
1327 
1328  const polyMesh& mesh0,
1329  const polyMesh& mesh1,
1330  const labelList& from0ToAllPoints,
1331  const labelList& from0ToAllFaces,
1332 
1333  const labelList& from1ToAllPoints,
1334  const labelList& from1ToAllFaces,
1335  const labelList& from1ToAllCells,
1336 
1337  DynamicList<word>& pointZoneNames,
1338  List<DynamicList<label>>& pzPoints,
1339 
1340  DynamicList<word>& faceZoneNames,
1341  List<DynamicList<label>>& fzFaces,
1342  List<DynamicList<bool>>& fzFlips,
1343 
1344  DynamicList<word>& cellZoneNames,
1345  List<DynamicList<label>>& czCells
1346 )
1347 {
1348  labelList from1ToAllPZones;
1349  mergePointZones
1350  (
1351  nAllPoints,
1352  mesh0.pointZones(),
1353  mesh1.pointZones(),
1354  from0ToAllPoints,
1355  from1ToAllPoints,
1356 
1357  pointZoneNames,
1358  from1ToAllPZones,
1359  pzPoints
1360  );
1361 
1362  labelList from1ToAllFZones;
1363  mergeFaceZones
1364  (
1365  allOwner,
1366  mesh0,
1367  mesh1,
1368  from0ToAllFaces,
1369  from1ToAllFaces,
1370  from1ToAllCells,
1371 
1372  faceZoneNames,
1373  from1ToAllFZones,
1374  fzFaces,
1375  fzFlips
1376  );
1377 
1378  labelList from1ToAllCZones;
1379  mergeCellZones
1380  (
1381  nAllCells,
1382  mesh0.cellZones(),
1383  mesh1.cellZones(),
1384  from1ToAllCells,
1385 
1386  cellZoneNames,
1387  from1ToAllCZones,
1388  czCells
1389  );
1390 }
1391 
1392 
1393 void Foam::polyMeshAdder::addZones
1394 (
1395  const DynamicList<word>& pointZoneNames,
1396  const List<DynamicList<label>>& pzPoints,
1397 
1398  const DynamicList<word>& faceZoneNames,
1399  const List<DynamicList<label>>& fzFaces,
1400  const List<DynamicList<bool>>& fzFlips,
1401 
1402  const DynamicList<word>& cellZoneNames,
1403  const List<DynamicList<label>>& czCells,
1404 
1405  polyMesh& mesh
1406 )
1407 {
1408  List<pointZone*> pZones(pzPoints.size());
1409  forAll(pZones, i)
1410  {
1411  pZones[i] = new pointZone
1412  (
1413  pointZoneNames[i],
1414  pzPoints[i],
1415  i,
1416  mesh.pointZones()
1417  );
1418  }
1419 
1420  List<faceZone*> fZones(fzFaces.size());
1421  forAll(fZones, i)
1422  {
1423  fZones[i] = new faceZone
1424  (
1425  faceZoneNames[i],
1426  fzFaces[i],
1427  fzFlips[i],
1428  i,
1429  mesh.faceZones()
1430  );
1431  }
1432 
1433  List<cellZone*> cZones(czCells.size());
1434  forAll(cZones, i)
1435  {
1436  cZones[i] = new cellZone
1437  (
1438  cellZoneNames[i],
1439  czCells[i],
1440  i,
1441  mesh.cellZones()
1442  );
1443  }
1444 
1445  mesh.addZones
1446  (
1447  pZones,
1448  fZones,
1449  cZones
1450  );
1451 }
1452 
1453 
1454 
1455 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1456 
1457 // Returns new mesh and sets
1458 // - map from new cell/face/point/patch to either mesh0 or mesh1
1459 //
1460 // mesh0Faces/mesh1Faces: corresponding faces on both meshes.
1463  const IOobject& io,
1464  const polyMesh& mesh0,
1465  const polyMesh& mesh1,
1466  const faceCoupleInfo& coupleInfo,
1468 )
1469 {
1470  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1471  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1472 
1473 
1474  DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1475  DynamicList<word> allPatchTypes(allPatchNames.size());
1476 
1477  // Patch maps
1478  labelList from1ToAllPatches(patches1.size());
1479  labelList fromAllTo1Patches(allPatchNames.size(), -1);
1480 
1481  mergePatchNames
1482  (
1483  patches0,
1484  patches1,
1485  allPatchNames,
1486  allPatchTypes,
1487  from1ToAllPatches,
1488  fromAllTo1Patches
1489  );
1490 
1491 
1492  // New points
1494 
1495  // Map from mesh0/1 points to allPoints.
1496  labelList from0ToAllPoints(mesh0.nPoints(), -1);
1497  labelList from1ToAllPoints(mesh1.nPoints(), -1);
1498 
1499  // New faces
1500  faceList allFaces;
1501  label nInternalFaces;
1502 
1503  // New cells
1504  labelList allOwner;
1505  labelList allNeighbour;
1506  label nCells;
1507 
1508  // Sizes per patch
1509  labelList nFaces(allPatchNames.size(), 0);
1510 
1511  // Maps
1512  labelList from0ToAllFaces(mesh0.nFaces(), -1);
1513  labelList from1ToAllFaces(mesh1.nFaces(), -1);
1514 
1515  // Map
1516  labelList from1ToAllCells(mesh1.nCells(), -1);
1517 
1518  mergePrimitives
1519  (
1520  mesh0,
1521  mesh1,
1522  coupleInfo,
1523 
1524  allPatchNames.size(),
1525  fromAllTo1Patches,
1526  from1ToAllPatches,
1527 
1528  allPoints,
1529  from0ToAllPoints,
1530  from1ToAllPoints,
1531 
1532  allFaces,
1533  allOwner,
1534  allNeighbour,
1535  nInternalFaces,
1536  nFaces,
1537  nCells,
1538 
1539  from0ToAllFaces,
1540  from1ToAllFaces,
1541  from1ToAllCells
1542  );
1543 
1544 
1545  // Zones
1546  // ~~~~~
1547 
1548  DynamicList<word> pointZoneNames;
1549  List<DynamicList<label>> pzPoints;
1550 
1551  DynamicList<word> faceZoneNames;
1552  List<DynamicList<label>> fzFaces;
1553  List<DynamicList<bool>> fzFlips;
1554 
1555  DynamicList<word> cellZoneNames;
1556  List<DynamicList<label>> czCells;
1557 
1558  mergeZones
1559  (
1560  allPoints.size(),
1561  allOwner,
1562  nCells,
1563 
1564  mesh0,
1565  mesh1,
1566 
1567  from0ToAllPoints,
1568  from0ToAllFaces,
1569 
1570  from1ToAllPoints,
1571  from1ToAllFaces,
1572  from1ToAllCells,
1573 
1574  pointZoneNames,
1575  pzPoints,
1576 
1577  faceZoneNames,
1578  fzFaces,
1579  fzFlips,
1580 
1581  cellZoneNames,
1582  czCells
1583  );
1584 
1585 
1586  // Patches
1587  // ~~~~~~~
1588 
1589  // Map from 0 to all patches (since gets compacted)
1590  labelList from0ToAllPatches(patches0.size(), -1);
1591 
1592  List<polyPatch*> allPatches
1593  (
1594  combinePatches
1595  (
1596  mesh0,
1597  mesh1,
1598  patches0, // Should be boundaryMesh() on new mesh.
1599  allPatchNames.size(),
1600  fromAllTo1Patches,
1601  mesh0.nInternalFaces()
1602  + mesh1.nInternalFaces()
1603  + coupleInfo.cutFaces().size(),
1604  nFaces,
1605 
1606  from0ToAllPatches,
1607  from1ToAllPatches
1608  )
1609  );
1610 
1611 
1612  // Map information
1613  // ~~~~~~~~~~~~~~~
1614 
1615  mapPtr.reset
1616  (
1617  new mapAddedPolyMesh
1618  (
1619  mesh0.nPoints(),
1620  mesh0.nFaces(),
1621  mesh0.nCells(),
1622 
1623  mesh1.nPoints(),
1624  mesh1.nFaces(),
1625  mesh1.nCells(),
1626 
1627  from0ToAllPoints,
1628  from0ToAllFaces,
1629  identity(mesh0.nCells()),
1630 
1631  from1ToAllPoints,
1632  from1ToAllFaces,
1633  from1ToAllCells,
1634 
1635  from0ToAllPatches,
1636  from1ToAllPatches,
1637  getPatchSizes(patches0),
1638  getPatchStarts(patches0)
1639  )
1640  );
1641 
1642 
1643 
1644  // Now we have extracted all information from all meshes.
1645  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1646 
1647  // Construct mesh
1648  autoPtr<polyMesh> tmesh
1649  (
1650  new polyMesh
1651  (
1652  io,
1653  xferMove(allPoints),
1654  xferMove(allFaces),
1655  xferMove(allOwner),
1656  xferMove(allNeighbour)
1657  )
1658  );
1659  polyMesh& mesh = tmesh();
1660 
1661  // Add zones to new mesh.
1662  addZones
1663  (
1664  pointZoneNames,
1665  pzPoints,
1666 
1667  faceZoneNames,
1668  fzFaces,
1669  fzFlips,
1670 
1671  cellZoneNames,
1672  czCells,
1673  mesh
1674  );
1675 
1676  // Add patches to new mesh
1677  mesh.addPatches(allPatches);
1678 
1679  return tmesh;
1680 }
1681 
1682 
1683 // Inplace add mesh1 to mesh0
1686  polyMesh& mesh0,
1687  const polyMesh& mesh1,
1688  const faceCoupleInfo& coupleInfo,
1689  const bool validBoundary
1690 )
1691 {
1692  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1693  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1694 
1695  DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1696  DynamicList<word> allPatchTypes(allPatchNames.size());
1697 
1698  // Patch maps
1699  labelList from1ToAllPatches(patches1.size());
1700  labelList fromAllTo1Patches(allPatchNames.size(), -1);
1701 
1702  mergePatchNames
1703  (
1704  patches0,
1705  patches1,
1706  allPatchNames,
1707  allPatchTypes,
1708  from1ToAllPatches,
1709  fromAllTo1Patches
1710  );
1711 
1712 
1713  // New points
1715 
1716  // Map from mesh0/1 points to allPoints.
1717  labelList from0ToAllPoints(mesh0.nPoints(), -1);
1718  labelList from1ToAllPoints(mesh1.nPoints(), -1);
1719 
1720  // New faces
1721  faceList allFaces;
1722  labelList allOwner;
1723  labelList allNeighbour;
1724  label nInternalFaces;
1725  // Sizes per patch
1726  labelList nFaces(allPatchNames.size(), 0);
1727  label nCells;
1728 
1729  // Maps
1730  labelList from0ToAllFaces(mesh0.nFaces(), -1);
1731  labelList from1ToAllFaces(mesh1.nFaces(), -1);
1732  // Map
1733  labelList from1ToAllCells(mesh1.nCells(), -1);
1734 
1735  mergePrimitives
1736  (
1737  mesh0,
1738  mesh1,
1739  coupleInfo,
1740 
1741  allPatchNames.size(),
1742  fromAllTo1Patches,
1743  from1ToAllPatches,
1744 
1745  allPoints,
1746  from0ToAllPoints,
1747  from1ToAllPoints,
1748 
1749  allFaces,
1750  allOwner,
1751  allNeighbour,
1752  nInternalFaces,
1753  nFaces,
1754  nCells,
1755 
1756  from0ToAllFaces,
1757  from1ToAllFaces,
1758  from1ToAllCells
1759  );
1760 
1761 
1762  // Zones
1763  // ~~~~~
1764 
1765  DynamicList<word> pointZoneNames;
1766  List<DynamicList<label>> pzPoints;
1767 
1768  DynamicList<word> faceZoneNames;
1769  List<DynamicList<label>> fzFaces;
1770  List<DynamicList<bool>> fzFlips;
1771 
1772  DynamicList<word> cellZoneNames;
1773  List<DynamicList<label>> czCells;
1774 
1775  mergeZones
1776  (
1777  allPoints.size(),
1778  allOwner,
1779  nCells,
1780 
1781  mesh0,
1782  mesh1,
1783 
1784  from0ToAllPoints,
1785  from0ToAllFaces,
1786 
1787  from1ToAllPoints,
1788  from1ToAllFaces,
1789  from1ToAllCells,
1790 
1791  pointZoneNames,
1792  pzPoints,
1793 
1794  faceZoneNames,
1795  fzFaces,
1796  fzFlips,
1797 
1798  cellZoneNames,
1799  czCells
1800  );
1801 
1802 
1803  // Patches
1804  // ~~~~~~~
1805 
1806 
1807  // Store mesh0 patch info before modifying patches0.
1808  labelList mesh0PatchSizes(getPatchSizes(patches0));
1809  labelList mesh0PatchStarts(getPatchStarts(patches0));
1810 
1811  // Map from 0 to all patches (since gets compacted)
1812  labelList from0ToAllPatches(patches0.size(), -1);
1813 
1814  // Inplace extend mesh0 patches (note that patches0.size() now also
1815  // has changed)
1816  polyBoundaryMesh& allPatches =
1817  const_cast<polyBoundaryMesh&>(mesh0.boundaryMesh());
1818  allPatches.setSize(allPatchNames.size());
1819  labelList patchSizes(allPatches.size());
1820  labelList patchStarts(allPatches.size());
1821 
1822  label startFacei = nInternalFaces;
1823 
1824  // Copy patches0 with new sizes. First patches always come from
1825  // mesh0 and will always be present.
1826  label allPatchi = 0;
1827 
1828  forAll(from0ToAllPatches, patch0)
1829  {
1830  // Originates from mesh0. Clone with new size & filter out empty
1831  // patch.
1832 
1833  if (nFaces[patch0] == 0 && isA<processorPolyPatch>(allPatches[patch0]))
1834  {
1835  //Pout<< "Removing zero sized mesh0 patch " << allPatchNames[patch0]
1836  // << endl;
1837  from0ToAllPatches[patch0] = -1;
1838  // Check if patch was also in mesh1 and update its addressing if so.
1839  if (fromAllTo1Patches[patch0] != -1)
1840  {
1841  from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
1842  }
1843  }
1844  else
1845  {
1846  // Clone. Note dummy size and start. Gets overwritten later in
1847  // resetPrimitives. This avoids getting temporarily illegal
1848  // SubList construction in polyPatch.
1849  allPatches.set
1850  (
1851  allPatchi,
1852  allPatches[patch0].clone
1853  (
1854  allPatches,
1855  allPatchi,
1856  0, // dummy size
1857  0 // dummy start
1858  )
1859  );
1860  patchSizes[allPatchi] = nFaces[patch0];
1861  patchStarts[allPatchi] = startFacei;
1862 
1863  // Record new index in allPatches
1864  from0ToAllPatches[patch0] = allPatchi;
1865 
1866  // Check if patch was also in mesh1 and update its addressing if so.
1867  if (fromAllTo1Patches[patch0] != -1)
1868  {
1869  from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchi;
1870  }
1871 
1872  startFacei += nFaces[patch0];
1873 
1874  allPatchi++;
1875  }
1876  }
1877 
1878  // Copy unique patches of mesh1.
1879  forAll(from1ToAllPatches, patch1)
1880  {
1881  label uncompactAllPatchi = from1ToAllPatches[patch1];
1882 
1883  if (uncompactAllPatchi >= from0ToAllPatches.size())
1884  {
1885  // Patch has not been merged with any mesh0 patch.
1886 
1887  if
1888  (
1889  nFaces[uncompactAllPatchi] == 0
1890  && isA<processorPolyPatch>(patches1[patch1])
1891  )
1892  {
1893  //Pout<< "Removing zero sized mesh1 patch "
1894  // << allPatchNames[uncompactAllPatchi] << endl;
1895  from1ToAllPatches[patch1] = -1;
1896  }
1897  else
1898  {
1899  // Clone.
1900  allPatches.set
1901  (
1902  allPatchi,
1903  patches1[patch1].clone
1904  (
1905  allPatches,
1906  allPatchi,
1907  0, // dummy size
1908  0 // dummy start
1909  )
1910  );
1911  patchSizes[allPatchi] = nFaces[uncompactAllPatchi];
1912  patchStarts[allPatchi] = startFacei;
1913 
1914  // Record new index in allPatches
1915  from1ToAllPatches[patch1] = allPatchi;
1916 
1917  startFacei += nFaces[uncompactAllPatchi];
1918 
1919  allPatchi++;
1920  }
1921  }
1922  }
1923 
1924  allPatches.setSize(allPatchi);
1925  patchSizes.setSize(allPatchi);
1926  patchStarts.setSize(allPatchi);
1927 
1928 
1929  // Construct map information before changing mesh0 primitives
1930  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1931 
1933  (
1934  new mapAddedPolyMesh
1935  (
1936  mesh0.nPoints(),
1937  mesh0.nFaces(),
1938  mesh0.nCells(),
1939 
1940  mesh1.nPoints(),
1941  mesh1.nFaces(),
1942  mesh1.nCells(),
1943 
1944  from0ToAllPoints,
1945  from0ToAllFaces,
1946  identity(mesh0.nCells()),
1947 
1948  from1ToAllPoints,
1949  from1ToAllFaces,
1950  from1ToAllCells,
1951 
1952  from0ToAllPatches,
1953  from1ToAllPatches,
1954 
1955  mesh0PatchSizes,
1956  mesh0PatchStarts
1957  )
1958  );
1959 
1960 
1961 
1962  // Now we have extracted all information from all meshes.
1963  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1964 
1965  mesh0.resetMotion(); // delete any oldPoints.
1966  mesh0.resetPrimitives
1967  (
1968  xferMove(allPoints),
1969  xferMove(allFaces),
1970  xferMove(allOwner),
1971  xferMove(allNeighbour),
1972  patchSizes, // size
1973  patchStarts, // patchstarts
1974  validBoundary // boundary valid?
1975  );
1976 
1977  // Add zones to new mesh.
1978  mesh0.pointZones().clear();
1979  mesh0.faceZones().clear();
1980  mesh0.cellZones().clear();
1981  addZones
1982  (
1983  pointZoneNames,
1984  pzPoints,
1985 
1986  faceZoneNames,
1987  fzFaces,
1988  fzFlips,
1989 
1990  cellZoneNames,
1991  czCells,
1992  mesh0
1993  );
1994 
1995  return mapPtr;
1996 }
1997 
1998 
2001  const polyMesh& mesh,
2002  const scalar mergeDist
2003 )
2004 {
2005  const labelList& sharedPointLabels = mesh.globalData().sharedPointLabels();
2006  const labelList& sharedPointAddr = mesh.globalData().sharedPointAddr();
2007 
2008  // Because of adding the missing pieces e.g. when redistributing a mesh
2009  // it can be that there are multiple points on the same processor that
2010  // refer to the same shared point.
2011 
2012  // Invert point-to-shared addressing
2013  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2014 
2015  Map<labelList> sharedToMesh(sharedPointLabels.size());
2016 
2017  label nMultiple = 0;
2018 
2019  forAll(sharedPointLabels, i)
2020  {
2021  label pointi = sharedPointLabels[i];
2022 
2023  label sharedI = sharedPointAddr[i];
2024 
2025  Map<labelList>::iterator iter = sharedToMesh.find(sharedI);
2026 
2027  if (iter != sharedToMesh.end())
2028  {
2029  // sharedI already used by other point. Add this one.
2030 
2031  nMultiple++;
2032 
2033  labelList& connectedPointLabels = iter();
2034 
2035  label sz = connectedPointLabels.size();
2036 
2037  // Check just to make sure.
2038  if (findIndex(connectedPointLabels, pointi) != -1)
2039  {
2041  << "Duplicate point in sharedPoint addressing." << endl
2042  << "When trying to add point " << pointi << " on shared "
2043  << sharedI << " with connected points "
2044  << connectedPointLabels
2045  << abort(FatalError);
2046  }
2047 
2048  connectedPointLabels.setSize(sz+1);
2049  connectedPointLabels[sz] = pointi;
2050  }
2051  else
2052  {
2053  sharedToMesh.insert(sharedI, labelList(1, pointi));
2054  }
2055  }
2056 
2057 
2058  // Assign single master for every shared with multiple geometric points
2059  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2060 
2061  Map<label> pointToMaster(nMultiple);
2062 
2063  forAllConstIter(Map<labelList>, sharedToMesh, iter)
2064  {
2065  const labelList& connectedPointLabels = iter();
2066 
2067  //Pout<< "For shared:" << iter.key()
2068  // << " found points:" << connectedPointLabels
2069  // << " at coords:"
2070  // << pointField(mesh.points(), connectedPointLabels) << endl;
2071 
2072  if (connectedPointLabels.size() > 1)
2073  {
2074  const pointField connectedPoints
2075  (
2076  mesh.points(),
2077  connectedPointLabels
2078  );
2079 
2080  labelList toMergedPoints;
2081  label nUnique = Foam::mergePoints
2082  (
2083  connectedPoints,
2084  mergeDist,
2085  false,
2086  toMergedPoints
2087  );
2088 
2089  if (nUnique < connectedPoints.size())
2090  {
2091  // Invert toMergedPoints
2092  const labelListList mergeSets
2093  (
2095  (
2096  nUnique,
2097  toMergedPoints
2098  )
2099  );
2100 
2101  // Find master for valid merges
2102  forAll(mergeSets, setI)
2103  {
2104  const labelList& mergeSet = mergeSets[setI];
2105 
2106  if (mergeSet.size() > 1)
2107  {
2108  // Pick lowest numbered point
2109  label masterPointi = labelMax;
2110 
2111  forAll(mergeSet, i)
2112  {
2113  label pointi = connectedPointLabels[mergeSet[i]];
2114 
2115  masterPointi = min(masterPointi, pointi);
2116  }
2117 
2118  forAll(mergeSet, i)
2119  {
2120  label pointi = connectedPointLabels[mergeSet[i]];
2121 
2122  //Pout<< "Merging point " << pointi
2123  // << " at " << mesh.points()[pointi]
2124  // << " into master point "
2125  // << masterPointi
2126  // << " at " << mesh.points()[masterPointi]
2127  // << endl;
2128 
2129  pointToMaster.insert(pointi, masterPointi);
2130  }
2131  }
2132  }
2133  }
2134  }
2135  }
2136 
2137  //- Old: geometric merging. Causes problems for two close shared points.
2138  //labelList sharedToMerged;
2139  //label nUnique = Foam::mergePoints
2140  //(
2141  // pointField
2142  // (
2143  // mesh.points(),
2144  // sharedPointLabels
2145  // ),
2146  // mergeDist,
2147  // false,
2148  // sharedToMerged
2149  //);
2150  //
2153  //
2154  //Map<label> pointToMaster(10*sharedToMerged.size());
2155  //
2156  //if (nUnique < sharedPointLabels.size())
2157  //{
2158  // labelListList mergeSets
2159  // (
2160  // invertOneToMany
2161  // (
2162  // sharedToMerged.size(),
2163  // sharedToMerged
2164  // )
2165  // );
2166  //
2167  // label nMergeSets = 0;
2168  //
2169  // forAll(mergeSets, setI)
2170  // {
2171  // const labelList& mergeSet = mergeSets[setI];
2172  //
2173  // if (mergeSet.size() > 1)
2174  // {
2175  // // Take as master the shared point with the lowest mesh
2176  // // point label. (rather arbitrarily - could use max or
2177  // // any other one of the points)
2178  //
2179  // nMergeSets++;
2180  //
2181  // label masterI = labelMax;
2182  //
2183  // forAll(mergeSet, i)
2184  // {
2185  // label sharedI = mergeSet[i];
2186  //
2187  // masterI = min(masterI, sharedPointLabels[sharedI]);
2188  // }
2189  //
2190  // forAll(mergeSet, i)
2191  // {
2192  // label sharedI = mergeSet[i];
2193  //
2194  // pointToMaster.insert(sharedPointLabels[sharedI], masterI);
2195  // }
2196  // }
2197  // }
2198  //
2199  // //if (debug)
2200  // //{
2201  // // Pout<< "polyMeshAdder : merging:"
2202  // // << pointToMaster.size() << " into " << nMergeSets
2203  // // << " sets." << endl;
2204  // //}
2205  //}
2206 
2207  return pointToMaster;
2208 }
2209 
2210 
2213  const polyMesh& mesh,
2214  const Map<label>& pointToMaster,
2215  polyTopoChange& meshMod
2216 )
2217 {
2218  // Remove all non-master points.
2219  forAll(mesh.points(), pointi)
2220  {
2221  Map<label>::const_iterator iter = pointToMaster.find(pointi);
2222 
2223  if (iter != pointToMaster.end())
2224  {
2225  if (iter() != pointi)
2226  {
2227  meshMod.removePoint(pointi, iter());
2228  }
2229  }
2230  }
2231 
2232  // Modify faces for points. Note: could use pointFaces here but want to
2233  // avoid addressing calculation.
2234  const faceList& faces = mesh.faces();
2235 
2236  forAll(faces, facei)
2237  {
2238  const face& f = faces[facei];
2239 
2240  bool hasMerged = false;
2241 
2242  forAll(f, fp)
2243  {
2244  label pointi = f[fp];
2245 
2246  Map<label>::const_iterator iter = pointToMaster.find(pointi);
2247 
2248  if (iter != pointToMaster.end())
2249  {
2250  if (iter() != pointi)
2251  {
2252  hasMerged = true;
2253  break;
2254  }
2255  }
2256  }
2257 
2258  if (hasMerged)
2259  {
2260  face newF(f);
2261 
2262  forAll(f, fp)
2263  {
2264  label pointi = f[fp];
2265 
2266  Map<label>::const_iterator iter = pointToMaster.find(pointi);
2267 
2268  if (iter != pointToMaster.end())
2269  {
2270  newF[fp] = iter();
2271  }
2272  }
2273 
2274  label patchID = mesh.boundaryMesh().whichPatch(facei);
2275  label nei = (patchID == -1 ? mesh.faceNeighbour()[facei] : -1);
2276  label zoneID = mesh.faceZones().whichZone(facei);
2277  bool zoneFlip = false;
2278 
2279  if (zoneID >= 0)
2280  {
2281  const faceZone& fZone = mesh.faceZones()[zoneID];
2282  zoneFlip = fZone.flipMap()[fZone.whichFace(facei)];
2283  }
2284 
2285  meshMod.setAction
2286  (
2288  (
2289  newF, // modified face
2290  facei, // label of face
2291  mesh.faceOwner()[facei], // owner
2292  nei, // neighbour
2293  false, // face flip
2294  patchID, // patch for face
2295  false, // remove from zone
2296  zoneID, // zone for face
2297  zoneFlip // face flip in zone
2298  )
2299  );
2300  }
2301  }
2302 }
2303 
2304 
2305 // ************************************************************************* //
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
const labelList & sharedPointAddr() const
Return addressing into the complete globally shared points.
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
List< List< bool > > boolListList
Definition: boolList.H:51
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:253
Class describing modification of a face.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:106
error FatalError
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
labelListList invertOneToMany(const label len, const labelUList &)
Invert one-to-many map. Unmapped elements will be size 0.
Definition: ListOps.C:67
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
List< face > faceList
Definition: faceListFwd.H:43
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:440
Class containing mesh-to-mesh mapping information after a mesh addition where we add a mesh (&#39;added m...
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
HashTable< label, label, Hash< label > >::const_iterator const_iterator
Definition: Map.H:59
void removePoint(const label, const label)
Remove/merge point.
PrimitivePatch< face, IndirectList, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
label nCells() const
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:979
Container for information needed to couple to meshes. When constructed from two meshes and a geometri...
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:138
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:210
An STL-conforming iterator.
Definition: HashTable.H:415
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:305
void clear()
Delete object (if the pointer is valid) and set pointer to NULL.
Definition: autoPtrI.H:126
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
void reset(T *=0)
If object pointer already set, delete object and set to given.
Definition: autoPtrI.H:114
static void mergePoints(const polyMesh &, const Map< label > &pointToMaster, polyTopoChange &meshMod)
Helper: Merge points.
Xfer< T > xferMove(T &)
Construct by transferring the contents of the arg.
label nPoints
friend class const_iterator
Declare friendship with the const_iterator.
Definition: HashTable.H:192
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:97
static const label labelMax
Definition: label.H:62
List< label > labelList
A List of labels.
Definition: labelList.H:56
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
errorManip< error > abort(error &err)
Definition: errorManip.H:131
void setSize(const label)
Reset size of PtrList. If extending the PtrList, new entries are.
Definition: PtrList.C:131
Foam::polyBoundaryMesh.
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1140
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
Merge points. See below.
labelList f(nPoints)
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
PrimitivePatch< face, List, const pointField & > primitiveFacePatch
Foam::primitiveFacePatch.
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
void addPatches(const List< polyPatch * > &, const bool validBoundary=true)
Add boundary patches.
Definition: polyMesh.C:878
label nFaces() const
const primitiveFacePatch & cutFaces() const
Addressing engine for combined set of faces.
void setSize(const label)
Reset size of List.
Definition: List.C:295
label patchi
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1023
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
label whichZone(const label objectIndex) const
Given a global object index, return the zone it is in.
Definition: ZoneMesh.C:221
Direct mesh changes based on v1.3 polyTopoChange syntax.
label mergePoints(const UList< Type > &points, const scalar mergeTol, const bool verbose, labelList &pointMap, const Type &origin=Type::zero)
Sorts and merges points. All points closer than/equal mergeTol get merged.
label nPoints() const
tmp< pointField > allPoints(const Triangulation &t)
Extract all points in vertex-index order.
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:463
HashTable< labelList, edge, Hash< edge > > edgeLookup
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:53
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
const labelList & sharedPointLabels() const
Return indices of local points that are globally shared.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1017
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1004
void stableSort(UList< T > &)
Definition: UList.C:129
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.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
List< cell > cellList
list of cells
Definition: cellList.H:42
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.
IOporosityModelList pZones(mesh)
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
A HashTable to objects of type <T> with a label key.
Definition: Map.H:49
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.