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