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