polyMeshAdder.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2025 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 "faceCoupleInfo.H"
29 #include "processorPolyPatch.H"
30 #include "Time.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 // Get index of patch in new set of patchnames/types
35 Foam::label Foam::polyMeshAdder::patchIndex
36 (
37  const polyPatch& p,
38  DynamicList<word>& allPatchNames,
39  DynamicList<word>& allPatchTypes
40 )
41 {
42  // Find the patch name on the list. If the patch is already there
43  // and patch types match, return index
44  const word& pType = p.type();
45  const word& pName = p.name();
46 
47  label patchi = findIndex(allPatchNames, pName);
48 
49  if (patchi == -1)
50  {
51  // Patch not found. Append to the list
52  allPatchNames.append(pName);
53  allPatchTypes.append(pType);
54 
55  return allPatchNames.size() - 1;
56  }
57  else if (allPatchTypes[patchi] == pType)
58  {
59  // Found name and types match
60  return patchi;
61  }
62  else
63  {
64  // Found the name, but type is different
65 
66  // Duplicate name is not allowed. Create a composite name from the
67  // patch name and case name
68  const word& caseName = p.boundaryMesh().mesh().time().caseName();
69 
70  allPatchNames.append(pName + "_" + caseName);
71  allPatchTypes.append(pType);
72 
73  Pout<< "label patchIndex(const polyPatch& p) : "
74  << "Patch " << p.index() << " named "
75  << pName << " in mesh " << caseName
76  << " already exists, but patch types"
77  << " do not match.\nCreating a composite name as "
78  << allPatchNames.last() << endl;
79 
80  return allPatchNames.size() - 1;
81  }
82 }
83 
84 
85 // Get index of zone in new set of zone names
86 Foam::label Foam::polyMeshAdder::zoneIndex
87 (
88  const word& curName,
89  DynamicList<word>& names
90 )
91 {
92  label zi = findIndex(names, curName);
93 
94  if (zi != -1)
95  {
96  return zi;
97  }
98  else
99  {
100  // Not found. Add new name to the list
101  names.append(curName);
102 
103  return names.size() - 1;
104  }
105 }
106 
107 
108 void Foam::polyMeshAdder::mergePatchNames
109 (
110  const polyBoundaryMesh& patches0,
111  const polyBoundaryMesh& patches1,
112 
113  DynamicList<word>& allPatchNames,
114  DynamicList<word>& allPatchTypes,
115 
116  labelList& from1ToAllPatches,
117  labelList& fromAllTo1Patches
118 )
119 {
120  // Insert the mesh0 patches and zones
121  allPatchNames.append(patches0.names());
122  allPatchTypes.append(patches0.types());
123 
124 
125  // Patches
126  // ~~~~~~~
127  // Patches from 0 are taken over as is; those from 1 get either merged
128  // (if they share name and type) or appended.
129  // Empty patches are filtered out much much later on.
130 
131  // Add mesh1 patches and build map both ways.
132  from1ToAllPatches.setSize(patches1.size());
133 
134  forAll(patches1, patchi)
135  {
136  from1ToAllPatches[patchi] = patchIndex
137  (
138  patches1[patchi],
139  allPatchNames,
140  allPatchTypes
141  );
142  }
143  allPatchTypes.shrink();
144  allPatchNames.shrink();
145 
146  // Invert 1 to all patch map
147  fromAllTo1Patches.setSize(allPatchNames.size());
148  fromAllTo1Patches = -1;
149 
150  forAll(from1ToAllPatches, i)
151  {
152  fromAllTo1Patches[from1ToAllPatches[i]] = i;
153  }
154 }
155 
156 
157 Foam::labelList Foam::polyMeshAdder::getPatchStarts
158 (
159  const polyBoundaryMesh& patches
160 )
161 {
162  labelList patchStarts(patches.size());
164  {
165  patchStarts[patchi] = patches[patchi].start();
166  }
167  return patchStarts;
168 }
169 
170 
171 Foam::labelList Foam::polyMeshAdder::getPatchSizes
172 (
173  const polyBoundaryMesh& patches
174 )
175 {
176  labelList patchSizes(patches.size());
178  {
179  patchSizes[patchi] = patches[patchi].size();
180  }
181  return patchSizes;
182 }
183 
184 
185 Foam::labelList Foam::polyMeshAdder::getFaceOrder
186 (
187  const cellList& cells,
188  const label nInternalFaces,
189  const labelList& owner,
190  const labelList& neighbour
191 )
192 {
193  labelList oldToNew(owner.size(), -1);
194 
195  // Leave boundary faces in order
196  for (label facei = nInternalFaces; facei < owner.size(); ++facei)
197  {
198  oldToNew[facei] = facei;
199  }
200 
201  // First unassigned face
202  label newFacei = 0;
203 
204  forAll(cells, celli)
205  {
206  const labelList& cFaces = cells[celli];
207 
208  SortableList<label> nbr(cFaces.size());
209 
210  forAll(cFaces, i)
211  {
212  label facei = cFaces[i];
213 
214  label nbrCelli = neighbour[facei];
215 
216  if (nbrCelli != -1)
217  {
218  // Internal face. Get cell on other side.
219  if (nbrCelli == celli)
220  {
221  nbrCelli = owner[facei];
222  }
223 
224  if (celli < nbrCelli)
225  {
226  // Celli is master
227  nbr[i] = nbrCelli;
228  }
229  else
230  {
231  // nbrCell is master. Let it handle this face.
232  nbr[i] = -1;
233  }
234  }
235  else
236  {
237  // External face. Do later.
238  nbr[i] = -1;
239  }
240  }
241 
242  nbr.sort();
243 
244  forAll(nbr, i)
245  {
246  if (nbr[i] != -1)
247  {
248  oldToNew[cFaces[nbr.indices()[i]]] = newFacei++;
249  }
250  }
251  }
252 
253 
254  // Check done all faces.
255  forAll(oldToNew, facei)
256  {
257  if (oldToNew[facei] == -1)
258  {
260  << "Did not determine new position"
261  << " for face " << facei
262  << abort(FatalError);
263  }
264  }
265 
266  return oldToNew;
267 }
268 
269 
270 // Adds primitives (cells, faces, points)
271 // Cells:
272 // - all of mesh0
273 // - all of mesh1
274 // Faces:
275 // - all uncoupled of mesh0
276 // - all coupled faces
277 // - all uncoupled of mesh1
278 // Points:
279 // - all coupled
280 // - all uncoupled of mesh0
281 // - all uncoupled of mesh1
282 void Foam::polyMeshAdder::mergePrimitives
283 (
284  const polyMesh& mesh0,
285  const polyMesh& mesh1,
286  const faceCoupleInfo& coupleInfo,
287 
288  const label nAllPatches, // number of patches in the new mesh
289  const labelList& fromAllTo1Patches,
290  const labelList& from1ToAllPatches,
291 
292  pointField& allPoints,
293  labelList& from0ToAllPoints,
294  labelList& from1ToAllPoints,
295 
296  faceList& allFaces,
297  labelList& allOwner,
298  labelList& allNeighbour,
299  label& nInternalFaces,
300  labelList& nFacesPerPatch,
301  label& nCells,
302 
303  labelList& from0ToAllFaces,
304  labelList& from1ToAllFaces,
305  labelList& from1ToAllCells
306 )
307 {
308  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
309  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
310 
311  const indirectPrimitivePatch& masterPatch = coupleInfo.masterPatch();
312  const indirectPrimitivePatch& slavePatch = coupleInfo.slavePatch();
313 
314 
315  // Points
316  // ~~~~~~
317 
318  // Storage for new points
319  allPoints.setSize(mesh0.nPoints() + mesh1.nPoints());
320  label allPointi = 0;
321 
322  from0ToAllPoints.setSize(mesh0.nPoints());
323  from0ToAllPoints = -1;
324  from1ToAllPoints.setSize(mesh1.nPoints());
325  from1ToAllPoints = -1;
326 
327  // Copy coupled points
328  {
329  const labelListList coupleToMasterPoints
330  (
331  coupleInfo.coupleToMasterPoints()
332  );
333  const labelListList coupleToSlavePoints
334  (
335  coupleInfo.coupleToSlavePoints()
336  );
337 
338  forAll(coupleToMasterPoints, couplePointi)
339  {
340  const labelList& masterPoints = coupleToMasterPoints[couplePointi];
341 
342  forAll(masterPoints, j)
343  {
344  label mesh0Pointi = masterPatch.meshPoints()[masterPoints[j]];
345  from0ToAllPoints[mesh0Pointi] = allPointi;
346  allPoints[allPointi] = mesh0.points()[mesh0Pointi];
347  }
348 
349  const labelList& slavePoints = coupleToSlavePoints[couplePointi];
350 
351  forAll(slavePoints, j)
352  {
353  label mesh1Pointi = slavePatch.meshPoints()[slavePoints[j]];
354  from1ToAllPoints[mesh1Pointi] = allPointi;
355  allPoints[allPointi] = mesh1.points()[mesh1Pointi];
356  }
357 
358  allPointi++;
359  }
360  }
361 
362  // Add uncoupled mesh0 points
363  forAll(mesh0.points(), pointi)
364  {
365  if (from0ToAllPoints[pointi] == -1)
366  {
367  allPoints[allPointi] = mesh0.points()[pointi];
368  from0ToAllPoints[pointi] = allPointi;
369  allPointi++;
370  }
371  }
372 
373  // Add uncoupled mesh1 points
374  forAll(mesh1.points(), pointi)
375  {
376  if (from1ToAllPoints[pointi] == -1)
377  {
378  allPoints[allPointi] = mesh1.points()[pointi];
379  from1ToAllPoints[pointi] = allPointi;
380  allPointi++;
381  }
382  }
383 
384  allPoints.setSize(allPointi);
385 
386 
387  // Faces
388  // ~~~~~
389 
390  // Sizes per patch
391  nFacesPerPatch.setSize(nAllPatches);
392  nFacesPerPatch = 0;
393 
394  // Storage for faces and owner/neighbour
395  allFaces.setSize(mesh0.nFaces() + mesh1.nFaces());
396  allOwner.setSize(allFaces.size());
397  allOwner = -1;
398  allNeighbour.setSize(allFaces.size());
399  allNeighbour = -1;
400  label allFacei = 0;
401 
402  from0ToAllFaces.setSize(mesh0.nFaces());
403  from0ToAllFaces = -1;
404  from1ToAllFaces.setSize(mesh1.nFaces());
405  from1ToAllFaces = -1;
406 
407  // Copy mesh0 internal faces (always uncoupled)
408  for (label facei = 0; facei < mesh0.nInternalFaces(); facei++)
409  {
410  allFaces[allFacei] = renumber(from0ToAllPoints, mesh0.faces()[facei]);
411  allOwner[allFacei] = mesh0.faceOwner()[facei];
412  allNeighbour[allFacei] = mesh0.faceNeighbour()[facei];
413  from0ToAllFaces[facei] = allFacei++;
414  }
415 
416  // Copy coupled faces. Every coupled face has an equivalent master and
417  // slave. Also uncount as boundary faces all the newly coupled faces.
418  forAll(masterPatch, coupleFacei)
419  {
420  const label mesh0Facei = masterPatch.addressing()[coupleFacei];
421 
422  if (from0ToAllFaces[mesh0Facei] == -1)
423  {
424  // First occurrence of face
425  from0ToAllFaces[mesh0Facei] = allFacei;
426 
427  // External face becomes internal so uncount
428  label patch0 = patches0.whichPatch(mesh0Facei);
429  nFacesPerPatch[patch0]--;
430  }
431 
432  const label mesh1Facei = slavePatch.addressing()[coupleFacei];
433 
434  if (from1ToAllFaces[mesh1Facei] == -1)
435  {
436  from1ToAllFaces[mesh1Facei] = allFacei;
437 
438  label patch1 = patches1.whichPatch(mesh1Facei);
439  nFacesPerPatch[from1ToAllPatches[patch1]]--;
440  }
441 
442  // Copy cut face (since cutPoints are copied first no renumbering
443  // necessary)
444  allFaces[allFacei] = coupleInfo.coupleFace(coupleFacei);
445  allOwner[allFacei] = mesh0.faceOwner()[mesh0Facei];
446  allNeighbour[allFacei] = mesh1.faceOwner()[mesh1Facei] + mesh0.nCells();
447 
448  allFacei++;
449  }
450 
451  // Copy mesh1 internal faces (always uncoupled)
452  for (label facei = 0; facei < mesh1.nInternalFaces(); facei++)
453  {
454  allFaces[allFacei] = renumber(from1ToAllPoints, mesh1.faces()[facei]);
455  allOwner[allFacei] = mesh1.faceOwner()[facei] + mesh0.nCells();
456  allNeighbour[allFacei] = mesh1.faceNeighbour()[facei] + mesh0.nCells();
457  from1ToAllFaces[facei] = allFacei++;
458  }
459 
460  nInternalFaces = allFacei;
461 
462  // Copy (unmarked/uncoupled) external faces in new order.
463  for (label allPatchi = 0; allPatchi < nAllPatches; allPatchi++)
464  {
465  if (allPatchi < patches0.size())
466  {
467  // Patch is present in mesh0
468  const polyPatch& pp = patches0[allPatchi];
469 
470  nFacesPerPatch[allPatchi] += pp.size();
471 
472  label facei = pp.start();
473 
474  forAll(pp, i)
475  {
476  if (from0ToAllFaces[facei] == -1)
477  {
478  // Is uncoupled face since has not yet been dealt with
479  allFaces[allFacei] = renumber
480  (
481  from0ToAllPoints,
482  mesh0.faces()[facei]
483  );
484  allOwner[allFacei] = mesh0.faceOwner()[facei];
485  allNeighbour[allFacei] = -1;
486 
487  from0ToAllFaces[facei] = allFacei++;
488  }
489  facei++;
490  }
491  }
492  if (fromAllTo1Patches[allPatchi] != -1)
493  {
494  // Patch is present in mesh1
495  const polyPatch& pp = patches1[fromAllTo1Patches[allPatchi]];
496 
497  nFacesPerPatch[allPatchi] += pp.size();
498 
499  label facei = pp.start();
500 
501  forAll(pp, i)
502  {
503  if (from1ToAllFaces[facei] == -1)
504  {
505  // Is uncoupled face
506  allFaces[allFacei] = renumber
507  (
508  from1ToAllPoints,
509  mesh1.faces()[facei]
510  );
511  allOwner[allFacei] =
512  mesh1.faceOwner()[facei]
513  + mesh0.nCells();
514  allNeighbour[allFacei] = -1;
515 
516  from1ToAllFaces[facei] = allFacei++;
517  }
518  facei++;
519  }
520  }
521  }
522  allFaces.setSize(allFacei);
523  allOwner.setSize(allFacei);
524  allNeighbour.setSize(allFacei);
525 
526  // Cells
527  // ~~~~~
528 
529  from1ToAllCells.setSize(mesh1.nCells());
530  from1ToAllCells = -1;
531 
532  forAll(mesh1.cells(), i)
533  {
534  from1ToAllCells[i] = i + mesh0.nCells();
535  }
536 
537  // Make cells (= cell-face addressing)
538  nCells = mesh0.nCells() + mesh1.nCells();
539  cellList allCells(nCells);
540  primitiveMesh::calcCells(allCells, allOwner, allNeighbour, nCells);
541 
542  // Reorder faces for upper-triangular order.
543  labelList oldToNew
544  (
545  getFaceOrder
546  (
547  allCells,
548  nInternalFaces,
549  allOwner,
550  allNeighbour
551  )
552  );
553 
554  inplaceReorder(oldToNew, allFaces);
555  inplaceReorder(oldToNew, allOwner);
556  inplaceReorder(oldToNew, allNeighbour);
557  inplaceRenumber(oldToNew, from0ToAllFaces);
558  inplaceRenumber(oldToNew, from1ToAllFaces);
559 }
560 
561 
562 void Foam::polyMeshAdder::mergePointZones
563 (
564  const label nAllPoints,
565  const pointZoneList& pz0,
566  const pointZoneList& pz1,
567  const labelList& from0ToAllPoints,
568  const labelList& from1ToAllPoints,
569 
570  DynamicList<word>& zoneNames,
571  labelList& from1ToAll,
572  List<DynamicList<label>>& pzPoints
573 )
574 {
575  zoneNames.setCapacity(pz0.size() + pz1.size());
576  zoneNames.append(pz0.toc());
577 
578  from1ToAll.setSize(pz1.size());
579 
580  forAll(pz1, zi)
581  {
582  from1ToAll[zi] = zoneIndex(pz1[zi].name(), zoneNames);
583  }
584  zoneNames.shrink();
585 
586 
587 
588  // Zone(s) per point. Two levels: if only one zone
589  // stored in pointToZone. Any extra stored in additionalPointToZones.
590  // This is so we only allocate labelLists per point if absolutely
591  // necessary.
592  labelList pointToZone(nAllPoints, -1);
593  labelListList addPointToZones(nAllPoints);
594 
595  // mesh0 zones kept
596  forAll(pz0, zi)
597  {
598  const pointZone& pz = pz0[zi];
599 
600  forAll(pz, i)
601  {
602  label point0 = pz[i];
603  label allPointi = from0ToAllPoints[point0];
604 
605  if (pointToZone[allPointi] == -1)
606  {
607  pointToZone[allPointi] = zi;
608  }
609  else if (pointToZone[allPointi] != zi)
610  {
611  labelList& pZones = addPointToZones[allPointi];
612  if (findIndex(pZones, zi) == -1)
613  {
614  pZones.append(zi);
615  }
616  }
617  }
618  }
619 
620  // mesh1 zones renumbered
621  forAll(pz1, zi)
622  {
623  const pointZone& pz = pz1[zi];
624  const label allZoneI = from1ToAll[zi];
625 
626  forAll(pz, i)
627  {
628  label point1 = pz[i];
629  label allPointi = from1ToAllPoints[point1];
630 
631  if (pointToZone[allPointi] == -1)
632  {
633  pointToZone[allPointi] = allZoneI;
634  }
635  else if (pointToZone[allPointi] != allZoneI)
636  {
637  labelList& pZones = addPointToZones[allPointi];
638  if (findIndex(pZones, allZoneI) == -1)
639  {
640  pZones.append(allZoneI);
641  }
642  }
643  }
644  }
645 
646  // Extract back into zones
647 
648  // 1. Count
649  labelList nPoints(zoneNames.size(), 0);
650  forAll(pointToZone, allPointi)
651  {
652  label zi = pointToZone[allPointi];
653  if (zi != -1)
654  {
655  nPoints[zi]++;
656  }
657  }
658  forAll(addPointToZones, allPointi)
659  {
660  const labelList& pZones = addPointToZones[allPointi];
661  forAll(pZones, i)
662  {
663  nPoints[pZones[i]]++;
664  }
665  }
666 
667  // 2. Fill
668  pzPoints.setSize(zoneNames.size());
669  forAll(pzPoints, zi)
670  {
671  pzPoints[zi].setCapacity(nPoints[zi]);
672  }
673  forAll(pointToZone, allPointi)
674  {
675  label zi = pointToZone[allPointi];
676  if (zi != -1)
677  {
678  pzPoints[zi].append(allPointi);
679  }
680  }
681  forAll(addPointToZones, allPointi)
682  {
683  const labelList& pZones = addPointToZones[allPointi];
684  forAll(pZones, i)
685  {
686  pzPoints[pZones[i]].append(allPointi);
687  }
688  }
689  forAll(pzPoints, i)
690  {
691  pzPoints[i].shrink();
692  stableSort(pzPoints[i]);
693  }
694 }
695 
696 
697 void Foam::polyMeshAdder::mergeFaceZones
698 (
699  const labelList& allOwner,
700 
701  const polyMesh& mesh0,
702  const polyMesh& mesh1,
703 
704  const labelList& from0ToAllFaces,
705  const labelList& from1ToAllFaces,
706 
707  const labelList& from1ToAllCells,
708 
709  DynamicList<word>& zoneNames,
710  labelList& from1ToAll,
711  List<DynamicList<label>>& fzFaces,
712  boolList& fzOrientations,
713  List<DynamicList<bool>>& fzFlips
714 )
715 {
716  const faceZoneList& fz0 = mesh0.faceZones();
717  const labelList& owner0 = mesh0.faceOwner();
718  const faceZoneList& fz1 = mesh1.faceZones();
719  const labelList& owner1 = mesh1.faceOwner();
720 
721 
722  zoneNames.setCapacity(fz0.size() + fz1.size());
723  zoneNames.append(fz0.toc());
724 
725  from1ToAll.setSize(fz1.size());
726 
727  forAll(fz1, zi)
728  {
729  from1ToAll[zi] = zoneIndex(fz1[zi].name(), zoneNames);
730  }
731  zoneNames.shrink();
732 
733  fzOrientations.setSize(zoneNames.size(), false);
734 
735  // Zone(s) per face
736  labelList faceToZone(allOwner.size(), -1);
737  labelListList addFaceToZones(allOwner.size());
738  boolList faceToFlip(allOwner.size(), false);
739  boolListList addFaceToFlips(allOwner.size());
740 
741  // mesh0 zones kept
742  forAll(fz0, zi)
743  {
744  const labelList& addressing = fz0[zi];
745 
746  fzOrientations[zi] = fz0[zi].oriented();
747 
748  if (fz0[zi].oriented())
749  {
750  const boolList& flipMap = fz0[zi].flipMap();
751 
752  forAll(addressing, i)
753  {
754  const label face0 = addressing[i];
755  bool flip0 = flipMap[i];
756  const label allFacei = from0ToAllFaces[face0];
757 
758  if (allFacei != -1)
759  {
760  // Check if orientation same
761  const label allCell0 = owner0[face0];
762  if (allOwner[allFacei] != allCell0)
763  {
764  flip0 = !flip0;
765  }
766 
767  if (faceToZone[allFacei] == -1)
768  {
769  faceToZone[allFacei] = zi;
770  faceToFlip[allFacei] = flip0;
771  }
772  else if (faceToZone[allFacei] != zi)
773  {
774  labelList& fZones = addFaceToZones[allFacei];
775  boolList& flipZones = addFaceToFlips[allFacei];
776 
777  if (findIndex(fZones, zi) == -1)
778  {
779  fZones.append(zi);
780  flipZones.append(flip0);
781  }
782  }
783  }
784  }
785  }
786  else
787  {
788  forAll(addressing, i)
789  {
790  const label face0 = addressing[i];
791  const label allFacei = from0ToAllFaces[face0];
792 
793  if (allFacei != -1)
794  {
795  if (faceToZone[allFacei] == -1)
796  {
797  faceToZone[allFacei] = zi;
798  }
799  else if (faceToZone[allFacei] != zi)
800  {
801  labelList& fZones = addFaceToZones[allFacei];
802 
803  if (findIndex(fZones, zi) == -1)
804  {
805  fZones.append(zi);
806  }
807  }
808  }
809  }
810  }
811  }
812 
813  // mesh1 zones renumbered
814  forAll(fz1, zi)
815  {
816  const labelList& addressing = fz1[zi];
817  const boolList& flipMap = fz1[zi].flipMap();
818 
819  const label allZoneI = from1ToAll[zi];
820 
821  fzOrientations[allZoneI] = fz1[zi].oriented();
822 
823  if (fz1[zi].oriented())
824  {
825  forAll(addressing, i)
826  {
827  const label face1 = addressing[i];
828  bool flip1 = flipMap[i];
829  const label allFacei = from1ToAllFaces[face1];
830 
831  if (allFacei != -1)
832  {
833  // Check if orientation same
834  const label allCell1 = from1ToAllCells[owner1[face1]];
835  if (allOwner[allFacei] != allCell1)
836  {
837  flip1 = !flip1;
838  }
839 
840  if (faceToZone[allFacei] == -1)
841  {
842  faceToZone[allFacei] = allZoneI;
843  faceToFlip[allFacei] = flip1;
844  }
845  else if (faceToZone[allFacei] != allZoneI)
846  {
847  labelList& fZones = addFaceToZones[allFacei];
848  boolList& flipZones = addFaceToFlips[allFacei];
849 
850  if (findIndex(fZones, allZoneI) == -1)
851  {
852  fZones.append(allZoneI);
853  flipZones.append(flip1);
854  }
855  }
856  }
857  }
858  }
859  else
860  {
861  forAll(addressing, i)
862  {
863  const label face1 = addressing[i];
864  const label allFacei = from1ToAllFaces[face1];
865 
866  if (allFacei != -1)
867  {
868  if (faceToZone[allFacei] == -1)
869  {
870  faceToZone[allFacei] = allZoneI;
871  }
872  else if (faceToZone[allFacei] != allZoneI)
873  {
874  labelList& fZones = addFaceToZones[allFacei];
875 
876  if (findIndex(fZones, allZoneI) == -1)
877  {
878  fZones.append(allZoneI);
879  }
880  }
881  }
882  }
883  }
884  }
885 
886 
887  // Extract back into zones
888 
889  // 1. Count
890  labelList nFaces(zoneNames.size(), 0);
891  forAll(faceToZone, allFacei)
892  {
893  label zi = faceToZone[allFacei];
894  if (zi != -1)
895  {
896  nFaces[zi]++;
897  }
898  }
899  forAll(addFaceToZones, allFacei)
900  {
901  const labelList& fZones = addFaceToZones[allFacei];
902  forAll(fZones, i)
903  {
904  nFaces[fZones[i]]++;
905  }
906  }
907 
908  // 2. Fill
909  fzFaces.setSize(zoneNames.size());
910  fzFlips.setSize(zoneNames.size());
911 
912  forAll(fzFaces, zi)
913  {
914  fzFaces[zi].setCapacity(nFaces[zi]);
915 
916  if (fzOrientations[zi])
917  {
918  fzFlips[zi].setCapacity(nFaces[zi]);
919  }
920  }
921 
922  forAll(faceToZone, allFacei)
923  {
924  label zi = faceToZone[allFacei];
925  bool flip = faceToFlip[allFacei];
926  if (zi != -1)
927  {
928  fzFaces[zi].append(allFacei);
929 
930  if (fzOrientations[zi])
931  {
932  fzFlips[zi].append(flip);
933  }
934  }
935  }
936  forAll(addFaceToZones, allFacei)
937  {
938  const labelList& fZones = addFaceToZones[allFacei];
939  const boolList& flipZones = addFaceToFlips[allFacei];
940 
941  forAll(fZones, i)
942  {
943  label zi = fZones[i];
944  fzFaces[zi].append(allFacei);
945  if (fzOrientations[zi])
946  {
947  fzFlips[zi].append(flipZones[i]);
948  }
949  }
950  }
951 
952  forAll(fzFaces, zi)
953  {
954  fzFaces[zi].shrink();
955  fzFlips[zi].shrink();
956 
958  sortedOrder(fzFaces[zi], order);
959  fzFaces[zi] = UIndirectList<label>(fzFaces[zi], order)();
960  fzFlips[zi] = UIndirectList<bool>(fzFlips[zi], order)();
961  }
962 }
963 
964 
965 void Foam::polyMeshAdder::mergeCellZones
966 (
967  const label nAllCells,
968 
969  const cellZoneList& cz0,
970  const cellZoneList& cz1,
971  const labelList& from1ToAllCells,
972 
973  DynamicList<word>& zoneNames,
974  labelList& from1ToAll,
975  List<DynamicList<label>>& czCells
976 )
977 {
978  zoneNames.setCapacity(cz0.size() + cz1.size());
979  zoneNames.append(cz0.toc());
980 
981  from1ToAll.setSize(cz1.size());
982  forAll(cz1, zi)
983  {
984  from1ToAll[zi] = zoneIndex(cz1[zi].name(), zoneNames);
985  }
986  zoneNames.shrink();
987 
988 
989  // Zone(s) per cell. Two levels: if only one zone
990  // stored in cellToZone. Any extra stored in additionalCellToZones.
991  // This is so we only allocate labelLists per cell if absolutely
992  // necessary.
993  labelList cellToZone(nAllCells, -1);
994  labelListList addCellToZones(nAllCells);
995 
996  // mesh0 zones kept
997  forAll(cz0, zi)
998  {
999  const cellZone& cz = cz0[zi];
1000  forAll(cz, i)
1001  {
1002  label cell0 = cz[i];
1003 
1004  if (cellToZone[cell0] == -1)
1005  {
1006  cellToZone[cell0] = zi;
1007  }
1008  else if (cellToZone[cell0] != zi)
1009  {
1010  labelList& cZones = addCellToZones[cell0];
1011  if (findIndex(cZones, zi) == -1)
1012  {
1013  cZones.append(zi);
1014  }
1015  }
1016  }
1017  }
1018 
1019  // mesh1 zones renumbered
1020  forAll(cz1, zi)
1021  {
1022  const cellZone& cz = cz1[zi];
1023  const label allZoneI = from1ToAll[zi];
1024  forAll(cz, i)
1025  {
1026  label cell1 = cz[i];
1027  label allCelli = from1ToAllCells[cell1];
1028 
1029  if (cellToZone[allCelli] == -1)
1030  {
1031  cellToZone[allCelli] = allZoneI;
1032  }
1033  else if (cellToZone[allCelli] != allZoneI)
1034  {
1035  labelList& cZones = addCellToZones[allCelli];
1036  if (findIndex(cZones, allZoneI) == -1)
1037  {
1038  cZones.append(allZoneI);
1039  }
1040  }
1041  }
1042  }
1043 
1044  // Extract back into zones
1045 
1046  // 1. Count
1047  labelList nCells(zoneNames.size(), 0);
1048  forAll(cellToZone, allCelli)
1049  {
1050  label zi = cellToZone[allCelli];
1051  if (zi != -1)
1052  {
1053  nCells[zi]++;
1054  }
1055  }
1056  forAll(addCellToZones, allCelli)
1057  {
1058  const labelList& cZones = addCellToZones[allCelli];
1059  forAll(cZones, i)
1060  {
1061  nCells[cZones[i]]++;
1062  }
1063  }
1064 
1065  // 2. Fill
1066  czCells.setSize(zoneNames.size());
1067  forAll(czCells, zi)
1068  {
1069  czCells[zi].setCapacity(nCells[zi]);
1070  }
1071  forAll(cellToZone, allCelli)
1072  {
1073  label zi = cellToZone[allCelli];
1074  if (zi != -1)
1075  {
1076  czCells[zi].append(allCelli);
1077  }
1078  }
1079  forAll(addCellToZones, allCelli)
1080  {
1081  const labelList& cZones = addCellToZones[allCelli];
1082  forAll(cZones, i)
1083  {
1084  czCells[cZones[i]].append(allCelli);
1085  }
1086  }
1087  forAll(czCells, i)
1088  {
1089  czCells[i].shrink();
1090  stableSort(czCells[i]);
1091  }
1092 }
1093 
1094 
1095 void Foam::polyMeshAdder::mergeZones
1096 (
1097  const label nAllPoints,
1098  const labelList& allOwner,
1099  const label nAllCells,
1100 
1101  const polyMesh& mesh0,
1102  const polyMesh& mesh1,
1103  const labelList& from0ToAllPoints,
1104  const labelList& from0ToAllFaces,
1105 
1106  const labelList& from1ToAllPoints,
1107  const labelList& from1ToAllFaces,
1108  const labelList& from1ToAllCells,
1109 
1110  DynamicList<word>& pointZoneNames,
1111  List<DynamicList<label>>& pzPoints,
1112 
1113  DynamicList<word>& faceZoneNames,
1114  List<DynamicList<label>>& fzFaces,
1115  boolList& fzOrientations,
1116  List<DynamicList<bool>>& fzFlips,
1117 
1118  DynamicList<word>& cellZoneNames,
1119  List<DynamicList<label>>& czCells
1120 )
1121 {
1122  labelList from1ToAllPZones;
1123  mergePointZones
1124  (
1125  nAllPoints,
1126  mesh0.pointZones(),
1127  mesh1.pointZones(),
1128  from0ToAllPoints,
1129  from1ToAllPoints,
1130 
1131  pointZoneNames,
1132  from1ToAllPZones,
1133  pzPoints
1134  );
1135 
1136  labelList from1ToAllFZones;
1137  mergeFaceZones
1138  (
1139  allOwner,
1140  mesh0,
1141  mesh1,
1142  from0ToAllFaces,
1143  from1ToAllFaces,
1144  from1ToAllCells,
1145 
1146  faceZoneNames,
1147  from1ToAllFZones,
1148  fzFaces,
1149  fzOrientations,
1150  fzFlips
1151  );
1152 
1153  labelList from1ToAllCZones;
1154  mergeCellZones
1155  (
1156  nAllCells,
1157  mesh0.cellZones(),
1158  mesh1.cellZones(),
1159  from1ToAllCells,
1160 
1161  cellZoneNames,
1162  from1ToAllCZones,
1163  czCells
1164  );
1165 }
1166 
1167 
1168 void Foam::polyMeshAdder::addZones
1169 (
1170  const DynamicList<word>& pointZoneNames,
1171  const List<DynamicList<label>>& pzPoints,
1172 
1173  const DynamicList<word>& faceZoneNames,
1174  const List<DynamicList<label>>& fzFaces,
1175  const boolList& fzOrientations,
1176  const List<DynamicList<bool>>& fzFlips,
1177 
1178  const DynamicList<word>& cellZoneNames,
1179  const List<DynamicList<label>>& czCells,
1180 
1181  polyMesh& mesh
1182 )
1183 {
1184  List<pointZone*> pZones(pzPoints.size());
1185  forAll(pZones, i)
1186  {
1187  pZones[i] = new pointZone
1188  (
1189  pointZoneNames[i],
1190  pzPoints[i],
1191  mesh.pointZones()
1192  );
1193  }
1194 
1195  List<faceZone*> fZones(fzFaces.size());
1196  forAll(fZones, i)
1197  {
1198  if (fzOrientations[i])
1199  {
1200  fZones[i] = new faceZone
1201  (
1202  faceZoneNames[i],
1203  fzFaces[i],
1204  fzFlips[i],
1205  mesh.faceZones()
1206  );
1207  }
1208  else
1209  {
1210  fZones[i] = new faceZone
1211  (
1212  faceZoneNames[i],
1213  fzFaces[i],
1214  mesh.faceZones()
1215  );
1216  }
1217  }
1218 
1219  List<cellZone*> cZones(czCells.size());
1220  forAll(cZones, i)
1221  {
1222  cZones[i] = new cellZone
1223  (
1224  cellZoneNames[i],
1225  czCells[i],
1226  mesh.cellZones()
1227  );
1228  }
1229 
1230  mesh.addZones
1231  (
1232  pZones,
1233  fZones,
1234  cZones
1235  );
1236 }
1237 
1238 
1239 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1240 
1242 (
1243  polyMesh& mesh0,
1244  const polyMesh& mesh1,
1245  const faceCoupleInfo& coupleInfo,
1246  const bool validBoundary
1247 )
1248 {
1249  const polyBoundaryMesh& patches0 = mesh0.boundaryMesh();
1250  const polyBoundaryMesh& patches1 = mesh1.boundaryMesh();
1251 
1252  DynamicList<word> allPatchNames(patches0.size() + patches1.size());
1253  DynamicList<word> allPatchTypes(allPatchNames.size());
1254 
1255  // Patch maps
1256  labelList from1ToAllPatches(patches1.size());
1257  labelList fromAllTo1Patches(allPatchNames.size(), -1);
1258 
1259  mergePatchNames
1260  (
1261  patches0,
1262  patches1,
1263  allPatchNames,
1264  allPatchTypes,
1265  from1ToAllPatches,
1266  fromAllTo1Patches
1267  );
1268 
1269 
1270  // New points
1271  pointField allPoints;
1272 
1273  // Map from mesh0/1 points to allPoints.
1274  labelList from0ToAllPoints(mesh0.nPoints(), -1);
1275  labelList from1ToAllPoints(mesh1.nPoints(), -1);
1276 
1277  // New faces
1278  faceList allFaces;
1279  labelList allOwner;
1280  labelList allNeighbour;
1281  label nInternalFaces;
1282  // Sizes per patch
1283  labelList nFaces(allPatchNames.size(), 0);
1284  label nCells;
1285 
1286  // Maps
1287  labelList from0ToAllFaces(mesh0.nFaces(), -1);
1288  labelList from1ToAllFaces(mesh1.nFaces(), -1);
1289  // Map
1290  labelList from1ToAllCells(mesh1.nCells(), -1);
1291 
1292  mergePrimitives
1293  (
1294  mesh0,
1295  mesh1,
1296  coupleInfo,
1297 
1298  allPatchNames.size(),
1299  fromAllTo1Patches,
1300  from1ToAllPatches,
1301 
1302  allPoints,
1303  from0ToAllPoints,
1304  from1ToAllPoints,
1305 
1306  allFaces,
1307  allOwner,
1308  allNeighbour,
1309  nInternalFaces,
1310  nFaces,
1311  nCells,
1312 
1313  from0ToAllFaces,
1314  from1ToAllFaces,
1315  from1ToAllCells
1316  );
1317 
1318 
1319  // Zones
1320  // ~~~~~
1321 
1322  DynamicList<word> pointZoneNames;
1323  List<DynamicList<label>> pzPoints;
1324 
1325  DynamicList<word> faceZoneNames;
1326  List<DynamicList<label>> fzFaces;
1327  boolList fzOrientations;
1328  List<DynamicList<bool>> fzFlips;
1329 
1330  DynamicList<word> cellZoneNames;
1331  List<DynamicList<label>> czCells;
1332 
1333  mergeZones
1334  (
1335  allPoints.size(),
1336  allOwner,
1337  nCells,
1338 
1339  mesh0,
1340  mesh1,
1341 
1342  from0ToAllPoints,
1343  from0ToAllFaces,
1344 
1345  from1ToAllPoints,
1346  from1ToAllFaces,
1347  from1ToAllCells,
1348 
1349  pointZoneNames,
1350  pzPoints,
1351 
1352  faceZoneNames,
1353  fzFaces,
1354  fzOrientations,
1355  fzFlips,
1356 
1357  cellZoneNames,
1358  czCells
1359  );
1360 
1361 
1362  // Patches
1363  // ~~~~~~~
1364 
1365 
1366  // Store mesh0 patch info before modifying patches0.
1367  labelList mesh0PatchSizes(getPatchSizes(patches0));
1368  labelList mesh0PatchStarts(getPatchStarts(patches0));
1369 
1370  // Map from 0 to all patches (since gets compacted)
1371  labelList from0ToAllPatches(patches0.size(), -1);
1372 
1373  // Inplace extend mesh0 patches (note that patches0.size() now also
1374  // has changed)
1375  labelList patchSizes(allPatchNames.size());
1376  labelList patchStarts(allPatchNames.size());
1377 
1378  label startFacei = nInternalFaces;
1379 
1380  // Copy patches0 with new sizes. First patches always come from
1381  // mesh0 and will always be present.
1382  label allPatchi = 0;
1383 
1384  forAll(from0ToAllPatches, patch0)
1385  {
1386  // Originates from mesh0. Clone with new size & filter out empty
1387  // patch.
1388 
1389  if (nFaces[patch0] == 0 && isA<processorPolyPatch>(patches0[patch0]))
1390  {
1391  // Pout<< "Removing zero sized mesh0 patch "
1392  // << allPatchNames[patch0]
1393  // << endl;
1394  from0ToAllPatches[patch0] = -1;
1395 
1396  // Check if patch was also in mesh1 and update its addressing if so.
1397  if (fromAllTo1Patches[patch0] != -1)
1398  {
1399  from1ToAllPatches[fromAllTo1Patches[patch0]] = -1;
1400  }
1401  }
1402  else
1403  {
1404  patchSizes[allPatchi] = nFaces[patch0];
1405  patchStarts[allPatchi] = startFacei;
1406 
1407  // Record new index in allPatches
1408  from0ToAllPatches[patch0] = allPatchi;
1409 
1410  // Check if patch was also in mesh1 and update its addressing if so.
1411  if (fromAllTo1Patches[patch0] != -1)
1412  {
1413  from1ToAllPatches[fromAllTo1Patches[patch0]] = allPatchi;
1414  }
1415 
1416  startFacei += nFaces[patch0];
1417 
1418  allPatchi++;
1419  }
1420  }
1421 
1422  // Trim the existing patches
1423  {
1424  const label sz0 = from0ToAllPatches.size();
1425  labelList newToOld(sz0, sz0-1);
1426  label nNew = 0;
1427  forAll(from0ToAllPatches, patchi)
1428  {
1429  if (from0ToAllPatches[patchi] != -1)
1430  {
1431  newToOld[nNew++] = patchi;
1432  }
1433  }
1434  newToOld.setSize(nNew);
1435  mesh0.reorderPatches(newToOld, false);
1436  }
1437 
1438  // Copy unique patches of mesh1.
1439  forAll(from1ToAllPatches, patch1)
1440  {
1441  label uncompactAllPatchi = from1ToAllPatches[patch1];
1442 
1443  if (uncompactAllPatchi >= from0ToAllPatches.size())
1444  {
1445  // Patch has not been merged with any mesh0 patch.
1446 
1447  if
1448  (
1449  nFaces[uncompactAllPatchi] == 0
1450  && isA<processorPolyPatch>(patches1[patch1])
1451  )
1452  {
1453  // Pout<< "Removing zero sized mesh1 patch "
1454  // << allPatchNames[uncompactAllPatchi] << endl;
1455  from1ToAllPatches[patch1] = -1;
1456  }
1457  else
1458  {
1459  patchSizes[allPatchi] = nFaces[uncompactAllPatchi];
1460  patchStarts[allPatchi] = startFacei;
1461 
1462  // Clone. Note dummy size and start. Gets overwritten later in
1463  // resetPrimitives. This avoids getting temporarily illegal
1464  // SubList construction in polyPatch.
1465  mesh0.addPatch(allPatchi, patches1[patch1]);
1466 
1467  // Record new index in allPatches
1468  from1ToAllPatches[patch1] = allPatchi;
1469 
1470  startFacei += nFaces[uncompactAllPatchi];
1471 
1472  allPatchi++;
1473  }
1474  }
1475  }
1476  patchSizes.setSize(allPatchi);
1477  patchStarts.setSize(allPatchi);
1478 
1479 
1480  // Construct map information before changing mesh0 primitives
1481  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1482 
1484  (
1485  new mapAddedPolyMesh
1486  (
1487  mesh0.nPoints(),
1488  mesh0.nFaces(),
1489  mesh0.nCells(),
1490 
1491  mesh1.nPoints(),
1492  mesh1.nFaces(),
1493  mesh1.nCells(),
1494 
1495  from0ToAllPoints,
1496  from0ToAllFaces,
1497  identityMap(mesh0.nCells()),
1498 
1499  from1ToAllPoints,
1500  from1ToAllFaces,
1501  from1ToAllCells,
1502 
1503  from0ToAllPatches,
1504  from1ToAllPatches,
1505 
1506  mesh0PatchSizes,
1507  mesh0PatchStarts
1508  )
1509  );
1510 
1511 
1512 
1513  // Now we have extracted all information from all meshes.
1514  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1515 
1516  mesh0.resetMotion(); // delete any oldPoints.
1517  mesh0.resetPrimitives
1518  (
1519  move(allPoints),
1520  move(allFaces),
1521  move(allOwner),
1522  move(allNeighbour),
1523  patchSizes, // size
1524  patchStarts, // patchstarts
1525  validBoundary // boundary valid?
1526  );
1527 
1528  // Add zones to new mesh.
1529  mesh0.pointZones().clear();
1530  mesh0.faceZones().clear();
1531  mesh0.cellZones().clear();
1532  addZones
1533  (
1534  pointZoneNames,
1535  pzPoints,
1536 
1537  faceZoneNames,
1538  fzFaces,
1539  fzOrientations,
1540  fzFlips,
1541 
1542  cellZoneNames,
1543  czCells,
1544  mesh0
1545  );
1546 
1547  return mapPtr;
1548 }
1549 
1550 
1551 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void setSize(const label)
Reset size of List.
Definition: List.C:281
void append(T *)
Append an element at the end of the list.
Definition: PtrListI.H:39
label size() const
Return the number of elements in the UPtrList.
Definition: UPtrListI.H:29
void clear()
Clear the zones.
Definition: ZoneList.C:282
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
Container for information needed to couple to meshes. When constructed from two meshes and a list of ...
Class containing mesh-to-mesh mapping information after a mesh addition where we add a mesh ('added m...
Foam::polyBoundaryMesh.
static autoPtr< mapAddedPolyMesh > add(polyMesh &mesh0, const polyMesh &mesh1, const faceCoupleInfo &coupleInfo, const bool validBoundary=true)
Inplace add mesh to polyMesh. Returns map construct.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
const pointZoneList & pointZones() const
Return point zones.
Definition: polyMesh.H:437
const cellZoneList & cellZones() const
Return cell zones.
Definition: polyMesh.H:449
void resetPrimitives(pointField &&points, faceList &&faces, labelList &&owner, labelList &&neighbour, const labelList &patchSizes, const labelList &patchStarts, const bool validBoundary=true)
Reset mesh primitive data. Assumes all patch info correct.
Definition: polyMesh.C:716
void resetMotion() const
Reset motion.
Definition: polyMesh.C:1513
const faceZoneList & faceZones() const
Return face zones.
Definition: polyMesh.H:443
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:401
void addZones(const List< pointZone * > &pz, const List< faceZone * > &fz, const List< cellZone * > &cz)
Add mesh zones.
Definition: polyMesh.C:1145
virtual void reorderPatches(const labelUList &newToOld, const bool validBoundary)
Reorder and trim existing patches. If validBoundary the new.
Definition: polyMesh.C:1203
virtual void addPatch(const label insertPatchi, const polyPatch &patch)
Add/insert single patch.
Definition: polyMesh.C:1246
label nCells() const
label nPoints() const
label nFaces() const
IOporosityModelList pZones(mesh)
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
label patchi
label nPoints
const cellShapeList & cells
const fvPatchList & patches
List< label > labelList
A List of labels.
Definition: labelList.H:56
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< cell > cellList
list of cells
Definition: cellList.H:42
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
int order(const scalar s)
errorManip< error > abort(error &err)
Definition: errorManip.H:131
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:42
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:57
List< List< bool > > boolListList
Definition: boolList.H:51
void inplaceRenumber(const labelUList &oldToNew, ListType &)
Inplace renumber the values of a list.
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurrence of given element and return index,.
error FatalError
void stableSort(UList< T > &)
Definition: UList.C:129
labelList identityMap(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
List< face > faceList
Definition: faceListFwd.H:41
PrimitivePatch< IndirectList< face >, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
void inplaceReorder(const labelUList &oldToNew, ListType &)
Inplace reorder the elements of a list.
volScalarField & p