polyTopoChange.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-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2022,2024 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 "polyTopoChange.H"
30 #include "polyMesh.H"
31 #include "polyAddPoint.H"
32 #include "polyModifyPoint.H"
33 #include "polyRemovePoint.H"
34 #include "polyAddFace.H"
35 #include "polyModifyFace.H"
36 #include "polyRemoveFace.H"
37 #include "polyAddCell.H"
38 #include "polyModifyCell.H"
39 #include "polyRemoveCell.H"
40 #include "CircularBuffer.H"
41 #include "CompactListList.H"
42 #include "objectMap.H"
43 #include "processorPolyPatch.H"
44 #include "mapPolyMesh.H"
45 
46 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
47 
48 namespace Foam
49 {
50  defineTypeNameAndDebug(polyTopoChange, 0);
51 }
52 
53 
54 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
55 
56 // Renumber with special handling for merged items (marked with <-1)
57 void Foam::polyTopoChange::renumberReverseMap
58 (
59  const labelUList& oldToNew,
60  DynamicList<label>& elems
61 )
62 {
63  forAll(elems, elemI)
64  {
65  const label val = elems[elemI];
66 
67  if (val >= 0)
68  {
69  elems[elemI] = oldToNew[val];
70  }
71  else if (val < -1)
72  {
73  const label mergedVal = -val-2;
74  elems[elemI] = -oldToNew[mergedVal]-2;
75  }
76  }
77 }
78 
79 
80 void Foam::polyTopoChange::renumber
81 (
82  const labelUList& oldToNew,
83  labelHashSet& labels
84 )
85 {
86  labelHashSet newSet(labels.capacity());
87 
88  for (const label val : labels)
89  {
90  const label newVal = oldToNew[val];
91 
92  if (newVal >= 0)
93  {
94  newSet.insert(newVal);
95  }
96  }
97 
98  labels.transfer(newSet);
99 }
100 
101 
102 // Renumber and remove -1 elements.
103 void Foam::polyTopoChange::renumberCompact
104 (
105  const labelUList& oldToNew,
106  labelList& elems
107 )
108 {
109  label nElem = 0;
110 
111  for (const label val : elems)
112  {
113  const label newVal = oldToNew[val];
114 
115  if (newVal != -1)
116  {
117  elems[nElem++] = newVal;
118  }
119  }
120  elems.setSize(nElem);
121 }
122 
123 
124 void Foam::polyTopoChange::countMap
125 (
126  const labelUList& map,
127  const labelUList& reverseMap,
128  label& nAdd,
129  label& nInflate,
130  label& nMerge,
131  label& nRemove
132 )
133 {
134  nAdd = 0;
135  nInflate = 0;
136  nMerge = 0;
137  nRemove = 0;
138 
139  forAll(map, newCelli)
140  {
141  const label oldCelli = map[newCelli];
142 
143  if (oldCelli >= 0)
144  {
145  if
146  (
147  oldCelli < reverseMap.size()
148  && reverseMap[oldCelli] == newCelli
149  )
150  {
151  // unchanged
152  }
153  else
154  {
155  // Added (from another cell v.s. inflated from face/point)
156  nAdd++;
157  }
158  }
159  else if (oldCelli == -1)
160  {
161  // Created from nothing
162  nInflate++;
163  }
164  else
165  {
167  << " new:" << newCelli << abort(FatalError);
168  }
169  }
170 
171  forAll(reverseMap, oldCelli)
172  {
173  const label newCelli = reverseMap[oldCelli];
174 
175  if (newCelli >= 0)
176  {
177  // unchanged
178  }
179  else if (newCelli == -1)
180  {
181  // removed
182  nRemove++;
183  }
184  else
185  {
186  // merged into -newCelli-2
187  nMerge++;
188  }
189  }
190 }
191 
192 
193 void Foam::polyTopoChange::writeMeshStats(const polyMesh& mesh, Ostream& os)
194 {
195  const polyBoundaryMesh& patches = mesh.boundaryMesh();
196 
197  labelList patchSizes(patches.size());
198  labelList patchStarts(patches.size());
199  forAll(patches, patchi)
200  {
201  patchSizes[patchi] = patches[patchi].size();
202  patchStarts[patchi] = patches[patchi].start();
203  }
204 
205  const auto& czs = mesh.cellZones();
206  labelList cellZoneSizes(czs.size(), 0);
207  for (const auto& cz : czs)
208  {
209  cellZoneSizes[cz.index()] = cz.size();
210  }
211  const auto& fzs = mesh.faceZones();
212  labelList faceZoneSizes(fzs.size(), 0);
213  for (const auto& fz : fzs)
214  {
215  faceZoneSizes[fz.index()] = fz.size();
216  }
217  const auto& pzs = mesh.pointZones();
218  labelList pointZoneSizes(pzs.size(), 0);
219  for (const auto& pz : pzs)
220  {
221  pointZoneSizes[pz.index()] = pz.size();
222  }
223 
224  os << " Points : " << mesh.nPoints() << nl
225  << " Faces : " << mesh.nFaces() << nl
226  << " Cells : " << mesh.nCells() << nl
227  << " PatchSizes : " << flatOutput(patchSizes) << nl
228  << " PatchStarts : " << flatOutput(patchStarts) << nl
229  << " cZoneSizes : " << flatOutput(cellZoneSizes) << nl
230  << " fZoneSizes : " << flatOutput(faceZoneSizes) << nl
231  << " pZoneSizes : " << flatOutput(pointZoneSizes) << nl
232  << endl;
233 }
234 
235 
236 void Foam::polyTopoChange::getMergeSets
237 (
238  const labelUList& reverseCellMap,
239  const labelUList& cellMap,
240  List<objectMap>& cellsFromCells
241 )
242 {
243  // Per new cell the number of old cells that have been merged into it
244  labelList nMerged(cellMap.size(), 1);
245 
246  forAll(reverseCellMap, oldCelli)
247  {
248  const label newCelli = reverseCellMap[oldCelli];
249 
250  if (newCelli < -1)
251  {
252  label mergeCelli = -newCelli-2;
253 
254  nMerged[mergeCelli]++;
255  }
256  }
257 
258  // From merged cell to set index
259  labelList cellToMergeSet(cellMap.size(), -1);
260 
261  label nSets = 0;
262 
263  forAll(nMerged, celli)
264  {
265  if (nMerged[celli] > 1)
266  {
267  cellToMergeSet[celli] = nSets++;
268  }
269  }
270 
271  // Collect cell labels.
272  // Each objectMap will have
273  // - index : new mesh cell label
274  // - masterObjects : list of old cells that have been merged. Element 0
275  // will be the original destination cell label.
276 
277  cellsFromCells.setSize(nSets);
278 
279  forAll(reverseCellMap, oldCelli)
280  {
281  const label newCelli = reverseCellMap[oldCelli];
282 
283  if (newCelli < -1)
284  {
285  const label mergeCelli = -newCelli-2;
286 
287  // oldCelli was merged into mergeCelli
288 
289  const label setI = cellToMergeSet[mergeCelli];
290 
291  objectMap& mergeSet = cellsFromCells[setI];
292 
293  if (mergeSet.masterObjects().empty())
294  {
295  // First occurrence of master cell mergeCelli
296 
297  mergeSet.index() = mergeCelli;
298  mergeSet.masterObjects().setSize(nMerged[mergeCelli]);
299 
300  // old master label
301  mergeSet.masterObjects()[0] = cellMap[mergeCelli];
302 
303  // old slave label
304  mergeSet.masterObjects()[1] = oldCelli;
305 
306  nMerged[mergeCelli] = 2;
307  }
308  else
309  {
310  mergeSet.masterObjects()[nMerged[mergeCelli]++] = oldCelli;
311  }
312  }
313  }
314 }
315 
316 
317 bool Foam::polyTopoChange::hasValidPoints(const face& f) const
318 {
319  for (const label fp : f)
320  {
321  if (fp < 0 || fp >= points_.size())
322  {
323  return false;
324  }
325  }
326  return true;
327 }
328 
329 
330 Foam::pointField Foam::polyTopoChange::facePoints(const face& f) const
331 {
332  pointField points(f.size());
333  forAll(f, fp)
334  {
335  if (f[fp] < 0 && f[fp] >= points_.size())
336  {
338  << "Problem." << abort(FatalError);
339  }
340  points[fp] = points_[f[fp]];
341  }
342  return points;
343 }
344 
345 
346 void Foam::polyTopoChange::checkFace
347 (
348  const face& f,
349  const label facei,
350  const label own,
351  const label nei,
352  const label patchi,
353  const label zoneI
354 ) const
355 {
356  if (nei == -1)
357  {
358  if (own == -1 && zoneI != -1)
359  {
360  // retired face
361  }
362  else if (patchi == -1 || patchi >= nPatches_)
363  {
365  << "Face has no neighbour (so external) but does not have"
366  << " a valid patch" << nl
367  << "f:" << f
368  << " facei(-1 if added face):" << facei
369  << " own:" << own << " nei:" << nei
370  << " patchi:" << patchi << nl;
371  if (hasValidPoints(f))
372  {
373  FatalError
374  << "points (removed points marked with "
375  << vector::max << ") " << facePoints(f);
376  }
378  }
379  }
380  else
381  {
382  if (patchi != -1)
383  {
385  << "Cannot both have valid patchi and neighbour" << nl
386  << "f:" << f
387  << " facei(-1 if added face):" << facei
388  << " own:" << own << " nei:" << nei
389  << " patchi:" << patchi << nl;
390  if (hasValidPoints(f))
391  {
392  FatalError
393  << "points (removed points marked with "
394  << vector::max << ") : " << facePoints(f);
395  }
397  }
398 
399  if (nei <= own)
400  {
402  << "Owner cell label should be less than neighbour cell label"
403  << nl
404  << "f:" << f
405  << " facei(-1 if added face):" << facei
406  << " own:" << own << " nei:" << nei
407  << " patchi:" << patchi << nl;
408  if (hasValidPoints(f))
409  {
410  FatalError
411  << "points (removed points marked with "
412  << vector::max << ") : " << facePoints(f);
413  }
415  }
416  }
417 
418  if (f.size() < 3 || f.found(-1))
419  {
421  << "Illegal vertices in face"
422  << nl
423  << "f:" << f
424  << " facei(-1 if added face):" << facei
425  << " own:" << own << " nei:" << nei
426  << " patchi:" << patchi << nl;
427  if (hasValidPoints(f))
428  {
429  FatalError
430  << "points (removed points marked with "
431  << vector::max << ") : " << facePoints(f);
432  }
434  }
435  if (facei >= 0 && facei < faces_.size() && faceRemoved(facei))
436  {
438  << "Face already marked for removal"
439  << nl
440  << "f:" << f
441  << " facei(-1 if added face):" << facei
442  << " own:" << own << " nei:" << nei
443  << " patchi:" << patchi << nl;
444  if (hasValidPoints(f))
445  {
446  FatalError
447  << "points (removed points marked with "
448  << vector::max << ") : " << facePoints(f);
449  }
451  }
452  forAll(f, fp)
453  {
454  if (f[fp] < points_.size() && pointRemoved(f[fp]))
455  {
457  << "Face uses removed vertices"
458  << nl
459  << "f:" << f
460  << " facei(-1 if added face):" << facei
461  << " own:" << own << " nei:" << nei
462  << " patchi:" << patchi << nl;
463  if (hasValidPoints(f))
464  {
465  FatalError
466  << "points (removed points marked with "
467  << vector::max << ") : " << facePoints(f);
468  }
470  }
471  }
472 }
473 
474 
475 void Foam::polyTopoChange::makeCells
476 (
477  const label nActiveFaces,
478  labelList& cellFaces,
479  labelList& cellFaceOffsets
480 ) const
481 {
482  cellFaces.setSize(2*nActiveFaces);
483  cellFaceOffsets.setSize(cellMap_.size() + 1);
484 
485  // Faces per cell
486  labelList nNbrs(cellMap_.size(), Zero);
487 
488  // 1. Count faces per cell
489 
490  for (label facei = 0; facei < nActiveFaces; facei++)
491  {
492  if (faceOwner_[facei] < 0)
493  {
494  pointField newPoints;
495  if (facei < faces_.size())
496  {
497  const face& f = faces_[facei];
498  newPoints.setSize(f.size(), vector::max);
499  forAll(f, fp)
500  {
501  if (f[fp] < points_.size())
502  {
503  newPoints[fp] = points_[f[fp]];
504  }
505  }
506  }
507 
508 
510  << "Face " << facei << " is active but its owner has"
511  << " been deleted. This is usually due to deleting cells"
512  << " without modifying exposed faces to be boundary faces."
513  << exit(FatalError);
514  }
515  nNbrs[faceOwner_[facei]]++;
516  }
517  for (label facei = 0; facei < nActiveFaces; facei++)
518  {
519  if (faceNeighbour_[facei] >= 0)
520  {
521  nNbrs[faceNeighbour_[facei]]++;
522  }
523  }
524 
525  // 2. Calculate offsets
526 
527  cellFaceOffsets[0] = 0;
528  forAll(nNbrs, celli)
529  {
530  cellFaceOffsets[celli+1] = cellFaceOffsets[celli] + nNbrs[celli];
531  }
532 
533  // 3. Fill faces per cell
534 
535  // reset the whole list to use as counter
536  nNbrs = 0;
537 
538  for (label facei = 0; facei < nActiveFaces; facei++)
539  {
540  label celli = faceOwner_[facei];
541 
542  cellFaces[cellFaceOffsets[celli] + nNbrs[celli]++] = facei;
543  }
544 
545  for (label facei = 0; facei < nActiveFaces; facei++)
546  {
547  label celli = faceNeighbour_[facei];
548 
549  if (celli >= 0)
550  {
551  cellFaces[cellFaceOffsets[celli] + nNbrs[celli]++] = facei;
552  }
553  }
554 
555  // Last offset points to beyond end of cellFaces.
556  cellFaces.setSize(cellFaceOffsets[cellMap_.size()]);
557 }
558 
559 
560 // Create cell-cell addressing. Called after compaction (but before ordering)
561 // of faces
562 void Foam::polyTopoChange::makeCellCells
563 (
564  const label nActiveFaces,
565  CompactListList<label>& cellCells
566 ) const
567 {
568  // Neighbours per cell
569  labelList nNbrs(cellMap_.size(), Zero);
570 
571  // 1. Count neighbours (through internal faces) per cell
572 
573  for (label facei = 0; facei < nActiveFaces; facei++)
574  {
575  if (faceNeighbour_[facei] >= 0)
576  {
577  nNbrs[faceOwner_[facei]]++;
578  nNbrs[faceNeighbour_[facei]]++;
579  }
580  }
581 
582  // 2. Construct csr
583  cellCells.setSize(nNbrs);
584 
585 
586  // 3. Fill faces per cell
587 
588  // reset the whole list to use as counter
589  nNbrs = 0;
590 
591  for (label facei = 0; facei < nActiveFaces; facei++)
592  {
593  label nei = faceNeighbour_[facei];
594 
595  if (nei >= 0)
596  {
597  label own = faceOwner_[facei];
598  cellCells(own, nNbrs[own]++) = nei;
599  cellCells(nei, nNbrs[nei]++) = own;
600  }
601  }
602 }
603 
604 
605 // Cell ordering (based on bandCompression).
606 // Handles removed cells. Returns number of remaining cells.
607 Foam::label Foam::polyTopoChange::getCellOrder
608 (
609  const CompactListList<label>& cellCellAddressing,
610  labelList& oldToNew
611 ) const
612 {
613  const label nOldCells(cellCellAddressing.size());
614 
615  // Which cells are visited/unvisited
616  bitSet unvisited(nOldCells, true);
617 
618  // Exclude removed cells
619  for (label celli = 0; celli < nOldCells; ++celli)
620  {
621  if (cellRemoved(celli))
622  {
623  unvisited.unset(celli);
624  }
625  }
626 
627  // The new output order
628  labelList newOrder(unvisited.count());
629 
630 
631  // Various work arrays
632  // ~~~~~~~~~~~~~~~~~~~
633 
634  //- Neighbour cells
635  DynamicList<label> nbrCells;
636 
637  //- Neighbour ordering
638  DynamicList<label> nbrOrder;
639 
640  //- Corresponding weights for neighbour cells
641  DynamicList<label> weights;
642 
643  // FIFO buffer for renumbering.
644  CircularBuffer<label> queuedCells(1024);
645 
646 
647  label cellInOrder = 0;
648 
649  while (true)
650  {
651  // For a disconnected region find the lowest connected cell.
652  label currCelli = -1;
653  label minCount = labelMax;
654 
655  for (const label celli : unvisited)
656  {
657  const label nbrCount = cellCellAddressing[celli].size();
658 
659  if (minCount > nbrCount)
660  {
661  minCount = nbrCount;
662  currCelli = celli;
663  }
664  }
665 
666  if (currCelli == -1)
667  {
668  break;
669  }
670 
671 
672  // Starting from currCelli - walk breadth-first
673 
674  queuedCells.push_back(currCelli);
675 
676  // Loop through queuedCells list. Add the first cell into the
677  // cell order if it has not already been visited and ask for its
678  // neighbours. If the neighbour in question has not been visited,
679  // add it to the end of the queuedCells list
680 
681  while (!queuedCells.empty())
682  {
683  // Process as FIFO
684  currCelli = queuedCells.front();
685  queuedCells.pop_front();
686 
687  if (unvisited.test(currCelli))
688  {
689  // First visit...
690  unvisited.unset(currCelli);
691 
692  // Add into cellOrder
693  newOrder[cellInOrder] = currCelli;
694  ++cellInOrder;
695 
696  // Find if the neighbours have been visited
697  const auto& neighbours = cellCellAddressing[currCelli];
698 
699  // Add in increasing order of connectivity
700 
701  // 1. Count neighbours of unvisited neighbours
702  nbrCells.clear();
703  weights.clear();
704 
705  for (const label nbr : neighbours)
706  {
707  const label nbrCount = cellCellAddressing[nbr].size();
708 
709  if (unvisited.test(nbr))
710  {
711  // Not visited (or removed), add to the list
712  nbrCells.push_back(nbr);
713  weights.push_back(nbrCount);
714  }
715  }
716 
717  // Resize DynamicList prior to sortedOrder
718  nbrOrder.resize_nocopy(weights.size());
719 
720  // 2. Ascending order
721  Foam::sortedOrder(weights, nbrOrder);
722 
723  // 3. Add to FIFO in sorted order
724  for (const label nbrIdx : nbrOrder)
725  {
726  queuedCells.push_back(nbrCells[nbrIdx]);
727  }
728  }
729  }
730  }
731 
732  // Now we have new-to-old in newOrder.
733  newOrder.resize(cellInOrder); // Extra safety, but should be a no-op
734 
735  // Invert to get old-to-new. Make sure removed (i.e. unmapped) cells are -1.
736  oldToNew = invert(nOldCells, newOrder);
737 
738  return cellInOrder;
739 }
740 
741 
742 // Determine order for faces:
743 // - upper-triangular order for internal faces
744 // - external faces after internal faces and in patch order.
745 void Foam::polyTopoChange::getFaceOrder
746 (
747  const label nActiveFaces,
748  const labelUList& cellFaces,
749  const labelUList& cellFaceOffsets,
750 
751  labelList& oldToNew,
752  labelList& patchSizes,
753  labelList& patchStarts
754 ) const
755 {
756  oldToNew.setSize(faceOwner_.size());
757  oldToNew = -1;
758 
759  // First unassigned face
760  label newFacei = 0;
761 
762  labelList nbr;
763  labelList order;
764 
765  forAll(cellMap_, celli)
766  {
767  label startOfCell = cellFaceOffsets[celli];
768  label nFaces = cellFaceOffsets[celli+1] - startOfCell;
769 
770  // Neighbouring cells
771  nbr.setSize(nFaces);
772 
773  for (label i = 0; i < nFaces; i++)
774  {
775  label facei = cellFaces[startOfCell + i];
776 
777  label nbrCelli = faceNeighbour_[facei];
778 
779  if (facei >= nActiveFaces)
780  {
781  // Retired face.
782  nbr[i] = -1;
783  }
784  else if (nbrCelli != -1)
785  {
786  // Internal face. Get cell on other side.
787  if (nbrCelli == celli)
788  {
789  nbrCelli = faceOwner_[facei];
790  }
791 
792  if (celli < nbrCelli)
793  {
794  // Celli is master
795  nbr[i] = nbrCelli;
796  }
797  else
798  {
799  // nbrCell is master. Let it handle this face.
800  nbr[i] = -1;
801  }
802  }
803  else
804  {
805  // External face. Do later.
806  nbr[i] = -1;
807  }
808  }
809 
810  sortedOrder(nbr, order);
811 
812  for (const label index : order)
813  {
814  if (nbr[index] != -1)
815  {
816  oldToNew[cellFaces[startOfCell + index]] = newFacei++;
817  }
818  }
819  }
820 
821 
822  // Pick up all patch faces in patch face order.
823  patchStarts.setSize(nPatches_);
824  patchStarts = 0;
825  patchSizes.setSize(nPatches_);
826  patchSizes = 0;
827 
828  if (nPatches_ > 0)
829  {
830  patchStarts[0] = newFacei;
831 
832  for (label facei = 0; facei < nActiveFaces; facei++)
833  {
834  if (region_[facei] >= 0)
835  {
836  patchSizes[region_[facei]]++;
837  }
838  }
839 
840  label facei = patchStarts[0];
841 
842  forAll(patchStarts, patchi)
843  {
844  patchStarts[patchi] = facei;
845  facei += patchSizes[patchi];
846  }
847  }
848 
849  //if (debug)
850  //{
851  // Pout<< "patchSizes:" << patchSizes << nl
852  // << "patchStarts:" << patchStarts << endl;
853  //}
854 
855  labelList workPatchStarts(patchStarts);
856 
857  for (label facei = 0; facei < nActiveFaces; facei++)
858  {
859  if (region_[facei] >= 0)
860  {
861  oldToNew[facei] = workPatchStarts[region_[facei]]++;
862  }
863  }
864 
865  // Retired faces.
866  for (label facei = nActiveFaces; facei < oldToNew.size(); facei++)
867  {
868  oldToNew[facei] = facei;
869  }
870 
871  // Check done all faces.
872  forAll(oldToNew, facei)
873  {
874  if (oldToNew[facei] == -1)
875  {
877  << "Did not determine new position"
878  << " for face " << facei
879  << " owner " << faceOwner_[facei]
880  << " neighbour " << faceNeighbour_[facei]
881  << " region " << region_[facei] << endl
882  << "This is usually caused by not specifying a patch for"
883  << " a boundary face." << nl
884  << "Switch on the polyTopoChange::debug flag to catch"
885  << " this error earlier." << nl;
886  if (hasValidPoints(faces_[facei]))
887  {
888  FatalError
889  << "points (removed points marked with "
890  << vector::max << ") " << facePoints(faces_[facei]);
891  }
893  }
894  }
895 }
896 
897 
898 // Reorder and compact faces according to map.
899 void Foam::polyTopoChange::reorderCompactFaces
900 (
901  const label newSize,
902  const labelUList& oldToNew
903 )
904 {
905  reorder(oldToNew, faces_);
906  faces_.setCapacity(newSize);
907 
908  reorder(oldToNew, region_);
909  region_.setCapacity(newSize);
910 
911  reorder(oldToNew, faceOwner_);
912  faceOwner_.setCapacity(newSize);
913 
914  reorder(oldToNew, faceNeighbour_);
915  faceNeighbour_.setCapacity(newSize);
916 
917  // Update faceMaps.
918  reorder(oldToNew, faceMap_);
919  faceMap_.setCapacity(newSize);
920 
921  renumberReverseMap(oldToNew, reverseFaceMap_);
922 
923  renumberKey(oldToNew, faceFromPoint_);
924  renumberKey(oldToNew, faceFromEdge_);
925  inplaceReorder(oldToNew, flipFaceFlux_);
926  flipFaceFlux_.setCapacity(newSize);
927  renumberKey(oldToNew, faceZone_);
928  inplaceReorder(oldToNew, faceZoneFlip_);
929  faceZoneFlip_.setCapacity(newSize);
930  if (faceAdditionalZones_.size())
931  {
932  // Extend to number of faces so oldToNew can be used
933  faceAdditionalZones_.setSize(newSize);
934  inplaceReorder(oldToNew, faceAdditionalZones_);
935  //faceAdditionalZones_.setCapacity(newSize);
936  }
937 }
938 
941 {
942  points_.shrink();
943  pointMap_.shrink();
944  reversePointMap_.shrink();
945  pointAdditionalZones_.shrink();
946 
947  faces_.shrink();
948  region_.shrink();
949  faceOwner_.shrink();
950  faceNeighbour_.shrink();
951  faceMap_.shrink();
952  reverseFaceMap_.shrink();
953  faceAdditionalZones_.shrink();
954 
955  cellMap_.shrink();
956  reverseCellMap_.shrink();
957  cellZone_.shrink();
958  cellAdditionalZones_.shrink();
959 }
960 
961 
962 // Compact all and orders points and faces:
963 // - points into internal followed by external points
964 // - internalfaces upper-triangular
965 // - externalfaces after internal ones.
966 void Foam::polyTopoChange::compact
967 (
968  const bool orderCells,
969  const bool orderPoints,
970  label& nInternalPoints,
971  labelList& patchSizes,
972  labelList& patchStarts
973 )
974 {
975  shrink();
976 
977  // Compact points
978  label nActivePoints = 0;
979  {
980  labelList localPointMap(points_.size(), -1);
981  label newPointi = 0;
982 
983  if (!orderPoints)
984  {
985  nInternalPoints = -1;
986 
987  forAll(points_, pointi)
988  {
989  if (!pointRemoved(pointi) && !retiredPoints_.found(pointi))
990  {
991  localPointMap[pointi] = newPointi++;
992  }
993  }
994  nActivePoints = newPointi;
995  }
996  else
997  {
998  forAll(points_, pointi)
999  {
1000  if (!pointRemoved(pointi) && !retiredPoints_.found(pointi))
1001  {
1002  nActivePoints++;
1003  }
1004  }
1005 
1006  // Mark boundary points
1007  forAll(faceOwner_, facei)
1008  {
1009  if
1010  (
1011  !faceRemoved(facei)
1012  && faceOwner_[facei] >= 0
1013  && faceNeighbour_[facei] < 0
1014  )
1015  {
1016  // Valid boundary face
1017  const face& f = faces_[facei];
1018 
1019  forAll(f, fp)
1020  {
1021  label pointi = f[fp];
1022 
1023  if (localPointMap[pointi] == -1)
1024  {
1025  if
1026  (
1027  pointRemoved(pointi)
1028  || retiredPoints_.found(pointi)
1029  )
1030  {
1032  << "Removed or retired point " << pointi
1033  << " in face " << f
1034  << " at position " << facei << endl
1035  << "Probably face has not been adapted for"
1036  << " removed points." << abort(FatalError);
1037  }
1038  localPointMap[pointi] = newPointi++;
1039  }
1040  }
1041  }
1042  }
1043 
1044  label nBoundaryPoints = newPointi;
1045  nInternalPoints = nActivePoints - nBoundaryPoints;
1046 
1047  // Move the boundary addressing up
1048  forAll(localPointMap, pointi)
1049  {
1050  if (localPointMap[pointi] != -1)
1051  {
1052  localPointMap[pointi] += nInternalPoints;
1053  }
1054  }
1055 
1056  newPointi = 0;
1057 
1058  // Mark internal points
1059  forAll(faceOwner_, facei)
1060  {
1061  if
1062  (
1063  !faceRemoved(facei)
1064  && faceOwner_[facei] >= 0
1065  && faceNeighbour_[facei] >= 0
1066  )
1067  {
1068  // Valid internal face
1069  const face& f = faces_[facei];
1070 
1071  forAll(f, fp)
1072  {
1073  label pointi = f[fp];
1074 
1075  if (localPointMap[pointi] == -1)
1076  {
1077  if
1078  (
1079  pointRemoved(pointi)
1080  || retiredPoints_.found(pointi)
1081  )
1082  {
1084  << "Removed or retired point " << pointi
1085  << " in face " << f
1086  << " at position " << facei << endl
1087  << "Probably face has not been adapted for"
1088  << " removed points." << abort(FatalError);
1089  }
1090  localPointMap[pointi] = newPointi++;
1091  }
1092  }
1093  }
1094  }
1095 
1096  if (newPointi != nInternalPoints)
1097  {
1099  << "Problem." << abort(FatalError);
1100  }
1101  newPointi = nActivePoints;
1102  }
1103 
1104  for (const label pointi : retiredPoints_)
1105  {
1106  localPointMap[pointi] = newPointi++;
1107  }
1108 
1109 
1110  if (debug)
1111  {
1112  Pout<< "Points : active:" << nActivePoints
1113  << " removed:" << points_.size()-newPointi << endl;
1114  }
1115 
1116  reorder(localPointMap, points_);
1117  points_.setCapacity(newPointi);
1118 
1119  // Update pointMaps
1120  reorder(localPointMap, pointMap_);
1121  pointMap_.setCapacity(newPointi);
1122  renumberReverseMap(localPointMap, reversePointMap_);
1123 
1124  renumberKey(localPointMap, pointZone_);
1125  renumber(localPointMap, retiredPoints_);
1126  if (pointAdditionalZones_.size())
1127  {
1128  reorder(localPointMap, pointAdditionalZones_);
1129  }
1130 
1131  // Use map to relabel face vertices
1132  forAll(faces_, facei)
1133  {
1134  face& f = faces_[facei];
1135 
1136  //labelList oldF(f);
1137  renumberCompact(localPointMap, f);
1138 
1139  if (!faceRemoved(facei) && f.size() < 3)
1140  {
1142  << "Created illegal face " << f
1143  //<< " from face " << oldF
1144  << " at position:" << facei
1145  << " when filtering removed points"
1146  << abort(FatalError);
1147  }
1148  }
1149  }
1150 
1151 
1152  // Compact faces.
1153  {
1154  labelList localFaceMap(faces_.size(), -1);
1155  label newFacei = 0;
1156 
1157  forAll(faces_, facei)
1158  {
1159  if (!faceRemoved(facei) && faceOwner_[facei] >= 0)
1160  {
1161  localFaceMap[facei] = newFacei++;
1162  }
1163  }
1164  nActiveFaces_ = newFacei;
1165 
1166  forAll(faces_, facei)
1167  {
1168  if (!faceRemoved(facei) && faceOwner_[facei] < 0)
1169  {
1170  // Retired face
1171  localFaceMap[facei] = newFacei++;
1172  }
1173  }
1174 
1175  if (debug)
1176  {
1177  Pout<< "Faces : active:" << nActiveFaces_
1178  << " removed:" << faces_.size()-newFacei << endl;
1179  }
1180 
1181  // Reorder faces.
1182  reorderCompactFaces(newFacei, localFaceMap);
1183  }
1184 
1185  // Compact cells.
1186  {
1187  labelList localCellMap;
1188  label newCelli;
1189 
1190  if (orderCells)
1191  {
1192  // Construct cellCell addressing
1193  CompactListList<label> cellCells;
1194  makeCellCells(nActiveFaces_, cellCells);
1195 
1196  // Cell ordering (based on bandCompression). Handles removed cells.
1197  newCelli = getCellOrder(cellCells, localCellMap);
1198  }
1199  else
1200  {
1201  // Compact out removed cells
1202  localCellMap.setSize(cellMap_.size());
1203  localCellMap = -1;
1204 
1205  newCelli = 0;
1206  forAll(cellMap_, celli)
1207  {
1208  if (!cellRemoved(celli))
1209  {
1210  localCellMap[celli] = newCelli++;
1211  }
1212  }
1213  }
1214 
1215  if (debug)
1216  {
1217  Pout<< "Cells : active:" << newCelli
1218  << " removed:" << cellMap_.size()-newCelli << endl;
1219  }
1220 
1221  // Renumber -if cells reordered or -if cells removed
1222  if (orderCells || (newCelli != cellMap_.size()))
1223  {
1224  reorder(localCellMap, cellMap_);
1225  cellMap_.setCapacity(newCelli);
1226  renumberReverseMap(localCellMap, reverseCellMap_);
1227 
1228  reorder(localCellMap, cellZone_);
1229  cellZone_.setCapacity(newCelli);
1230  if (cellAdditionalZones_.size())
1231  {
1232  reorder(localCellMap, cellAdditionalZones_);
1233  cellAdditionalZones_.setCapacity(newCelli);
1234  }
1235 
1236  renumberKey(localCellMap, cellFromPoint_);
1237  renumberKey(localCellMap, cellFromEdge_);
1238  renumberKey(localCellMap, cellFromFace_);
1239 
1240  // Renumber owner/neighbour. Take into account if neighbour suddenly
1241  // gets lower cell than owner.
1242  forAll(faceOwner_, facei)
1243  {
1244  label own = faceOwner_[facei];
1245  label nei = faceNeighbour_[facei];
1246 
1247  if (own >= 0)
1248  {
1249  // Update owner
1250  faceOwner_[facei] = localCellMap[own];
1251 
1252  if (nei >= 0)
1253  {
1254  // Update neighbour.
1255  faceNeighbour_[facei] = localCellMap[nei];
1256 
1257  // Check if face needs reversing.
1258  if
1259  (
1260  faceNeighbour_[facei] >= 0
1261  && faceNeighbour_[facei] < faceOwner_[facei]
1262  )
1263  {
1264  faces_[facei].flip();
1265  std::swap(faceOwner_[facei], faceNeighbour_[facei]);
1266  flipFaceFlux_.flip(facei);
1267  faceZoneFlip_.flip(facei);
1268  if (facei < faceAdditionalZones_.size())
1269  {
1270  for (auto& zas : faceAdditionalZones_[facei])
1271  {
1272  // Flip sign
1273  zas = -zas;
1274  }
1275  }
1276  }
1277  }
1278  }
1279  else if (nei >= 0)
1280  {
1281  // Update neighbour.
1282  faceNeighbour_[facei] = localCellMap[nei];
1283  }
1284  }
1285  }
1286  }
1287 
1288  // Reorder faces into upper-triangular and patch ordering
1289  {
1290  // Create cells (packed storage)
1291  labelList cellFaces;
1292  labelList cellFaceOffsets;
1293  makeCells(nActiveFaces_, cellFaces, cellFaceOffsets);
1294 
1295  // Do upper triangular order and patch sorting
1296  labelList localFaceMap;
1297  getFaceOrder
1298  (
1299  nActiveFaces_,
1300  cellFaces,
1301  cellFaceOffsets,
1302 
1303  localFaceMap,
1304  patchSizes,
1305  patchStarts
1306  );
1307 
1308  // Reorder faces.
1309  reorderCompactFaces(localFaceMap.size(), localFaceMap);
1310  }
1311 }
1312 
1313 
1314 // Find faces to interpolate to create value for new face. Only used if
1315 // face was inflated from edge or point. Internal faces should only be
1316 // created from internal faces, external faces only from external faces
1317 // (and ideally the same patch)
1318 // Is bit problematic if there are no faces to select, i.e. in polyDualMesh
1319 // an internal face can be created from a boundary edge with no internal
1320 // faces connected to it.
1321 Foam::labelList Foam::polyTopoChange::selectFaces
1322 (
1323  const primitiveMesh& mesh,
1324  const labelUList& faceLabels,
1325  const bool internalFacesOnly
1326 )
1327 {
1328  label nFaces = 0;
1329 
1330  forAll(faceLabels, i)
1331  {
1332  label facei = faceLabels[i];
1333 
1334  if (internalFacesOnly == mesh.isInternalFace(facei))
1335  {
1336  nFaces++;
1337  }
1338  }
1339 
1340  labelList collectedFaces;
1341 
1342  if (nFaces == 0)
1343  {
1344  // Did not find any faces of the correct type so just use any old
1345  // face.
1346  collectedFaces = faceLabels;
1347  }
1348  else
1349  {
1350  collectedFaces.setSize(nFaces);
1351 
1352  nFaces = 0;
1353 
1354  forAll(faceLabels, i)
1355  {
1356  label facei = faceLabels[i];
1357 
1358  if (internalFacesOnly == mesh.isInternalFace(facei))
1359  {
1360  collectedFaces[nFaces++] = facei;
1361  }
1362  }
1363  }
1364 
1365  return collectedFaces;
1366 }
1367 
1368 
1369 // Calculate pointMap per patch (so from patch point label to old patch point
1370 // label)
1371 void Foam::polyTopoChange::calcPatchPointMap
1372 (
1373  const UList<Map<label>>& oldPatchMeshPointMaps,
1374  const labelUList& patchMap,
1375  const polyBoundaryMesh& boundary,
1376  labelListList& patchPointMap
1377 ) const
1378 {
1379  patchPointMap.setSize(patchMap.size());
1380 
1381  forAll(patchMap, patchi)
1382  {
1383  const label oldPatchi = patchMap[patchi];
1384 
1385  if (oldPatchi != -1)
1386  {
1387  const labelList& meshPoints = boundary[patchi].meshPoints();
1388 
1389  const Map<label>& oldMeshPointMap =
1390  oldPatchMeshPointMaps[oldPatchi];
1391 
1392  labelList& curPatchPointRnb = patchPointMap[patchi];
1393 
1394  curPatchPointRnb.setSize(meshPoints.size());
1395 
1396  forAll(meshPoints, i)
1397  {
1398  if (meshPoints[i] < pointMap_.size())
1399  {
1400  // Check if old point was part of same patch
1401  curPatchPointRnb[i] = oldMeshPointMap.lookup
1402  (
1403  pointMap_[meshPoints[i]],
1404  -1
1405  );
1406  }
1407  else
1408  {
1409  curPatchPointRnb[i] = -1;
1410  }
1411  }
1412  }
1413  }
1414 }
1415 
1416 
1417 void Foam::polyTopoChange::calcFaceInflationMaps
1418 (
1419  const polyMesh& mesh,
1420  List<objectMap>& facesFromPoints,
1421  List<objectMap>& facesFromEdges,
1422  List<objectMap>& facesFromFaces
1423 ) const
1424 {
1425  // Faces inflated from points
1426  // ~~~~~~~~~~~~~~~~~~~~~~~~~~
1427 
1428  facesFromPoints.setSize(faceFromPoint_.size());
1429 
1430  if (faceFromPoint_.size())
1431  {
1432  label nFacesFromPoints = 0;
1433 
1434  // Collect all still existing faces connected to this point.
1435  forAllConstIters(faceFromPoint_, iter)
1436  {
1437  const label facei = iter.key();
1438  const label pointi = iter.val();
1439 
1440  // Get internal or patch faces using point on old mesh
1441  const bool internal = (region_[facei] == -1);
1442 
1443  facesFromPoints[nFacesFromPoints++] = objectMap
1444  (
1445  facei,
1446  selectFaces
1447  (
1448  mesh,
1449  mesh.pointFaces()[pointi],
1450  internal
1451  )
1452  );
1453  }
1454  }
1455 
1456 
1457  // Faces inflated from edges
1458  // ~~~~~~~~~~~~~~~~~~~~~~~~~
1459 
1460  facesFromEdges.setSize(faceFromEdge_.size());
1461 
1462  if (faceFromEdge_.size())
1463  {
1464  label nFacesFromEdges = 0;
1465 
1466  // Collect all still existing faces connected to this edge.
1467  forAllConstIters(faceFromEdge_, iter)
1468  {
1469  const label facei = iter.key();
1470  const label edgei = iter.val();
1471 
1472  // Get internal or patch faces using edge on old mesh
1473  const bool internal = (region_[facei] == -1);
1474 
1475  facesFromEdges[nFacesFromEdges++] = objectMap
1476  (
1477  facei,
1478  selectFaces
1479  (
1480  mesh,
1481  mesh.edgeFaces(edgei),
1482  internal
1483  )
1484  );
1485  }
1486  }
1487 
1488 
1489  // Faces from face merging
1490  // ~~~~~~~~~~~~~~~~~~~~~~~
1491 
1492  getMergeSets
1493  (
1494  reverseFaceMap_,
1495  faceMap_,
1496  facesFromFaces
1497  );
1498 }
1499 
1500 
1501 void Foam::polyTopoChange::calcCellInflationMaps
1502 (
1503  const polyMesh& mesh,
1504  List<objectMap>& cellsFromPoints,
1505  List<objectMap>& cellsFromEdges,
1506  List<objectMap>& cellsFromFaces,
1507  List<objectMap>& cellsFromCells
1508 ) const
1509 {
1510  cellsFromPoints.setSize(cellFromPoint_.size());
1511 
1512  if (cellFromPoint_.size())
1513  {
1514  label nCellsFromPoints = 0;
1515 
1516  // Collect all still existing cells connected to this point.
1517  forAllConstIters(cellFromPoint_, iter)
1518  {
1519  const label celli = iter.key();
1520  const label pointi = iter.val();
1521 
1522  cellsFromPoints[nCellsFromPoints++] = objectMap
1523  (
1524  celli,
1525  mesh.pointCells()[pointi]
1526  );
1527  }
1528  }
1529 
1530 
1531  cellsFromEdges.setSize(cellFromEdge_.size());
1532 
1533  if (cellFromEdge_.size())
1534  {
1535  label nCellsFromEdges = 0;
1536 
1537  // Collect all still existing cells connected to this edge.
1538  forAllConstIters(cellFromEdge_, iter)
1539  {
1540  const label celli = iter.key();
1541  const label edgei = iter.val();
1542 
1543  cellsFromEdges[nCellsFromEdges++] = objectMap
1544  (
1545  celli,
1546  mesh.edgeCells()[edgei]
1547  );
1548  }
1549  }
1550 
1551 
1552  cellsFromFaces.setSize(cellFromFace_.size());
1553 
1554  if (cellFromFace_.size())
1555  {
1556  label nCellsFromFaces = 0;
1557 
1558  labelList twoCells(2);
1559 
1560  // Collect all still existing faces connected to this point.
1561  forAllConstIters(cellFromFace_, iter)
1562  {
1563  const label celli = iter.key();
1564  const label oldFacei = iter.val();
1565 
1566  if (mesh.isInternalFace(oldFacei))
1567  {
1568  twoCells[0] = mesh.faceOwner()[oldFacei];
1569  twoCells[1] = mesh.faceNeighbour()[oldFacei];
1570  cellsFromFaces[nCellsFromFaces++] = objectMap
1571  (
1572  celli,
1573  twoCells
1574  );
1575  }
1576  else
1577  {
1578  cellsFromFaces[nCellsFromFaces++] = objectMap
1579  (
1580  celli,
1581  labelList(1, mesh.faceOwner()[oldFacei])
1582  );
1583  }
1584  }
1585  }
1586 
1587 
1588  // Cells from cell merging
1589  // ~~~~~~~~~~~~~~~~~~~~~~~
1590 
1591  getMergeSets
1592  (
1593  reverseCellMap_,
1594  cellMap_,
1595  cellsFromCells
1596  );
1597 }
1598 
1599 
1600 void Foam::polyTopoChange::resetZones
1601 (
1602  const polyMesh& mesh,
1603  polyMesh& newMesh,
1604  labelListList& pointZoneMap,
1605  labelListList& faceZoneFaceMap,
1606  labelListList& cellZoneMap
1607 ) const
1608 {
1609  // pointZones
1610  // ~~~~~~~~~~
1611 
1612  pointZoneMap.setSize(mesh.pointZones().size());
1613  {
1614  const pointZoneMesh& pointZones = mesh.pointZones();
1615 
1616  // Count points per zone
1617 
1618  labelList nPoints(pointZones.size(), Zero);
1619 
1620  forAllConstIters(pointZone_, iter)
1621  {
1622  const label pointi = iter.key();
1623  const label zonei = iter.val();
1624 
1625  if (zonei < 0 || zonei >= pointZones.size())
1626  {
1628  << "Illegal zoneID " << zonei << " for point "
1629  << pointi << " coord " << mesh.points()[pointi]
1630  << abort(FatalError);
1631  }
1632  nPoints[zonei]++;
1633  }
1634  forAll(pointAdditionalZones_, pointi)
1635  {
1636  for (const label zonei : pointAdditionalZones_[pointi])
1637  {
1638  if (zonei < 0 || zonei >= pointZones.size())
1639  {
1641  << "Illegal zoneID " << zonei << " for point "
1642  << pointi << abort(FatalError);
1643  }
1644  nPoints[zonei]++;
1645  }
1646  }
1647 
1648  // Distribute points per zone
1649 
1650  labelListList addressing(pointZones.size());
1651  forAll(addressing, zonei)
1652  {
1653  addressing[zonei].setSize(nPoints[zonei]);
1654  }
1655  nPoints = 0;
1656 
1657  forAllConstIters(pointZone_, iter)
1658  {
1659  const label pointi = iter.key();
1660  const label zonei = iter.val();
1661 
1662  addressing[zonei][nPoints[zonei]++] = pointi;
1663  }
1664  forAll(pointAdditionalZones_, pointi)
1665  {
1666  for (const label zonei : pointAdditionalZones_[pointi])
1667  {
1668  addressing[zonei][nPoints[zonei]++] = pointi;
1669  }
1670  }
1671  // Sort the addressing
1672  forAll(addressing, zonei)
1673  {
1674  stableSort(addressing[zonei]);
1675  }
1676 
1677  // So now we both have old zones and the new addressing.
1678  // Invert the addressing to get pointZoneMap.
1679  forAll(addressing, zonei)
1680  {
1681  const pointZone& oldZone = pointZones[zonei];
1682  const labelList& newZoneAddr = addressing[zonei];
1683 
1684  labelList& curPzRnb = pointZoneMap[zonei];
1685  curPzRnb.setSize(newZoneAddr.size());
1686 
1687  forAll(newZoneAddr, i)
1688  {
1689  if (newZoneAddr[i] < pointMap_.size())
1690  {
1691  curPzRnb[i] = oldZone.whichPoint(pointMap_[newZoneAddr[i]]);
1692  }
1693  else
1694  {
1695  curPzRnb[i] = -1;
1696  }
1697  }
1698  }
1699 
1700  // Reset the addressing on the zone
1701  newMesh.pointZones().clearAddressing();
1702  forAll(newMesh.pointZones(), zonei)
1703  {
1704  if (debug)
1705  {
1706  Pout<< "pointZone:" << zonei
1707  << " name:" << newMesh.pointZones()[zonei].name()
1708  << " size:" << addressing[zonei].size()
1709  << endl;
1710  }
1711 
1712  newMesh.pointZones()[zonei] = addressing[zonei];
1713  }
1714  }
1715 
1716 
1717  // faceZones
1718  // ~~~~~~~~~
1719 
1720  faceZoneFaceMap.setSize(mesh.faceZones().size());
1721  {
1722  const faceZoneMesh& faceZones = mesh.faceZones();
1723 
1724  labelList nFaces(faceZones.size(), Zero);
1725 
1726  forAllConstIters(faceZone_, iter)
1727  {
1728  const label facei = iter.key();
1729  const label zonei = iter.val();
1730 
1731  if (zonei < 0 || zonei >= faceZones.size())
1732  {
1734  << "Illegal zoneID " << zonei << " for face "
1735  << facei
1736  << abort(FatalError);
1737  }
1738  nFaces[zonei]++;
1739  }
1740  forAll(faceAdditionalZones_, facei)
1741  {
1742  for (const label zoneAndSign : faceAdditionalZones_[facei])
1743  {
1744  const label zonei = mag(zoneAndSign)-1;
1745  if (zonei < 0 || zonei >= faceZones.size())
1746  {
1748  << "Illegal zoneID " << zonei << " for face "
1749  << facei << abort(FatalError);
1750  }
1751  nFaces[zonei]++;
1752  }
1753  }
1754 
1755  labelListList addressing(faceZones.size());
1756  boolListList flipMode(faceZones.size());
1757 
1758  forAll(addressing, zonei)
1759  {
1760  addressing[zonei].setSize(nFaces[zonei]);
1761  flipMode[zonei].setSize(nFaces[zonei]);
1762  }
1763  nFaces = 0;
1764 
1765  forAllConstIters(faceZone_, iter)
1766  {
1767  const label facei = iter.key();
1768  const label zonei = iter.val();
1769 
1770  const label index = nFaces[zonei]++;
1771  addressing[zonei][index] = facei;
1772  flipMode[zonei][index] = faceZoneFlip_.test(facei);
1773 
1774  if (facei < faceAdditionalZones_.size())
1775  {
1776  for (const label zoneAndSign : faceAdditionalZones_[facei])
1777  {
1778  const label zonei = mag(zoneAndSign)-1;
1779  const bool flip = (zoneAndSign > 0);
1780 
1781  const label index = nFaces[zonei]++;
1782  addressing[zonei][index] = facei;
1783  flipMode[zonei][index] = flip;
1784  }
1785  }
1786  }
1787 
1788  // Sort the addressing
1789  forAll(addressing, zonei)
1790  {
1791  labelList newToOld(sortedOrder(addressing[zonei]));
1792  {
1793  labelList newAddressing(addressing[zonei].size());
1794  forAll(newAddressing, i)
1795  {
1796  newAddressing[i] = addressing[zonei][newToOld[i]];
1797  }
1798  addressing[zonei].transfer(newAddressing);
1799  }
1800  {
1801  boolList newFlipMode(flipMode[zonei].size());
1802  forAll(newFlipMode, i)
1803  {
1804  newFlipMode[i] = flipMode[zonei][newToOld[i]];
1805  }
1806  flipMode[zonei].transfer(newFlipMode);
1807  }
1808  }
1809 
1810  // So now we both have old zones and the new addressing.
1811  // Invert the addressing to get faceZoneFaceMap.
1812  forAll(addressing, zonei)
1813  {
1814  const faceZone& oldZone = faceZones[zonei];
1815  const labelList& newZoneAddr = addressing[zonei];
1816 
1817  labelList& curFzFaceRnb = faceZoneFaceMap[zonei];
1818 
1819  curFzFaceRnb.setSize(newZoneAddr.size());
1820 
1821  forAll(newZoneAddr, i)
1822  {
1823  if (newZoneAddr[i] < faceMap_.size())
1824  {
1825  curFzFaceRnb[i] =
1826  oldZone.whichFace(faceMap_[newZoneAddr[i]]);
1827  }
1828  else
1829  {
1830  curFzFaceRnb[i] = -1;
1831  }
1832  }
1833  }
1834 
1835 
1836  // Reset the addressing on the zone
1837  newMesh.faceZones().clearAddressing();
1838  forAll(newMesh.faceZones(), zonei)
1839  {
1840  if (debug)
1841  {
1842  Pout<< "faceZone:" << zonei
1843  << " name:" << newMesh.faceZones()[zonei].name()
1844  << " size:" << addressing[zonei].size()
1845  << endl;
1846  }
1847 
1848  newMesh.faceZones()[zonei].resetAddressing
1849  (
1850  addressing[zonei],
1851  flipMode[zonei]
1852  );
1853  }
1854  }
1855 
1856 
1857  // cellZones
1858  // ~~~~~~~~~
1859 
1860  cellZoneMap.setSize(mesh.cellZones().size());
1861  {
1862  const cellZoneMesh& cellZones = mesh.cellZones();
1863 
1864  labelList nCells(cellZones.size(), Zero);
1865 
1866  forAll(cellZone_, celli)
1867  {
1868  const label zonei = cellZone_[celli];
1869 
1870  if (zonei >= cellZones.size())
1871  {
1873  << "Illegal zoneID " << zonei << " for cell "
1874  << celli << abort(FatalError);
1875  }
1876 
1877  if (zonei >= 0)
1878  {
1879  nCells[zonei]++;
1880  }
1881  }
1882  forAll(cellAdditionalZones_, celli)
1883  {
1884  for (const label zonei : cellAdditionalZones_[celli])
1885  {
1886  if (zonei < 0 || zonei >= cellZones.size())
1887  {
1889  << "Illegal zoneID " << zonei << " for cell "
1890  << celli << abort(FatalError);
1891  }
1892  nCells[zonei]++;
1893  }
1894  }
1895 
1896 
1897  labelListList addressing(cellZones.size());
1898  forAll(addressing, zonei)
1899  {
1900  addressing[zonei].setSize(nCells[zonei]);
1901  }
1902  nCells = 0;
1903 
1904  forAll(cellZone_, celli)
1905  {
1906  const label zonei = cellZone_[celli];
1907 
1908  if (zonei >= 0)
1909  {
1910  addressing[zonei][nCells[zonei]++] = celli;
1911  }
1912  }
1913  forAll(cellAdditionalZones_, celli)
1914  {
1915  for (const label zonei : cellAdditionalZones_[celli])
1916  {
1917  addressing[zonei][nCells[zonei]++] = celli;
1918  }
1919  }
1920  // Sort the addressing
1921  forAll(addressing, zonei)
1922  {
1923  stableSort(addressing[zonei]);
1924  }
1925 
1926  // So now we both have old zones and the new addressing.
1927  // Invert the addressing to get cellZoneMap.
1928  forAll(addressing, zonei)
1929  {
1930  const cellZone& oldZone = cellZones[zonei];
1931  const labelList& newZoneAddr = addressing[zonei];
1932 
1933  labelList& curCellRnb = cellZoneMap[zonei];
1934 
1935  curCellRnb.setSize(newZoneAddr.size());
1936 
1937  forAll(newZoneAddr, i)
1938  {
1939  if (newZoneAddr[i] < cellMap_.size())
1940  {
1941  curCellRnb[i] =
1942  oldZone.whichCell(cellMap_[newZoneAddr[i]]);
1943  }
1944  else
1945  {
1946  curCellRnb[i] = -1;
1947  }
1948  }
1949  }
1950 
1951  // Reset the addressing on the zone
1952  newMesh.cellZones().clearAddressing();
1953  forAll(newMesh.cellZones(), zonei)
1954  {
1955  if (debug)
1956  {
1957  Pout<< "cellZone:" << zonei
1958  << " name:" << newMesh.cellZones()[zonei].name()
1959  << " size:" << addressing[zonei].size()
1960  << endl;
1961  }
1962 
1963  newMesh.cellZones()[zonei] = addressing[zonei];
1964  }
1965  }
1966 }
1967 
1968 
1969 void Foam::polyTopoChange::calcFaceZonePointMap
1970 (
1971  const polyMesh& mesh,
1972  const UList<Map<label>>& oldFaceZoneMeshPointMaps,
1973  labelListList& faceZonePointMap
1974 ) const
1975 {
1976  const faceZoneMesh& faceZones = mesh.faceZones();
1977 
1978  faceZonePointMap.setSize(faceZones.size());
1979 
1980  forAll(faceZones, zonei)
1981  {
1982  const faceZone& newZone = faceZones[zonei];
1983 
1984  const labelList& newZoneMeshPoints = newZone.patch().meshPoints();
1985 
1986  const Map<label>& oldZoneMeshPointMap = oldFaceZoneMeshPointMaps[zonei];
1987 
1988  labelList& curFzPointRnb = faceZonePointMap[zonei];
1989 
1990  curFzPointRnb.setSize(newZoneMeshPoints.size());
1991 
1992  forAll(newZoneMeshPoints, pointi)
1993  {
1994  if (newZoneMeshPoints[pointi] < pointMap_.size())
1995  {
1996  curFzPointRnb[pointi] =
1997  oldZoneMeshPointMap.lookup
1998  (
1999  pointMap_[newZoneMeshPoints[pointi]],
2000  -1
2001  );
2002  }
2003  else
2004  {
2005  curFzPointRnb[pointi] = -1;
2006  }
2007  }
2008  }
2009 }
2010 
2011 
2012 void Foam::polyTopoChange::reorderCoupledFaces
2013 (
2014  const bool syncParallel,
2015  const polyBoundaryMesh& oldBoundary,
2016  const labelUList& patchMap, // new to old patches
2017  const labelUList& patchStarts,
2018  const labelUList& patchSizes,
2019  const pointField& points
2020 )
2021 {
2022  // Mapping for faces (old to new). Extends over all mesh faces for
2023  // convenience (could be just the external faces)
2024  labelList oldToNew(identity(faces_.size()));
2025 
2026  // Rotation on new faces.
2027  labelList rotation(faces_.size(), Zero);
2028 
2029  PstreamBuffers pBufs;
2030 
2031  // Send ordering
2032  forAll(patchMap, patchi)
2033  {
2034  const label oldPatchi = patchMap[patchi];
2035 
2036  if
2037  (
2038  oldPatchi != -1
2039  && (syncParallel || !isA<processorPolyPatch>(oldBoundary[oldPatchi]))
2040  )
2041  {
2042  oldBoundary[oldPatchi].initOrder
2043  (
2044  pBufs,
2046  (
2047  SubList<face>
2048  (
2049  faces_,
2050  patchSizes[patchi],
2051  patchStarts[patchi]
2052  ),
2053  points
2054  )
2055  );
2056  }
2057  }
2058 
2059  if (syncParallel)
2060  {
2061  pBufs.finishedSends();
2062  }
2063 
2064  // Receive and calculate ordering
2065 
2066  bool anyChanged = false;
2067 
2068  forAll(patchMap, patchi)
2069  {
2070  const label oldPatchi = patchMap[patchi];
2071 
2072  if
2073  (
2074  oldPatchi != -1
2075  && (syncParallel || !isA<processorPolyPatch>(oldBoundary[oldPatchi]))
2076  )
2077  {
2078  labelList patchFaceMap(patchSizes[patchi], -1);
2079  labelList patchFaceRotation(patchSizes[patchi], Zero);
2080 
2081  const bool changed = oldBoundary[oldPatchi].order
2082  (
2083  pBufs,
2085  (
2086  SubList<face>
2087  (
2088  faces_,
2089  patchSizes[patchi],
2090  patchStarts[patchi]
2091  ),
2092  points
2093  ),
2094  patchFaceMap,
2095  patchFaceRotation
2096  );
2097 
2098  if (changed)
2099  {
2100  // Merge patch face reordering into mesh face reordering table
2101  const label start = patchStarts[patchi];
2102 
2103  forAll(patchFaceMap, patchFacei)
2104  {
2105  oldToNew[patchFacei + start] =
2106  start + patchFaceMap[patchFacei];
2107  }
2108 
2109  forAll(patchFaceRotation, patchFacei)
2110  {
2111  rotation[patchFacei + start] =
2112  patchFaceRotation[patchFacei];
2113  }
2114 
2115  anyChanged = true;
2116  }
2117  }
2118  }
2119 
2120  if (syncParallel ? returnReduceOr(anyChanged) : anyChanged)
2121  {
2122  // Reorder faces according to oldToNew.
2123  reorderCompactFaces(oldToNew.size(), oldToNew);
2124 
2125  // Rotate faces (rotation is already in new face indices).
2126  forAll(rotation, facei)
2127  {
2128  if (rotation[facei] != 0)
2129  {
2130  inplaceRotateList<List, label>(faces_[facei], rotation[facei]);
2131  }
2132  }
2133  }
2134 }
2135 
2136 
2137 void Foam::polyTopoChange::compactAndReorder
2138 (
2139  const polyMesh& mesh,
2140  const labelUList& patchMap, // from new to old patch
2141  const bool syncParallel,
2142  const bool orderCells,
2143  const bool orderPoints,
2144 
2145  label& nInternalPoints,
2146  pointField& newPoints,
2147  labelList& patchSizes,
2148  labelList& patchStarts,
2149  List<objectMap>& pointsFromPoints,
2150  List<objectMap>& facesFromPoints,
2151  List<objectMap>& facesFromEdges,
2152  List<objectMap>& facesFromFaces,
2153  List<objectMap>& cellsFromPoints,
2154  List<objectMap>& cellsFromEdges,
2155  List<objectMap>& cellsFromFaces,
2156  List<objectMap>& cellsFromCells,
2157  List<Map<label>>& oldPatchMeshPointMaps,
2158  labelList& oldPatchNMeshPoints,
2159  labelList& oldPatchStarts,
2160  List<Map<label>>& oldFaceZoneMeshPointMaps
2161 )
2162 {
2163  if (patchMap.size() != nPatches_)
2164  {
2166  << "polyTopoChange was constructed with a mesh with "
2167  << nPatches_ << " patches." << endl
2168  << "The mesh now provided has a different number of patches "
2169  << patchMap.size()
2170  << " which is illegal" << endl
2171  << abort(FatalError);
2172  }
2173 
2174  // Remove any holes from points/faces/cells and sort faces.
2175  // Sets nActiveFaces_.
2176  compact(orderCells, orderPoints, nInternalPoints, patchSizes, patchStarts);
2177 
2178  // Transfer points to pointField. points_ are now cleared!
2179  // Only done since e.g. reorderCoupledFaces requires pointField.
2180  newPoints.transfer(points_);
2181 
2182  // Reorder any coupled faces
2183  reorderCoupledFaces
2184  (
2185  syncParallel,
2186  mesh.boundaryMesh(),
2187  patchMap,
2188  patchStarts,
2189  patchSizes,
2190  newPoints
2191  );
2192 
2193 
2194  // Calculate inflation/merging maps
2195  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2196  // These are for the new face(/point/cell) the old faces whose value
2197  // needs to be
2198  // averaged/summed to get the new value. These old faces come either from
2199  // merged old faces (face remove into other face),
2200  // the old edgeFaces (inflate from edge) or the old pointFaces (inflate
2201  // from point). As an additional complexity will use only internal faces
2202  // to create new value for internal face and vice versa only patch
2203  // faces to to create patch face value.
2204 
2205  // For point only point merging
2206  getMergeSets
2207  (
2208  reversePointMap_,
2209  pointMap_,
2210  pointsFromPoints
2211  );
2212 
2213  calcFaceInflationMaps
2214  (
2215  mesh,
2216  facesFromPoints,
2217  facesFromEdges,
2218  facesFromFaces
2219  );
2220 
2221  calcCellInflationMaps
2222  (
2223  mesh,
2224  cellsFromPoints,
2225  cellsFromEdges,
2226  cellsFromFaces,
2227  cellsFromCells
2228  );
2229 
2230  // Clear inflation info
2231  {
2232  faceFromPoint_.clearStorage();
2233  faceFromEdge_.clearStorage();
2234 
2235  cellFromPoint_.clearStorage();
2236  cellFromEdge_.clearStorage();
2237  cellFromFace_.clearStorage();
2238  }
2239 
2240 
2241  const polyBoundaryMesh& boundary = mesh.boundaryMesh();
2242 
2243  // Grab patch mesh point maps
2244  oldPatchMeshPointMaps.setSize(boundary.size());
2245  oldPatchNMeshPoints.setSize(boundary.size());
2246  oldPatchStarts.setSize(boundary.size());
2247 
2248  forAll(boundary, patchi)
2249  {
2250  // Copy old face zone mesh point maps
2251  oldPatchMeshPointMaps[patchi] = boundary[patchi].meshPointMap();
2252  oldPatchNMeshPoints[patchi] = boundary[patchi].meshPoints().size();
2253  oldPatchStarts[patchi] = boundary[patchi].start();
2254  }
2255 
2256  // Grab old face zone mesh point maps.
2257  // These need to be saved before resetting the mesh and are used
2258  // later on to calculate the faceZone pointMaps.
2259  oldFaceZoneMeshPointMaps.setSize(mesh.faceZones().size());
2260 
2261  forAll(mesh.faceZones(), zonei)
2262  {
2263  const faceZone& oldZone = mesh.faceZones()[zonei];
2264 
2265  oldFaceZoneMeshPointMaps[zonei] = oldZone.patch().meshPointMap();
2266  }
2267 }
2268 
2269 
2270 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
2271 
2272 // Construct from components
2273 Foam::polyTopoChange::polyTopoChange(const label nPatches, const bool strict)
2274 :
2275  strict_(strict),
2276  nPatches_(nPatches),
2277  points_(0),
2278  pointMap_(0),
2279  reversePointMap_(0),
2280  pointZone_(0),
2281  retiredPoints_(0),
2282  faces_(0),
2283  region_(0),
2284  faceOwner_(0),
2285  faceNeighbour_(0),
2286  faceMap_(0),
2287  reverseFaceMap_(0),
2288  faceFromPoint_(0),
2289  faceFromEdge_(0),
2290  flipFaceFlux_(0),
2291  faceZone_(0),
2292  faceZoneFlip_(0),
2293  nActiveFaces_(0),
2294  cellMap_(0),
2295  reverseCellMap_(0),
2296  cellFromPoint_(0),
2297  cellFromEdge_(0),
2298  cellFromFace_(0),
2299  cellZone_(0)
2300 {}
2301 
2302 
2303 // Construct from components
2305 (
2306  const polyMesh& mesh,
2307  const bool strict
2308 )
2309 :
2310  strict_(strict),
2311  nPatches_(0),
2312  points_(0),
2313  pointMap_(0),
2314  reversePointMap_(0),
2315  pointZone_(0),
2316  retiredPoints_(0),
2317  faces_(0),
2318  region_(0),
2319  faceOwner_(0),
2320  faceNeighbour_(0),
2321  faceMap_(0),
2322  reverseFaceMap_(0),
2323  faceFromPoint_(0),
2324  faceFromEdge_(0),
2325  flipFaceFlux_(0),
2326  faceZone_(0),
2327  faceZoneFlip_(0),
2328  nActiveFaces_(0),
2329  cellMap_(0),
2330  reverseCellMap_(0),
2331  cellFromPoint_(0),
2332  cellFromEdge_(0),
2333  cellFromFace_(0),
2334  cellZone_(0)
2335 {
2336  addMesh
2337  (
2338  mesh,
2339  identity(mesh.boundaryMesh().size()),
2340  identity(mesh.pointZones().size()),
2341  identity(mesh.faceZones().size()),
2342  identity(mesh.cellZones().size())
2343  );
2344 }
2345 
2346 
2347 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2350 {
2351  points_.clearStorage();
2352  pointMap_.clearStorage();
2353  reversePointMap_.clearStorage();
2354  pointZone_.clearStorage();
2355  pointAdditionalZones_.clearStorage();
2356  retiredPoints_.clearStorage();
2357 
2358  faces_.clearStorage();
2359  region_.clearStorage();
2360  faceOwner_.clearStorage();
2361  faceNeighbour_.clearStorage();
2362  faceMap_.clearStorage();
2363  reverseFaceMap_.clearStorage();
2364  faceFromPoint_.clearStorage();
2365  faceFromEdge_.clearStorage();
2366  flipFaceFlux_.clearStorage();
2367  faceZone_.clearStorage();
2368  faceZoneFlip_.clearStorage();
2369  faceAdditionalZones_.clearStorage();
2370  nActiveFaces_ = 0;
2371 
2372  cellMap_.clearStorage();
2373  reverseCellMap_.clearStorage();
2374  cellZone_.clearStorage();
2375  cellAdditionalZones_.clearStorage();
2376  cellFromPoint_.clearStorage();
2377  cellFromEdge_.clearStorage();
2378  cellFromFace_.clearStorage();
2379 }
2380 
2381 
2383 (
2384  const polyMesh& mesh,
2385  const labelUList& patchMap,
2386  const labelUList& pointZoneMap,
2387  const labelUList& faceZoneMap,
2388  const labelUList& cellZoneMap
2389 )
2390 {
2391  label maxRegion = nPatches_ - 1;
2392  for (const label regioni : patchMap)
2393  {
2394  maxRegion = max(maxRegion, regioni);
2395  }
2396  nPatches_ = maxRegion + 1;
2397 
2398 
2399  // Add points
2400  {
2401  const pointField& points = mesh.points();
2402  const pointZoneMesh& pointZones = mesh.pointZones();
2403 
2404  // Extend
2405  points_.setCapacity(points_.size() + points.size());
2406  pointMap_.setCapacity(pointMap_.size() + points.size());
2407  reversePointMap_.setCapacity(reversePointMap_.size() + points.size());
2408  pointZone_.resize(pointZone_.size() + points.size()/128);
2409 
2410  // Add points without pointZone
2411  labelList newPointID(points.size());
2412  forAll(newPointID, pointi)
2413  {
2414  // Add point from point
2415  newPointID[pointi] = addPoint
2416  (
2417  points[pointi],
2418  pointi,
2419  -1,
2420  true
2421  );
2422  }
2423 
2424  // Modify for pointZones
2425  DynamicList<label> zones;
2426  forAll(pointZones, zonei)
2427  {
2428  for (const label pointi : pointZones[zonei])
2429  {
2430  // Get previous zones
2431  this->pointZones(newPointID[pointi], zones);
2432  for (auto& zonei : zones)
2433  {
2434  zonei = pointZoneMap[zonei];
2435  }
2436  // Add new zone
2437  zones.append(pointZoneMap[zonei]);
2438  modifyPoint
2439  (
2440  newPointID[pointi],
2441  points_[newPointID[pointi]],
2442  zones,
2443  true
2444  );
2445  }
2446  }
2447  }
2448 
2449  // Add cells
2450  {
2451  const cellZoneMesh& cellZones = mesh.cellZones();
2452 
2453  // Resize
2454 
2455  // Note: polyMesh does not allow retired cells anymore. So allCells
2456  // always equals nCells
2457  label nAllCells = mesh.nCells();
2458 
2459  cellMap_.setCapacity(cellMap_.size() + nAllCells);
2460  reverseCellMap_.setCapacity(reverseCellMap_.size() + nAllCells);
2461  cellFromPoint_.resize(cellFromPoint_.size() + nAllCells/128);
2462  cellFromEdge_.resize(cellFromEdge_.size() + nAllCells/128);
2463  cellFromFace_.resize(cellFromFace_.size() + nAllCells/128);
2464  cellZone_.setCapacity(cellZone_.size() + nAllCells);
2465 
2466 
2467  // Add cells without cellZone
2468  labelList newCellID(nAllCells);
2469  for (label celli = 0; celli < nAllCells; celli++)
2470  {
2471  // Add cell from cell
2472  newCellID[celli] = addCell(-1, -1, -1, celli, -1);
2473  }
2474 
2475  // Modify for cellZones
2476  DynamicList<label> zones;
2477  forAll(cellZones, zonei)
2478  {
2479  for (const label celli : cellZones[zonei])
2480  {
2481  // Get previous zones
2482  this->cellZones(newCellID[celli], zones);
2483  for (auto& zonei : zones)
2484  {
2485  zonei = cellZoneMap[zonei];
2486  }
2487  // Add new zone
2488  zones.append(cellZoneMap[zonei]);
2489  modifyCell(newCellID[celli], zones);
2490  }
2491  }
2492  }
2493 
2494  // Add faces
2495  {
2497  const faceList& faces = mesh.faces();
2498  const labelList& faceOwner = mesh.faceOwner();
2499  const labelList& faceNeighbour = mesh.faceNeighbour();
2500  const faceZoneMesh& faceZones = mesh.faceZones();
2501 
2502  // Resize
2503  label nAllFaces = mesh.faces().size();
2504 
2505  faces_.setCapacity(faces_.size() + nAllFaces);
2506  region_.setCapacity(region_.size() + nAllFaces);
2507  faceOwner_.setCapacity(faceOwner_.size() + nAllFaces);
2508  faceNeighbour_.setCapacity(faceNeighbour_.size() + nAllFaces);
2509  faceMap_.setCapacity(faceMap_.size() + nAllFaces);
2510  reverseFaceMap_.setCapacity(reverseFaceMap_.size() + nAllFaces);
2511  faceFromPoint_.resize(faceFromPoint_.size() + nAllFaces/128);
2512  faceFromEdge_.resize(faceFromEdge_.size() + nAllFaces/128);
2513  flipFaceFlux_.setCapacity(faces_.size() + nAllFaces);
2514  faceZone_.resize(faceZone_.size() + nAllFaces/128);
2515  faceZoneFlip_.setCapacity(faceMap_.capacity());
2516 
2517 
2518  // Add faces (in mesh order) without faceZone
2519  labelList newFaceID(nAllFaces);
2520 
2521  // 1. Internal faces
2522  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
2523  {
2524  newFaceID[facei] = addFace
2525  (
2526  faces[facei],
2527  faceOwner[facei],
2528  faceNeighbour[facei],
2529  -1, // masterPointID
2530  -1, // masterEdgeID
2531  facei, // masterFaceID
2532  false, // flipFaceFlux
2533  -1, // patchID
2534  -1, // zoneID
2535  false // zoneFlip
2536  );
2537  }
2538 
2539  // 2. Patch faces
2540  forAll(patches, patchi)
2541  {
2542  const polyPatch& pp = patches[patchi];
2543 
2544  if (pp.start() != faces_.size())
2545  {
2547  << "Problem : "
2548  << "Patch " << pp.name() << " starts at " << pp.start()
2549  << endl
2550  << "Current face counter at " << faces_.size() << endl
2551  << "Are patches in incremental order?"
2552  << abort(FatalError);
2553  }
2554  forAll(pp, patchFacei)
2555  {
2556  const label facei = pp.start() + patchFacei;
2557 
2558  newFaceID[facei] = addFace
2559  (
2560  faces[facei],
2561  faceOwner[facei],
2562  -1, // neighbour
2563  -1, // masterPointID
2564  -1, // masterEdgeID
2565  facei, // masterFaceID
2566  false, // flipFaceFlux
2567  patchMap[patchi], // patchID
2568  -1, // zoneID
2569  false // zoneFlip
2570  );
2571  }
2572  }
2573 
2574 
2575  // Modify for faceZones
2576 
2577  DynamicList<label> zones;
2578  DynamicList<bool> flips;
2579  forAll(faceZones, zonei)
2580  {
2581  const auto& fz = faceZones[zonei];
2582 
2583  forAll(fz, i)
2584  {
2585  const label facei = fz[i];
2586  const bool flip = fz.flipMap()[i];
2587 
2588  // Modify face index for combined zones
2589  const label newFacei = newFaceID[facei];
2590 
2591  // Get previous zones
2592  this->faceZones(newFacei, zones, flips);
2593  for (auto& zonei : zones)
2594  {
2595  zonei = faceZoneMap[zonei];
2596  }
2597  // Add new zone
2598  zones.append(faceZoneMap[zonei]);
2599  flips.append(flip);
2600 
2601  modifyFace
2602  (
2603  faces_[newFacei],
2604  newFacei,
2605  faceOwner_[newFacei],
2606  faceNeighbour_[newFacei],
2607  flipFaceFlux_(newFacei),
2608  region_[newFacei],
2609  zones,
2610  flips
2611  );
2612  }
2613  }
2614  }
2615 }
2616 
2617 
2619 (
2620  const label nPoints,
2621  const label nFaces,
2622  const label nCells
2623 )
2624 {
2625  points_.setCapacity(nPoints);
2626  pointMap_.setCapacity(nPoints);
2627  reversePointMap_.setCapacity(nPoints);
2628  pointZone_.resize(pointZone_.size() + nPoints/128);
2629 
2630  faces_.setCapacity(nFaces);
2631  region_.setCapacity(nFaces);
2632  faceOwner_.setCapacity(nFaces);
2633  faceNeighbour_.setCapacity(nFaces);
2634  faceMap_.setCapacity(nFaces);
2635  reverseFaceMap_.setCapacity(nFaces);
2636  faceFromPoint_.resize(faceFromPoint_.size() + nFaces/128);
2637  faceFromEdge_.resize(faceFromEdge_.size() + nFaces/128);
2638  flipFaceFlux_.setCapacity(nFaces);
2639  faceZone_.resize(faceZone_.size() + nFaces/128);
2640  faceZoneFlip_.setCapacity(nFaces);
2641 
2642  cellMap_.setCapacity(nCells);
2643  reverseCellMap_.setCapacity(nCells);
2644  cellFromPoint_.resize(cellFromPoint_.size() + nCells/128);
2645  cellFromEdge_.resize(cellFromEdge_.size() + nCells/128);
2646  cellFromFace_.resize(cellFromFace_.size() + nCells/128);
2647  cellZone_.setCapacity(nCells);
2648 }
2649 
2651 Foam::label Foam::polyTopoChange::setAction(const topoAction& action)
2652 {
2653  if (isType<polyAddPoint>(action))
2654  {
2655  const polyAddPoint& pap = refCast<const polyAddPoint>(action);
2656 
2657  return addPoint
2658  (
2659  pap.newPoint(),
2660  pap.masterPointID(),
2661  pap.zoneID(),
2662  pap.inCell()
2663  );
2664  }
2665  else if (isType<polyModifyPoint>(action))
2666  {
2667  const polyModifyPoint& pmp = refCast<const polyModifyPoint>(action);
2668 
2669  modifyPoint
2670  (
2671  pmp.pointID(),
2672  pmp.newPoint(),
2673  pmp.zoneID(),
2674  pmp.inCell()
2675  );
2676 
2677  return -1;
2678  }
2679  else if (isType<polyRemovePoint>(action))
2680  {
2681  const polyRemovePoint& prp = refCast<const polyRemovePoint>(action);
2682 
2683  removePoint(prp.pointID(), prp.mergePointID());
2684 
2685  return -1;
2686  }
2687  else if (isType<polyAddFace>(action))
2688  {
2689  const polyAddFace& paf = refCast<const polyAddFace>(action);
2690 
2691  return addFace
2692  (
2693  paf.newFace(),
2694  paf.owner(),
2695  paf.neighbour(),
2696  paf.masterPointID(),
2697  paf.masterEdgeID(),
2698  paf.masterFaceID(),
2699  paf.flipFaceFlux(),
2700  paf.patchID(),
2701  paf.zoneID(),
2702  paf.zoneFlip()
2703  );
2704  }
2705  else if (isType<polyModifyFace>(action))
2706  {
2707  const polyModifyFace& pmf = refCast<const polyModifyFace>(action);
2708 
2709  modifyFace
2710  (
2711  pmf.newFace(),
2712  pmf.faceID(),
2713  pmf.owner(),
2714  pmf.neighbour(),
2715  pmf.flipFaceFlux(),
2716  pmf.patchID(),
2717  pmf.zoneID(),
2718  pmf.zoneFlip()
2719  );
2720 
2721  return -1;
2722  }
2723  else if (isType<polyRemoveFace>(action))
2724  {
2725  const polyRemoveFace& prf = refCast<const polyRemoveFace>(action);
2726 
2727  removeFace(prf.faceID(), prf.mergeFaceID());
2728 
2729  return -1;
2730  }
2731  else if (isType<polyAddCell>(action))
2732  {
2733  const polyAddCell& pac = refCast<const polyAddCell>(action);
2734 
2735  return addCell
2736  (
2737  pac.masterPointID(),
2738  pac.masterEdgeID(),
2739  pac.masterFaceID(),
2740  pac.masterCellID(),
2741  pac.zoneID()
2742  );
2743  }
2744  else if (isType<polyModifyCell>(action))
2745  {
2746  const polyModifyCell& pmc = refCast<const polyModifyCell>(action);
2747 
2748  if (pmc.removeFromZone())
2749  {
2750  modifyCell(pmc.cellID(), -1);
2751  }
2752  else
2753  {
2754  modifyCell(pmc.cellID(), pmc.zoneID());
2755  }
2756 
2757  return -1;
2758  }
2759  else if (isType<polyRemoveCell>(action))
2760  {
2761  const polyRemoveCell& prc = refCast<const polyRemoveCell>(action);
2762 
2763  removeCell(prc.cellID(), prc.mergeCellID());
2764 
2765  return -1;
2766  }
2767  else
2768  {
2770  << "Unknown type of topoChange: " << action.type()
2771  << abort(FatalError);
2772 
2773  // Dummy return to keep compiler happy
2774  return -1;
2775  }
2776 }
2777 
2778 
2780 (
2781  const point& pt,
2782  const label masterPointID,
2783  const label zoneID,
2784  const bool inCell
2785 )
2786 {
2787  const label pointi = points_.size();
2788 
2789  points_.append(pt);
2790  pointMap_.append(masterPointID);
2791  reversePointMap_.append(pointi);
2792 
2793  if (zoneID >= 0)
2794  {
2795  pointZone_.insert(pointi, zoneID);
2796  }
2797  // Delay extending the pointAdditionalZones
2798 
2799  if (!inCell)
2800  {
2801  retiredPoints_.insert(pointi);
2802  }
2803 
2804  return pointi;
2805 }
2806 
2807 
2809 (
2810  const point& pt,
2811  const label masterPointID,
2812  const labelUList& zoneIDs,
2813  const bool inCell
2814 )
2815 {
2816  const label pointi = points_.size();
2817 
2818  points_.append(pt);
2819  pointMap_.append(masterPointID);
2820  reversePointMap_.append(pointi);
2821 
2822  if (zoneIDs.size())
2823  {
2824  const label minIndex = findMin(zoneIDs);
2825 
2826  pointZone_.set(pointi, zoneIDs[minIndex]);
2827 
2828  // Clear any additional storage
2829  if (pointi < pointAdditionalZones_.size())
2830  {
2831  pointAdditionalZones_[pointi].clear();
2832  }
2833  // (auto-vivify and) store additional zones
2834  forAll(zoneIDs, i)
2835  {
2836  if (i != minIndex)
2837  {
2838  if (zoneIDs[i] == zoneIDs[minIndex])
2839  {
2840  FatalErrorInFunction << "Duplicates in zones "
2841  << flatOutput(zoneIDs) << " for point " << pointi
2842  << exit(FatalError);
2843  }
2844  pointAdditionalZones_(pointi).push_uniq(zoneIDs[i]);
2845  }
2846  }
2847  }
2848 
2849  if (!inCell)
2850  {
2851  retiredPoints_.insert(pointi);
2852  }
2853 
2854  return pointi;
2855 }
2856 
2857 
2859 (
2860  const label pointi,
2861  const point& pt,
2862  const label zoneID,
2863  const bool inCell,
2864  const bool multiZone
2865 )
2866 {
2867  if (pointi < 0 || pointi >= points_.size())
2868  {
2870  << "illegal point label " << pointi << endl
2871  << "Valid point labels are 0 .. " << points_.size()-1
2872  << abort(FatalError);
2873  }
2874  if (pointRemoved(pointi) || pointMap_[pointi] == -1)
2875  {
2877  << "point " << pointi << " already marked for removal"
2878  << abort(FatalError);
2879  }
2880  points_[pointi] = pt;
2881 
2882  if (!multiZone)
2883  {
2884  if (zoneID >= 0)
2885  {
2886  pointZone_.set(pointi, zoneID);
2887  }
2888  else
2889  {
2890  pointZone_.erase(pointi);
2891  }
2892  if (pointi < pointAdditionalZones_.size())
2893  {
2894  pointAdditionalZones_[pointi].clear();
2895  }
2896  }
2897  else
2898  {
2899  auto fnd = pointZone_.find(pointi);
2900  if (!fnd)
2901  {
2902  pointZone_.set(pointi, zoneID);
2903 
2904  // Check that no leftover additional zones
2905  if (pointAdditionalZones_(pointi).size())
2906  {
2908  << "Additional zones for point:"
2909  << pointAdditionalZones_(pointi)
2910  << abort(FatalError);
2911  }
2912  }
2913  else if (zoneID == -1)
2914  {
2915  // Clear
2916  pointZone_.erase(fnd);
2917  if (pointi < pointAdditionalZones_.size())
2918  {
2919  pointAdditionalZones_[pointi].clear();
2920  }
2921  }
2922  else if (zoneID != fnd())
2923  {
2924  // New zone. Store in additional storage.
2925  pointAdditionalZones_(pointi).push_uniq(zoneID);
2926  }
2927  }
2928 
2929  if (inCell)
2930  {
2931  retiredPoints_.erase(pointi);
2932  }
2933  else
2934  {
2935  retiredPoints_.insert(pointi);
2936  }
2937 }
2938 
2939 
2941 (
2942  const label pointi,
2943  const point& pt,
2944  const labelUList& zoneIDs,
2945  const bool inCell
2946 )
2947 {
2948  if (pointi < 0 || pointi >= points_.size())
2949  {
2951  << "illegal point label " << pointi << endl
2952  << "Valid point labels are 0 .. " << points_.size()-1
2953  << abort(FatalError);
2954  }
2955  if (pointRemoved(pointi) || pointMap_[pointi] == -1)
2956  {
2958  << "point " << pointi << " already marked for removal"
2959  << abort(FatalError);
2960  }
2961  points_[pointi] = pt;
2962 
2963  if (zoneIDs.size())
2964  {
2965  if (zoneIDs.found(-1))
2966  {
2968  << "zones cannot contain -1 : " << flatOutput(zoneIDs)
2969  << " for point:" << pointi
2970  << abort(FatalError);
2971  }
2972 
2973  pointZone_.set(pointi, zoneIDs[0]);
2974  if (pointi < pointAdditionalZones_.size())
2975  {
2976  pointAdditionalZones_[pointi].clear();
2977  }
2978  for (label i = 1; i < zoneIDs.size(); ++i)
2979  {
2980  pointAdditionalZones_(pointi).push_uniq(zoneIDs[i]);
2981  }
2982  }
2983  else
2984  {
2985  pointZone_.erase(pointi);
2986  if (pointi < pointAdditionalZones_.size())
2987  {
2988  pointAdditionalZones_[pointi].clear();
2989  }
2990  }
2991 
2992  if (inCell)
2993  {
2994  retiredPoints_.erase(pointi);
2995  }
2996  else
2997  {
2998  retiredPoints_.insert(pointi);
2999  }
3000 }
3002 void Foam::polyTopoChange::movePoints(const pointField& newPoints)
3003 {
3004  if (newPoints.size() != points_.size())
3005  {
3007  << "illegal pointField size." << endl
3008  << "Size:" << newPoints.size() << endl
3009  << "Points in mesh:" << points_.size()
3010  << abort(FatalError);
3011  }
3012 
3013  forAll(points_, pointi)
3014  {
3015  points_[pointi] = newPoints[pointi];
3016  }
3017 }
3018 
3019 
3021 (
3022  const label pointi,
3023  const label mergePointi
3024 )
3025 {
3026  if (pointi < 0 || pointi >= points_.size())
3027  {
3029  << "illegal point label " << pointi << endl
3030  << "Valid point labels are 0 .. " << points_.size()-1
3031  << abort(FatalError);
3032  }
3033 
3034  if
3035  (
3036  strict_
3037  && (pointRemoved(pointi) || pointMap_[pointi] == -1)
3038  )
3039  {
3041  << "point " << pointi << " already marked for removal" << nl
3042  << "Point:" << points_[pointi] << " pointMap:" << pointMap_[pointi]
3043  << abort(FatalError);
3044  }
3045 
3046  if (pointi == mergePointi)
3047  {
3049  << "Cannot remove/merge point " << pointi << " onto itself."
3050  << abort(FatalError);
3051  }
3052 
3053  points_[pointi] = point::max;
3054  pointMap_[pointi] = -1;
3055  if (mergePointi >= 0)
3056  {
3057  reversePointMap_[pointi] = -mergePointi-2;
3058  }
3059  else
3060  {
3061  reversePointMap_[pointi] = -1;
3062  }
3063  pointZone_.erase(pointi);
3064  if (pointi < pointAdditionalZones_.size())
3065  {
3066  pointAdditionalZones_[pointi].clear();
3067  }
3068  retiredPoints_.erase(pointi);
3069 }
3070 
3071 
3073 (
3074  const face& f,
3075  const label own,
3076  const label nei,
3077  const label masterPointID,
3078  const label masterEdgeID,
3079  const label masterFaceID,
3080  const bool flipFaceFlux,
3081  const label patchID,
3082  const label zoneID,
3083  const bool zoneFlip
3084 )
3085 {
3086  // Check validity
3087  if (debug)
3088  {
3089  checkFace(f, -1, own, nei, patchID, zoneID);
3090  }
3091 
3092  label facei = faces_.size();
3093 
3094  faces_.append(f);
3095  region_.append(patchID);
3096  faceOwner_.append(own);
3097  faceNeighbour_.append(nei);
3098 
3099  if (masterPointID >= 0)
3100  {
3101  faceMap_.append(-1);
3102  faceFromPoint_.insert(facei, masterPointID);
3103  }
3104  else if (masterEdgeID >= 0)
3105  {
3106  faceMap_.append(-1);
3107  faceFromEdge_.insert(facei, masterEdgeID);
3108  }
3109  else if (masterFaceID >= 0)
3110  {
3111  faceMap_.append(masterFaceID);
3112  }
3113  else
3114  {
3115  // Allow inflate-from-nothing?
3116  //FatalErrorInFunction
3117  // << "Need to specify a master point, edge or face"
3118  // << "face:" << f << " own:" << own << " nei:" << nei
3119  // << abort(FatalError);
3120  faceMap_.append(-1);
3121  }
3122  reverseFaceMap_.append(facei);
3123 
3124  flipFaceFlux_.set(facei, flipFaceFlux);
3125 
3126  if (zoneID >= 0)
3127  {
3128  faceZone_.insert(facei, zoneID);
3129  }
3130  faceZoneFlip_.set(facei, zoneFlip);
3131  // Delay extending the faceAdditionalZones
3132 
3133  return facei;
3134 }
3135 
3136 
3138 (
3139  const face& f,
3140  const label own,
3141  const label nei,
3142  const label masterPointID,
3143  const label masterEdgeID,
3144  const label masterFaceID,
3145  const bool flipFaceFlux,
3146  const label patchID,
3147  const labelUList& zoneIDs,
3148  const UList<bool>& zoneFlips
3149 )
3150 {
3151  // Check validity
3152  if (debug)
3153  {
3154  // Note: no check on zones
3155  checkFace(f, -1, own, nei, patchID, -1);
3156  }
3157 
3158  label facei = faces_.size();
3159 
3160  faces_.append(f);
3161  region_.append(patchID);
3162  faceOwner_.append(own);
3163  faceNeighbour_.append(nei);
3164 
3165  if (masterPointID >= 0)
3166  {
3167  faceMap_.append(-1);
3168  faceFromPoint_.insert(facei, masterPointID);
3169  }
3170  else if (masterEdgeID >= 0)
3171  {
3172  faceMap_.append(-1);
3173  faceFromEdge_.insert(facei, masterEdgeID);
3174  }
3175  else if (masterFaceID >= 0)
3176  {
3177  faceMap_.append(masterFaceID);
3178  }
3179  else
3180  {
3181  // Allow inflate-from-nothing?
3182  //FatalErrorInFunction
3183  // << "Need to specify a master point, edge or face"
3184  // << "face:" << f << " own:" << own << " nei:" << nei
3185  // << abort(FatalError);
3186  faceMap_.append(-1);
3187  }
3188  reverseFaceMap_.append(facei);
3189 
3190  flipFaceFlux_.set(facei, flipFaceFlux);
3191 
3192  if (zoneIDs.size())
3193  {
3194  const label minIndex = findMin(zoneIDs);
3195 
3196  faceZone_.set(facei, zoneIDs[minIndex]);
3197  faceZoneFlip_.set(facei, zoneFlips[minIndex]);
3198 
3199  // Clear any additional storage
3200  if (facei < faceAdditionalZones_.size())
3201  {
3202  faceAdditionalZones_[facei].clear();
3203  }
3204  // (auto-vivify and) store additional zones
3205  forAll(zoneIDs, i)
3206  {
3207  if (i != minIndex)
3208  {
3209  if (zoneIDs[i] == zoneIDs[minIndex])
3210  {
3211  FatalErrorInFunction << "Duplicates in zones "
3212  << flatOutput(zoneIDs) << " for face " << facei
3213  << exit(FatalError);
3214  }
3215  const label zoneAndSign
3216  (
3217  zoneFlips[i]
3218  ? zoneIDs[i]+1
3219  : -(zoneIDs[i]+1)
3220  );
3221  faceAdditionalZones_(facei).push_uniq(zoneAndSign);
3222  }
3223  }
3224  }
3225 
3226  return facei;
3227 }
3228 
3229 
3231 (
3232  const face& f,
3233  const label facei,
3234  const label own,
3235  const label nei,
3236  const bool flipFaceFlux,
3237  const label patchID,
3238  const label zoneID,
3239  const bool zoneFlip,
3240  const bool multiZone
3241 )
3242 {
3243  // Check validity
3244  if (debug)
3245  {
3246  checkFace(f, facei, own, nei, patchID, zoneID);
3247  }
3248 
3249  faces_[facei] = f;
3250  faceOwner_[facei] = own;
3251  faceNeighbour_[facei] = nei;
3252  region_[facei] = patchID;
3253 
3254  flipFaceFlux_.set(facei, flipFaceFlux);
3255 
3256  // Note: same logic as modifyCell except storage is now sparse instead
3257  // of marked with -1
3258 
3259  if (!multiZone)
3260  {
3261  if (zoneID == -1)
3262  {
3263  faceZone_.erase(facei);
3264  faceZoneFlip_.set(facei, zoneFlip);
3265  }
3266  else
3267  {
3268  faceZone_.set(facei, zoneID);
3269  faceZoneFlip_.set(facei, zoneFlip);
3270  }
3271  if (facei < faceAdditionalZones_.size())
3272  {
3273  faceAdditionalZones_[facei].clear();
3274  }
3275  }
3276  else
3277  {
3278  auto fnd = faceZone_.find(facei);
3279  if (!fnd)
3280  {
3281  faceZone_.set(facei, zoneID);
3282  faceZoneFlip_.set(facei, zoneFlip);
3283 
3284  // Check that no leftover additional zones
3285  if (faceAdditionalZones_(facei).size())
3286  {
3288  << "Additional zones for face:"
3289  << faceAdditionalZones_(facei)
3290  << abort(FatalError);
3291  }
3292  }
3293  else if (zoneID == -1)
3294  {
3295  // Clear
3296  faceZone_.erase(fnd);
3297  faceZoneFlip_.set(facei, false);
3298  if (facei < faceAdditionalZones_.size())
3299  {
3300  faceAdditionalZones_[facei].clear();
3301  }
3302  }
3303  else if (zoneID != fnd())
3304  {
3305  // New zone. Store in additional storage.
3306  const label zoneAndSign
3307  (
3308  zoneFlip
3309  ? zoneID+1
3310  : -(zoneID+1)
3311  );
3312  faceAdditionalZones_(facei).push_uniq(zoneAndSign);
3313  }
3314  }
3315 }
3316 
3317 
3319 (
3320  const face& f,
3321  const label facei,
3322  const label own,
3323  const label nei,
3324  const bool flipFaceFlux,
3325  const label patchID,
3326  const labelUList& zoneIDs,
3327  const UList<bool>& zoneFlips
3328 )
3329 {
3330  // Check validity
3331  if (debug)
3332  {
3333  // Note: no check on zones
3334  checkFace(f, facei, own, nei, patchID, -1);
3335  }
3336 
3337  faces_[facei] = f;
3338  faceOwner_[facei] = own;
3339  faceNeighbour_[facei] = nei;
3340  region_[facei] = patchID;
3341 
3342  flipFaceFlux_.set(facei, flipFaceFlux);
3343 
3344  // Note: same logic as modifyCell except storage is now sparse instead
3345  // of marked with -1
3346 
3347  if (zoneIDs.size())
3348  {
3349  if (zoneIDs.found(-1))
3350  {
3352  << "zones cannot contain -1 : " << flatOutput(zoneIDs)
3353  << " for face:" << facei
3354  << abort(FatalError);
3355  }
3356 
3357  faceZone_.set(facei, zoneIDs[0]);
3358  faceZoneFlip_.set(facei, zoneFlips[0]);
3359  if (facei < faceAdditionalZones_.size())
3360  {
3361  faceAdditionalZones_[facei].clear();
3362  }
3363  for (label i = 1; i < zoneIDs.size(); ++i)
3364  {
3365  const label zoneAndSign
3366  (
3367  zoneFlips[i]
3368  ? zoneIDs[i]+1
3369  : -(zoneIDs[i]+1)
3370  );
3371  faceAdditionalZones_(facei).push_uniq(zoneAndSign);
3372  }
3373  }
3374  else
3375  {
3376  faceZone_.erase(facei);
3377  faceZoneFlip_.set(facei, false);
3378  if (facei < faceAdditionalZones_.size())
3379  {
3380  faceAdditionalZones_[facei].clear();
3381  }
3382  }
3383 }
3384 
3385 
3387 (
3388  const label facei,
3389  const label mergeFacei
3390 )
3391 {
3392  if (facei < 0 || facei >= faces_.size())
3393  {
3395  << "illegal face label " << facei << endl
3396  << "Valid face labels are 0 .. " << faces_.size()-1
3397  << abort(FatalError);
3398  }
3399 
3400  if
3401  (
3402  strict_
3403  && (faceRemoved(facei) || faceMap_[facei] == -1)
3404  )
3405  {
3407  << "face " << facei
3408  << " already marked for removal"
3409  << abort(FatalError);
3410  }
3411 
3412  faces_[facei].clear();
3413  region_[facei] = -1;
3414  faceOwner_[facei] = -1;
3415  faceNeighbour_[facei] = -1;
3416  faceMap_[facei] = -1;
3417  if (mergeFacei >= 0)
3418  {
3419  reverseFaceMap_[facei] = -mergeFacei-2;
3420  }
3421  else
3422  {
3423  reverseFaceMap_[facei] = -1;
3424  }
3425  faceFromEdge_.erase(facei);
3426  faceFromPoint_.erase(facei);
3427  flipFaceFlux_.unset(facei);
3428  faceZoneFlip_.unset(facei);
3429  faceZone_.erase(facei);
3430  if (facei < faceAdditionalZones_.size())
3431  {
3432  faceAdditionalZones_[facei].clear();
3433  }
3434 }
3435 
3436 
3438 (
3439  const label masterPointID,
3440  const label masterEdgeID,
3441  const label masterFaceID,
3442  const label masterCellID,
3443  const label zoneID
3444 )
3445 {
3446  label celli = cellMap_.size();
3447 
3448  if (masterPointID >= 0)
3449  {
3450  cellMap_.append(-1);
3451  cellFromPoint_.insert(celli, masterPointID);
3452  }
3453  else if (masterEdgeID >= 0)
3454  {
3455  cellMap_.append(-1);
3456  cellFromEdge_.insert(celli, masterEdgeID);
3457  }
3458  else if (masterFaceID >= 0)
3459  {
3460  cellMap_.append(-1);
3461  cellFromFace_.insert(celli, masterFaceID);
3462  }
3463  else
3464  {
3465  cellMap_.append(masterCellID);
3466  }
3467  reverseCellMap_.append(celli);
3468 
3469  cellZone_.append(zoneID);
3470  // Delay extending the cellAdditionalZones
3471 
3472  return celli;
3473 }
3474 
3475 
3477 (
3478  const label masterPointID,
3479  const label masterEdgeID,
3480  const label masterFaceID,
3481  const label masterCellID,
3482  const labelUList& zoneIDs
3483 )
3484 {
3485  label celli = cellMap_.size();
3486 
3487  if (masterPointID >= 0)
3488  {
3489  cellMap_.append(-1);
3490  cellFromPoint_.insert(celli, masterPointID);
3491  }
3492  else if (masterEdgeID >= 0)
3493  {
3494  cellMap_.append(-1);
3495  cellFromEdge_.insert(celli, masterEdgeID);
3496  }
3497  else if (masterFaceID >= 0)
3498  {
3499  cellMap_.append(-1);
3500  cellFromFace_.insert(celli, masterFaceID);
3501  }
3502  else
3503  {
3504  cellMap_.append(masterCellID);
3505  }
3506  reverseCellMap_.append(celli);
3507 
3508  if (zoneIDs.size())
3509  {
3510  cellZone_.append(zoneIDs[0]);
3511 
3512  // Clear any additional storage
3513  if (celli < cellAdditionalZones_.size())
3514  {
3515  cellAdditionalZones_[celli].clear();
3516  }
3517  // (auto-vivify and) store additional zones
3518  for (label i = 1; i < zoneIDs.size(); ++i)
3519  {
3520  cellAdditionalZones_(celli).push_uniq(zoneIDs[i]);
3521  }
3522  }
3523  else
3524  {
3525  cellZone_.append(-1);
3526  }
3527 
3528  return celli;
3529 }
3530 
3531 
3533 (
3534  const label celli,
3535  const label zoneID,
3536  const bool multiZone
3537 )
3538 {
3539  if (!multiZone)
3540  {
3541  cellZone_[celli] = zoneID;
3542  if (celli < cellAdditionalZones_.size())
3543  {
3544  cellAdditionalZones_[celli].clear();
3545  }
3546  }
3547  else
3548  {
3549  if (cellZone_[celli] == -1)
3550  {
3551  cellZone_[celli] = zoneID;
3552 
3553  // Check that no leftover additional zones
3554  if (cellAdditionalZones_(celli).size())
3555  {
3557  << "Additional zones for cell:"
3558  << cellAdditionalZones_(celli)
3559  << abort(FatalError);
3560  }
3561  }
3562  else
3563  {
3564  if (zoneID == -1)
3565  {
3566  // Clear
3567  cellZone_[celli] = zoneID;
3568  if (celli < cellAdditionalZones_.size())
3569  {
3570  cellAdditionalZones_[celli].clear();
3571  }
3572  }
3573  else if (zoneID != cellZone_[celli])
3574  {
3575  // New zone. Store in additional storage.
3576  cellAdditionalZones_(celli).push_uniq(zoneID);
3577  }
3578  }
3579  }
3580 }
3581 
3582 
3584 (
3585  const label celli,
3586  const labelUList& zoneIDs
3587 )
3588 {
3589  if (celli < 0 || celli >= cellMap_.size())
3590  {
3592  << "illegal cell label " << celli << endl
3593  << "Valid cell labels are 0 .. " << cellMap_.size()-1
3594  << abort(FatalError);
3595  }
3596 
3597  if (zoneIDs.size())
3598  {
3599  if (zoneIDs.found(-1))
3600  {
3602  << "zones cannot contain -1 : " << flatOutput(zoneIDs)
3603  << " for cell:" << celli
3604  << abort(FatalError);
3605  }
3606 
3607  cellZone_[celli] = zoneIDs[0];
3608  if (celli < cellAdditionalZones_.size())
3609  {
3610  cellAdditionalZones_[celli].clear();
3611  }
3612  for (label i = 1; i < zoneIDs.size(); ++i)
3613  {
3614  cellAdditionalZones_(celli).push_uniq(zoneIDs[i]);
3615  }
3616  }
3617  else
3618  {
3619  cellZone_[celli] = -1;
3620  if (celli < cellAdditionalZones_.size())
3621  {
3622  cellAdditionalZones_[celli].clear();
3623  }
3624  }
3625 }
3626 
3627 
3629 (
3630  const label celli,
3631  const label mergeCelli
3632 )
3633 {
3634  if (celli < 0 || celli >= cellMap_.size())
3635  {
3637  << "illegal cell label " << celli << endl
3638  << "Valid cell labels are 0 .. " << cellMap_.size()-1
3639  << abort(FatalError);
3640  }
3641 
3642  if (strict_ && cellMap_[celli] == -2)
3643  {
3645  << "cell " << celli
3646  << " already marked for removal"
3647  << abort(FatalError);
3648  }
3649 
3650  cellMap_[celli] = -2;
3651  if (mergeCelli >= 0)
3652  {
3653  reverseCellMap_[celli] = -mergeCelli-2;
3654  }
3655  else
3656  {
3657  reverseCellMap_[celli] = -1;
3658  }
3659  cellFromPoint_.erase(celli);
3660  cellFromEdge_.erase(celli);
3661  cellFromFace_.erase(celli);
3662  cellZone_[celli] = -1;
3663  if (celli < cellAdditionalZones_.size())
3664  {
3665  cellAdditionalZones_[celli].clear();
3666  }
3667 }
3668 
3669 
3671 (
3672  const label pointi,
3673  DynamicList<label>& zones
3674 ) const
3675 {
3676  if (pointi < 0 || pointi >= pointMap_.size())
3677  {
3679  << "illegal point label " << pointi << endl
3680  << "Valid point labels are 0 .. " << pointMap_.size()-1
3681  << abort(FatalError);
3682  }
3683  zones.clear();
3684 
3685  const auto fnd = pointZone_.find(pointi);
3686  if (fnd)
3687  {
3688  zones.push_back(fnd());
3689  if (pointi < pointAdditionalZones_.size())
3690  {
3691  for (const label zonei : pointAdditionalZones_[pointi])
3692  {
3693  zones.push_uniq(zonei);
3694  }
3695  }
3696  }
3697  return zones.size();
3698 }
3699 
3700 
3702 (
3703  const label facei,
3704  DynamicList<label>& zones,
3705  DynamicList<bool>& flips
3706 ) const
3707 {
3708  if (facei < 0 || facei >= faceMap_.size())
3709  {
3711  << "illegal face label " << facei << endl
3712  << "Valid face labels are 0 .. " << faceMap_.size()-1
3713  << abort(FatalError);
3714  }
3715  zones.clear();
3716  flips.clear();
3717 
3718  const auto fnd = faceZone_.find(facei);
3719  if (fnd)
3720  {
3721  zones.push_back(fnd());
3722  flips.push_back(flipFaceFlux_[facei]);
3723  if (facei < faceAdditionalZones_.size())
3724  {
3725  for (const label zoneAndSign : faceAdditionalZones_[facei])
3726  {
3727  const label zonei = mag(zoneAndSign)-1;
3728  if (!zones.found(zonei))
3729  {
3730  zones.push_back(zonei);
3731  flips.push_back((zoneAndSign > 0));
3732  }
3733  }
3734  }
3735  }
3736  return zones.size();
3737 }
3738 
3739 
3741 (
3742  const label celli,
3743  DynamicList<label>& zones
3744 ) const
3745 {
3746  if (celli < 0 || celli >= cellMap_.size())
3747  {
3749  << "illegal cell label " << celli << endl
3750  << "Valid cell labels are 0 .. " << cellMap_.size()-1
3751  << abort(FatalError);
3752  }
3753  zones.clear();
3754  if (cellZone_[celli] != -1)
3755  {
3756  zones.push_back(cellZone_[celli]);
3757  }
3758  if (celli < cellAdditionalZones_.size())
3759  {
3760  for (const label zonei : cellAdditionalZones_[celli])
3761  {
3762  zones.push_uniq(zonei);
3763  }
3764  }
3765  return zones.size();
3766 }
3767 
3768 
3770 (
3771  polyMesh& mesh,
3772  const labelUList& patchMap,
3773  const bool inflate,
3774  const bool syncParallel,
3775  const bool orderCells,
3776  const bool orderPoints
3777 )
3778 {
3779  if (debug)
3780  {
3781  Pout<< "polyTopoChange::changeMesh"
3782  << "(polyMesh&, const bool, const bool, const bool, const bool)"
3783  << endl;
3784  }
3785 
3786  if (debug)
3787  {
3788  Pout<< "Old mesh:" << nl;
3789  writeMeshStats(mesh, Pout);
3790  }
3791 
3792  // new mesh points
3793  pointField newPoints;
3794  // number of internal points
3795  label nInternalPoints;
3796  // patch slicing
3797  labelList patchSizes;
3798  labelList patchStarts;
3799  // inflate maps
3800  List<objectMap> pointsFromPoints;
3801  List<objectMap> facesFromPoints;
3802  List<objectMap> facesFromEdges;
3803  List<objectMap> facesFromFaces;
3804  List<objectMap> cellsFromPoints;
3805  List<objectMap> cellsFromEdges;
3806  List<objectMap> cellsFromFaces;
3807  List<objectMap> cellsFromCells;
3808  // old mesh info
3809  List<Map<label>> oldPatchMeshPointMaps;
3810  labelList oldPatchNMeshPoints;
3811  labelList oldPatchStarts;
3812  List<Map<label>> oldFaceZoneMeshPointMaps;
3813 
3814  // Compact, reorder patch faces and calculate mesh/patch maps.
3815  compactAndReorder
3816  (
3817  mesh,
3818  patchMap,
3819  syncParallel,
3820  orderCells,
3821  orderPoints,
3822 
3823  nInternalPoints,
3824  newPoints,
3825  patchSizes,
3826  patchStarts,
3827  pointsFromPoints,
3828  facesFromPoints,
3829  facesFromEdges,
3830  facesFromFaces,
3831  cellsFromPoints,
3832  cellsFromEdges,
3833  cellsFromFaces,
3834  cellsFromCells,
3835  oldPatchMeshPointMaps,
3836  oldPatchNMeshPoints,
3837  oldPatchStarts,
3838  oldFaceZoneMeshPointMaps
3839  );
3840 
3841  const label nOldPoints(mesh.nPoints());
3842  const label nOldFaces(mesh.nFaces());
3843  const label nOldCells(mesh.nCells());
3844  autoPtr<scalarField> oldCellVolumes(new scalarField(mesh.cellVolumes()));
3845 
3846 
3847  // Change the mesh
3848  // ~~~~~~~~~~~~~~~
3849  // This will invalidate any addressing so better make sure you have
3850  // all the information you need!!!
3851 
3852  if (inflate)
3853  {
3854  // Keep (renumbered) mesh points, store new points in map for inflation
3855  // (appended points (i.e. from nowhere) get value zero)
3856  pointField renumberedMeshPoints(newPoints.size());
3857 
3858  forAll(pointMap_, newPointi)
3859  {
3860  const label oldPointi = pointMap_[newPointi];
3861 
3862  if (oldPointi >= 0)
3863  {
3864  renumberedMeshPoints[newPointi] = mesh.points()[oldPointi];
3865  }
3866  else
3867  {
3868  renumberedMeshPoints[newPointi] = Zero;
3869  }
3870  }
3871 
3873  (
3874  autoPtr<pointField>::New(std::move(renumberedMeshPoints)),
3875  autoPtr<faceList>::New(std::move(faces_)),
3876  autoPtr<labelList>::New(std::move(faceOwner_)),
3877  autoPtr<labelList>::New(std::move(faceNeighbour_)),
3878  patchSizes,
3879  patchStarts,
3880  syncParallel
3881  );
3882 
3883  mesh.topoChanging(true);
3884  // Note: could already set moving flag as well
3885  // mesh.moving(true);
3886  }
3887  else
3888  {
3889  // Set new points.
3891  (
3892  autoPtr<pointField>::New(std::move(newPoints)),
3893  autoPtr<faceList>::New(std::move(faces_)),
3894  autoPtr<labelList>::New(std::move(faceOwner_)),
3895  autoPtr<labelList>::New(std::move(faceNeighbour_)),
3896  patchSizes,
3897  patchStarts,
3898  syncParallel
3899  );
3900  mesh.topoChanging(true);
3901  }
3902 
3903  // Clear out primitives
3904  {
3905  retiredPoints_.clearStorage();
3906  region_.clearStorage();
3907  }
3908 
3909 
3910  if (debug)
3911  {
3912  // Some stats on changes
3913  label nAdd, nInflate, nMerge, nRemove;
3914  countMap(pointMap_, reversePointMap_, nAdd, nInflate, nMerge, nRemove);
3915  Pout<< "Points:"
3916  << " added(from point):" << nAdd
3917  << " added(from nothing):" << nInflate
3918  << " merged(into other point):" << nMerge
3919  << " removed:" << nRemove
3920  << nl;
3921 
3922  countMap(faceMap_, reverseFaceMap_, nAdd, nInflate, nMerge, nRemove);
3923  Pout<< "Faces:"
3924  << " added(from face):" << nAdd
3925  << " added(inflated):" << nInflate
3926  << " merged(into other face):" << nMerge
3927  << " removed:" << nRemove
3928  << nl;
3929 
3930  countMap(cellMap_, reverseCellMap_, nAdd, nInflate, nMerge, nRemove);
3931  Pout<< "Cells:"
3932  << " added(from cell):" << nAdd
3933  << " added(inflated):" << nInflate
3934  << " merged(into other cell):" << nMerge
3935  << " removed:" << nRemove
3936  << nl
3937  << endl;
3938  }
3939 
3940  // Zones
3941  // ~~~~~
3942 
3943  // Inverse of point/face/cell zone addressing.
3944  // For every preserved point/face/cells in zone give the old position.
3945  // For added points, the index is set to -1
3946  labelListList pointZoneMap(mesh.pointZones().size());
3947  labelListList faceZoneFaceMap(mesh.faceZones().size());
3948  labelListList cellZoneMap(mesh.cellZones().size());
3949 
3950  resetZones(mesh, mesh, pointZoneMap, faceZoneFaceMap, cellZoneMap);
3951 
3952  if (debug)
3953  {
3954  Pout<< "New mesh:" << nl;
3955  writeMeshStats(mesh, Pout);
3956  }
3957 
3958  // Clear zone info
3959  {
3960  pointZone_.clearStorage();
3961  faceZone_.clearStorage();
3962  faceZoneFlip_.clearStorage();
3963  cellZone_.clearStorage();
3964  }
3965 
3966 
3967  // Patch point renumbering
3968  // For every preserved point on a patch give the old position.
3969  // For added points, the index is set to -1
3970  labelListList patchPointMap(mesh.boundaryMesh().size());
3971  calcPatchPointMap
3972  (
3973  oldPatchMeshPointMaps,
3974  patchMap,
3975  mesh.boundaryMesh(),
3976  patchPointMap
3977  );
3978 
3979  // Create the face zone mesh point renumbering
3980  labelListList faceZonePointMap(mesh.faceZones().size());
3981  calcFaceZonePointMap(mesh, oldFaceZoneMeshPointMaps, faceZonePointMap);
3982 
3983  labelHashSet flipFaceFluxSet(HashSetOps::used(flipFaceFlux_));
3984 
3986  (
3987  mesh,
3988  nOldPoints,
3989  nOldFaces,
3990  nOldCells,
3991 
3992  pointMap_,
3993  pointsFromPoints,
3994 
3995  faceMap_,
3996  facesFromPoints,
3997  facesFromEdges,
3998  facesFromFaces,
3999 
4000  cellMap_,
4001  cellsFromPoints,
4002  cellsFromEdges,
4003  cellsFromFaces,
4004  cellsFromCells,
4005 
4006  reversePointMap_,
4007  reverseFaceMap_,
4008  reverseCellMap_,
4009 
4010  flipFaceFluxSet,
4011 
4012  patchPointMap,
4013 
4014  pointZoneMap,
4015 
4016  faceZonePointMap,
4017  faceZoneFaceMap,
4018  cellZoneMap,
4019 
4020  newPoints, // if empty signals no inflation.
4021  oldPatchStarts,
4022  oldPatchNMeshPoints,
4023 
4024  oldCellVolumes,
4025 
4026  true // steal storage.
4027  );
4028 
4029  // At this point all member DynamicList (pointMap_, cellMap_ etc.) will
4030  // be invalid.
4031 }
4032 
4033 
4035 (
4036  polyMesh& mesh,
4037  const bool inflate,
4038  const bool syncParallel,
4039  const bool orderCells,
4040  const bool orderPoints
4041 )
4042 {
4043  return changeMesh
4044  (
4045  mesh,
4047  inflate,
4048  syncParallel,
4049  orderCells,
4050  orderPoints
4051  );
4052 }
4053 
4054 
4055 // ************************************************************************* //
label nPatches
Definition: readKivaGrid.H:396
const face & newFace() const
Return face.
faceListList boundary
Class containing data for face removal.
label zoneID() const
Face zone ID.
Definition: polyAddFace.H:384
label mergePointID() const
label neighbour() const
Return owner cell ID.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
const labelIOList & zoneIDs
Definition: correctPhi.H:59
List< List< bool > > boolListList
List of boolList.
Definition: boolList.H:36
label faceID() const
Return master face ID.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
Class describing modification of a face.
void modifyCell(const label celli, const label zoneID, const bool multiZone=false)
Modify zone of cell. Optionally add to zone.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label zoneFlip() const
Face zone flip.
const face & newFace() const
Return face.
Definition: polyAddFace.H:264
polyTopoChange(const label nPatches, const bool strict=true)
Construct without mesh. Either specify nPatches or use setNumPatches before trying to make a mesh (ma...
labelHashSet used(const bitSet &select)
Convert a bitset to a labelHashSet of the indices used.
Definition: HashOps.C:26
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:608
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.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
IntListType renumber(const labelUList &oldToNew, const IntListType &input)
Renumber the values within a list.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
label start() const noexcept
The start label of boundary faces in the polyMesh face list.
bool inCell() const
Does the point support a cell.
label patchID() const
Boundary patch ID.
label owner() const
Return owner cell ID.
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:888
label zoneID() const
Point zone ID.
Definition: polyAddPoint.H:170
label cellID() const
Cell ID.
void resetPrimitives(autoPtr< pointField > &&points, autoPtr< faceList > &&faces, autoPtr< labelList > &&owner, autoPtr< labelList > &&neighbour, const labelUList &patchSizes, const labelUList &patchStarts, const bool validBoundary=true)
Reset mesh primitive data. Assumes all patch info correct.
Definition: polyMesh.C:704
label zoneID() const
Face zone ID.
label masterCellID() const
Return master cell ID.
Definition: polyAddCell.H:200
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:312
Class containing data for point addition.
Definition: polyAddPoint.H:43
label masterEdgeID() const
Return master edge ID.
Definition: polyAddCell.H:184
label pointID() const
Point ID.
label nFaces() const noexcept
Number of mesh faces.
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const labelUList &patchMap, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
label masterPointID() const
Return master point ID.
Definition: polyAddFace.H:320
virtual const fileName & name() const override
Get the name of the output serial stream. (eg, the name of the Fstream file name) ...
Definition: OSstream.H:134
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:232
labelList faceLabels(nFaceLabels)
List< labelList > labelListList
List of labelList.
Definition: labelList.H:38
Class describing modification of a cell.
A face addition data class. A face can be inflated either from a point or from another face and can e...
Definition: polyAddFace.H:47
void clear()
Clear all storage.
bool isInternalFace(const label faceIndex) const noexcept
Return true if given face label is internal to the mesh.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
label addCell(const label masterPointID, const label masterEdgeID, const label masterFaceID, const label masterCellID, const label zoneID)
Add cell. Return new cell label.
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
bool removeFromZone() const
const point & newPoint() const
Point location.
Definition: polyAddPoint.H:138
label owner() const
Return owner cell.
Definition: polyAddFace.H:272
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
label zoneFlip() const
Face zone flip.
Definition: polyAddFace.H:392
label cellZones(const label celli, DynamicList< label > &zones) const
Get current cellZone(s). Return number of zones.
const labelListList & edgeCells() const
Class containing data for cell addition.
Definition: polyAddCell.H:42
label findMin(const ListType &input, label start=0)
Linear search for the index of the min element, similar to std::min_element but for lists and returns...
bool flipFaceFlux() const
Does the face flux need to be flipped.
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
Class containing data for cell removal.
void setSize(const label n)
Alias for resize()
Definition: List.H:320
dynamicFvMesh & mesh
label cellID() const
Return cell ID.
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
label faceID() const
Return face ID.
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
bool inCell() const
Does the point support a cell.
Definition: polyAddPoint.H:178
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:130
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:609
label nPoints
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void removeCell(const label celli, const label mergeCelli)
Remove/merge cell.
label faceZones(const label facei, DynamicList< label > &zones, DynamicList< bool > &flips) const
Get current faceZone(s). Return number of zones.
label size() const noexcept
The number of entries in the list.
Definition: UPtrListI.H:106
label mergeCellID() const
Return cell ID.
label zoneID() const
Cell zone ID.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
label masterFaceID() const
Return master face ID.
Definition: polyAddFace.H:336
label masterPointID() const
Return master point ID.
Definition: polyAddCell.H:176
void modifyFace(const face &f, const label facei, const label own, const label nei, const bool flipFaceFlux, const label patchID, const label zoneID, const bool zoneFlip, const bool multiZone=false)
Modify vertices or cell of face.
label nInternalFaces() const noexcept
Number of internal faces.
ZoneMesh< pointZone, polyMesh > pointZoneMesh
A ZoneMesh with the type pointZone.
void shrink()
Shrink storage (does not remove any elements; just compacts dynamic lists.
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:584
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
errorManip< error > abort(error &err)
Definition: errorManip.H:139
const labelListList & pointCells() const
A virtual base class for topological actions.
Definition: topoAction.H:47
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
void setCapacity(const label nPoints, const label nFaces, const label nCells)
Explicitly pre-size the dynamic storage for expected mesh size for if construct-without-mesh.
bool topoChanging() const noexcept
Is mesh topology changing.
Definition: polyMesh.H:750
label patchID() const
Boundary patch ID.
Definition: polyAddFace.H:360
Class describing modification of a point.
void movePoints(const pointField &newPoints)
Move all points. Incompatible with other topology changes.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
OBJstream os(runTime.globalPath()/outputName)
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:671
defineTypeNameAndDebug(combustionModel, 0)
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:405
labelList f(nPoints)
void setSize(const label newLen)
Same as resize()
Definition: PtrList.H:337
PrimitivePatch< SubList< face >, const pointField & > primitivePatch
A PrimitivePatch with a SubList addressing for the faces, const reference for the point field...
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:555
void resize(const label newLen)
Adjust size of PtrList.
Definition: PtrList.C:95
label zoneID() const
Point zone ID.
label push_uniq(const T &val)
Append an element if not already in the list.
Definition: DynamicListI.H:686
label zoneID() const
Cell zone ID.
Definition: polyAddCell.H:216
labelList invert(const label len, const labelUList &map)
Create an inverse one-to-one mapping.
Definition: ListOps.C:30
const pointZoneMesh & pointZones() const noexcept
Return point zone mesh.
Definition: polyMesh.H:663
label masterFaceID() const
Return master face ID.
Definition: polyAddCell.H:192
void addMesh(const polyMesh &mesh, const labelUList &patchMap, const labelUList &pointZoneMap, const labelUList &faceZoneMap, const labelUList &cellZoneMap)
Add all points/faces/cells of mesh. Additional offset for patch or zone ids.
label neighbour() const
Return neighbour cell.
Definition: polyAddFace.H:280
const wordList internal
Standard dimensioned field types (scalar, vector, tensor, etc)
label newPointi
Definition: readKivaGrid.H:496
label nCells() const noexcept
Number of mesh cells.
void removePoint(const label pointi, const label mergePointi)
Remove/merge point.
const polyBoundaryMesh & patches
void modifyPoint(const label pointi, const point &pt, const label zoneID, const bool inCell, const bool multiZone=false)
Modify coordinate.
const cellZoneMesh & cellZones() const noexcept
Return cell zone mesh.
Definition: polyMesh.H:679
label pointZones(const label pointi, DynamicList< label > &zones) const
Get current cellZone(s). Return number of zones.
const labelListList & pointFaces() const
constexpr label labelMax
Definition: label.H:55
const point & newPoint() const
New point location.
label pointID() const
Return point ID.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
label addPoint(const point &pt, const label masterPointID, const label zoneID, const bool inCell)
Add point. Return new point label.
bool flipFaceFlux() const
Does the face flux need to be flipped.
Definition: polyAddFace.H:344
List< label > labelList
A List of labels.
Definition: List.H:62
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
ListType reorder(const labelUList &oldToNew, const ListType &input, const bool prune=false)
Reorder the elements of a list.
void removeFace(const label facei, const label mergeFacei)
Remove/merge face.
List< bool > boolList
A List of bools.
Definition: List.H:60
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Class containing data for point removal.
ZoneMesh< cellZone, polyMesh > cellZoneMesh
A ZoneMesh with the type cellZone.
const labelListList & edgeFaces() const
label mergeFaceID() const
Return merge face ID.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
label masterEdgeID() const
Return master edge ID.
Definition: polyAddFace.H:328
const scalarField & cellVolumes() const
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
label setAction(const topoAction &action)
For compatibility with polyTopoChange: set topological action.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
label masterPointID() const
Master point label.
Definition: polyAddPoint.H:146