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