meshRefinementMerge.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-2022 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 "meshRefinement.H"
27 #include "combineFaces.H"
28 #include "polyTopoChange.H"
29 #include "removePoints.H"
30 #include "faceSet.H"
31 #include "Time.H"
32 #include "motionSmoother.H"
33 #include "syncTools.H"
34 
35 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
36 
38 //Foam::label Foam::meshRefinement::mergePatchFaces
39 //(
40 // const scalar minCos,
41 // const scalar concaveCos,
42 // const labelList& patchIDs
43 //)
44 //{
45 // // Patch face merging engine
46 // combineFaces faceCombiner(mesh_);
47 //
48 // const polyBoundaryMesh& patches = mesh_.boundaryMesh();
49 //
50 // // Pick up all candidate cells on boundary
51 // labelHashSet boundaryCells(mesh_.nFaces()-mesh_.nInternalFaces());
52 //
53 // forAll(patchIDs, i)
54 // {
55 // label patchi = patchIDs[i];
56 //
57 // const polyPatch& patch = patches[patchi];
58 //
59 // if (!patch.coupled())
60 // {
61 // forAll(patch, i)
62 // {
63 // boundaryCells.insert(mesh_.faceOwner()[patch.start()+i]);
64 // }
65 // }
66 // }
67 //
68 // // Get all sets of faces that can be merged
69 // labelListList mergeSets
70 // (
71 // faceCombiner.getMergeSets
72 // (
73 // minCos,
74 // concaveCos,
75 // boundaryCells
76 // )
77 // );
78 //
79 // label nFaceSets = returnReduce(mergeSets.size(), sumOp<label>());
80 //
81 // Info<< "mergePatchFaces : Merging " << nFaceSets
82 // << " sets of faces." << endl;
83 //
84 // if (nFaceSets > 0)
85 // {
86 // // Topology changes container
87 // polyTopoChange meshMod(mesh_);
88 //
89 // // Merge all faces of a set into the first face of the set. Remove
90 // // unused points.
91 // faceCombiner.setRefinement(mergeSets, meshMod);
92 //
93 // // Change the mesh (no inflation)
94 // autoPtr<polyTopoChangeMap> map =
95 // meshMod.changeMesh(mesh_, false, true);
96 //
97 // // Update fields
98 // mesh_.topoChange(map);
99 //
100 // // Move mesh (since morphing does not do this)
101 // if (map().hasMotionPoints())
102 // {
103 // mesh_.movePoints(map().preMotionPoints());
104 // }
105 // else
106 // {
107 // // Delete mesh volumes. No other way to do this?
108 // mesh_.clearOut();
109 // }
110 //
111 //
112 // // Reset the instance for if in overwrite mode
113 // mesh_.setInstance(timeName());
114 //
115 // faceCombiner.topoChange(map);
116 //
117 // // Get the kept faces that need to be recalculated.
118 // // Merging two boundary faces might shift the cell centre
119 // // (unless the faces are absolutely planar)
120 // labelHashSet retestFaces(6*mergeSets.size());
121 //
122 // forAll(mergeSets, seti)
123 // {
124 // label oldMasterI = mergeSets[seti][0];
125 //
126 // label facei = map().reverseFaceMap()[oldMasterI];
127 //
128 // // facei is always uncoupled boundary face
129 // const cell& cFaces = mesh_.cells()[mesh_.faceOwner()[facei]];
130 //
131 // forAll(cFaces, i)
132 // {
133 // retestFaces.insert(cFaces[i]);
134 // }
135 // }
136 // topoChange(map, retestFaces.toc());
137 // }
138 //
139 //
140 // return nFaceSets;
141 //}
142 //
143 //
146 //Foam::autoPtr<Foam::polyTopoChangeMap> Foam::meshRefinement::mergeEdges
147 //(
148 // const scalar minCos
149 //)
150 //{
151 // // Point removal analysis engine
152 // removePoints pointRemover(mesh_);
153 //
154 // // Count usage of points
155 // boolList pointCanBeDeleted;
156 // label nRemove = pointRemover.countPointUsage(minCos, pointCanBeDeleted);
157 //
158 // Info<< "Removing " << nRemove
159 // << " straight edge points." << endl;
160 //
161 // autoPtr<polyTopoChangeMap> map;
162 //
163 // if (nRemove > 0)
164 // {
165 // // Save my local faces that will change. These changed faces might
166 // // cause a shift in the cell centre which needs to be retested.
167 // // Have to do this before changing mesh since point will be removed.
168 // labelHashSet retestOldFaces(nRemove / Pstream::nProcs());
169 //
170 // {
171 // const faceList& faces = mesh_.faces();
172 //
173 // forAll(faces, facei)
174 // {
175 // const face& f = faces[facei];
176 //
177 // forAll(f, fp)
178 // {
179 // if (pointCanBeDeleted[f[fp]])
180 // {
181 // retestOldFaces.insert(facei);
182 // break;
183 // }
184 // }
185 // }
186 // }
187 //
188 // // Topology changes container
189 // polyTopoChange meshMod(mesh_);
190 //
191 // pointRemover.setRefinement(pointCanBeDeleted, meshMod);
192 //
193 // // Change the mesh (no inflation)
194 // map = meshMod.changeMesh(mesh_, false, true);
195 //
196 // // Update fields
197 // mesh_.topoChange(map);
198 //
199 // // Move mesh (since morphing does not do this)
200 // if (map().hasMotionPoints())
201 // {
202 // mesh_.movePoints(map().preMotionPoints());
203 // }
204 // else
205 // {
206 // // Delete mesh volumes. No other way to do this?
207 // mesh_.clearOut();
208 // }
209 //
210 // // Reset the instance for if in overwrite mode
211 // mesh_.setInstance(timeName());
212 //
213 // pointRemover.topoChange(map);
214 //
215 // // Get the kept faces that need to be recalculated.
216 // labelHashSet retestFaces(6*retestOldFaces.size());
217 //
218 // const cellList& cells = mesh_.cells();
219 //
220 // forAllConstIter(labelHashSet, retestOldFaces, iter)
221 // {
222 // label facei = map().reverseFaceMap()[iter.key()];
223 //
224 // const cell& ownFaces = cells[mesh_.faceOwner()[facei]];
225 //
226 // forAll(ownFaces, i)
227 // {
228 // retestFaces.insert(ownFaces[i]);
229 // }
230 //
231 // if (mesh_.isInternalFace(facei))
232 // {
233 // const cell& neiFaces = cells[mesh_.faceNeighbour()[facei]];
234 //
235 // forAll(neiFaces, i)
236 // {
237 // retestFaces.insert(neiFaces[i]);
238 // }
239 // }
240 // }
241 // topoChange(map, retestFaces.toc());
242 // }
243 //
244 // return map;
245 //}
246 
247 
249 (
250  const scalar minCos,
251  const scalar concaveCos,
252  const labelHashSet& patchIDs,
253  const dictionary& motionDict,
254  const labelList& preserveFaces
255 )
256 {
257  // Patch face merging engine
258  combineFaces faceCombiner(mesh_, true);
259 
260  // Get all sets of faces that can be merged. Since only faces on the same
261  // patch get merged there is no risk of e.g. patchID faces getting merged
262  // with original patches (or even processor patches). There is a risk
263  // though of original patch faces getting merged if they make a small
264  // angle. Would be pretty weird starting mesh though.
265  labelListList allFaceSets
266  (
267  faceCombiner.getMergeSets(minCos, concaveCos, patchIDs)
268  );
269 
270  // Filter out any set that contains any preserveFace
271  label compactI = 0;
272  forAll(allFaceSets, i)
273  {
274  const labelList& set = allFaceSets[i];
275 
276  bool keep = true;
277  forAll(set, j)
278  {
279  if (preserveFaces[set[j]] != -1)
280  {
281  keep = false;
282  break;
283  }
284  }
285 
286  if (keep)
287  {
288  if (compactI != i)
289  {
290  allFaceSets[compactI] = set;
291  }
292 
293  compactI++;
294  }
295  }
296  allFaceSets.setSize(compactI);
297 
298  label nFaceSets = returnReduce(allFaceSets.size(), sumOp<label>());
299 
300  Info<< "Merging " << nFaceSets << " sets of faces." << nl << endl;
301 
302  if (nFaceSets > 0)
303  {
304  if (debug&meshRefinement::MESH)
305  {
306  faceSet allSets(mesh_, "allFaceSets", allFaceSets.size());
307  forAll(allFaceSets, seti)
308  {
309  forAll(allFaceSets[seti], i)
310  {
311  allSets.insert(allFaceSets[seti][i]);
312  }
313  }
314  Pout<< "Writing all faces to be merged to set "
315  << allSets.objectPath() << endl;
316  allSets.instance() = timeName();
317  allSets.write();
318 
319  const_cast<Time&>(mesh_.time())++;
320  }
321 
322 
323  // Topology changes container
324  polyTopoChange meshMod(mesh_);
325 
326  // Merge all faces of a set into the first face of the set.
327  faceCombiner.setRefinement(allFaceSets, meshMod);
328 
329  // Experimental: store data for all the points that have been deleted
330  storeData
331  (
332  faceCombiner.savedPointLabels(), // points to store
333  labelList(0), // faces to store
334  labelList(0) // cells to store
335  );
336 
337  // Change the mesh (no inflation)
338  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh_, false, true);
339 
340  // Update fields
341  mesh_.topoChange(map);
342 
343  // Move mesh (since morphing does not do this)
344  if (map().hasMotionPoints())
345  {
346  mesh_.movePoints(map().preMotionPoints());
347  }
348  else
349  {
350  // Delete mesh volumes.
351  mesh_.clearOut();
352  }
353 
354  // Reset the instance for if in overwrite mode
355  mesh_.setInstance(timeName());
356 
357  faceCombiner.topoChange(map);
358 
359  // Get the kept faces that need to be recalculated.
360  // Merging two boundary faces might shift the cell centre
361  // (unless the faces are absolutely planar)
362  labelHashSet retestFaces(2*allFaceSets.size());
363 
364  forAll(allFaceSets, seti)
365  {
366  const label oldMasterI = allFaceSets[seti][0];
367  retestFaces.insert(map().reverseFaceMap()[oldMasterI]);
368  }
369  topoChange(map, growFaceCellFace(retestFaces));
370 
371  if (debug&meshRefinement::MESH)
372  {
373  // Check sync
374  Pout<< "Checking sync after initial merging " << nFaceSets
375  << " faces." << endl;
376  checkData();
377 
378  Pout<< "Writing initial merged-faces mesh to time "
379  << timeName() << nl << endl;
380  write();
381  }
382 
383  for (label iteration = 0; iteration < 100; iteration++)
384  {
385  Info<< nl
386  << "Undo iteration " << iteration << nl
387  << "----------------" << endl;
388 
389 
390  // Check mesh for errors
391  // ~~~~~~~~~~~~~~~~~~~~~
392 
393  faceSet errorFaces
394  (
395  mesh_,
396  "errorFaces",
397  mesh_.nFaces()-mesh_.nInternalFaces()
398  );
399  bool hasErrors = motionSmoother::checkMesh
400  (
401  false, // report
402  mesh_,
403  motionDict,
404  errorFaces
405  );
406 
407  // if (checkEdgeConnectivity)
408  //{
409  // Info<< "Checking edge-face connectivity (duplicate faces"
410  // << " or non-consecutive shared vertices)" << endl;
411  //
412  // label nOldSize = errorFaces.size();
413  //
414  // hasErrors =
415  // mesh_.checkFaceFaces
416  // (
417  // false,
418  // &errorFaces
419  // )
420  // || hasErrors;
421  //
422  // Info<< "Detected additional "
423  // << returnReduce
424  // (
425  // errorFaces.size() - nOldSize,
426  // sumOp<label>()
427  // )
428  // << " faces with illegal face-face connectivity"
429  // << endl;
430  //}
431 
432  if (!hasErrors)
433  {
434  break;
435  }
436 
437 
438  if (debug&meshRefinement::MESH)
439  {
440  errorFaces.instance() = timeName();
441  Pout<< "Writing all faces in error to faceSet "
442  << errorFaces.objectPath() << nl << endl;
443  errorFaces.write();
444  }
445 
446 
447  // Check any master cells for using any of the error faces
448  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
449 
450  DynamicList<label> mastersToRestore(allFaceSets.size());
451 
452  forAll(allFaceSets, seti)
453  {
454  const label masterFacei = faceCombiner.masterFace()[seti];
455 
456  if (masterFacei != -1)
457  {
458  const label masterCellII = mesh_.faceOwner()[masterFacei];
459 
460  const cell& cFaces = mesh_.cells()[masterCellII];
461 
462  forAll(cFaces, i)
463  {
464  if (errorFaces.found(cFaces[i]))
465  {
466  mastersToRestore.append(masterFacei);
467  break;
468  }
469  }
470  }
471  }
472  mastersToRestore.shrink();
473 
474  const label nRestore = returnReduce
475  (
476  mastersToRestore.size(),
477  sumOp<label>()
478  );
479 
480  Info<< "Masters that need to be restored:"
481  << nRestore << endl;
482 
483  if (debug&meshRefinement::MESH)
484  {
485  faceSet restoreSet(mesh_, "mastersToRestore", mastersToRestore);
486  restoreSet.instance() = timeName();
487  Pout<< "Writing all " << mastersToRestore.size()
488  << " masterfaces to be restored to set "
489  << restoreSet.objectPath() << endl;
490  restoreSet.write();
491  }
492 
493 
494  if (nRestore == 0)
495  {
496  break;
497  }
498 
499 
500  // Undo
501  // ~~~~
502 
503  if (debug)
504  {
505  const_cast<Time&>(mesh_.time())++;
506  }
507 
508  // Topology changes container
509  polyTopoChange meshMod(mesh_);
510 
511  // Merge all faces of a set into the first face of the set.
512  // Experimental:mark all points/faces/cells that have been restored.
513  Map<label> restoredPoints(0);
514  Map<label> restoredFaces(0);
515  Map<label> restoredCells(0);
516 
517  faceCombiner.setUnrefinement
518  (
519  mastersToRestore,
520  meshMod,
521  restoredPoints,
522  restoredFaces,
523  restoredCells
524  );
525 
526  // Change the mesh (no inflation)
528  meshMod.changeMesh(mesh_, false, true);
529 
530  // Update fields
531  mesh_.topoChange(map);
532 
533  // Move mesh (since morphing does not do this)
534  if (map().hasMotionPoints())
535  {
536  mesh_.movePoints(map().preMotionPoints());
537  }
538  else
539  {
540  // Delete mesh volumes.
541  mesh_.clearOut();
542  }
543 
544 
545  // Reset the instance for if in overwrite mode
546  mesh_.setInstance(timeName());
547 
548  faceCombiner.topoChange(map);
549 
550  // Renumber restore maps
551  inplaceMapKey(map().reversePointMap(), restoredPoints);
552  inplaceMapKey(map().reverseFaceMap(), restoredFaces);
553  inplaceMapKey(map().reverseCellMap(), restoredCells);
554 
555 
556  // Get the kept faces that need to be recalculated.
557  // Merging two boundary faces might shift the cell centre
558  // (unless the faces are absolutely planar)
559  labelHashSet retestFaces(2*restoredFaces.size());
560 
561  forAllConstIter(Map<label>, restoredFaces, iter)
562  {
563  retestFaces.insert(iter.key());
564  }
565 
566  // Experimental:restore all points/face/cells in maps
567  topoChange
568  (
569  map,
570  growFaceCellFace(retestFaces),
571  restoredPoints,
572  restoredFaces,
573  restoredCells
574  );
575 
576  if (debug&meshRefinement::MESH)
577  {
578  // Check sync
579  Pout<< "Checking sync after restoring " << retestFaces.size()
580  << " faces." << endl;
581  checkData();
582 
583  Pout<< "Writing merged-faces mesh to time "
584  << timeName() << nl << endl;
585  write();
586  }
587 
588  Info<< endl;
589  }
590  }
591  else
592  {
593  Info<< "No faces merged ..." << endl;
594  }
595 
596  return nFaceSets;
597 }
598 
599 
600 // Remove points. pointCanBeDeleted is parallel synchronised.
602 (
603  removePoints& pointRemover,
604  const boolList& pointCanBeDeleted
605 )
606 {
607  // Topology changes container
608  polyTopoChange meshMod(mesh_);
609 
610  pointRemover.setRefinement(pointCanBeDeleted, meshMod);
611 
612  // Change the mesh (no inflation)
613  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh_, false, true);
614 
615  // Update fields
616  mesh_.topoChange(map);
617 
618  // Move mesh (since morphing does not do this)
619  if (map().hasMotionPoints())
620  {
621  mesh_.movePoints(map().preMotionPoints());
622  }
623  else
624  {
625  // Delete mesh volumes.
626  mesh_.clearOut();
627  }
628 
629  // Reset the instance for if in overwrite mode
630  mesh_.setInstance(timeName());
631 
632  pointRemover.topoChange(map);
633 
634 
635  // Retest all affected faces and all the cells using them
636  labelHashSet retestFaces(pointRemover.savedFaceLabels().size());
637  forAll(pointRemover.savedFaceLabels(), i)
638  {
639  const label facei = pointRemover.savedFaceLabels()[i];
640  if (facei >= 0)
641  {
642  retestFaces.insert(facei);
643  }
644  }
645  topoChange(map, growFaceCellFace(retestFaces));
646 
647  if (debug)
648  {
649  // Check sync
650  Pout<< "Checking sync after removing points." << endl;
651  checkData();
652  }
653 
654  return map;
655 }
656 
657 
659 (
660  removePoints& pointRemover,
661  const labelList& facesToRestore
662 )
663 {
664  // Topology changes container
665  polyTopoChange meshMod(mesh_);
666 
667  // Determine sets of points and faces to restore
668  labelList localFaces, localPoints;
669  pointRemover.getUnrefimentSet
670  (
671  facesToRestore,
672  localFaces,
673  localPoints
674  );
675 
676  // Undo the changes on the faces that are in error.
677  pointRemover.setUnrefinement
678  (
679  localFaces,
680  localPoints,
681  meshMod
682  );
683 
684  // Change the mesh (no inflation)
685  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh_, false, true);
686 
687  // Update fields
688  mesh_.topoChange(map);
689 
690  // Move mesh (since morphing does not do this)
691  if (map().hasMotionPoints())
692  {
693  mesh_.movePoints(map().preMotionPoints());
694  }
695  else
696  {
697  // Delete mesh volumes.
698  mesh_.clearOut();
699  }
700 
701  // Reset the instance for if in overwrite mode
702  mesh_.setInstance(timeName());
703 
704  pointRemover.topoChange(map);
705 
706  labelHashSet retestFaces(2*facesToRestore.size());
707  forAll(facesToRestore, i)
708  {
709  const label facei = map().reverseFaceMap()[facesToRestore[i]];
710  if (facei >= 0)
711  {
712  retestFaces.insert(facei);
713  }
714  }
715  topoChange(map, growFaceCellFace(retestFaces));
716 
717  if (debug)
718  {
719  // Check sync
720  Pout<< "Checking sync after restoring points on "
721  << facesToRestore.size() << " faces." << endl;
722  checkData();
723  }
724 
725  return map;
726 }
727 
728 
729 // Collect all faces that are both in candidateFaces and in the set.
730 // If coupled face also collects the coupled face.
732 (
733  const labelList& candidateFaces,
734  const labelHashSet& set
735 ) const
736 {
737  // Has face been selected?
738  boolList selected(mesh_.nFaces(), false);
739 
740  forAll(candidateFaces, i)
741  {
742  const label facei = candidateFaces[i];
743 
744  if (set.found(facei))
745  {
746  selected[facei] = true;
747  }
748  }
749  syncTools::syncFaceList
750  (
751  mesh_,
752  selected,
753  orEqOp<bool>() // combine operator
754  );
755 
756  labelList selectedFaces(findIndices(selected, true));
757 
758  return selectedFaces;
759 }
760 
761 
762 // Pick up faces of cells of faces in set.
764 (
765  const labelHashSet& set
766 ) const
767 {
768  boolList selected(mesh_.nFaces(), false);
769 
770  forAllConstIter(faceSet, set, iter)
771  {
772  const label facei = iter.key();
773  const label own = mesh_.faceOwner()[facei];
774 
775  const cell& ownFaces = mesh_.cells()[own];
776  forAll(ownFaces, ownFacei)
777  {
778  selected[ownFaces[ownFacei]] = true;
779  }
780 
781  if (mesh_.isInternalFace(facei))
782  {
783  const label nbr = mesh_.faceNeighbour()[facei];
784 
785  const cell& nbrFaces = mesh_.cells()[nbr];
786  forAll(nbrFaces, nbrFacei)
787  {
788  selected[nbrFaces[nbrFacei]] = true;
789  }
790  }
791  }
792  syncTools::syncFaceList
793  (
794  mesh_,
795  selected,
796  orEqOp<bool>() // combine operator
797  );
798  return findIndices(selected, true);
799 }
800 
801 
802 // Remove points not used by any face or points used by only two faces where
803 // the edges are in line
805 (
806  const scalar minCos,
807  const dictionary& motionDict
808 )
809 {
810  Info<< nl
811  << "Merging all points on surface that" << nl
812  << "- are used by only two boundary faces and" << nl
813  << "- make an angle with a cosine of more than " << minCos
814  << "." << nl << endl;
815 
816  // Point removal analysis engine with undo
817  removePoints pointRemover(mesh_, true);
818 
819  // Count usage of points
820  boolList pointCanBeDeleted;
821  label nRemove = pointRemover.countPointUsage(minCos, pointCanBeDeleted);
822 
823  if (nRemove > 0)
824  {
825  Info<< "Removing " << nRemove
826  << " straight edge points ..." << nl << endl;
827 
828  // Remove points
829  // ~~~~~~~~~~~~~
830 
831  doRemovePoints(pointRemover, pointCanBeDeleted);
832 
833 
834  for (label iteration = 0; iteration < 100; iteration++)
835  {
836  Info<< nl
837  << "Undo iteration " << iteration << nl
838  << "----------------" << endl;
839 
840 
841  // Check mesh for errors
842  // ~~~~~~~~~~~~~~~~~~~~~
843 
844  faceSet errorFaces
845  (
846  mesh_,
847  "errorFaces",
848  mesh_.nFaces()-mesh_.nInternalFaces()
849  );
850  bool hasErrors = motionSmoother::checkMesh
851  (
852  false, // report
853  mesh_,
854  motionDict,
855  errorFaces
856  );
857  // if (checkEdgeConnectivity)
858  //{
859  // Info<< "Checking edge-face connectivity (duplicate faces"
860  // << " or non-consecutive shared vertices)" << endl;
861  //
862  // label nOldSize = errorFaces.size();
863  //
864  // hasErrors =
865  // mesh_.checkFaceFaces
866  // (
867  // false,
868  // &errorFaces
869  // )
870  // || hasErrors;
871  //
872  // Info<< "Detected additional "
873  // << returnReduce(errorFaces.size()-nOldSize,sumOp<label>())
874  // << " faces with illegal face-face connectivity"
875  // << endl;
876  //}
877 
878  if (!hasErrors)
879  {
880  break;
881  }
882 
883  if (debug&meshRefinement::MESH)
884  {
885  errorFaces.instance() = timeName();
886  Pout<< "**Writing all faces in error to faceSet "
887  << errorFaces.objectPath() << nl << endl;
888  errorFaces.write();
889  }
890 
891  labelList masterErrorFaces
892  (
893  collectFaces
894  (
895  pointRemover.savedFaceLabels(),
896  errorFaces
897  )
898  );
899 
900  const label n = returnReduce
901  (
902  masterErrorFaces.size(),
903  sumOp<label>()
904  );
905 
906  Info<< "Detected " << n
907  << " error faces on boundaries that have been merged."
908  << " These will be restored to their original faces." << nl
909  << endl;
910 
911  if (n == 0)
912  {
913  if (hasErrors)
914  {
915  Info<< "Detected "
916  << returnReduce(errorFaces.size(), sumOp<label>())
917  << " error faces in mesh."
918  << " Restoring neighbours of faces in error." << nl
919  << endl;
920 
921  labelList expandedErrorFaces
922  (
923  growFaceCellFace
924  (
925  errorFaces
926  )
927  );
928 
929  doRestorePoints(pointRemover, expandedErrorFaces);
930  }
931 
932  break;
933  }
934 
935  doRestorePoints(pointRemover, masterErrorFaces);
936  }
937 
938  if (debug&meshRefinement::MESH)
939  {
940  const_cast<Time&>(mesh_.time())++;
941  Pout<< "Writing merged-edges mesh to time "
942  << timeName() << nl << endl;
943  write();
944  }
945  }
946  else
947  {
948  Info<< "No straight edges simplified and no points removed ..." << endl;
949  }
950 
951  return nRemove;
952 }
953 
954 
955 // ************************************************************************* //
void inplaceMapKey(const labelUList &oldToNew, Container &)
Recreate with mapped keys. Do not map elements with negative key.
void setUnrefinement(const labelList &localFaces, const labelList &localPoints, polyTopoChange &)
Restore selected faces and vertices.
Definition: removePoints.C:770
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
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.
virtual Ostream & write(const char)=0
Write character.
A list of face labels.
Definition: faceSet.H:48
void setUnrefinement(const labelList &masterFaces, polyTopoChange &meshMod, Map< label > &restoredPoints, Map< label > &restoredFaces, Map< label > &restoredCells)
Play commands into polyTopoChange to reinsert original faces.
Definition: combineFaces.C:837
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
void topoChange(const polyTopoChangeMap &)
Force recalculation of locally stored data on topological change.
Definition: combineFaces.C:788
label mergePatchFacesUndo(const scalar minCos, const scalar concaveCos, const labelHashSet &patchIDs, const dictionary &motionDict, const labelList &preserveFaces)
Merge coplanar faces. preserveFaces is != -1 for faces.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
void getUnrefimentSet(const labelList &undoFaces, labelList &localFaces, labelList &localPoints) const
Given set of faces to restore calculates a consistent set of.
Definition: removePoints.C:558
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
fileName objectPath() const
Return complete path + object name.
Definition: regIOobject.H:159
Holds information (coordinate and normal) regarding nearest wall point.
const labelList & savedFaceLabels() const
If undoable: affected face labels. Already restored faces.
Definition: removePoints.H:111
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurrences of given element. Linear search.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
labelList collectFaces(const labelList &candidateFaces, const labelHashSet &set) const
labelListList getMergeSets(const scalar featureCos, const scalar minConcaveCos, const labelHashSet &patchIDs, const labelHashSet &boundaryCells) const
Extract lists of all (non-coupled) boundary faces on selected.
Definition: combineFaces.C:305
label mergeEdgesUndo(const scalar minCos, const dictionary &motionDict)
Merge edges, maintain mesh quality. Return global number.
Combines boundary faces into single face. The faces get the patch of the first face (&#39;the master&#39;) ...
Definition: combineFaces.H:55
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
void write(std::ostream &os, const bool binary, List< floatScalar > &fField)
Write floats ascii or binary.
word timeName
Definition: getTimeIndex.H:3
List< label > labelList
A List of labels.
Definition: labelList.H:56
autoPtr< polyTopoChangeMap > doRemovePoints(removePoints &pointRemover, const boolList &pointCanBeDeleted)
void setRefinement(const labelListList &, polyTopoChange &)
Play commands into polyTopoChange to combine faces. Gets.
Definition: combineFaces.C:563
static const char nl
Definition: Ostream.H:260
void setRefinement(const boolList &, polyTopoChange &)
Play commands into polyTopoChange to remove points. Gets.
Definition: removePoints.C:296
const labelList & masterFace() const
If undoable: masterface for every set.
Definition: combineFaces.H:137
label countPointUsage(const scalar minCos, boolList &pointCanBeDeleted) const
Mark in pointCanBeDeleted the points that can be deleted.
Definition: removePoints.C:145
const labelList & savedPointLabels() const
If undoable: set of original point labels of stored points.
Definition: combineFaces.H:143
void topoChange(const polyTopoChangeMap &)
Force recalculation of locally stored data on topological change.
Definition: removePoints.C:456
labelList growFaceCellFace(const labelHashSet &set) const
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:57
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Direct mesh changes based on v1.3 polyTopoChange syntax.
messageStream Info
label n
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
Removes selected points from mesh and updates faces using these points.
Definition: removePoints.H:58
fileName & instance() const
Return the instance directory, constant, system, <time> etc.
Definition: IOobject.C:355
virtual bool write(const bool write=true) const
Write using setting from DB.
bool found
autoPtr< polyTopoChangeMap > doRestorePoints(removePoints &pointRemover, const labelList &facesToRestore)