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