meshRefinementRefine.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
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 "trackedParticle.H"
28 #include "syncTools.H"
29 #include "Time.H"
30 #include "refinementSurfaces.H"
31 #include "refinementFeatures.H"
32 #include "shellSurfaces.H"
33 #include "faceSet.H"
34 #include "decompositionMethod.H"
35 #include "fvMeshDistribute.H"
36 #include "polyTopoChange.H"
37 #include "mapDistributePolyMesh.H"
38 #include "Cloud.H"
39 //#include "globalIndex.H"
40 #include "OBJstream.H"
41 #include "cellSet.H"
42 #include "treeDataCell.H"
43 
44 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
45 
46 namespace Foam
47 {
48  //- To compare normals
49  static bool less(const vector& x, const vector& y)
50  {
51  for (direction i = 0; i < vector::nComponents; i++)
52  {
53  if (x[i] < y[i])
54  {
55  return true;
56  }
57  else if (x[i] > y[i])
58  {
59  return false;
60  }
61  }
62  // All components the same
63  return false;
64  }
65 
66 
67  //- To compare normals
68  class normalLess
69  {
71 
72  public:
73 
74  normalLess(const vectorList& values)
75  :
76  values_(values)
77  {}
78 
79  bool operator()(const label a, const label b) const
80  {
81  return less(values_[a], values_[b]);
82  }
83  };
84 
85 
86  //- Template specialization for pTraits<labelList> so we can have fields
87  template<>
89  {
90 
91  public:
92 
93  //- Component type
95  };
96 
97  //- Template specialization for pTraits<labelList> so we can have fields
98  template<>
100  {
101 
102  public:
103 
104  //- Component type
106  };
107 }
108 
109 
110 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
111 
112 // Get faces (on the new mesh) that have in some way been affected by the
113 // mesh change. Picks up all faces but those that are between two
114 // unrefined faces. (Note that of an unchanged face the edge still might be
115 // split but that does not change any face centre or cell centre.
117 (
118  const mapPolyMesh& map,
119  const labelList& oldCellsToRefine
120 )
121 {
122  const polyMesh& mesh = map.mesh();
123 
124  labelList changedFaces;
125 
126  // For reporting: number of masterFaces changed
127  label nMasterChanged = 0;
128  PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh));
129 
130  {
131  // Mark any face on a cell which has been added or changed
132  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
133  // Note that refining a face changes the face centre (for a warped face)
134  // which changes the cell centre. This again changes the cellcentre-
135  // cellcentre edge across all faces of the cell.
136  // Note: this does not happen for unwarped faces but unfortunately
137  // we don't have this information.
138 
139  const labelList& faceOwner = mesh.faceOwner();
140  const labelList& faceNeighbour = mesh.faceNeighbour();
141  const cellList& cells = mesh.cells();
142  const label nInternalFaces = mesh.nInternalFaces();
143 
144  // Mark refined cells on old mesh
145  PackedBoolList oldRefineCell(map.nOldCells());
146 
147  forAll(oldCellsToRefine, i)
148  {
149  oldRefineCell.set(oldCellsToRefine[i], 1u);
150  }
151 
152  // Mark refined faces
153  PackedBoolList refinedInternalFace(nInternalFaces);
154 
155  // 1. Internal faces
156 
157  for (label faceI = 0; faceI < nInternalFaces; faceI++)
158  {
159  label oldOwn = map.cellMap()[faceOwner[faceI]];
160  label oldNei = map.cellMap()[faceNeighbour[faceI]];
161 
162  if
163  (
164  oldOwn >= 0
165  && oldRefineCell.get(oldOwn) == 0u
166  && oldNei >= 0
167  && oldRefineCell.get(oldNei) == 0u
168  )
169  {
170  // Unaffected face since both neighbours were not refined.
171  }
172  else
173  {
174  refinedInternalFace.set(faceI, 1u);
175  }
176  }
177 
178 
179  // 2. Boundary faces
180 
181  boolList refinedBoundaryFace(mesh.nFaces()-nInternalFaces, false);
182 
183  forAll(mesh.boundaryMesh(), patchI)
184  {
185  const polyPatch& pp = mesh.boundaryMesh()[patchI];
186 
187  label faceI = pp.start();
188 
189  forAll(pp, i)
190  {
191  label oldOwn = map.cellMap()[faceOwner[faceI]];
192 
193  if (oldOwn >= 0 && oldRefineCell.get(oldOwn) == 0u)
194  {
195  // owner did exist and wasn't refined.
196  }
197  else
198  {
199  refinedBoundaryFace[faceI-nInternalFaces] = true;
200  }
201  faceI++;
202  }
203  }
204 
205  // Synchronise refined face status
206  syncTools::syncBoundaryFaceList
207  (
208  mesh,
209  refinedBoundaryFace,
210  orEqOp<bool>()
211  );
212 
213 
214  // 3. Mark all faces affected by refinement. Refined faces are in
215  // - refinedInternalFace
216  // - refinedBoundaryFace
217  boolList changedFace(mesh.nFaces(), false);
218 
219  forAll(refinedInternalFace, faceI)
220  {
221  if (refinedInternalFace.get(faceI) == 1u)
222  {
223  const cell& ownFaces = cells[faceOwner[faceI]];
224  forAll(ownFaces, ownI)
225  {
226  changedFace[ownFaces[ownI]] = true;
227  }
228  const cell& neiFaces = cells[faceNeighbour[faceI]];
229  forAll(neiFaces, neiI)
230  {
231  changedFace[neiFaces[neiI]] = true;
232  }
233  }
234  }
235 
236  forAll(refinedBoundaryFace, i)
237  {
238  if (refinedBoundaryFace[i])
239  {
240  const cell& ownFaces = cells[faceOwner[i+nInternalFaces]];
241  forAll(ownFaces, ownI)
242  {
243  changedFace[ownFaces[ownI]] = true;
244  }
245  }
246  }
247 
248  syncTools::syncFaceList
249  (
250  mesh,
251  changedFace,
252  orEqOp<bool>()
253  );
254 
255 
256  // Now we have in changedFace marked all affected faces. Pack.
257  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
258 
259  changedFaces = findIndices(changedFace, true);
260 
261  // Count changed master faces.
262  nMasterChanged = 0;
263 
264  forAll(changedFace, faceI)
265  {
266  if (changedFace[faceI] && isMasterFace[faceI])
267  {
268  nMasterChanged++;
269  }
270  }
271 
272  }
273 
274  if (debug&meshRefinement::MESH)
275  {
276  Pout<< "getChangedFaces : Detected "
277  << " local:" << changedFaces.size()
278  << " global:" << returnReduce(nMasterChanged, sumOp<label>())
279  << " changed faces out of " << mesh.globalData().nTotalFaces()
280  << endl;
281 
282  faceSet changedFacesSet(mesh, "changedFaces", changedFaces);
283  Pout<< "getChangedFaces : Writing " << changedFaces.size()
284  << " changed faces to faceSet " << changedFacesSet.name()
285  << endl;
286  changedFacesSet.write();
287  }
288 
289  return changedFaces;
290 }
291 
292 
293 // Mark cell for refinement (if not already marked). Return false if
294 // refinelimit hit. Keeps running count (in nRefine) of cells marked for
295 // refinement
297 (
298  const label markValue,
299  const label nAllowRefine,
300 
301  label& cellValue,
302  label& nRefine
303 )
304 {
305  if (cellValue == -1)
306  {
307  cellValue = markValue;
308  nRefine++;
309  }
310 
311  return nRefine <= nAllowRefine;
312 }
313 
314 
316 (
317  const pointField& keepPoints,
318  labelList& maxFeatureLevel
319 ) const
320 {
321  // We want to refine all cells containing a feature edge.
322  // - don't want to search over whole mesh
323  // - don't want to build octree for whole mesh
324  // - so use tracking to follow the feature edges
325  //
326  // 1. find non-manifold points on feature edges (i.e. start of feature edge
327  // or 'knot')
328  // 2. seed particle starting at keepPoint going to this non-manifold point
329  // 3. track particles to their non-manifold point
330  //
331  // 4. track particles across their connected feature edges, marking all
332  // visited cells with their level (through trackingData)
333  // 5. do 4 until all edges have been visited.
334 
335 
336  // Find all start cells of features. Is done by tracking from keepPoint.
337  Cloud<trackedParticle> startPointCloud
338  (
339  mesh_,
340  "startPointCloud",
342  );
343 
344 
345  // Features are identical on all processors. Number them so we know
346  // what to seed. Do this on only the processor that
347  // holds the keepPoint.
348 
349  forAll(keepPoints, i)
350  {
351  const point& keepPoint = keepPoints[i];
352 
353  label cellI = -1;
354  label tetFaceI = -1;
355  label tetPtI = -1;
356 
357 
358  // Force construction of search tree even if processor holds no
359  // cells
360  (void)mesh_.cellTree();
361  if (mesh_.nCells())
362  {
363  mesh_.findCellFacePt(keepPoint, cellI, tetFaceI, tetPtI);
364  }
365 
366  if (cellI != -1)
367  {
368  // I am the processor that holds the keepPoint
369 
370  forAll(features_, featI)
371  {
372  const edgeMesh& featureMesh = features_[featI];
373  const label featureLevel = features_.levels()[featI][0];
374  const labelListList& pointEdges = featureMesh.pointEdges();
375 
376  // Find regions on edgeMesh
377  labelList edgeRegion;
378  label nRegions = featureMesh.regions(edgeRegion);
379 
380 
381  PackedBoolList regionVisited(nRegions);
382 
383 
384  // 1. Seed all 'knots' in edgeMesh
385 
386 
387  forAll(pointEdges, pointI)
388  {
389  if (pointEdges[pointI].size() != 2)
390  {
391  if (debug&meshRefinement::FEATURESEEDS)
392  {
393  Pout<< "Adding particle from point:" << pointI
394  << " coord:" << featureMesh.points()[pointI]
395  << " since number of emanating edges:"
396  << pointEdges[pointI].size()
397  << endl;
398  }
399 
400  // Non-manifold point. Create particle.
401  startPointCloud.addParticle
402  (
403  new trackedParticle
404  (
405  mesh_,
406  keepPoint,
407  cellI,
408  tetFaceI,
409  tetPtI,
410  featureMesh.points()[pointI], // endpos
411  featureLevel, // level
412  featI, // featureMesh
413  pointI, // end point
414  -1 // feature edge
415  )
416  );
417 
418  // Mark
419  if (pointEdges[pointI].size() > 0)
420  {
421  label e0 = pointEdges[pointI][0];
422  label regionI = edgeRegion[e0];
423  regionVisited[regionI] = 1u;
424  }
425  }
426  }
427 
428 
429  // 2. Any regions that have not been visited at all? These can
430  // only be circular regions!
431  forAll(featureMesh.edges(), edgeI)
432  {
433  if (regionVisited.set(edgeRegion[edgeI], 1u))
434  {
435  const edge& e = featureMesh.edges()[edgeI];
436  label pointI = e.start();
437  if (debug&meshRefinement::FEATURESEEDS)
438  {
439  Pout<< "Adding particle from point:" << pointI
440  << " coord:" << featureMesh.points()[pointI]
441  << " on circular region:" << edgeRegion[edgeI]
442  << endl;
443  }
444 
445  // Non-manifold point. Create particle.
446  startPointCloud.addParticle
447  (
448  new trackedParticle
449  (
450  mesh_,
451  keepPoint,
452  cellI,
453  tetFaceI,
454  tetPtI,
455  featureMesh.points()[pointI], // endpos
456  featureLevel, // level
457  featI, // featureMesh
458  pointI, // end point
459  -1 // feature edge
460  )
461  );
462  }
463  }
464  }
465  }
466  }
467 
468 
469  // Largest refinement level of any feature passed through
470  maxFeatureLevel = labelList(mesh_.nCells(), -1);
471 
472  // Whether edge has been visited.
473  List<PackedBoolList> featureEdgeVisited(features_.size());
474 
475  forAll(features_, featI)
476  {
477  featureEdgeVisited[featI].setSize(features_[featI].edges().size());
478  featureEdgeVisited[featI] = 0u;
479  }
480 
481  // Database to pass into trackedParticle::move
483  (
484  startPointCloud,
485  maxFeatureLevel,
486  featureEdgeVisited
487  );
488 
489 
490  // Track all particles to their end position (= starting feature point)
491  // Note that the particle might have started on a different processor
492  // so this will transfer across nicely until we can start tracking proper.
493  scalar maxTrackLen = 2.0*mesh_.bounds().mag();
494 
495  if (debug&meshRefinement::FEATURESEEDS)
496  {
497  Pout<< "Tracking " << startPointCloud.size()
498  << " particles over distance " << maxTrackLen
499  << " to find the starting cell" << endl;
500  }
501  startPointCloud.move(td, maxTrackLen);
502 
503 
504  // Reset levels
505  maxFeatureLevel = -1;
506  forAll(features_, featI)
507  {
508  featureEdgeVisited[featI] = 0u;
509  }
510 
511 
513  (
514  mesh_,
515  "featureCloud",
517  );
518 
519  if (debug&meshRefinement::FEATURESEEDS)
520  {
521  Pout<< "Constructing cloud for cell marking" << endl;
522  }
523 
524  forAllIter(Cloud<trackedParticle>, startPointCloud, iter)
525  {
526  const trackedParticle& startTp = iter();
527 
528  label featI = startTp.i();
529  label pointI = startTp.j();
530 
531  const edgeMesh& featureMesh = features_[featI];
532  const labelList& pEdges = featureMesh.pointEdges()[pointI];
533 
534  // Now shoot particles down all pEdges.
535  forAll(pEdges, pEdgeI)
536  {
537  label edgeI = pEdges[pEdgeI];
538 
539  if (featureEdgeVisited[featI].set(edgeI, 1u))
540  {
541  // Unvisited edge. Make the particle go to the other point
542  // on the edge.
543 
544  const edge& e = featureMesh.edges()[edgeI];
545  label otherPointI = e.otherVertex(pointI);
546 
547  trackedParticle* tp(new trackedParticle(startTp));
548  tp->end() = featureMesh.points()[otherPointI];
549  tp->j() = otherPointI;
550  tp->k() = edgeI;
551 
552  if (debug&meshRefinement::FEATURESEEDS)
553  {
554  Pout<< "Adding particle for point:" << pointI
555  << " coord:" << tp->position()
556  << " feature:" << featI
557  << " to track to:" << tp->end()
558  << endl;
559  }
560 
561  cloud.addParticle(tp);
562  }
563  }
564  }
565 
566  startPointCloud.clear();
567 
568 
569  while (true)
570  {
571  // Track all particles to their end position.
572  if (debug&meshRefinement::FEATURESEEDS)
573  {
574  Pout<< "Tracking " << cloud.size()
575  << " particles over distance " << maxTrackLen
576  << " to mark cells" << endl;
577  }
578  cloud.move(td, maxTrackLen);
579 
580  // Make particle follow edge.
582  {
583  trackedParticle& tp = iter();
584 
585  label featI = tp.i();
586  label pointI = tp.j();
587 
588  const edgeMesh& featureMesh = features_[featI];
589  const labelList& pEdges = featureMesh.pointEdges()[pointI];
590 
591  // Particle now at pointI. Check connected edges to see which one
592  // we have to visit now.
593 
594  bool keepParticle = false;
595 
596  forAll(pEdges, i)
597  {
598  label edgeI = pEdges[i];
599 
600  if (featureEdgeVisited[featI].set(edgeI, 1u))
601  {
602  // Unvisited edge. Make the particle go to the other point
603  // on the edge.
604 
605  const edge& e = featureMesh.edges()[edgeI];
606  label otherPointI = e.otherVertex(pointI);
607 
608  tp.end() = featureMesh.points()[otherPointI];
609  tp.j() = otherPointI;
610  tp.k() = edgeI;
611  keepParticle = true;
612  break;
613  }
614  }
615 
616  if (!keepParticle)
617  {
618  // Particle at 'knot' where another particle already has been
619  // seeded. Delete particle.
620  cloud.deleteParticle(tp);
621  }
622  }
623 
624 
625  if (debug&meshRefinement::FEATURESEEDS)
626  {
627  Pout<< "Remaining particles " << cloud.size() << endl;
628  }
629 
630  if (returnReduce(cloud.size(), sumOp<label>()) == 0)
631  {
632  break;
633  }
634  }
635 
636 
637 
638  //if (debug&meshRefinement::FEATURESEEDS)
639  //{
640  // forAll(maxFeatureLevel, cellI)
641  // {
642  // if (maxFeatureLevel[cellI] != -1)
643  // {
644  // Pout<< "Feature went through cell:" << cellI
645  // << " coord:" << mesh_.cellCentres()[cellI]
646  // << " leve:" << maxFeatureLevel[cellI]
647  // << endl;
648  // }
649  // }
650  //}
651 }
652 
653 
654 // Calculates list of cells to refine based on intersection with feature edge.
656 (
657  const pointField& keepPoints,
658  const label nAllowRefine,
659 
661  label& nRefine
662 ) const
663 {
664  // Largest refinement level of any feature passed through
665  labelList maxFeatureLevel;
666  markFeatureCellLevel(keepPoints, maxFeatureLevel);
667 
668  // See which cells to refine. maxFeatureLevel will hold highest level
669  // of any feature edge that passed through.
670 
671  const labelList& cellLevel = meshCutter_.cellLevel();
672 
673  label oldNRefine = nRefine;
674 
675  forAll(maxFeatureLevel, cellI)
676  {
677  if (maxFeatureLevel[cellI] > cellLevel[cellI])
678  {
679  // Mark
680  if
681  (
682  !markForRefine
683  (
684  0, // surface (n/a)
685  nAllowRefine,
686  refineCell[cellI],
687  nRefine
688  )
689  )
690  {
691  // Reached limit
692  break;
693  }
694  }
695  }
696 
697  if
698  (
699  returnReduce(nRefine, sumOp<label>())
700  > returnReduce(nAllowRefine, sumOp<label>())
701  )
702  {
703  Info<< "Reached refinement limit." << endl;
704  }
705 
706  return returnReduce(nRefine-oldNRefine, sumOp<label>());
707 }
708 
709 
710 // Mark cells for distance-to-feature based refinement.
712 (
713  const label nAllowRefine,
714 
716  label& nRefine
717 ) const
718 {
719  const labelList& cellLevel = meshCutter_.cellLevel();
720  const pointField& cellCentres = mesh_.cellCentres();
721 
722  // Detect if there are any distance shells
723  if (features_.maxDistance() <= 0.0)
724  {
725  return 0;
726  }
727 
728  label oldNRefine = nRefine;
729 
730  // Collect cells to test
731  pointField testCc(cellLevel.size()-nRefine);
732  labelList testLevels(cellLevel.size()-nRefine);
733  label testI = 0;
734 
735  forAll(cellLevel, cellI)
736  {
737  if (refineCell[cellI] == -1)
738  {
739  testCc[testI] = cellCentres[cellI];
740  testLevels[testI] = cellLevel[cellI];
741  testI++;
742  }
743  }
744 
745  // Do test to see whether cells are inside/outside shell with higher level
746  labelList maxLevel;
747  features_.findHigherLevel(testCc, testLevels, maxLevel);
748 
749  // Mark for refinement. Note that we didn't store the original cellID so
750  // now just reloop in same order.
751  testI = 0;
752  forAll(cellLevel, cellI)
753  {
754  if (refineCell[cellI] == -1)
755  {
756  if (maxLevel[testI] > testLevels[testI])
757  {
758  bool reachedLimit = !markForRefine
759  (
760  maxLevel[testI], // mark with any positive value
761  nAllowRefine,
762  refineCell[cellI],
763  nRefine
764  );
765 
766  if (reachedLimit)
767  {
768  if (debug)
769  {
770  Pout<< "Stopped refining internal cells"
771  << " since reaching my cell limit of "
772  << mesh_.nCells()+7*nRefine << endl;
773  }
774  break;
775  }
776  }
777  testI++;
778  }
779  }
780 
781  if
782  (
783  returnReduce(nRefine, sumOp<label>())
784  > returnReduce(nAllowRefine, sumOp<label>())
785  )
786  {
787  Info<< "Reached refinement limit." << endl;
788  }
789 
790  return returnReduce(nRefine-oldNRefine, sumOp<label>());
791 }
792 
793 
794 // Mark cells for non-surface intersection based refinement.
796 (
797  const label nAllowRefine,
798 
800  label& nRefine
801 ) const
802 {
803  const labelList& cellLevel = meshCutter_.cellLevel();
804  const pointField& cellCentres = mesh_.cellCentres();
805 
806  label oldNRefine = nRefine;
807 
808  // Collect cells to test
809  pointField testCc(cellLevel.size()-nRefine);
810  labelList testLevels(cellLevel.size()-nRefine);
811  label testI = 0;
812 
813  forAll(cellLevel, cellI)
814  {
815  if (refineCell[cellI] == -1)
816  {
817  testCc[testI] = cellCentres[cellI];
818  testLevels[testI] = cellLevel[cellI];
819  testI++;
820  }
821  }
822 
823  // Do test to see whether cells are inside/outside shell with higher level
824  labelList maxLevel;
825  shells_.findHigherLevel(testCc, testLevels, maxLevel);
826 
827  // Mark for refinement. Note that we didn't store the original cellID so
828  // now just reloop in same order.
829  testI = 0;
830  forAll(cellLevel, cellI)
831  {
832  if (refineCell[cellI] == -1)
833  {
834  if (maxLevel[testI] > testLevels[testI])
835  {
836  bool reachedLimit = !markForRefine
837  (
838  maxLevel[testI], // mark with any positive value
839  nAllowRefine,
840  refineCell[cellI],
841  nRefine
842  );
843 
844  if (reachedLimit)
845  {
846  if (debug)
847  {
848  Pout<< "Stopped refining internal cells"
849  << " since reaching my cell limit of "
850  << mesh_.nCells()+7*nRefine << endl;
851  }
852  break;
853  }
854  }
855  testI++;
856  }
857  }
858 
859  if
860  (
861  returnReduce(nRefine, sumOp<label>())
862  > returnReduce(nAllowRefine, sumOp<label>())
863  )
864  {
865  Info<< "Reached refinement limit." << endl;
866  }
867 
868  return returnReduce(nRefine-oldNRefine, sumOp<label>());
869 }
870 
871 
873 (
875  label& nRefine
876 ) const
877 {
878  const labelList& cellLevel = meshCutter_.cellLevel();
879  const pointField& cellCentres = mesh_.cellCentres();
880 
881  label oldNRefine = nRefine;
882 
883  // Collect cells to test
884  pointField testCc(nRefine);
885  labelList testLevels(nRefine);
886  label testI = 0;
887 
888  forAll(cellLevel, cellI)
889  {
890  if (refineCell[cellI] >= 0)
891  {
892  testCc[testI] = cellCentres[cellI];
893  testLevels[testI] = cellLevel[cellI];
894  testI++;
895  }
896  }
897 
898  // Do test to see whether cells are inside/outside shell with higher level
899  labelList levelShell;
900  limitShells_.findLevel(testCc, testLevels, levelShell);
901 
902  // Mark for refinement. Note that we didn't store the original cellID so
903  // now just reloop in same order.
904  testI = 0;
905  forAll(cellLevel, cellI)
906  {
907  if (refineCell[cellI] >= 0)
908  {
909  if (levelShell[testI] != -1)
910  {
911  refineCell[cellI] = -1;
912  nRefine--;
913  }
914  testI++;
915  }
916  }
917 
918  return returnReduce(oldNRefine-nRefine, sumOp<label>());
919 }
920 
921 
922 // Collect faces that are intersected and whose neighbours aren't yet marked
923 // for refinement.
925 (
926  const labelList& refineCell
927 ) const
928 {
929  labelList testFaces(mesh_.nFaces());
930 
931  label nTest = 0;
932 
933  forAll(surfaceIndex_, faceI)
934  {
935  if (surfaceIndex_[faceI] != -1)
936  {
937  label own = mesh_.faceOwner()[faceI];
938 
939  if (mesh_.isInternalFace(faceI))
940  {
941  label nei = mesh_.faceNeighbour()[faceI];
942 
943  if (refineCell[own] == -1 || refineCell[nei] == -1)
944  {
945  testFaces[nTest++] = faceI;
946  }
947  }
948  else
949  {
950  if (refineCell[own] == -1)
951  {
952  testFaces[nTest++] = faceI;
953  }
954  }
955  }
956  }
957  testFaces.setSize(nTest);
958 
959  return testFaces;
960 }
961 
962 
963 // Mark cells for surface intersection based refinement.
965 (
966  const label nAllowRefine,
967  const labelList& neiLevel,
968  const pointField& neiCc,
969 
971  label& nRefine
972 ) const
973 {
974  const labelList& cellLevel = meshCutter_.cellLevel();
975 
976  label oldNRefine = nRefine;
977 
978  // Use cached surfaceIndex_ to detect if any intersection. If so
979  // re-intersect to determine level wanted.
980 
981  // Collect candidate faces
982  // ~~~~~~~~~~~~~~~~~~~~~~~
983 
984  labelList testFaces(getRefineCandidateFaces(refineCell));
985 
986  // Collect segments
987  // ~~~~~~~~~~~~~~~~
988 
989  pointField start(testFaces.size());
990  pointField end(testFaces.size());
991  labelList minLevel(testFaces.size());
992 
993  calcCellCellRays
994  (
995  neiCc,
996  neiLevel,
997  testFaces,
998  start,
999  end,
1000  minLevel
1001  );
1002 
1003 
1004  // Do test for higher intersections
1005  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1006 
1007  labelList surfaceHit;
1008  labelList surfaceMinLevel;
1009  surfaces_.findHigherIntersection
1010  (
1011  shells_,
1012  start,
1013  end,
1014  minLevel,
1015 
1016  surfaceHit,
1017  surfaceMinLevel
1018  );
1019 
1020 
1021  // Mark cells for refinement
1022  // ~~~~~~~~~~~~~~~~~~~~~~~~~
1023 
1024  forAll(testFaces, i)
1025  {
1026  label faceI = testFaces[i];
1027 
1028  label surfI = surfaceHit[i];
1029 
1030  if (surfI != -1)
1031  {
1032  // Found intersection with surface with higher wanted
1033  // refinement. Check if the level field on that surface
1034  // specifies an even higher level. Note:this is weird. Should
1035  // do the check with the surfaceMinLevel whilst intersecting the
1036  // surfaces?
1037 
1038  label own = mesh_.faceOwner()[faceI];
1039 
1040  if (surfaceMinLevel[i] > cellLevel[own])
1041  {
1042  // Owner needs refining
1043  if
1044  (
1045  !markForRefine
1046  (
1047  surfI,
1048  nAllowRefine,
1049  refineCell[own],
1050  nRefine
1051  )
1052  )
1053  {
1054  break;
1055  }
1056  }
1057 
1058  if (mesh_.isInternalFace(faceI))
1059  {
1060  label nei = mesh_.faceNeighbour()[faceI];
1061  if (surfaceMinLevel[i] > cellLevel[nei])
1062  {
1063  // Neighbour needs refining
1064  if
1065  (
1066  !markForRefine
1067  (
1068  surfI,
1069  nAllowRefine,
1070  refineCell[nei],
1071  nRefine
1072  )
1073  )
1074  {
1075  break;
1076  }
1077  }
1078  }
1079  }
1080  }
1081 
1082  if
1083  (
1084  returnReduce(nRefine, sumOp<label>())
1085  > returnReduce(nAllowRefine, sumOp<label>())
1086  )
1087  {
1088  Info<< "Reached refinement limit." << endl;
1089  }
1090 
1091  return returnReduce(nRefine-oldNRefine, sumOp<label>());
1092 }
1093 
1094 
1095 // Count number of matches of first argument in second argument
1098  const List<point>& normals1,
1099  const List<point>& normals2,
1100  const scalar tol
1101 ) const
1102 {
1103  label nMatches = 0;
1104 
1105  forAll(normals1, i)
1106  {
1107  const vector& n1 = normals1[i];
1108 
1109  forAll(normals2, j)
1110  {
1111  const vector& n2 = normals2[j];
1112 
1113  if (magSqr(n1-n2) < tol)
1114  {
1115  nMatches++;
1116  break;
1117  }
1118  }
1119  }
1120 
1121  return nMatches;
1122 }
1123 
1124 
1125 // Mark cells for surface curvature based refinement.
1128  const scalar curvature,
1129  const label nAllowRefine,
1130  const labelList& neiLevel,
1131  const pointField& neiCc,
1132 
1134  label& nRefine
1135 ) const
1136 {
1137  const labelList& cellLevel = meshCutter_.cellLevel();
1138  const pointField& cellCentres = mesh_.cellCentres();
1139 
1140  label oldNRefine = nRefine;
1141 
1142  // 1. local test: any cell on more than one surface gets refined
1143  // (if its current level is < max of the surface max level)
1144 
1145  // 2. 'global' test: any cell on only one surface with a neighbour
1146  // on a different surface gets refined (if its current level etc.)
1147 
1148 
1149  const PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh_));
1150 
1151 
1152  // Collect candidate faces (i.e. intersecting any surface and
1153  // owner/neighbour not yet refined.
1154  labelList testFaces(getRefineCandidateFaces(refineCell));
1155 
1156  // Collect segments
1157  pointField start(testFaces.size());
1158  pointField end(testFaces.size());
1159  labelList minLevel(testFaces.size());
1160 
1161  // Note: uses isMasterFace otherwise could be call to calcCellCellRays
1162  forAll(testFaces, i)
1163  {
1164  label faceI = testFaces[i];
1165 
1166  label own = mesh_.faceOwner()[faceI];
1167 
1168  if (mesh_.isInternalFace(faceI))
1169  {
1170  label nei = mesh_.faceNeighbour()[faceI];
1171 
1172  start[i] = cellCentres[own];
1173  end[i] = cellCentres[nei];
1174  minLevel[i] = min(cellLevel[own], cellLevel[nei]);
1175  }
1176  else
1177  {
1178  label bFaceI = faceI - mesh_.nInternalFaces();
1179 
1180  start[i] = cellCentres[own];
1181  end[i] = neiCc[bFaceI];
1182 
1183  if (!isMasterFace[faceI])
1184  {
1185  Swap(start[i], end[i]);
1186  }
1187 
1188  minLevel[i] = min(cellLevel[own], neiLevel[bFaceI]);
1189  }
1190  }
1191 
1192  // Extend segments a bit
1193  {
1194  const vectorField smallVec(ROOTSMALL*(end-start));
1195  start -= smallVec;
1196  end += smallVec;
1197  }
1198 
1199 
1200  // Test for all intersections (with surfaces of higher max level than
1201  // minLevel) and cache per cell the interesting inter
1202  labelListList cellSurfLevels(mesh_.nCells());
1203  List<vectorList> cellSurfNormals(mesh_.nCells());
1204 
1205  {
1206  // Per segment the normals of the surfaces
1207  List<vectorList> surfaceNormal;
1208  // Per segment the list of levels of the surfaces
1209  labelListList surfaceLevel;
1210 
1211  surfaces_.findAllHigherIntersections
1212  (
1213  start,
1214  end,
1215  minLevel, // max level of surface has to be bigger
1216  // than min level of neighbouring cells
1217 
1218  surfaces_.maxLevel(),
1219 
1220  surfaceNormal,
1221  surfaceLevel
1222  );
1223 
1224 
1225  // Sort the data according to surface location. This will guarantee
1226  // that on coupled faces both sides visit the intersections in
1227  // the same order so will decide the same
1228  labelList visitOrder;
1229  forAll(surfaceNormal, pointI)
1230  {
1231  vectorList& pNormals = surfaceNormal[pointI];
1232  labelList& pLevel = surfaceLevel[pointI];
1233 
1234  sortedOrder(pNormals, visitOrder, normalLess(pNormals));
1235 
1236  pNormals = List<point>(pNormals, visitOrder);
1237  pLevel = UIndirectList<label>(pLevel, visitOrder);
1238  }
1239 
1240  // Clear out unnecessary data
1241  start.clear();
1242  end.clear();
1243  minLevel.clear();
1244 
1245  // Convert face-wise data to cell.
1246  forAll(testFaces, i)
1247  {
1248  label faceI = testFaces[i];
1249  label own = mesh_.faceOwner()[faceI];
1250 
1251  const vectorList& fNormals = surfaceNormal[i];
1252  const labelList& fLevels = surfaceLevel[i];
1253 
1254  forAll(fNormals, hitI)
1255  {
1256  if (fLevels[hitI] > cellLevel[own])
1257  {
1258  cellSurfLevels[own].append(fLevels[hitI]);
1259  cellSurfNormals[own].append(fNormals[hitI]);
1260  }
1261 
1262  if (mesh_.isInternalFace(faceI))
1263  {
1264  label nei = mesh_.faceNeighbour()[faceI];
1265  if (fLevels[hitI] > cellLevel[nei])
1266  {
1267  cellSurfLevels[nei].append(fLevels[hitI]);
1268  cellSurfNormals[nei].append(fNormals[hitI]);
1269  }
1270  }
1271  }
1272  }
1273  }
1274 
1275 
1276 
1277  // Bit of statistics
1278  if (debug)
1279  {
1280  label nSet = 0;
1281  label nNormals = 9;
1282  forAll(cellSurfNormals, cellI)
1283  {
1284  const vectorList& normals = cellSurfNormals[cellI];
1285  if (normals.size())
1286  {
1287  nSet++;
1288  nNormals += normals.size();
1289  }
1290  }
1291  reduce(nSet, sumOp<label>());
1292  reduce(nNormals, sumOp<label>());
1293  Info<< "markSurfaceCurvatureRefinement :"
1294  << " cells:" << mesh_.globalData().nTotalCells()
1295  << " of which with normals:" << nSet
1296  << " ; total normals stored:" << nNormals
1297  << endl;
1298  }
1299 
1300 
1301 
1302  bool reachedLimit = false;
1303 
1304 
1305  // 1. Check normals per cell
1306  // ~~~~~~~~~~~~~~~~~~~~~~~~~
1307 
1308  for
1309  (
1310  label cellI = 0;
1311  !reachedLimit && cellI < cellSurfNormals.size();
1312  cellI++
1313  )
1314  {
1315  const vectorList& normals = cellSurfNormals[cellI];
1316  const labelList& levels = cellSurfLevels[cellI];
1317 
1318  // n^2 comparison of all normals in a cell
1319  for (label i = 0; !reachedLimit && i < normals.size(); i++)
1320  {
1321  for (label j = i+1; !reachedLimit && j < normals.size(); j++)
1322  {
1323  if ((normals[i] & normals[j]) < curvature)
1324  {
1325  label maxLevel = max(levels[i], levels[j]);
1326 
1327  if (cellLevel[cellI] < maxLevel)
1328  {
1329  if
1330  (
1331  !markForRefine
1332  (
1333  maxLevel,
1334  nAllowRefine,
1335  refineCell[cellI],
1336  nRefine
1337  )
1338  )
1339  {
1340  if (debug)
1341  {
1342  Pout<< "Stopped refining since reaching my cell"
1343  << " limit of " << mesh_.nCells()+7*nRefine
1344  << endl;
1345  }
1346  reachedLimit = true;
1347  break;
1348  }
1349  }
1350  }
1351  }
1352  }
1353  }
1354 
1355 
1356 
1357  // 2. Find out a measure of surface curvature
1358  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1359  // Look at normals between neighbouring surfaces
1360  // Loop over all faces. Could only be checkFaces, except if they're coupled
1361 
1362  // Internal faces
1363  for
1364  (
1365  label faceI = 0;
1366  !reachedLimit && faceI < mesh_.nInternalFaces();
1367  faceI++
1368  )
1369  {
1370  label own = mesh_.faceOwner()[faceI];
1371  label nei = mesh_.faceNeighbour()[faceI];
1372 
1373  const vectorList& ownNormals = cellSurfNormals[own];
1374  const labelList& ownLevels = cellSurfLevels[own];
1375  const vectorList& neiNormals = cellSurfNormals[nei];
1376  const labelList& neiLevels = cellSurfLevels[nei];
1377 
1378 
1379  // Special case: owner normals set is a subset of the neighbour
1380  // normals. Do not do curvature refinement since other cell's normals
1381  // do not add any information. Avoids weird corner extensions of
1382  // refinement regions.
1383  bool ownIsSubset =
1384  countMatches(ownNormals, neiNormals)
1385  == ownNormals.size();
1386 
1387  bool neiIsSubset =
1388  countMatches(neiNormals, ownNormals)
1389  == neiNormals.size();
1390 
1391 
1392  if (!ownIsSubset && !neiIsSubset)
1393  {
1394  // n^2 comparison of between ownNormals and neiNormals
1395  for (label i = 0; !reachedLimit && i < ownNormals.size(); i++)
1396  {
1397  for (label j = 0; !reachedLimit && j < neiNormals.size(); j++)
1398  {
1399  // Have valid data on both sides. Check curvature.
1400  if ((ownNormals[i] & neiNormals[j]) < curvature)
1401  {
1402  // See which side to refine.
1403  if (cellLevel[own] < ownLevels[i])
1404  {
1405  if
1406  (
1407  !markForRefine
1408  (
1409  ownLevels[i],
1410  nAllowRefine,
1411  refineCell[own],
1412  nRefine
1413  )
1414  )
1415  {
1416  if (debug)
1417  {
1418  Pout<< "Stopped refining since reaching"
1419  << " my cell limit of "
1420  << mesh_.nCells()+7*nRefine << endl;
1421  }
1422  reachedLimit = true;
1423  break;
1424  }
1425  }
1426  if (cellLevel[nei] < neiLevels[j])
1427  {
1428  if
1429  (
1430  !markForRefine
1431  (
1432  neiLevels[j],
1433  nAllowRefine,
1434  refineCell[nei],
1435  nRefine
1436  )
1437  )
1438  {
1439  if (debug)
1440  {
1441  Pout<< "Stopped refining since reaching"
1442  << " my cell limit of "
1443  << mesh_.nCells()+7*nRefine << endl;
1444  }
1445  reachedLimit = true;
1446  break;
1447  }
1448  }
1449  }
1450  }
1451  }
1452  }
1453  }
1454 
1455 
1456  // Send over surface normal to neighbour cell.
1457  List<vectorList> neiSurfaceNormals;
1458  syncTools::swapBoundaryCellList(mesh_, cellSurfNormals, neiSurfaceNormals);
1459 
1460  // Boundary faces
1461  for
1462  (
1463  label faceI = mesh_.nInternalFaces();
1464  !reachedLimit && faceI < mesh_.nFaces();
1465  faceI++
1466  )
1467  {
1468  label own = mesh_.faceOwner()[faceI];
1469  label bFaceI = faceI - mesh_.nInternalFaces();
1470 
1471  const vectorList& ownNormals = cellSurfNormals[own];
1472  const labelList& ownLevels = cellSurfLevels[own];
1473  const vectorList& neiNormals = neiSurfaceNormals[bFaceI];
1474 
1475  // Special case: owner normals set is a subset of the neighbour
1476  // normals. Do not do curvature refinement since other cell's normals
1477  // do not add any information. Avoids weird corner extensions of
1478  // refinement regions.
1479  bool ownIsSubset =
1480  countMatches(ownNormals, neiNormals)
1481  == ownNormals.size();
1482 
1483  bool neiIsSubset =
1484  countMatches(neiNormals, ownNormals)
1485  == neiNormals.size();
1486 
1487 
1488  if (!ownIsSubset && !neiIsSubset)
1489  {
1490  // n^2 comparison of between ownNormals and neiNormals
1491  for (label i = 0; !reachedLimit && i < ownNormals.size(); i++)
1492  {
1493  for (label j = 0; !reachedLimit && j < neiNormals.size(); j++)
1494  {
1495  // Have valid data on both sides. Check curvature.
1496  if ((ownNormals[i] & neiNormals[j]) < curvature)
1497  {
1498  if (cellLevel[own] < ownLevels[i])
1499  {
1500  if
1501  (
1502  !markForRefine
1503  (
1504  ownLevels[i],
1505  nAllowRefine,
1506  refineCell[own],
1507  nRefine
1508  )
1509  )
1510  {
1511  if (debug)
1512  {
1513  Pout<< "Stopped refining since reaching"
1514  << " my cell limit of "
1515  << mesh_.nCells()+7*nRefine
1516  << endl;
1517  }
1518  reachedLimit = true;
1519  break;
1520  }
1521  }
1522  }
1523  }
1524  }
1525  }
1526  }
1527 
1528 
1529  if
1530  (
1531  returnReduce(nRefine, sumOp<label>())
1532  > returnReduce(nAllowRefine, sumOp<label>())
1533  )
1534  {
1535  Info<< "Reached refinement limit." << endl;
1536  }
1537 
1538  return returnReduce(nRefine-oldNRefine, sumOp<label>());
1539 }
1540 
1541 
1544  const scalar planarCos,
1545  const vector& point0,
1546  const vector& normal0,
1547 
1548  const vector& point1,
1549  const vector& normal1
1550 ) const
1551 {
1552  //- Hits differ and angles are oppositeish and
1553  // hits have a normal distance
1554  vector d = point1-point0;
1555  scalar magD = mag(d);
1556 
1557  if (magD > mergeDistance())
1558  {
1559  scalar cosAngle = (normal0 & normal1);
1560 
1561  vector avg = vector::zero;
1562  if (cosAngle < (-1+planarCos))
1563  {
1564  // Opposite normals
1565  avg = 0.5*(normal0-normal1);
1566  }
1567  else if (cosAngle > (1-planarCos))
1568  {
1569  avg = 0.5*(normal0+normal1);
1570  }
1571 
1572  if (avg != vector::zero)
1573  {
1574  avg /= mag(avg);
1575 
1576  // Check normal distance of intersection locations
1577  if (mag(avg&d) > mergeDistance())
1578  {
1579  return true;
1580  }
1581  else
1582  {
1583  return false;
1584  }
1585  }
1586  else
1587  {
1588  return false;
1589  }
1590  }
1591  else
1592  {
1593  return false;
1594  }
1595 }
1596 
1597 
1598 // Mark small gaps
1601  const scalar planarCos,
1602  const vector& point0,
1603  const vector& normal0,
1604 
1605  const vector& point1,
1606  const vector& normal1
1607 ) const
1608 {
1609  //- Hits differ and angles are oppositeish and
1610  // hits have a normal distance
1611  vector d = point1-point0;
1612  scalar magD = mag(d);
1613 
1614  if (magD > mergeDistance())
1615  {
1616  scalar cosAngle = (normal0 & normal1);
1617 
1618  vector avg = vector::zero;
1619  if (cosAngle < (-1+planarCos))
1620  {
1621  // Opposite normals
1622  avg = 0.5*(normal0-normal1);
1623  }
1624  else if (cosAngle > (1-planarCos))
1625  {
1626  avg = 0.5*(normal0+normal1);
1627  }
1628 
1629  if (avg != vector::zero)
1630  {
1631  avg /= mag(avg);
1632  d /= magD;
1633 
1634  // Check average normal with respect to intersection locations
1635  if (mag(avg&d) > Foam::cos(degToRad(45)))
1636  {
1637  return true;
1638  }
1639  else
1640  {
1641  return false;
1642  }
1643  }
1644  else
1645  {
1646  return false;
1647  }
1648  }
1649  else
1650  {
1651  return false;
1652  }
1653 }
1654 
1655 
1658  const scalar planarCos,
1659  const label nAllowRefine,
1660 
1661  const label surfaceLevel, // current intersection max level
1662  const vector& surfaceLocation, // current intersection location
1663  const vector& surfaceNormal, // current intersection normal
1664 
1665  const label cellI,
1666 
1667  label& cellMaxLevel, // cached max surface level for this cell
1668  vector& cellMaxLocation, // cached surface normal for this cell
1669  vector& cellMaxNormal, // cached surface normal for this cell
1670 
1672  label& nRefine
1673 ) const
1674 {
1675  const labelList& cellLevel = meshCutter_.cellLevel();
1676 
1677  // Test if surface applicable
1678  if (surfaceLevel > cellLevel[cellI])
1679  {
1680  if (cellMaxLevel == -1)
1681  {
1682  // First visit of cell. Store
1683  cellMaxLevel = surfaceLevel;
1684  cellMaxLocation = surfaceLocation;
1685  cellMaxNormal = surfaceNormal;
1686  }
1687  else
1688  {
1689  // Second or more visit.
1690  // Check if
1691  // - different location
1692  // - opposite surface
1693 
1694  bool closeSurfaces = isNormalGap
1695  (
1696  planarCos,
1697  cellMaxLocation,
1698  cellMaxNormal,
1700  surfaceNormal
1701  );
1702 
1703  // Set normal to that of highest surface. Not really necessary
1704  // over here but we reuse cellMax info when doing coupled faces.
1705  if (surfaceLevel > cellMaxLevel)
1706  {
1707  cellMaxLevel = surfaceLevel;
1708  cellMaxLocation = surfaceLocation;
1709  cellMaxNormal = surfaceNormal;
1710  }
1711 
1712 
1713  if (closeSurfaces)
1714  {
1715  //Pout<< "Found gap:" << nl
1716  // << " location:" << surfaceLocation
1717  // << "\tnormal :" << surfaceNormal << nl
1719  // << "\tnormal :" << cellMaxNormal << nl
1720  // << "\tcos :" << (surfaceNormal&cellMaxNormal) << nl
1721  // << endl;
1722 
1723  return markForRefine
1724  (
1725  surfaceLevel, // mark with any non-neg number.
1726  nAllowRefine,
1727  refineCell[cellI],
1728  nRefine
1729  );
1730  }
1731  }
1732  }
1733 
1734  // Did not reach refinement limit.
1735  return true;
1736 }
1737 
1738 
1741  const scalar planarCos,
1742  const label nAllowRefine,
1743  const labelList& neiLevel,
1744  const pointField& neiCc,
1745 
1747  label& nRefine
1748 ) const
1749 {
1750  const labelList& cellLevel = meshCutter_.cellLevel();
1751 
1752  label oldNRefine = nRefine;
1753 
1754  // 1. local test: any cell on more than one surface gets refined
1755  // (if its current level is < max of the surface max level)
1756 
1757  // 2. 'global' test: any cell on only one surface with a neighbour
1758  // on a different surface gets refined (if its current level etc.)
1759 
1760 
1761  // Collect candidate faces (i.e. intersecting any surface and
1762  // owner/neighbour not yet refined.
1763  labelList testFaces(getRefineCandidateFaces(refineCell));
1764 
1765  // Collect segments
1766  pointField start(testFaces.size());
1767  pointField end(testFaces.size());
1768  labelList minLevel(testFaces.size());
1769 
1770  calcCellCellRays
1771  (
1772  neiCc,
1773  neiLevel,
1774  testFaces,
1775  start,
1776  end,
1777  minLevel
1778  );
1779 
1780 
1781  // Test for all intersections (with surfaces of higher gap level than
1782  // minLevel) and cache per cell the max surface level and the local normal
1783  // on that surface.
1784  labelList cellMaxLevel(mesh_.nCells(), -1);
1785  vectorField cellMaxNormal(mesh_.nCells(), vector::zero);
1786  pointField cellMaxLocation(mesh_.nCells(), vector::zero);
1787 
1788  {
1789  // Per segment the normals of the surfaces
1791  List<vectorList> surfaceNormal;
1792  // Per segment the list of levels of the surfaces
1793  labelListList surfaceLevel;
1794 
1795  surfaces_.findAllHigherIntersections
1796  (
1797  start,
1798  end,
1799  minLevel, // gap level of surface has to be bigger
1800  // than min level of neighbouring cells
1801 
1802  surfaces_.gapLevel(),
1803 
1805  surfaceNormal,
1806  surfaceLevel
1807  );
1808  // Clear out unnecessary data
1809  start.clear();
1810  end.clear();
1811  minLevel.clear();
1812 
1814  //OBJstream str
1815  //(
1816  // mesh_.time().path()
1817  // / "findAllHigherIntersections_"
1818  // + mesh_.time().timeName()
1819  // + ".obj"
1820  //);
1822  //OBJstream str2
1823  //(
1824  // mesh_.time().path()
1825  // / "findAllHigherIntersections2_"
1826  // + mesh_.time().timeName()
1827  // + ".obj"
1828  //);
1829 
1830  forAll(testFaces, i)
1831  {
1832  label faceI = testFaces[i];
1833  label own = mesh_.faceOwner()[faceI];
1834 
1835  const labelList& fLevels = surfaceLevel[i];
1836  const vectorList& fPoints = surfaceLocation[i];
1837  const vectorList& fNormals = surfaceNormal[i];
1838 
1839  forAll(fLevels, hitI)
1840  {
1841  checkProximity
1842  (
1843  planarCos,
1844  nAllowRefine,
1845 
1846  fLevels[hitI],
1847  fPoints[hitI],
1848  fNormals[hitI],
1849 
1850  own,
1851  cellMaxLevel[own],
1852  cellMaxLocation[own],
1853  cellMaxNormal[own],
1854 
1855  refineCell,
1856  nRefine
1857  );
1858  }
1859 
1860  if (mesh_.isInternalFace(faceI))
1861  {
1862  label nei = mesh_.faceNeighbour()[faceI];
1863 
1864  forAll(fLevels, hitI)
1865  {
1866  checkProximity
1867  (
1868  planarCos,
1869  nAllowRefine,
1870 
1871  fLevels[hitI],
1872  fPoints[hitI],
1873  fNormals[hitI],
1874 
1875  nei,
1876  cellMaxLevel[nei],
1877  cellMaxLocation[nei],
1878  cellMaxNormal[nei],
1879 
1880  refineCell,
1881  nRefine
1882  );
1883  }
1884  }
1885  }
1886  }
1887 
1888  // 2. Find out a measure of surface curvature and region edges.
1889  // Send over surface region and surface normal to neighbour cell.
1890 
1891  labelList neiBndMaxLevel(mesh_.nFaces()-mesh_.nInternalFaces());
1892  pointField neiBndMaxLocation(mesh_.nFaces()-mesh_.nInternalFaces());
1893  vectorField neiBndMaxNormal(mesh_.nFaces()-mesh_.nInternalFaces());
1894 
1895  for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
1896  {
1897  label bFaceI = faceI-mesh_.nInternalFaces();
1898  label own = mesh_.faceOwner()[faceI];
1899 
1900  neiBndMaxLevel[bFaceI] = cellMaxLevel[own];
1901  neiBndMaxLocation[bFaceI] = cellMaxLocation[own];
1902  neiBndMaxNormal[bFaceI] = cellMaxNormal[own];
1903  }
1904  syncTools::swapBoundaryFaceList(mesh_, neiBndMaxLevel);
1905  syncTools::swapBoundaryFaceList(mesh_, neiBndMaxLocation);
1906  syncTools::swapBoundaryFaceList(mesh_, neiBndMaxNormal);
1907 
1908  // Loop over all faces. Could only be checkFaces.. except if they're coupled
1909 
1910  // Internal faces
1911  for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
1912  {
1913  label own = mesh_.faceOwner()[faceI];
1914  label nei = mesh_.faceNeighbour()[faceI];
1915 
1916  if (cellMaxLevel[own] != -1 && cellMaxLevel[nei] != -1)
1917  {
1918  // Have valid data on both sides. Check planarCos.
1919  if
1920  (
1921  isNormalGap
1922  (
1923  planarCos,
1924  cellMaxLocation[own],
1925  cellMaxNormal[own],
1926  cellMaxLocation[nei],
1927  cellMaxNormal[nei]
1928  )
1929  )
1930  {
1931  // See which side to refine
1932  if (cellLevel[own] < cellMaxLevel[own])
1933  {
1934  if
1935  (
1936  !markForRefine
1937  (
1938  cellMaxLevel[own],
1939  nAllowRefine,
1940  refineCell[own],
1941  nRefine
1942  )
1943  )
1944  {
1945  if (debug)
1946  {
1947  Pout<< "Stopped refining since reaching my cell"
1948  << " limit of " << mesh_.nCells()+7*nRefine
1949  << endl;
1950  }
1951  break;
1952  }
1953  }
1954 
1955  if (cellLevel[nei] < cellMaxLevel[nei])
1956  {
1957  if
1958  (
1959  !markForRefine
1960  (
1961  cellMaxLevel[nei],
1962  nAllowRefine,
1963  refineCell[nei],
1964  nRefine
1965  )
1966  )
1967  {
1968  if (debug)
1969  {
1970  Pout<< "Stopped refining since reaching my cell"
1971  << " limit of " << mesh_.nCells()+7*nRefine
1972  << endl;
1973  }
1974  break;
1975  }
1976  }
1977  }
1978  }
1979  }
1980  // Boundary faces
1981  for (label faceI = mesh_.nInternalFaces(); faceI < mesh_.nFaces(); faceI++)
1982  {
1983  label own = mesh_.faceOwner()[faceI];
1984  label bFaceI = faceI - mesh_.nInternalFaces();
1985 
1986  if (cellLevel[own] < cellMaxLevel[own] && neiBndMaxLevel[bFaceI] != -1)
1987  {
1988  // Have valid data on both sides. Check planarCos.
1989  if
1990  (
1991  isNormalGap
1992  (
1993  planarCos,
1994  cellMaxLocation[own],
1995  cellMaxNormal[own],
1996  neiBndMaxLocation[bFaceI],
1997  neiBndMaxNormal[bFaceI]
1998  )
1999  )
2000  {
2001  if
2002  (
2003  !markForRefine
2004  (
2005  cellMaxLevel[own],
2006  nAllowRefine,
2007  refineCell[own],
2008  nRefine
2009  )
2010  )
2011  {
2012  if (debug)
2013  {
2014  Pout<< "Stopped refining since reaching my cell"
2015  << " limit of " << mesh_.nCells()+7*nRefine
2016  << endl;
2017  }
2018  break;
2019  }
2020  }
2021  }
2022  }
2023 
2024  if
2025  (
2026  returnReduce(nRefine, sumOp<label>())
2027  > returnReduce(nAllowRefine, sumOp<label>())
2028  )
2029  {
2030  Info<< "Reached refinement limit." << endl;
2031  }
2032 
2033  return returnReduce(nRefine-oldNRefine, sumOp<label>());
2034 }
2035 
2036 
2037 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
2038 
2039 // Calculate list of cells to refine. Gets for any edge (start - end)
2040 // whether it intersects the surface. Does more accurate test and checks
2041 // the wanted level on the surface intersected.
2042 // Does approximate precalculation of how many cells can be refined before
2043 // hitting overall limit maxGlobalCells.
2046  const pointField& keepPoints,
2047  const scalar curvature,
2048  const scalar planarAngle,
2049 
2050  const bool featureRefinement,
2051  const bool featureDistanceRefinement,
2052  const bool internalRefinement,
2053  const bool surfaceRefinement,
2054  const bool curvatureRefinement,
2055  const bool smallFeatureRefinement,
2056  const bool gapRefinement,
2057  const bool bigGapRefinement,
2058  const bool spreadGapSize,
2059  const label maxGlobalCells,
2060  const label maxLocalCells
2061 ) const
2062 {
2063  label totNCells = mesh_.globalData().nTotalCells();
2064 
2065  labelList cellsToRefine;
2066 
2067  if (totNCells >= maxGlobalCells)
2068  {
2069  Info<< "No cells marked for refinement since reached limit "
2070  << maxGlobalCells << '.' << endl;
2071  }
2072  else
2073  {
2074  // Every cell I refine adds 7 cells. Estimate the number of cells
2075  // I am allowed to refine.
2076  // Assume perfect distribution so can only refine as much the fraction
2077  // of the mesh I hold. This prediction step prevents us having to do
2078  // lots of reduces to keep count of the total number of cells selected
2079  // for refinement.
2080 
2081  //scalar fraction = scalar(mesh_.nCells())/totNCells;
2082  //label myMaxCells = label(maxGlobalCells*fraction);
2083  //label nAllowRefine = (myMaxCells - mesh_.nCells())/7;
2085  //
2086  //Pout<< "refineCandidates:" << nl
2087  // << " total cells:" << totNCells << nl
2088  // << " local cells:" << mesh_.nCells() << nl
2089  // << " local fraction:" << fraction << nl
2090  // << " local allowable cells:" << myMaxCells << nl
2091  // << " local allowable refinement:" << nAllowRefine << nl
2092  // << endl;
2093 
2094  //- Disable refinement shortcut. nAllowRefine is per processor limit.
2095  label nAllowRefine = labelMax / Pstream::nProcs();
2096 
2097  // Marked for refinement (>= 0) or not (-1). Actual value is the
2098  // index of the surface it intersects.
2099  labelList refineCell(mesh_.nCells(), -1);
2100  label nRefine = 0;
2101 
2102 
2103  // Swap neighbouring cell centres and cell level
2104  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
2105  pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
2106  calcNeighbourData(neiLevel, neiCc);
2107 
2108 
2109  const scalar planarCos = Foam::cos(degToRad(planarAngle));
2110 
2111 
2112  // Cells pierced by feature lines
2113  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2114 
2115  if (featureRefinement)
2116  {
2117  label nFeatures = markFeatureRefinement
2118  (
2119  keepPoints,
2120  nAllowRefine,
2121 
2122  refineCell,
2123  nRefine
2124  );
2125 
2126  Info<< "Marked for refinement due to explicit features "
2127  << ": " << nFeatures << " cells." << endl;
2128  }
2129 
2130  // Inside distance-to-feature shells
2131  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2132 
2133  if (featureDistanceRefinement)
2134  {
2135  label nShell = markInternalDistanceToFeatureRefinement
2136  (
2137  nAllowRefine,
2138 
2139  refineCell,
2140  nRefine
2141  );
2142  Info<< "Marked for refinement due to distance to explicit features "
2143  ": " << nShell << " cells." << endl;
2144  }
2145 
2146  // Inside refinement shells
2147  // ~~~~~~~~~~~~~~~~~~~~~~~~
2148 
2149  if (internalRefinement)
2150  {
2151  label nShell = markInternalRefinement
2152  (
2153  nAllowRefine,
2154 
2155  refineCell,
2156  nRefine
2157  );
2158  Info<< "Marked for refinement due to refinement shells "
2159  << ": " << nShell << " cells." << endl;
2160  }
2161 
2162  // Refinement based on intersection of surface
2163  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2164 
2165  if (surfaceRefinement)
2166  {
2167  label nSurf = markSurfaceRefinement
2168  (
2169  nAllowRefine,
2170  neiLevel,
2171  neiCc,
2172 
2173  refineCell,
2174  nRefine
2175  );
2176  Info<< "Marked for refinement due to surface intersection "
2177  << ": " << nSurf << " cells." << endl;
2178 
2179  // Refine intersected-cells only inside gaps. See
2180  // markInternalGapRefinement to refine all cells inside gaps.
2181  if
2182  (
2183  planarCos >= -1
2184  && planarCos <= 1
2185  && max(shells_.maxGapLevel()) > 0
2186  )
2187  {
2188  label nGapSurf = markSurfaceGapRefinement
2189  (
2190  planarCos,
2191  nAllowRefine,
2192  neiLevel,
2193  neiCc,
2194 
2195  refineCell,
2196  nRefine
2197  );
2198  Info<< "Marked for refinement due to surface intersection"
2199  << " (at gaps)"
2200  << ": " << nGapSurf << " cells." << endl;
2201  }
2202  }
2203 
2204  // Refinement based on curvature of surface
2205  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2206 
2207  if
2208  (
2209  curvatureRefinement
2210  && (curvature >= -1 && curvature <= 1)
2211  && (surfaces_.minLevel() != surfaces_.maxLevel())
2212  )
2213  {
2214  label nCurv = markSurfaceCurvatureRefinement
2215  (
2216  curvature,
2217  nAllowRefine,
2218  neiLevel,
2219  neiCc,
2220 
2221  refineCell,
2222  nRefine
2223  );
2224  Info<< "Marked for refinement due to curvature/regions "
2225  << ": " << nCurv << " cells." << endl;
2226  }
2227 
2228 
2229  // Refinement based on features smaller than cell size
2230  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2231 
2232  if
2233  (
2234  smallFeatureRefinement
2235  && (planarCos >= -1 && planarCos <= 1)
2236  && max(shells_.maxGapLevel()) > 0
2237  )
2238  {
2239  label nGap = markSmallFeatureRefinement
2240  (
2241  planarCos,
2242  nAllowRefine,
2243  neiLevel,
2244  neiCc,
2245 
2246  refineCell,
2247  nRefine
2248  );
2249  Info<< "Marked for refinement due to close opposite surfaces "
2250  << ": " << nGap << " cells." << endl;
2251  }
2252 
2253 
2254  // Refinement based on gap (only neighbouring cells)
2255  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2256 
2257  if
2258  (
2259  gapRefinement
2260  && (planarCos >= -1 && planarCos <= 1)
2261  && (max(surfaces_.gapLevel()) > -1)
2262  )
2263  {
2264  Info<< "Specified gap level : " << max(surfaces_.gapLevel())
2265  << ", planar angle " << planarAngle << endl;
2266 
2267  label nGap = markProximityRefinement
2268  (
2269  planarCos,
2270  nAllowRefine,
2271  neiLevel,
2272  neiCc,
2273 
2274  refineCell,
2275  nRefine
2276  );
2277  Info<< "Marked for refinement due to close opposite surfaces "
2278  << ": " << nGap << " cells." << endl;
2279  }
2280 
2281 
2282  // Refinement based on gaps larger than cell size
2283  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2284 
2285  if
2286  (
2287  bigGapRefinement
2288  && (planarCos >= -1 && planarCos <= 1)
2289  && max(shells_.maxGapLevel()) > 0
2290  )
2291  {
2292  // Refine based on gap information provided by shell and nearest
2293  // surface
2294  labelList numGapCells;
2295  scalarField gapSize;
2296  label nGap = markInternalGapRefinement
2297  (
2298  planarCos,
2299  spreadGapSize,
2300  nAllowRefine,
2301 
2302  refineCell,
2303  nRefine,
2304  numGapCells,
2305  gapSize
2306  );
2307  Info<< "Marked for refinement due to opposite surfaces"
2308  << " "
2309  << ": " << nGap << " cells." << endl;
2310  }
2311 
2312 
2313  // Limit refinement
2314  // ~~~~~~~~~~~~~~~~
2315 
2316  {
2317  label nUnmarked = unmarkInternalRefinement(refineCell, nRefine);
2318  if (nUnmarked > 0)
2319  {
2320  Info<< "Unmarked for refinement due to limit shells"
2321  << " : " << nUnmarked << " cells." << endl;
2322  }
2323  }
2324 
2325 
2326 
2327  // Pack cells-to-refine
2328  // ~~~~~~~~~~~~~~~~~~~~
2329 
2330  cellsToRefine.setSize(nRefine);
2331  nRefine = 0;
2332 
2333  forAll(refineCell, cellI)
2334  {
2335  if (refineCell[cellI] != -1)
2336  {
2337  cellsToRefine[nRefine++] = cellI;
2338  }
2339  }
2340  }
2341 
2342  return cellsToRefine;
2343 }
2344 
2345 
2348  const labelList& cellsToRefine
2349 )
2350 {
2351  // Mesh changing engine.
2352  polyTopoChange meshMod(mesh_);
2353 
2354  // Play refinement commands into mesh changer.
2355  meshCutter_.setRefinement(cellsToRefine, meshMod);
2356 
2357  // Create mesh (no inflation), return map from old to new mesh.
2358  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false);
2359 
2360  // Update fields
2361  mesh_.updateMesh(map);
2362 
2363  // Optionally inflate mesh
2364  if (map().hasMotionPoints())
2365  {
2366  mesh_.movePoints(map().preMotionPoints());
2367  }
2368  else
2369  {
2370  // Delete mesh volumes.
2371  mesh_.clearOut();
2372  }
2373 
2374  // Reset the instance for if in overwrite mode
2375  mesh_.setInstance(timeName());
2376 
2377  // Update intersection info
2378  updateMesh(map, getChangedFaces(map, cellsToRefine));
2379 
2380  return map;
2381 }
2382 
2383 
2384 // Do refinement of consistent set of cells followed by truncation and
2385 // load balancing.
2389  const string& msg,
2390  decompositionMethod& decomposer,
2391  fvMeshDistribute& distributor,
2392  const labelList& cellsToRefine,
2393  const scalar maxLoadUnbalance
2394 )
2395 {
2396  // Do all refinement
2397  refine(cellsToRefine);
2398 
2399  if (debug&meshRefinement::MESH)
2400  {
2401  Pout<< "Writing refined but unbalanced " << msg
2402  << " mesh to time " << timeName() << endl;
2403  write
2404  (
2405  debugType(debug),
2406  writeType(writeLevel() | WRITEMESH),
2407  mesh_.time().path()/timeName()
2408  );
2409  Pout<< "Dumped debug data in = "
2410  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2411 
2412  // test all is still synced across proc patches
2413  checkData();
2414  }
2415 
2416  Info<< "Refined mesh in = "
2417  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2418  printMeshInfo(debug, "After refinement " + msg);
2419 
2420 
2421  // Load balancing
2422  // ~~~~~~~~~~~~~~
2423 
2425 
2426  if (Pstream::nProcs() > 1)
2427  {
2428  scalar nIdealCells =
2429  mesh_.globalData().nTotalCells()
2430  / Pstream::nProcs();
2431 
2432  scalar unbalance = returnReduce
2433  (
2434  mag(1.0-mesh_.nCells()/nIdealCells),
2435  maxOp<scalar>()
2436  );
2437 
2438  if (unbalance <= maxLoadUnbalance)
2439  {
2440  Info<< "Skipping balancing since max unbalance " << unbalance
2441  << " is less than allowable " << maxLoadUnbalance
2442  << endl;
2443  }
2444  else
2445  {
2446  scalarField cellWeights(mesh_.nCells(), 1);
2447 
2448  distMap = balance
2449  (
2450  false, //keepZoneFaces
2451  false, //keepBaffles
2452  cellWeights,
2453  decomposer,
2454  distributor
2455  );
2456 
2457  Info<< "Balanced mesh in = "
2458  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2459 
2460  printMeshInfo(debug, "After balancing " + msg);
2461 
2462 
2463  if (debug&meshRefinement::MESH)
2464  {
2465  Pout<< "Writing balanced " << msg
2466  << " mesh to time " << timeName() << endl;
2467  write
2468  (
2469  debugType(debug),
2470  writeType(writeLevel() | WRITEMESH),
2471  mesh_.time().path()/timeName()
2472  );
2473  Pout<< "Dumped debug data in = "
2474  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2475 
2476  // test all is still synced across proc patches
2477  checkData();
2478  }
2479  }
2480  }
2481 
2482  return distMap;
2483 }
2484 
2485 
2486 // Do load balancing followed by refinement of consistent set of cells.
2490  const string& msg,
2491  decompositionMethod& decomposer,
2492  fvMeshDistribute& distributor,
2493  const labelList& initCellsToRefine,
2494  const scalar maxLoadUnbalance
2495 )
2496 {
2497  labelList cellsToRefine(initCellsToRefine);
2498 
2499  //{
2500  // globalIndex globalCells(mesh_.nCells());
2501  //
2502  // Info<< "** Distribution before balancing/refining:" << endl;
2503  // for (label procI = 0; procI < Pstream::nProcs(); procI++)
2504  // {
2505  // Info<< " " << procI << '\t'
2506  // << globalCells.localSize(procI) << endl;
2507  // }
2508  // Info<< endl;
2509  //}
2510  //{
2511  // globalIndex globalCells(cellsToRefine.size());
2512  //
2513  // Info<< "** Cells to be refined:" << endl;
2514  // for (label procI = 0; procI < Pstream::nProcs(); procI++)
2515  // {
2516  // Info<< " " << procI << '\t'
2517  // << globalCells.localSize(procI) << endl;
2518  // }
2519  // Info<< endl;
2520  //}
2521 
2522 
2523  // Load balancing
2524  // ~~~~~~~~~~~~~~
2525 
2527 
2528  if (Pstream::nProcs() > 1)
2529  {
2530  // First check if we need to balance at all. Precalculate number of
2531  // cells after refinement and see what maximum difference is.
2532  scalar nNewCells = scalar(mesh_.nCells() + 7*cellsToRefine.size());
2533  scalar nIdealNewCells =
2534  returnReduce(nNewCells, sumOp<scalar>())
2535  / Pstream::nProcs();
2536  scalar unbalance = returnReduce
2537  (
2538  mag(1.0-nNewCells/nIdealNewCells),
2539  maxOp<scalar>()
2540  );
2541 
2542  if (unbalance <= maxLoadUnbalance)
2543  {
2544  Info<< "Skipping balancing since max unbalance " << unbalance
2545  << " is less than allowable " << maxLoadUnbalance
2546  << endl;
2547  }
2548  else
2549  {
2550  scalarField cellWeights(mesh_.nCells(), 1);
2551  forAll(cellsToRefine, i)
2552  {
2553  cellWeights[cellsToRefine[i]] += 7;
2554  }
2555 
2556  distMap = balance
2557  (
2558  false, //keepZoneFaces
2559  false, //keepBaffles
2560  cellWeights,
2561  decomposer,
2562  distributor
2563  );
2564 
2565  // Update cells to refine
2566  distMap().distributeCellIndices(cellsToRefine);
2567 
2568  Info<< "Balanced mesh in = "
2569  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2570  }
2571 
2572  //{
2573  // globalIndex globalCells(mesh_.nCells());
2574  //
2575  // Info<< "** Distribution after balancing:" << endl;
2576  // for (label procI = 0; procI < Pstream::nProcs(); procI++)
2577  // {
2578  // Info<< " " << procI << '\t'
2579  // << globalCells.localSize(procI) << endl;
2580  // }
2581  // Info<< endl;
2582  //}
2583 
2584  printMeshInfo(debug, "After balancing " + msg);
2585 
2586  if (debug&meshRefinement::MESH)
2587  {
2588  Pout<< "Writing balanced " << msg
2589  << " mesh to time " << timeName() << endl;
2590  write
2591  (
2592  debugType(debug),
2593  writeType(writeLevel() | WRITEMESH),
2594  mesh_.time().path()/timeName()
2595  );
2596  Pout<< "Dumped debug data in = "
2597  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2598 
2599  // test all is still synced across proc patches
2600  checkData();
2601  }
2602  }
2603 
2604 
2605  // Refinement
2606  // ~~~~~~~~~~
2607 
2608  refine(cellsToRefine);
2609 
2610  if (debug&meshRefinement::MESH)
2611  {
2612  Pout<< "Writing refined " << msg
2613  << " mesh to time " << timeName() << endl;
2614  write
2615  (
2616  debugType(debug),
2617  writeType(writeLevel() | WRITEMESH),
2618  mesh_.time().path()/timeName()
2619  );
2620  Pout<< "Dumped debug data in = "
2621  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2622 
2623  // test all is still synced across proc patches
2624  checkData();
2625  }
2626 
2627  Info<< "Refined mesh in = "
2628  << mesh_.time().cpuTimeIncrement() << " s" << endl;
2629 
2630  //{
2631  // globalIndex globalCells(mesh_.nCells());
2632  //
2633  // Info<< "** After refinement distribution:" << endl;
2634  // for (label procI = 0; procI < Pstream::nProcs(); procI++)
2635  // {
2636  // Info<< " " << procI << '\t'
2637  // << globalCells.localSize(procI) << endl;
2638  // }
2639  // Info<< endl;
2640  //}
2641 
2642  printMeshInfo(debug, "After refinement " + msg);
2643 
2644  return distMap;
2645 }
2646 
2647 
2648 // ************************************************************************* //
Foam::Cloud::addParticle
void addParticle(ParticleType *pPtr)
Transfer particle to cloud.
Definition: Cloud.C:162
shellSurfaces.H
Foam::meshRefinement::isNormalGap
bool isNormalGap(const scalar, const vector &, const vector &, const vector &, const vector &) const
Is local topology a small gap normal to the test vector.
Definition: meshRefinementRefine.C:1600
Foam::pTraits< vectorList >::cmptType
vectorList cmptType
Component type.
Definition: meshRefinementRefine.C:105
Foam::trackedParticle::trackingData
Class used to pass tracking data to the trackToFace function.
Definition: trackedParticle.H:79
Foam::maxOp
Definition: ops.H:172
Foam::PackedBoolList
A bit-packed bool list.
Definition: PackedBoolList.H:63
Foam::edgeMesh::regions
label regions(labelList &edgeRegion) const
Find connected regions. Set region number per edge.
Definition: edgeMesh.C:214
forAllIter
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:431
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:86
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::normalLess::normalLess
normalLess(const vectorList &values)
Definition: meshRefinementRefine.C:74
Foam::polyTopoChange::changeMesh
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
Definition: polyTopoChange.C:3039
Foam::less
static bool less(const vector &x, const vector &y)
To compare normals.
Definition: meshRefinementRefine.C:49
Foam::meshRefinement::markFeatureRefinement
label markFeatureRefinement(const pointField &keepPoints, const label nAllowRefine, labelList &refineCell, label &nRefine) const
Calculate list of cells to refine based on intersection of.
Definition: meshRefinementRefine.C:656
Foam::labelMax
static const label labelMax
Definition: label.H:62
Foam::PackedBoolList::set
void set(const PackedList< 1 > &)
Set specified bits.
Definition: PackedBoolList.C:169
Foam::meshRefinement::markFeatureCellLevel
void markFeatureCellLevel(const pointField &keepPoints, labelList &maxFeatureLevel) const
Mark every cell with level of feature passing through it.
Definition: meshRefinementRefine.C:316
polyTopoChange.H
Foam::surfaceLocation
Contains information about location on a triSurface:
Definition: surfaceLocation.H:60
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:97
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::meshRefinement::markProximityRefinement
label markProximityRefinement(const scalar curvature, const label nAllowRefine, const labelList &neiLevel, const pointField &neiCc, labelList &refineCell, label &nRefine) const
Mark cells for surface proximity based refinement.
Definition: meshRefinementRefine.C:1740
Cloud.H
Foam::meshRefinement::checkProximity
bool checkProximity(const scalar planarCos, const label nAllowRefine, const label surfaceLevel, const vector &surfaceLocation, const vector &surfaceNormal, const label cellI, label &cellMaxLevel, vector &cellMaxLocation, vector &cellMaxNormal, labelList &refineCell, label &nRefine) const
Mark cell if local a gap topology or.
Definition: meshRefinementRefine.C:1657
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::nComponents
@ nComponents
Number of components in this vector space.
Definition: VectorSpace.H:88
Foam::regIOobject::write
virtual bool write() const
Write using setting from DB.
Definition: regIOobjectWrite.C:126
tp
volScalarField tp(IOobject("tp", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE), mesh, dimensionedScalar("tp", dimensionSet(0, 0, 1, 0, 0, 0, 0), 0))
Foam::faceSet
A list of face labels.
Definition: faceSet.H:48
Foam::pTraits< labelList >::cmptType
labelList cmptType
Component type.
Definition: meshRefinementRefine.C:94
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
decompositionMethod.H
Foam::meshRefinement::balanceAndRefine
autoPtr< mapDistributePolyMesh > balanceAndRefine(const string &msg, decompositionMethod &decomposer, fvMeshDistribute &distributor, const labelList &cellsToRefine, const scalar maxLoadUnbalance)
Balance before refining some cells.
Definition: meshRefinementRefine.C:2489
Foam::Cloud::clear
void clear()
Definition: Cloud.H:250
refinementFeatures.H
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::meshRefinement::refineAndBalance
autoPtr< mapDistributePolyMesh > refineAndBalance(const string &msg, decompositionMethod &decomposer, fvMeshDistribute &distributor, const labelList &cellsToRefine, const scalar maxLoadUnbalance)
Refine some cells and rebalance.
Definition: meshRefinementRefine.C:2388
syncTools.H
Foam::meshRefinement::unmarkInternalRefinement
label unmarkInternalRefinement(labelList &refineCell, label &nRefine) const
Unmark cells for refinement based on limit-shells. Return number.
Definition: meshRefinementRefine.C:873
Foam::meshRefinement::getChangedFaces
static labelList getChangedFaces(const mapPolyMesh &, const labelList &oldCellsToRefine)
Find out which faces have changed given cells (old mesh labels)
Definition: meshRefinementRefine.C:117
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
Foam::meshRefinement::markInternalRefinement
label markInternalRefinement(const label nAllowRefine, labelList &refineCell, label &nRefine) const
Mark cells for refinement-shells based refinement.
Definition: meshRefinementRefine.C:796
Foam::meshRefinement::refineCandidates
labelList refineCandidates(const pointField &keepPoints, const scalar curvature, const scalar planarAngle, const bool featureRefinement, const bool featureDistanceRefinement, const bool internalRefinement, const bool surfaceRefinement, const bool curvatureRefinement, const bool smallFeatureRefinement, const bool gapRefinement, const bool bigGapRefinement, const bool spreadGapSize, const label maxGlobalCells, const label maxLocalCells) const
Calculate list of cells to refine.
Definition: meshRefinementRefine.C:2045
mapDistributePolyMesh.H
Foam::sortedOrder
void sortedOrder(const UList< T > &, labelList &order)
Generate the (stable) sort order for the list.
Definition: ListOpsTemplates.C:179
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:43
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Foam::IDLList
Intrusive doubly-linked list.
Definition: IDLList.H:47
Foam::constant::physicoChemical::b
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:28
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
Foam::trackedParticle::i
label i() const
Transported label.
Definition: trackedParticle.H:171
Foam::meshRefinement::markSurfaceRefinement
label markSurfaceRefinement(const label nAllowRefine, const labelList &neiLevel, const pointField &neiCc, labelList &refineCell, label &nRefine) const
Mark cells for surface intersection based refinement.
Definition: meshRefinementRefine.C:965
Foam::List::append
void append(const T &)
Append an element at the end of the list.
Foam::Info
messageStream Info
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
refinementSurfaces.H
Foam::normalLess::values_
const vectorList & values_
Definition: meshRefinementRefine.C:70
Foam::Cloud::size
label size() const
Definition: Cloud.H:175
MESH
@ MESH
Definition: extrudeMesh.C:60
Foam::meshRefinement::markInternalDistanceToFeatureRefinement
label markInternalDistanceToFeatureRefinement(const label nAllowRefine, labelList &refineCell, label &nRefine) const
Mark cells for distance-to-feature based refinement.
Definition: meshRefinementRefine.C:712
Foam::edgeMesh::points
const pointField & points() const
Return points.
Definition: edgeMeshI.H:39
faceSet.H
Foam::meshRefinement::markForRefine
static bool markForRefine(const label markValue, const label nAllowRefine, label &cellValue, label &nRefine)
Mark cell for refinement (if not already marked). Return false.
Definition: meshRefinementRefine.C:297
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobject.H:273
Foam::orEqOp
Definition: ops.H:82
Foam::edgeMesh::edges
const edgeList & edges() const
Return edges.
Definition: edgeMeshI.H:45
Foam::meshRefinement::getRefineCandidateFaces
labelList getRefineCandidateFaces(const labelList &refineCell) const
Collect faces that are intersected and whose neighbours aren't.
Definition: meshRefinementRefine.C:925
Foam::edgeMesh::pointEdges
const labelListList & pointEdges() const
Return edges.
Definition: edgeMeshI.H:51
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Foam::normalLess::operator()
bool operator()(const label a, const label b) const
Definition: meshRefinementRefine.C:79
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:18
meshRefinement.H
Foam::decompositionMethod
Abstract base class for decomposition.
Definition: decompositionMethod.H:48
Foam::meshRefinement::countMatches
label countMatches(const List< point > &normals1, const List< point > &normals2, const scalar tol=1e-6) const
Helper: count number of normals1 that are in normals2.
Definition: meshRefinementRefine.C:1097
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
treeDataCell.H
trackedParticle.H
Foam::PackedList::get
unsigned int get(const label) const
Get value at index I.
Definition: PackedListI.H:964
Foam::meshRefinement::markSurfaceCurvatureRefinement
label markSurfaceCurvatureRefinement(const scalar curvature, const label nAllowRefine, const labelList &neiLevel, const pointField &neiCc, labelList &refineCell, label &nRefine) const
Mark cells for surface curvature based refinement. Marks if.
Definition: meshRefinementRefine.C:1127
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:312
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::meshRefinement::isGap
bool isGap(const scalar, const vector &, const vector &, const vector &, const vector &) const
Is local topology a small gap?
Definition: meshRefinementRefine.C:1543
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::autoPtr
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
Foam::cloud
A cloud is a collection of lagrangian particles.
Definition: cloud.H:51
Foam::refineCell
Container with cells to refine. Refinement given as single direction.
Definition: refineCell.H:52
fvMeshDistribute.H
Foam::sumOp
Definition: ops.H:162
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::trackedParticle::j
label j() const
Transported label.
Definition: trackedParticle.H:183
Foam::Vector< scalar >
Foam::meshRefinement::writeType
writeType
Definition: meshRefinement.H:130
Foam::normalLess
To compare normals.
Definition: meshRefinementRefine.C:68
Foam::List< vector >
Foam::pTraits
Traits class for primitives.
Definition: pTraits.H:50
Foam::mapPolyMesh::nOldCells
label nOldCells() const
Number of old cells.
Definition: mapPolyMesh.H:383
Foam::Cloud< trackedParticle >
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: doubleFloat.H:94
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: List.C:379
timeName
word timeName
Definition: getTimeIndex.H:3
x
x
Definition: LISASMDCalcMethod2.H:52
Foam::direction
unsigned char direction
Definition: direction.H:43
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
Foam::UIndirectList
A List with indirect addressing.
Definition: fvMatrix.H:106
Foam::meshRefinement::refine
autoPtr< mapPolyMesh > refine(const labelList &cellsToRefine)
Refine some cells.
Definition: meshRefinementRefine.C:2347
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
cellSet.H
Foam::trackedParticle
Particle class that marks cells it passes through. Used to mark cells visited by feature edges.
Definition: trackedParticle.H:52
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::Swap
void Swap(T &a, T &b)
Definition: Swap.H:43
Foam::mapPolyMesh::mesh
const polyMesh & mesh() const
Return polyMesh.
Definition: mapPolyMesh.H:359
Foam::findIndices
labelList findIndices(const ListType &, typename ListType::const_reference, const label start=0)
Find all occurences of given element. Linear search.
Foam::edgeMesh
Points connected by edges.
Definition: edgeMesh.H:69
Foam::min
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Foam::fvMeshDistribute
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
Definition: fvMeshDistribute.H:70
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
write
Tcoeff write()
OBJstream.H
Foam::mapPolyMesh::cellMap
const labelList & cellMap() const
Old cell map.
Definition: mapPolyMesh.H:431
Foam::Cloud::move
void move(TrackData &td, const scalar trackTime)
Move the particles.
Definition: Cloud.C:187
y
scalar y
Definition: LISASMDCalcMethod1.H:14
Foam::degToRad
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
Definition: unitConversion.H:45
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:256
Foam::meshRefinement::debugType
debugType
Definition: meshRefinement.H:100