meshRefinement.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 |
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 "volMesh.H"
28 #include "volFields.H"
29 #include "surfaceMesh.H"
30 #include "syncTools.H"
31 #include "Time.H"
32 #include "refinementHistory.H"
33 #include "refinementSurfaces.H"
34 #include "refinementFeatures.H"
35 #include "decompositionMethod.H"
36 #include "regionSplit.H"
37 #include "fvMeshDistribute.H"
38 #include "indirectPrimitivePatch.H"
39 #include "polyTopoChange.H"
40 #include "removeCells.H"
41 #include "mapDistributePolyMesh.H"
42 #include "localPointRegion.H"
43 #include "pointMesh.H"
44 #include "pointFields.H"
45 #include "slipPointPatchFields.H"
49 #include "processorPointPatch.H"
50 #include "globalIndex.H"
51 #include "meshTools.H"
52 #include "OFstream.H"
53 #include "geomDecomp.H"
54 #include "Random.H"
55 #include "searchableSurfaces.H"
56 #include "treeBoundBox.H"
58 #include "fvMeshTools.H"
59 
60 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
61 
62 namespace Foam
63 {
64  defineTypeNameAndDebug(meshRefinement, 0);
65 
66  template<>
67  const char* Foam::NamedEnum
68  <
70  5
71  >::names[] =
72  {
73  "mesh",
74  //"scalarLevels",
75  "intersections",
76  "featureSeeds",
77  "attraction",
78  "layerInfo"
79  };
80 
81  template<>
82  const char* Foam::NamedEnum
83  <
85  1
86  >::names[] =
87  {
88  "layerInfo"
89  };
90 
91  template<>
92  const char* Foam::NamedEnum
93  <
95  4
96  >::names[] =
97  {
98  "mesh",
99  "scalarLevels",
100  "layerSets",
101  "layerFields"
102  };
103 
104 }
105 
108 
111 
114 
115 
116 Foam::meshRefinement::writeType Foam::meshRefinement::writeLevel_;
117 
118 Foam::meshRefinement::outputType Foam::meshRefinement::outputLevel_;
119 
120 
121 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
122 
123 void Foam::meshRefinement::calcNeighbourData
124 (
125  labelList& neiLevel,
126  pointField& neiCc
127 ) const
128 {
129  const labelList& cellLevel = meshCutter_.cellLevel();
130  const pointField& cellCentres = mesh_.cellCentres();
131 
132  label nBoundaryFaces = mesh_.nFaces() - mesh_.nInternalFaces();
133 
134  if (neiLevel.size() != nBoundaryFaces || neiCc.size() != nBoundaryFaces)
135  {
136  FatalErrorIn("meshRefinement::calcNeighbour(..)") << "nBoundaries:"
137  << nBoundaryFaces << " neiLevel:" << neiLevel.size()
138  << abort(FatalError);
139  }
140 
141  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
142 
143  labelHashSet addedPatchIDSet(meshedPatches());
144 
145  forAll(patches, patchI)
146  {
147  const polyPatch& pp = patches[patchI];
148 
149  const labelUList& faceCells = pp.faceCells();
150  const vectorField::subField faceCentres = pp.faceCentres();
151  const vectorField::subField faceAreas = pp.faceAreas();
152 
153  label bFaceI = pp.start()-mesh_.nInternalFaces();
154 
155  if (pp.coupled())
156  {
157  forAll(faceCells, i)
158  {
159  neiLevel[bFaceI] = cellLevel[faceCells[i]];
160  neiCc[bFaceI] = cellCentres[faceCells[i]];
161  bFaceI++;
162  }
163  }
164  else if (addedPatchIDSet.found(patchI))
165  {
166  // Face was introduced from cell-cell intersection. Try to
167  // reconstruct other side cell(centre). Three possibilities:
168  // - cells same size.
169  // - preserved cell smaller. Not handled.
170  // - preserved cell larger.
171  forAll(faceCells, i)
172  {
173  // Extrapolate the face centre.
174  vector fn = faceAreas[i];
175  fn /= mag(fn)+VSMALL;
176 
177  label own = faceCells[i];
178  label ownLevel = cellLevel[own];
179  label faceLevel = meshCutter_.getAnchorLevel(pp.start()+i);
180 
181  // Normal distance from face centre to cell centre
182  scalar d = ((faceCentres[i] - cellCentres[own]) & fn);
183  if (faceLevel > ownLevel)
184  {
185  // Other cell more refined. Adjust normal distance
186  d *= 0.5;
187  }
188  neiLevel[bFaceI] = faceLevel;
189  // Calculate other cell centre by extrapolation
190  neiCc[bFaceI] = faceCentres[i] + d*fn;
191  bFaceI++;
192  }
193  }
194  else
195  {
196  forAll(faceCells, i)
197  {
198  neiLevel[bFaceI] = cellLevel[faceCells[i]];
199  neiCc[bFaceI] = faceCentres[i];
200  bFaceI++;
201  }
202  }
203  }
204 
205  // Swap coupled boundaries. Apply separation to cc since is coordinate.
207  syncTools::swapBoundaryFaceList(mesh_, neiLevel);
208 }
209 
210 
211 // Find intersections of edges (given by their two endpoints) with surfaces.
212 // Returns first intersection if there are more than one.
213 void Foam::meshRefinement::updateIntersections(const labelList& changedFaces)
214 {
215  const pointField& cellCentres = mesh_.cellCentres();
216 
217  // Stats on edges to test. Count proc faces only once.
218  PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh_));
219 
220  {
221  label nMasterFaces = 0;
222  forAll(isMasterFace, faceI)
223  {
224  if (isMasterFace.get(faceI) == 1)
225  {
226  nMasterFaces++;
227  }
228  }
229  reduce(nMasterFaces, sumOp<label>());
230 
231  label nChangedFaces = 0;
232  forAll(changedFaces, i)
233  {
234  if (isMasterFace.get(changedFaces[i]) == 1)
235  {
236  nChangedFaces++;
237  }
238  }
239  reduce(nChangedFaces, sumOp<label>());
240 
241  Info<< "Edge intersection testing:" << nl
242  << " Number of edges : " << nMasterFaces << nl
243  << " Number of edges to retest : " << nChangedFaces
244  << endl;
245  }
246 
247 
248  // Get boundary face centre and level. Coupled aware.
249  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
250  pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
251  calcNeighbourData(neiLevel, neiCc);
252 
253  // Collect segments we want to test for
254  pointField start(changedFaces.size());
255  pointField end(changedFaces.size());
256 
257  forAll(changedFaces, i)
258  {
259  label faceI = changedFaces[i];
260  label own = mesh_.faceOwner()[faceI];
261 
262  start[i] = cellCentres[own];
263  if (mesh_.isInternalFace(faceI))
264  {
265  end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
266  }
267  else
268  {
269  end[i] = neiCc[faceI-mesh_.nInternalFaces()];
270  }
271  }
272 
273  // Extend segments a bit
274  {
275  const vectorField smallVec(ROOTSMALL*(end-start));
276  start -= smallVec;
277  end += smallVec;
278  }
279 
280 
281  // Do tests in one go
282  labelList surfaceHit;
283  {
284  labelList surfaceLevel;
285  surfaces_.findHigherIntersection
286  (
287  start,
288  end,
289  labelList(start.size(), -1), // accept any intersection
290  surfaceHit,
291  surfaceLevel
292  );
293  }
294 
295  // Keep just surface hit
296  forAll(surfaceHit, i)
297  {
298  surfaceIndex_[changedFaces[i]] = surfaceHit[i];
299  }
300 
301  // Make sure both sides have same information. This should be
302  // case in general since same vectors but just to make sure.
303  syncTools::syncFaceList(mesh_, surfaceIndex_, maxEqOp<label>());
304 
305  label nHits = countHits();
306  label nTotHits = returnReduce(nHits, sumOp<label>());
307 
308  Info<< " Number of intersected edges : " << nTotHits << endl;
309 
310  // Set files to same time as mesh
311  setInstance(mesh_.facesInstance());
312 }
313 
314 
316 (
317  const string& msg,
318  const polyMesh& mesh,
319  const List<scalar>& fld
320 )
321 {
322  if (fld.size() != mesh.nPoints())
323  {
325  (
326  "meshRefinement::testSyncPointList(const polyMesh&"
327  ", const List<scalar>&)"
328  ) << msg << endl
329  << "fld size:" << fld.size() << " mesh points:" << mesh.nPoints()
330  << abort(FatalError);
331  }
332 
333  Pout<< "Checking field " << msg << endl;
334  scalarField minFld(fld);
336  (
337  mesh,
338  minFld,
339  minEqOp<scalar>(),
340  GREAT
341  );
342  scalarField maxFld(fld);
344  (
345  mesh,
346  maxFld,
347  maxEqOp<scalar>(),
348  -GREAT
349  );
350  forAll(minFld, pointI)
351  {
352  const scalar& minVal = minFld[pointI];
353  const scalar& maxVal = maxFld[pointI];
354  if (mag(minVal-maxVal) > SMALL)
355  {
356  Pout<< msg << " at:" << mesh.points()[pointI] << nl
357  << " minFld:" << minVal << nl
358  << " maxFld:" << maxVal << nl
359  << endl;
360  }
361  }
362 }
363 
364 
366 (
367  const string& msg,
368  const polyMesh& mesh,
369  const List<point>& fld
370 )
371 {
372  if (fld.size() != mesh.nPoints())
373  {
375  (
376  "meshRefinement::testSyncPointList(const polyMesh&"
377  ", const List<point>&)"
378  ) << msg << endl
379  << "fld size:" << fld.size() << " mesh points:" << mesh.nPoints()
380  << abort(FatalError);
381  }
382 
383  Pout<< "Checking field " << msg << endl;
384  pointField minFld(fld);
386  (
387  mesh,
388  minFld,
390  point(GREAT, GREAT, GREAT)
391  );
392  pointField maxFld(fld);
394  (
395  mesh,
396  maxFld,
399  );
400  forAll(minFld, pointI)
401  {
402  const point& minVal = minFld[pointI];
403  const point& maxVal = maxFld[pointI];
404  if (mag(minVal-maxVal) > SMALL)
405  {
406  Pout<< msg << " at:" << mesh.points()[pointI] << nl
407  << " minFld:" << minVal << nl
408  << " maxFld:" << maxVal << nl
409  << endl;
410  }
411  }
412 }
413 
414 
416 {
417  Pout<< "meshRefinement::checkData() : Checking refinement structure."
418  << endl;
419  meshCutter_.checkMesh();
420 
421  Pout<< "meshRefinement::checkData() : Checking refinement levels."
422  << endl;
423  meshCutter_.checkRefinementLevels(1, labelList(0));
424 
425 
426  label nBnd = mesh_.nFaces()-mesh_.nInternalFaces();
427 
428  Pout<< "meshRefinement::checkData() : Checking synchronization."
429  << endl;
430 
431  // Check face centres
432  {
433  // Boundary face centres
434  pointField::subList boundaryFc
435  (
436  mesh_.faceCentres(),
437  nBnd,
438  mesh_.nInternalFaces()
439  );
440 
441  // Get neighbouring face centres
442  pointField neiBoundaryFc(boundaryFc);
444  (
445  mesh_,
446  neiBoundaryFc,
447  eqOp<point>()
448  );
449 
450  // Compare
451  testSyncBoundaryFaceList
452  (
453  mergeDistance_,
454  "testing faceCentres : ",
455  boundaryFc,
456  neiBoundaryFc
457  );
458  }
459  // Check meshRefinement
460  {
461  // Get boundary face centre and level. Coupled aware.
462  labelList neiLevel(nBnd);
463  pointField neiCc(nBnd);
464  calcNeighbourData(neiLevel, neiCc);
465 
466  // Collect segments we want to test for
467  pointField start(mesh_.nFaces());
468  pointField end(mesh_.nFaces());
469 
470  forAll(start, faceI)
471  {
472  start[faceI] = mesh_.cellCentres()[mesh_.faceOwner()[faceI]];
473 
474  if (mesh_.isInternalFace(faceI))
475  {
476  end[faceI] = mesh_.cellCentres()[mesh_.faceNeighbour()[faceI]];
477  }
478  else
479  {
480  end[faceI] = neiCc[faceI-mesh_.nInternalFaces()];
481  }
482  }
483 
484  // Extend segments a bit
485  {
486  const vectorField smallVec(ROOTSMALL*(end-start));
487  start -= smallVec;
488  end += smallVec;
489  }
490 
491 
492  // Do tests in one go
493  labelList surfaceHit;
494  {
495  labelList surfaceLevel;
496  surfaces_.findHigherIntersection
497  (
498  start,
499  end,
500  labelList(start.size(), -1), // accept any intersection
501  surfaceHit,
502  surfaceLevel
503  );
504  }
505  // Get the coupled hit
506  labelList neiHit
507  (
509  (
510  surfaceHit,
511  nBnd,
512  mesh_.nInternalFaces()
513  )
514  );
515  syncTools::swapBoundaryFaceList(mesh_, neiHit);
516 
517  // Check
518  forAll(surfaceHit, faceI)
519  {
520  if (surfaceIndex_[faceI] != surfaceHit[faceI])
521  {
522  if (mesh_.isInternalFace(faceI))
523  {
524  WarningIn("meshRefinement::checkData()")
525  << "Internal face:" << faceI
526  << " fc:" << mesh_.faceCentres()[faceI]
527  << " cached surfaceIndex_:" << surfaceIndex_[faceI]
528  << " current:" << surfaceHit[faceI]
529  << " ownCc:"
530  << mesh_.cellCentres()[mesh_.faceOwner()[faceI]]
531  << " neiCc:"
532  << mesh_.cellCentres()[mesh_.faceNeighbour()[faceI]]
533  << endl;
534  }
535  else if
536  (
537  surfaceIndex_[faceI]
538  != neiHit[faceI-mesh_.nInternalFaces()]
539  )
540  {
541  WarningIn("meshRefinement::checkData()")
542  << "Boundary face:" << faceI
543  << " fc:" << mesh_.faceCentres()[faceI]
544  << " cached surfaceIndex_:" << surfaceIndex_[faceI]
545  << " current:" << surfaceHit[faceI]
546  << " ownCc:"
547  << mesh_.cellCentres()[mesh_.faceOwner()[faceI]]
548  << " end:" << end[faceI]
549  << endl;
550  }
551  }
552  }
553  }
554  {
555  labelList::subList boundarySurface
556  (
557  surfaceIndex_,
558  mesh_.nFaces()-mesh_.nInternalFaces(),
559  mesh_.nInternalFaces()
560  );
561 
562  labelList neiBoundarySurface(boundarySurface);
564  (
565  mesh_,
566  neiBoundarySurface
567  );
568 
569  // Compare
570  testSyncBoundaryFaceList
571  (
572  0, // tolerance
573  "testing surfaceIndex() : ",
574  boundarySurface,
575  neiBoundarySurface
576  );
577  }
578 
579 
580  // Find duplicate faces
581  Pout<< "meshRefinement::checkData() : Counting duplicate faces."
582  << endl;
583 
584  labelList duplicateFace
585  (
587  (
588  mesh_,
589  identity(mesh_.nFaces()-mesh_.nInternalFaces())
590  + mesh_.nInternalFaces()
591  )
592  );
593 
594  // Count
595  {
596  label nDup = 0;
597 
598  forAll(duplicateFace, i)
599  {
600  if (duplicateFace[i] != -1)
601  {
602  nDup++;
603  }
604  }
605  nDup /= 2; // will have counted both faces of duplicate
606  Pout<< "meshRefinement::checkData() : Found " << nDup
607  << " duplicate pairs of faces." << endl;
608  }
609 }
610 
611 
613 {
614  meshCutter_.setInstance(inst);
615  surfaceIndex_.instance() = inst;
616 }
617 
618 
619 // Remove cells. Put exposedFaces (output of getExposedFaces(cellsToRemove))
620 // into exposedPatchIDs.
621 Foam::autoPtr<Foam::mapPolyMesh> Foam::meshRefinement::doRemoveCells
622 (
623  const labelList& cellsToRemove,
624  const labelList& exposedFaces,
625  const labelList& exposedPatchIDs,
626  removeCells& cellRemover
627 )
628 {
629  polyTopoChange meshMod(mesh_);
630 
631  // Arbitrary: put exposed faces into last patch.
632  cellRemover.setRefinement
633  (
634  cellsToRemove,
635  exposedFaces,
636  exposedPatchIDs,
637  meshMod
638  );
639 
640  // Change the mesh (no inflation)
641  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
642 
643  // Update fields
644  mesh_.updateMesh(map);
645 
646  // Move mesh (since morphing might not do this)
647  if (map().hasMotionPoints())
648  {
649  mesh_.movePoints(map().preMotionPoints());
650  }
651  else
652  {
653  // Delete mesh volumes. No other way to do this?
654  mesh_.clearOut();
655  }
656 
657  // Reset the instance for if in overwrite mode
658  mesh_.setInstance(timeName());
659  setInstance(mesh_.facesInstance());
660 
661  // Update local mesh data
662  cellRemover.updateMesh(map);
663 
664  // Update intersections. Recalculate intersections for exposed faces.
665  labelList newExposedFaces = renumber
666  (
667  map().reverseFaceMap(),
668  exposedFaces
669  );
670 
671  //Pout<< "removeCells : updating intersections for "
672  // << newExposedFaces.size() << " newly exposed faces." << endl;
673 
674  updateMesh(map, newExposedFaces);
675 
676  return map;
677 }
678 
679 
680 // Split faces
682 (
683  const labelList& splitFaces,
684  const labelPairList& splits
685 )
686 {
687  polyTopoChange meshMod(mesh_);
688 
689  forAll(splitFaces, i)
690  {
691  label faceI = splitFaces[i];
692  const face& f = mesh_.faces()[faceI];
693 
694 
695  // Split as start and end index in face
696  const labelPair& split = splits[i];
697 
698  label nVerts = split[1]-split[0];
699  if (nVerts < 0)
700  {
701  nVerts += f.size();
702  }
703  nVerts += 1;
704 
705 
706  // Split into f0, f1
707  face f0(nVerts);
708 
709  label fp = split[0];
710  forAll(f0, i)
711  {
712  f0[i] = f[fp];
713  fp = f.fcIndex(fp);
714  }
715 
716  face f1(f.size()-f0.size()+2);
717  fp = split[1];
718  forAll(f1, i)
719  {
720  f1[i] = f[fp];
721  fp = f.fcIndex(fp);
722  }
723 
724 
725  // Determine face properties
726  label own = mesh_.faceOwner()[faceI];
727  label nei = -1;
728  label patchI = -1;
729  if (faceI >= mesh_.nInternalFaces())
730  {
731  patchI = mesh_.boundaryMesh().whichPatch(faceI);
732  }
733  else
734  {
735  nei = mesh_.faceNeighbour()[faceI];
736  }
737 
738  label zoneI = mesh_.faceZones().whichZone(faceI);
739  bool zoneFlip = false;
740  if (zoneI != -1)
741  {
742  const faceZone& fz = mesh_.faceZones()[zoneI];
743  zoneFlip = fz.flipMap()[fz.whichFace(faceI)];
744  }
745 
746 
747 Pout<< "face:" << faceI << " verts:" << f
748  << " split into f0:" << f0
749  << " f1:" << f1 << endl;
750 
751  // Change/add faces
752  meshMod.modifyFace
753  (
754  f0, // modified face
755  faceI, // label of face
756  own, // owner
757  nei, // neighbour
758  false, // face flip
759  patchI, // patch for face
760  zoneI, // zone for face
761  zoneFlip // face flip in zone
762  );
763  meshMod.addFace
764  (
765  f1, // modified face
766  own, // owner
767  nei, // neighbour
768  -1, // master point
769  -1, // master edge
770  faceI, // master face
771  false, // face flip
772  patchI, // patch for face
773  zoneI, // zone for face
774  zoneFlip // face flip in zone
775  );
776  }
777 
778 
779 
780  // Change the mesh (no inflation)
781  autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh_, false, true);
782 
783  // Update fields
784  mesh_.updateMesh(map);
785 
786  // Move mesh (since morphing might not do this)
787  if (map().hasMotionPoints())
788  {
789  mesh_.movePoints(map().preMotionPoints());
790  }
791  else
792  {
793  // Delete mesh volumes. No other way to do this?
794  mesh_.clearOut();
795  }
796 
797  // Reset the instance for if in overwrite mode
798  mesh_.setInstance(timeName());
799  setInstance(mesh_.facesInstance());
800 
801  // Update local mesh data
802  const labelList& oldToNew = map().reverseFaceMap();
803  labelList newSplitFaces(renumber(oldToNew, splitFaces));
804  // Add added faces (every splitFaces becomes two faces)
805  label sz = newSplitFaces.size();
806  newSplitFaces.setSize(2*sz);
807  forAll(map().faceMap(), faceI)
808  {
809  label oldFaceI = map().faceMap()[faceI];
810  if (oldToNew[oldFaceI] != faceI)
811  {
812  // Added face
813  newSplitFaces[sz++] = faceI;
814  }
815  }
816 
817  updateMesh(map, newSplitFaces);
818 
819  return map;
820 }
821 
822 
825 //void Foam::meshRefinement::getCoupledRegionMaster
826 //(
827 // const globalIndex& globalCells,
828 // const boolList& blockedFace,
829 // const regionSplit& globalRegion,
830 // Map<label>& regionToMaster
831 //) const
832 //{
833 // const polyBoundaryMesh& patches = mesh_.boundaryMesh();
834 //
835 // forAll(patches, patchI)
836 // {
837 // const polyPatch& pp = patches[patchI];
838 //
839 // if (isA<processorPolyPatch>(pp))
840 // {
841 // forAll(pp, i)
842 // {
843 // label faceI = pp.start()+i;
844 //
845 // if (!blockedFace[faceI])
846 // {
847 // // Only if there is a connection to the neighbour
848 // // will there be a multi-domain region; if not through
849 // // this face then through another.
850 //
851 // label cellI = mesh_.faceOwner()[faceI];
852 // label globalCellI = globalCells.toGlobal(cellI);
853 //
854 // Map<label>::iterator iter =
855 // regionToMaster.find(globalRegion[cellI]);
856 //
857 // if (iter != regionToMaster.end())
858 // {
859 // label master = iter();
860 // iter() = min(master, globalCellI);
861 // }
862 // else
863 // {
864 // regionToMaster.insert
865 // (
866 // globalRegion[cellI],
867 // globalCellI
868 // );
869 // }
870 // }
871 // }
872 // }
873 // }
874 //
875 // // Do reduction
876 // Pstream::mapCombineGather(regionToMaster, minEqOp<label>());
877 // Pstream::mapCombineScatter(regionToMaster);
878 //}
879 //
880 //
881 //void Foam::meshRefinement::calcLocalRegions
882 //(
883 // const globalIndex& globalCells,
884 // const labelList& globalRegion,
885 // const Map<label>& coupledRegionToMaster,
886 // const scalarField& cellWeights,
887 //
888 // Map<label>& globalToLocalRegion,
889 // pointField& localPoints,
890 // scalarField& localWeights
891 //) const
892 //{
893 // globalToLocalRegion.resize(globalRegion.size());
894 // DynamicList<point> localCc(globalRegion.size()/2);
895 // DynamicList<scalar> localWts(globalRegion.size()/2);
896 //
897 // forAll(globalRegion, cellI)
898 // {
899 // Map<label>::const_iterator fndMaster =
900 // coupledRegionToMaster.find(globalRegion[cellI]);
901 //
902 // if (fndMaster != coupledRegionToMaster.end())
903 // {
904 // // Multi-processor region.
905 // if (globalCells.toGlobal(cellI) == fndMaster())
906 // {
907 // // I am master. Allocate region for me.
908 // globalToLocalRegion.insert
909 // (
910 // globalRegion[cellI],
911 // localCc.size()
912 // );
913 // localCc.append(mesh_.cellCentres()[cellI]);
914 // localWts.append(cellWeights[cellI]);
915 // }
916 // }
917 // else
918 // {
919 // // Single processor region.
920 // if
921 // (
922 // globalToLocalRegion.insert
923 // (
924 // globalRegion[cellI],
925 // localCc.size()
926 // )
927 // )
928 // {
929 // localCc.append(mesh_.cellCentres()[cellI]);
930 // localWts.append(cellWeights[cellI]);
931 // }
932 // }
933 // }
934 //
935 // localPoints.transfer(localCc);
936 // localWeights.transfer(localWts);
937 //
938 // if (localPoints.size() != globalToLocalRegion.size())
939 // {
940 // FatalErrorIn("calcLocalRegions(..)")
941 // << "localPoints:" << localPoints.size()
942 // << " globalToLocalRegion:" << globalToLocalRegion.size()
943 // << exit(FatalError);
944 // }
945 //}
946 //
947 //
948 //Foam::label Foam::meshRefinement::getShiftedRegion
949 //(
950 // const globalIndex& indexer,
951 // const Map<label>& globalToLocalRegion,
952 // const Map<label>& coupledRegionToShifted,
953 // const label globalRegion
954 //)
955 //{
956 // Map<label>::const_iterator iter =
957 // globalToLocalRegion.find(globalRegion);
958 //
959 // if (iter != globalToLocalRegion.end())
960 // {
961 // // Region is 'owned' locally. Convert local region index into global.
962 // return indexer.toGlobal(iter());
963 // }
964 // else
965 // {
966 // return coupledRegionToShifted[globalRegion];
967 // }
968 //}
969 //
970 //
972 //void Foam::meshRefinement::addUnique(const label elem, labelList& lst)
973 //{
974 // if (findIndex(lst, elem) == -1)
975 // {
976 // label sz = lst.size();
977 // lst.setSize(sz+1);
978 // lst[sz] = elem;
979 // }
980 //}
981 //
982 //
983 //void Foam::meshRefinement::calcRegionRegions
984 //(
985 // const labelList& globalRegion,
986 // const Map<label>& globalToLocalRegion,
987 // const Map<label>& coupledRegionToMaster,
988 // labelListList& regionRegions
989 //) const
990 //{
991 // // Global region indexing since we now know the shifted regions.
992 // globalIndex shiftIndexer(globalToLocalRegion.size());
993 //
994 // // Redo the coupledRegionToMaster to be in shifted region indexing.
995 // Map<label> coupledRegionToShifted(coupledRegionToMaster.size());
996 // forAllConstIter(Map<label>, coupledRegionToMaster, iter)
997 // {
998 // label region = iter.key();
999 //
1000 // Map<label>::const_iterator fndRegion = globalToLocalRegion.find
1001 // (region);
1002 //
1003 // if (fndRegion != globalToLocalRegion.end())
1004 // {
1005 // // A local cell is master of this region. Get its shifted region.
1006 // coupledRegionToShifted.insert
1007 // (
1008 // region,
1009 // shiftIndexer.toGlobal(fndRegion())
1010 // );
1011 // }
1012 // Pstream::mapCombineGather(coupledRegionToShifted, minEqOp<label>());
1013 // Pstream::mapCombineScatter(coupledRegionToShifted);
1014 // }
1015 //
1016 //
1017 // // Determine region-region connectivity.
1018 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1019 // // This is for all my regions (so my local ones or the ones I am master
1020 // // of) the neighbouring region indices.
1021 //
1022 //
1023 // // Transfer lists.
1024 // PtrList<HashSet<edge, Hash<edge> > > regionConnectivity
1025 // (Pstream::nProcs());
1026 // forAll(regionConnectivity, procI)
1027 // {
1028 // if (procI != Pstream::myProcNo())
1029 // {
1030 // regionConnectivity.set
1031 // (
1032 // procI,
1033 // new HashSet<edge, Hash<edge> >
1034 // (
1035 // coupledRegionToShifted.size()
1036 // / Pstream::nProcs()
1037 // )
1038 // );
1039 // }
1040 // }
1041 //
1042 //
1043 // // Connectivity. For all my local regions the connected regions.
1044 // regionRegions.setSize(globalToLocalRegion.size());
1045 //
1046 // // Add all local connectivity to regionRegions; add all non-local
1047 // // to the transferlists.
1048 // for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
1049 // {
1050 // label ownRegion = globalRegion[mesh_.faceOwner()[faceI]];
1051 // label neiRegion = globalRegion[mesh_.faceNeighbour()[faceI]];
1052 //
1053 // if (ownRegion != neiRegion)
1054 // {
1055 // label shiftOwnRegion = getShiftedRegion
1056 // (
1057 // shiftIndexer,
1058 // globalToLocalRegion,
1059 // coupledRegionToShifted,
1060 // ownRegion
1061 // );
1062 // label shiftNeiRegion = getShiftedRegion
1063 // (
1064 // shiftIndexer,
1065 // globalToLocalRegion,
1066 // coupledRegionToShifted,
1067 // neiRegion
1068 // );
1069 //
1070 //
1071 // // Connection between two regions. Send to owner of region.
1072 // // - is ownRegion 'owned' by me
1073 // // - is neiRegion 'owned' by me
1074 //
1075 // if (shiftIndexer.isLocal(shiftOwnRegion))
1076 // {
1077 // label localI = shiftIndexer.toLocal(shiftOwnRegion);
1078 // addUnique(shiftNeiRegion, regionRegions[localI]);
1079 // }
1080 // else
1081 // {
1082 // label masterProc = shiftIndexer.whichProcID(shiftOwnRegion);
1083 // regionConnectivity[masterProc].insert
1084 // (
1085 // edge(shiftOwnRegion, shiftNeiRegion)
1086 // );
1087 // }
1088 //
1089 // if (shiftIndexer.isLocal(shiftNeiRegion))
1090 // {
1091 // label localI = shiftIndexer.toLocal(shiftNeiRegion);
1092 // addUnique(shiftOwnRegion, regionRegions[localI]);
1093 // }
1094 // else
1095 // {
1096 // label masterProc = shiftIndexer.whichProcID(shiftNeiRegion);
1097 // regionConnectivity[masterProc].insert
1098 // (
1099 // edge(shiftOwnRegion, shiftNeiRegion)
1100 // );
1101 // }
1102 // }
1103 // }
1104 //
1105 //
1106 // // Send
1107 // forAll(regionConnectivity, procI)
1108 // {
1109 // if (procI != Pstream::myProcNo())
1110 // {
1111 // OPstream str(Pstream::blocking, procI);
1112 // str << regionConnectivity[procI];
1113 // }
1114 // }
1115 // // Receive
1116 // forAll(regionConnectivity, procI)
1117 // {
1118 // if (procI != Pstream::myProcNo())
1119 // {
1120 // IPstream str(Pstream::blocking, procI);
1121 // str >> regionConnectivity[procI];
1122 // }
1123 // }
1124 //
1125 // // Add to addressing.
1126 // forAll(regionConnectivity, procI)
1127 // {
1128 // if (procI != Pstream::myProcNo())
1129 // {
1130 // for
1131 // (
1132 // HashSet<edge, Hash<edge> >::const_iterator iter =
1133 // regionConnectivity[procI].begin();
1134 // iter != regionConnectivity[procI].end();
1135 // ++iter
1136 // )
1137 // {
1138 // const edge& e = iter.key();
1139 //
1140 // bool someLocal = false;
1141 // if (shiftIndexer.isLocal(e[0]))
1142 // {
1143 // label localI = shiftIndexer.toLocal(e[0]);
1144 // addUnique(e[1], regionRegions[localI]);
1145 // someLocal = true;
1146 // }
1147 // if (shiftIndexer.isLocal(e[1]))
1148 // {
1149 // label localI = shiftIndexer.toLocal(e[1]);
1150 // addUnique(e[0], regionRegions[localI]);
1151 // someLocal = true;
1152 // }
1153 //
1154 // if (!someLocal)
1155 // {
1156 // FatalErrorIn("calcRegionRegions(..)")
1157 // << "Received from processor " << procI
1158 // << " connection " << e
1159 // << " where none of the elements is local to me."
1160 // << abort(FatalError);
1161 // }
1162 // }
1163 // }
1164 // }
1165 //}
1166 
1167 
1168 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1169 
1170 // Construct from components
1171 Foam::meshRefinement::meshRefinement
1173  fvMesh& mesh,
1174  const scalar mergeDistance,
1175  const bool overwrite,
1176  const refinementSurfaces& surfaces,
1177  const refinementFeatures& features,
1178  const shellSurfaces& shells
1179 )
1180 :
1181  mesh_(mesh),
1182  mergeDistance_(mergeDistance),
1183  overwrite_(overwrite),
1184  oldInstance_(mesh.pointsInstance()),
1185  surfaces_(surfaces),
1186  features_(features),
1187  shells_(shells),
1188  meshCutter_
1189  (
1190  mesh,
1191  false // do not try to read history.
1192  ),
1193  surfaceIndex_
1194  (
1195  IOobject
1196  (
1197  "surfaceIndex",
1198  mesh_.facesInstance(),
1200  mesh_,
1203  false
1204  ),
1205  labelList(mesh_.nFaces(), -1)
1206  ),
1207  userFaceData_(0)
1208 {
1209  // recalculate intersections for all faces
1210  updateIntersections(identity(mesh_.nFaces()));
1211 }
1212 
1213 
1214 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1215 
1217 {
1218  // Stats on edges to test. Count proc faces only once.
1219  PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh_));
1220 
1221  label nHits = 0;
1222 
1223  forAll(surfaceIndex_, faceI)
1224  {
1225  if (surfaceIndex_[faceI] >= 0 && isMasterFace.get(faceI) == 1)
1226  {
1227  nHits++;
1228  }
1229  }
1230  return nHits;
1231 }
1232 
1233 
1235 //Foam::labelList Foam::meshRefinement::decomposeCombineRegions
1236 //(
1237 // const scalarField& cellWeights,
1238 // const boolList& blockedFace,
1239 // const List<labelPair>& explicitConnections,
1240 // decompositionMethod& decomposer
1241 //) const
1242 //{
1243 // // Determine global regions, separated by blockedFaces
1244 // regionSplit globalRegion(mesh_, blockedFace, explicitConnections);
1245 //
1246 // // Now globalRegion has global region per cell. Problem is that
1247 // // the region might span multiple domains so we want to get
1248 // // a "region master" per domain. Note that multi-processor
1249 // // regions can only occur on cells on coupled patches.
1250 // // Note: since the number of regions does not change by this the
1251 // // process can be seen as just a shift of a region onto a single
1252 // // processor.
1253 //
1254 //
1255 // // Global cell numbering engine
1256 // globalIndex globalCells(mesh_.nCells());
1257 //
1258 //
1259 // // Determine per coupled region the master cell (lowest numbered cell
1260 // // on lowest numbered processor)
1261 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1262 // // (does not determine master for non-coupled=fully-local regions)
1263 //
1264 // Map<label> coupledRegionToMaster(mesh_.nFaces()-mesh_.nInternalFaces());
1265 // getCoupledRegionMaster
1266 // (
1267 // globalCells,
1268 // blockedFace,
1269 // globalRegion,
1270 // coupledRegionToMaster
1271 // );
1272 //
1273 // // Determine my regions
1274 // // ~~~~~~~~~~~~~~~~~~~~
1275 // // These are the fully local ones or the coupled ones of which I am master
1276 //
1277 // Map<label> globalToLocalRegion;
1278 // pointField localPoints;
1279 // scalarField localWeights;
1280 // calcLocalRegions
1281 // (
1282 // globalCells,
1283 // globalRegion,
1284 // coupledRegionToMaster,
1285 // cellWeights,
1286 //
1287 // globalToLocalRegion,
1288 // localPoints,
1289 // localWeights
1290 // );
1291 //
1292 //
1293 //
1294 // // Find distribution for regions
1295 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1296 //
1297 // labelList regionDistribution;
1298 //
1299 // if (isA<geomDecomp>(decomposer))
1300 // {
1301 // regionDistribution = decomposer.decompose(localPoints, localWeights);
1302 // }
1303 // else
1304 // {
1305 // labelListList regionRegions;
1306 // calcRegionRegions
1307 // (
1308 // globalRegion,
1309 // globalToLocalRegion,
1310 // coupledRegionToMaster,
1311 //
1312 // regionRegions
1313 // );
1314 //
1315 // regionDistribution = decomposer.decompose
1316 // (
1317 // regionRegions,
1318 // localPoints,
1319 // localWeights
1320 // );
1321 // }
1322 //
1323 //
1324 //
1325 // // Convert region-based decomposition back to cell-based one
1326 // // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1327 //
1328 // // Transfer destination processor back to all. Use global reduce for now.
1329 // Map<label> regionToDist(coupledRegionToMaster.size());
1330 // forAllConstIter(Map<label>, coupledRegionToMaster, iter)
1331 // {
1332 // label region = iter.key();
1333 //
1334 // Map<label>::const_iterator regionFnd = globalToLocalRegion.find
1335 // (region);
1336 //
1337 // if (regionFnd != globalToLocalRegion.end())
1338 // {
1339 // // Master cell is local. Store my distribution.
1340 // regionToDist.insert(iter.key(), regionDistribution[regionFnd()]);
1341 // }
1342 // else
1343 // {
1344 // // Master cell is not on this processor. Make sure it is
1345 // // overridden.
1346 // regionToDist.insert(iter.key(), labelMax);
1347 // }
1348 // }
1349 // Pstream::mapCombineGather(regionToDist, minEqOp<label>());
1350 // Pstream::mapCombineScatter(regionToDist);
1351 //
1352 //
1353 // // Determine destination for all cells
1354 // labelList distribution(mesh_.nCells());
1355 //
1356 // forAll(globalRegion, cellI)
1357 // {
1358 // Map<label>::const_iterator fndRegion =
1359 // regionToDist.find(globalRegion[cellI]);
1360 //
1361 // if (fndRegion != regionToDist.end())
1362 // {
1363 // distribution[cellI] = fndRegion();
1364 // }
1365 // else
1366 // {
1367 // // region is local to the processor.
1368 // label localRegionI = globalToLocalRegion[globalRegion[cellI]];
1369 //
1370 // distribution[cellI] = regionDistribution[localRegionI];
1371 // }
1372 // }
1373 //
1374 // return distribution;
1375 //}
1376 
1377 
1380  const bool keepZoneFaces,
1381  const bool keepBaffles,
1382  const scalarField& cellWeights,
1383  decompositionMethod& decomposer,
1384  fvMeshDistribute& distributor
1385 )
1386 {
1388 
1389  if (Pstream::parRun())
1390  {
1391  //if (debug_)
1392  //{
1393  // const_cast<Time&>(mesh_.time())++;
1394  //}
1395 
1396  // Wanted distribution
1398 
1399 
1400  // Faces where owner and neighbour are not 'connected' so can
1401  // go to different processors.
1402  boolList blockedFace;
1403  label nUnblocked = 0;
1404 
1405  // Faces that move as block onto single processor
1406  PtrList<labelList> specifiedProcessorFaces;
1407  labelList specifiedProcessor;
1408 
1409  // Pairs of baffles
1410  List<labelPair> couples;
1411 
1412  // Constraints from decomposeParDict
1413  decomposer.setConstraints
1414  (
1415  mesh_,
1416  blockedFace,
1417  specifiedProcessorFaces,
1418  specifiedProcessor,
1419  couples
1420  );
1421 
1422 
1423  if (keepZoneFaces || keepBaffles)
1424  {
1425  if (keepZoneFaces)
1426  {
1427  // Determine decomposition to keep/move surface zones
1428  // on one processor. The reason is that snapping will make these
1429  // into baffles, move and convert them back so if they were
1430  // proc boundaries after baffling&moving the points might be no
1431  // longer synchronised so recoupling will fail. To prevent this
1432  // keep owner&neighbour of such a surface zone on the same
1433  // processor.
1434 
1435  const PtrList<surfaceZonesInfo>& surfZones =
1436  surfaces().surfZones();
1437  const faceZoneMesh& fZones = mesh_.faceZones();
1438  const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
1439 
1440  // Get faces whose owner and neighbour should stay together,
1441  // i.e. they are not 'blocked'.
1442 
1443  forAll(surfZones, surfI)
1444  {
1445  const word& fzName = surfZones[surfI].faceZoneName();
1446 
1447  if (fzName.size())
1448  {
1449  // Get zone
1450  const faceZone& fZone = fZones[fzName];
1451 
1452  forAll(fZone, i)
1453  {
1454  label faceI = fZone[i];
1455  if (blockedFace[faceI])
1456  {
1457  if
1458  (
1459  mesh_.isInternalFace(faceI)
1460  || pbm[pbm.whichPatch(faceI)].coupled()
1461  )
1462  {
1463  blockedFace[faceI] = false;
1464  nUnblocked++;
1465  }
1466  }
1467  }
1468  }
1469  }
1470 
1471 
1472  // If the faceZones are not synchronised the blockedFace
1473  // might not be synchronised. If you are sure the faceZones
1474  // are synchronised remove below check.
1476  (
1477  mesh_,
1478  blockedFace,
1479  andEqOp<bool>() // combine operator
1480  );
1481  }
1482  reduce(nUnblocked, sumOp<label>());
1483 
1484  if (keepZoneFaces)
1485  {
1486  Info<< "Found " << nUnblocked
1487  << " zoned faces to keep together." << endl;
1488  }
1489 
1490 
1491  // Extend un-blockedFaces with any cyclics
1492  {
1493  boolList separatedCoupledFace(mesh_.nFaces(), false);
1494  selectSeparatedCoupledFaces(separatedCoupledFace);
1495 
1496  label nSeparated = 0;
1497  forAll(separatedCoupledFace, faceI)
1498  {
1499  if (separatedCoupledFace[faceI])
1500  {
1501  if (blockedFace[faceI])
1502  {
1503  blockedFace[faceI] = false;
1504  nSeparated++;
1505  }
1506  }
1507  }
1508  reduce(nSeparated, sumOp<label>());
1509  Info<< "Found " << nSeparated
1510  << " separated coupled faces to keep together." << endl;
1511 
1512  nUnblocked += nSeparated;
1513  }
1514 
1515 
1516  if (keepBaffles)
1517  {
1518  label nBnd = mesh_.nFaces()-mesh_.nInternalFaces();
1519 
1520  labelList coupledFace(mesh_.nFaces(), -1);
1521  {
1522  // Get boundary baffles that need to stay together
1523  List<labelPair> allCouples
1524  (
1526  );
1527 
1528  // Merge with any couples from
1529  // decompositionMethod::setConstraints
1530  forAll(couples, i)
1531  {
1532  const labelPair& baffle = couples[i];
1533  coupledFace[baffle.first()] = baffle.second();
1534  coupledFace[baffle.second()] = baffle.first();
1535  }
1536  forAll(allCouples, i)
1537  {
1538  const labelPair& baffle = allCouples[i];
1539  coupledFace[baffle.first()] = baffle.second();
1540  coupledFace[baffle.second()] = baffle.first();
1541  }
1542  }
1543 
1544  couples.setSize(nBnd);
1545  label nCpl = 0;
1546  forAll(coupledFace, faceI)
1547  {
1548  if (coupledFace[faceI] != -1 && faceI < coupledFace[faceI])
1549  {
1550  couples[nCpl++] = labelPair(faceI, coupledFace[faceI]);
1551  }
1552  }
1553  couples.setSize(nCpl);
1554  }
1555  label nCouples = returnReduce(couples.size(), sumOp<label>());
1556 
1557  if (keepBaffles)
1558  {
1559  Info<< "Found " << nCouples << " baffles to keep together."
1560  << endl;
1561  }
1562 
1563  //if (nUnblocked > 0 || nCouples > 0)
1564  //{
1565  // Info<< "Applying special decomposition to keep baffles"
1566  // << " and zoned faces together." << endl;
1567  //
1568  // distribution = decomposeCombineRegions
1569  // (
1570  // cellWeights,
1571  // blockedFace,
1572  // couples,
1573  // decomposer
1574  // );
1575  //
1576  // labelList nProcCells(distributor.countCells(distribution));
1577  // Pstream::listCombineGather(nProcCells, plusEqOp<label>());
1578  // Pstream::listCombineScatter(nProcCells);
1579  //
1580  // Info<< "Calculated decomposition:" << endl;
1581  // forAll(nProcCells, procI)
1582  // {
1583  // Info<< " " << procI << '\t' << nProcCells[procI]
1584  // << endl;
1585  // }
1586  // Info<< endl;
1587  //}
1588  //else
1589  //{
1590  // // Normal decomposition
1591  // distribution = decomposer.decompose
1592  // (
1593  // mesh_,
1594  // mesh_.cellCentres(),
1595  // cellWeights
1596  // );
1597  //}
1598  }
1599  //else
1600  //{
1601  // // Normal decomposition
1602  // distribution = decomposer.decompose
1603  // (
1604  // mesh_,
1605  // cellWeights
1606  // );
1607  //}
1608 
1609 
1610  // Make sure blockedFace not set on couples
1611  forAll(couples, i)
1612  {
1613  const labelPair& baffle = couples[i];
1614  blockedFace[baffle.first()] = false;
1615  blockedFace[baffle.second()] = false;
1616  }
1617 
1618  distribution = decomposer.decompose
1619  (
1620  mesh_,
1621  cellWeights,
1622  blockedFace,
1623  specifiedProcessorFaces,
1624  specifiedProcessor,
1625  couples // explicit connections
1626  );
1627 
1628  if (debug)
1629  {
1630  labelList nProcCells(distributor.countCells(distribution));
1631  Pout<< "Wanted distribution:" << nProcCells << endl;
1632 
1634  Pstream::listCombineScatter(nProcCells);
1635 
1636  Pout<< "Wanted resulting decomposition:" << endl;
1637  forAll(nProcCells, procI)
1638  {
1639  Pout<< " " << procI << '\t' << nProcCells[procI] << endl;
1640  }
1641  Pout<< endl;
1642  }
1643  // Do actual sending/receiving of mesh
1644  map = distributor.distribute(distribution);
1645 
1646  // Update numbering of meshRefiner
1647  distribute(map);
1648 
1649  // Set correct instance (for if overwrite)
1650  mesh_.setInstance(timeName());
1651  setInstance(mesh_.facesInstance());
1652  }
1653 
1654  return map;
1655 }
1656 
1657 
1658 // Helper function to get intersected faces
1660 {
1661  label nBoundaryFaces = 0;
1662 
1663  forAll(surfaceIndex_, faceI)
1664  {
1665  if (surfaceIndex_[faceI] != -1)
1666  {
1667  nBoundaryFaces++;
1668  }
1669  }
1670 
1671  labelList surfaceFaces(nBoundaryFaces);
1672  nBoundaryFaces = 0;
1673 
1674  forAll(surfaceIndex_, faceI)
1675  {
1676  if (surfaceIndex_[faceI] != -1)
1677  {
1678  surfaceFaces[nBoundaryFaces++] = faceI;
1679  }
1680  }
1681  return surfaceFaces;
1682 }
1683 
1684 
1685 // Helper function to get points used by faces
1687 {
1688  const faceList& faces = mesh_.faces();
1689 
1690  // Mark all points on faces that will become baffles
1691  PackedBoolList isBoundaryPoint(mesh_.nPoints());
1692  label nBoundaryPoints = 0;
1693 
1694  forAll(surfaceIndex_, faceI)
1695  {
1696  if (surfaceIndex_[faceI] != -1)
1697  {
1698  const face& f = faces[faceI];
1699 
1700  forAll(f, fp)
1701  {
1702  if (isBoundaryPoint.set(f[fp], 1u))
1703  {
1704  nBoundaryPoints++;
1705  }
1706  }
1707  }
1708  }
1709 
1711  //labelList adaptPatchIDs(meshedPatches());
1712  //forAll(adaptPatchIDs, i)
1713  //{
1714  // label patchI = adaptPatchIDs[i];
1715  //
1716  // if (patchI != -1)
1717  // {
1718  // const polyPatch& pp = mesh_.boundaryMesh()[patchI];
1719  //
1720  // label faceI = pp.start();
1721  //
1722  // forAll(pp, i)
1723  // {
1724  // const face& f = faces[faceI];
1725  //
1726  // forAll(f, fp)
1727  // {
1728  // if (isBoundaryPoint.set(f[fp], 1u))
1729  // nBoundaryPoints++;
1730  // }
1731  // }
1732  // faceI++;
1733  // }
1734  // }
1735  //}
1736 
1737 
1738  // Pack
1739  labelList boundaryPoints(nBoundaryPoints);
1740  nBoundaryPoints = 0;
1741  forAll(isBoundaryPoint, pointI)
1742  {
1743  if (isBoundaryPoint.get(pointI) == 1u)
1744  {
1745  boundaryPoints[nBoundaryPoints++] = pointI;
1746  }
1747  }
1748 
1749  return boundaryPoints;
1750 }
1751 
1752 
1753 //- Create patch from set of patches
1756  const polyMesh& mesh,
1757  const labelList& patchIDs
1758 )
1759 {
1760  const polyBoundaryMesh& patches = mesh.boundaryMesh();
1761 
1762  // Count faces.
1763  label nFaces = 0;
1764 
1765  forAll(patchIDs, i)
1766  {
1767  const polyPatch& pp = patches[patchIDs[i]];
1768 
1769  nFaces += pp.size();
1770  }
1771 
1772  // Collect faces.
1773  labelList addressing(nFaces);
1774  nFaces = 0;
1775 
1776  forAll(patchIDs, i)
1777  {
1778  const polyPatch& pp = patches[patchIDs[i]];
1779 
1780  label meshFaceI = pp.start();
1781 
1782  forAll(pp, i)
1783  {
1784  addressing[nFaces++] = meshFaceI++;
1785  }
1786  }
1787 
1789  (
1791  (
1792  IndirectList<face>(mesh.faces(), addressing),
1793  mesh.points()
1794  )
1795  );
1796 }
1797 
1798 
1799 // Construct pointVectorField with correct boundary conditions
1802  const pointMesh& pMesh,
1803  const labelList& adaptPatchIDs
1804 )
1805 {
1806  const polyMesh& mesh = pMesh();
1807 
1808  // Construct displacement field.
1809  const pointBoundaryMesh& pointPatches = pMesh.boundary();
1810 
1811  wordList patchFieldTypes
1812  (
1813  pointPatches.size(),
1814  slipPointPatchVectorField::typeName
1815  );
1816 
1817  forAll(adaptPatchIDs, i)
1818  {
1819  patchFieldTypes[adaptPatchIDs[i]] =
1820  fixedValuePointPatchVectorField::typeName;
1821  }
1822 
1823  forAll(pointPatches, patchI)
1824  {
1825  if (isA<processorPointPatch>(pointPatches[patchI]))
1826  {
1827  patchFieldTypes[patchI] = calculatedPointPatchVectorField::typeName;
1828  }
1829  else if (isA<cyclicPointPatch>(pointPatches[patchI]))
1830  {
1831  patchFieldTypes[patchI] = cyclicSlipPointPatchVectorField::typeName;
1832  }
1833  }
1834 
1835  // Note: time().timeName() instead of meshRefinement::timeName() since
1836  // postprocessable field.
1838  (
1839  new pointVectorField
1840  (
1841  IOobject
1842  (
1843  "pointDisplacement",
1844  mesh.time().timeName(),
1845  mesh,
1848  ),
1849  pMesh,
1850  dimensionedVector("displacement", dimLength, vector::zero),
1851  patchFieldTypes
1852  )
1853  );
1854  return tfld;
1855 }
1856 
1857 
1859 {
1860  const faceZoneMesh& fZones = mesh.faceZones();
1861 
1862  // Check any zones are present anywhere and in same order
1863 
1864  {
1865  List<wordList> zoneNames(Pstream::nProcs());
1866  zoneNames[Pstream::myProcNo()] = fZones.names();
1867  Pstream::gatherList(zoneNames);
1868  Pstream::scatterList(zoneNames);
1869  // All have same data now. Check.
1870  forAll(zoneNames, procI)
1871  {
1872  if (procI != Pstream::myProcNo())
1873  {
1874  if (zoneNames[procI] != zoneNames[Pstream::myProcNo()])
1875  {
1876  FatalErrorIn
1877  (
1878  "meshRefinement::checkCoupledFaceZones(const polyMesh&)"
1879  ) << "faceZones are not synchronised on processors." << nl
1880  << "Processor " << procI << " has faceZones "
1881  << zoneNames[procI] << nl
1882  << "Processor " << Pstream::myProcNo()
1883  << " has faceZones "
1884  << zoneNames[Pstream::myProcNo()] << nl
1885  << exit(FatalError);
1886  }
1887  }
1888  }
1889  }
1890 
1891  // Check that coupled faces are present on both sides.
1892 
1893  labelList faceToZone(mesh.nFaces()-mesh.nInternalFaces(), -1);
1894 
1895  forAll(fZones, zoneI)
1896  {
1897  const faceZone& fZone = fZones[zoneI];
1898 
1899  forAll(fZone, i)
1900  {
1901  label bFaceI = fZone[i]-mesh.nInternalFaces();
1902 
1903  if (bFaceI >= 0)
1904  {
1905  if (faceToZone[bFaceI] == -1)
1906  {
1907  faceToZone[bFaceI] = zoneI;
1908  }
1909  else if (faceToZone[bFaceI] == zoneI)
1910  {
1911  FatalErrorIn
1912  (
1913  "meshRefinement::checkCoupledFaceZones(const polyMesh&)"
1914  ) << "Face " << fZone[i] << " in zone "
1915  << fZone.name()
1916  << " is twice in zone!"
1917  << abort(FatalError);
1918  }
1919  else
1920  {
1921  FatalErrorIn
1922  (
1923  "meshRefinement::checkCoupledFaceZones(const polyMesh&)"
1924  ) << "Face " << fZone[i] << " in zone "
1925  << fZone.name()
1926  << " is also in zone "
1927  << fZones[faceToZone[bFaceI]].name()
1928  << abort(FatalError);
1929  }
1930  }
1931  }
1932  }
1933 
1934  labelList neiFaceToZone(faceToZone);
1935  syncTools::swapBoundaryFaceList(mesh, neiFaceToZone);
1936 
1937  forAll(faceToZone, i)
1938  {
1939  if (faceToZone[i] != neiFaceToZone[i])
1940  {
1941  FatalErrorIn
1942  (
1943  "meshRefinement::checkCoupledFaceZones(const polyMesh&)"
1944  ) << "Face " << mesh.nInternalFaces()+i
1945  << " is in zone " << faceToZone[i]
1946  << ", its coupled face is in zone " << neiFaceToZone[i]
1947  << abort(FatalError);
1948  }
1949  }
1950 }
1951 
1952 
1955  const polyMesh& mesh,
1956  const PackedBoolList& isMasterEdge,
1957  const labelList& meshPoints,
1958  const edgeList& edges,
1959  scalarField& edgeWeights,
1960  scalarField& invSumWeight
1961 )
1962 {
1963  const pointField& pts = mesh.points();
1964 
1965  // Calculate edgeWeights and inverse sum of edge weights
1966  edgeWeights.setSize(isMasterEdge.size());
1967  invSumWeight.setSize(meshPoints.size());
1968 
1969  forAll(edges, edgeI)
1970  {
1971  const edge& e = edges[edgeI];
1972  scalar eMag = max
1973  (
1974  SMALL,
1975  mag
1976  (
1977  pts[meshPoints[e[1]]]
1978  - pts[meshPoints[e[0]]]
1979  )
1980  );
1981  edgeWeights[edgeI] = 1.0/eMag;
1982  }
1983 
1984  // Sum per point all edge weights
1985  weightedSum
1986  (
1987  mesh,
1988  isMasterEdge,
1989  meshPoints,
1990  edges,
1991  edgeWeights,
1992  scalarField(meshPoints.size(), 1.0), // data
1993  invSumWeight
1994  );
1995 
1996  // Inplace invert
1997  forAll(invSumWeight, pointI)
1998  {
1999  scalar w = invSumWeight[pointI];
2000 
2001  if (w > 0.0)
2002  {
2003  invSumWeight[pointI] = 1.0/w;
2004  }
2005  }
2006 }
2007 
2008 
2011  fvMesh& mesh,
2012  const label insertPatchI,
2013  const word& patchName,
2014  const dictionary& patchDict
2015 )
2016 {
2017  // Clear local fields and e.g. polyMesh parallelInfo.
2018  mesh.clearOut();
2019 
2020  polyBoundaryMesh& polyPatches =
2021  const_cast<polyBoundaryMesh&>(mesh.boundaryMesh());
2022  fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh.boundary());
2023 
2024  label patchI = polyPatches.size();
2025 
2026  // Add polyPatch at the end
2027  polyPatches.setSize(patchI+1);
2028  polyPatches.set
2029  (
2030  patchI,
2032  (
2033  patchName,
2034  patchDict,
2035  insertPatchI,
2036  polyPatches
2037  )
2038  );
2039  fvPatches.setSize(patchI+1);
2040  fvPatches.set
2041  (
2042  patchI,
2043  fvPatch::New
2044  (
2045  polyPatches[patchI], // point to newly added polyPatch
2046  mesh.boundary()
2047  )
2048  );
2049 
2050  addPatchFields<volScalarField>
2051  (
2052  mesh,
2054  );
2055  addPatchFields<volVectorField>
2056  (
2057  mesh,
2059  );
2060  addPatchFields<volSphericalTensorField>
2061  (
2062  mesh,
2064  );
2065  addPatchFields<volSymmTensorField>
2066  (
2067  mesh,
2069  );
2070  addPatchFields<volTensorField>
2071  (
2072  mesh,
2074  );
2075 
2076  // Surface fields
2077 
2078  addPatchFields<surfaceScalarField>
2079  (
2080  mesh,
2082  );
2083  addPatchFields<surfaceVectorField>
2084  (
2085  mesh,
2087  );
2088  addPatchFields<surfaceSphericalTensorField>
2089  (
2090  mesh,
2092  );
2093  addPatchFields<surfaceSymmTensorField>
2094  (
2095  mesh,
2097  );
2098  addPatchFields<surfaceTensorField>
2099  (
2100  mesh,
2102  );
2103  return patchI;
2104 }
2105 
2106 
2107 // Adds patch if not yet there. Returns patchID.
2110  fvMesh& mesh,
2111  const word& patchName,
2112  const dictionary& patchInfo
2113 )
2114 {
2115  polyBoundaryMesh& polyPatches =
2116  const_cast<polyBoundaryMesh&>(mesh.boundaryMesh());
2117  fvBoundaryMesh& fvPatches = const_cast<fvBoundaryMesh&>(mesh.boundary());
2118 
2119  const label patchI = polyPatches.findPatchID(patchName);
2120  if (patchI != -1)
2121  {
2122  // Already there
2123  return patchI;
2124  }
2125 
2126 
2127  label insertPatchI = polyPatches.size();
2128  label startFaceI = mesh.nFaces();
2129 
2130  forAll(polyPatches, patchI)
2131  {
2132  const polyPatch& pp = polyPatches[patchI];
2133 
2134  if (isA<processorPolyPatch>(pp))
2135  {
2136  insertPatchI = patchI;
2137  startFaceI = pp.start();
2138  break;
2139  }
2140  }
2141 
2142  dictionary patchDict(patchInfo);
2143  patchDict.set("nFaces", 0);
2144  patchDict.set("startFace", startFaceI);
2145 
2146  // Below is all quite a hack. Feel free to change once there is a better
2147  // mechanism to insert and reorder patches.
2148 
2149  label addedPatchI = appendPatch(mesh, insertPatchI, patchName, patchDict);
2150 
2151 
2152  // Create reordering list
2153  // patches before insert position stay as is
2154  labelList oldToNew(addedPatchI+1);
2155  for (label i = 0; i < insertPatchI; i++)
2156  {
2157  oldToNew[i] = i;
2158  }
2159  // patches after insert position move one up
2160  for (label i = insertPatchI; i < addedPatchI; i++)
2161  {
2162  oldToNew[i] = i+1;
2163  }
2164  // appended patch gets moved to insert position
2165  oldToNew[addedPatchI] = insertPatchI;
2166 
2167  // Shuffle into place
2168  polyPatches.reorder(oldToNew, true);
2169  fvPatches.reorder(oldToNew);
2170 
2171  reorderPatchFields<volScalarField>(mesh, oldToNew);
2172  reorderPatchFields<volVectorField>(mesh, oldToNew);
2173  reorderPatchFields<volSphericalTensorField>(mesh, oldToNew);
2174  reorderPatchFields<volSymmTensorField>(mesh, oldToNew);
2175  reorderPatchFields<volTensorField>(mesh, oldToNew);
2176  reorderPatchFields<surfaceScalarField>(mesh, oldToNew);
2177  reorderPatchFields<surfaceVectorField>(mesh, oldToNew);
2178  reorderPatchFields<surfaceSphericalTensorField>(mesh, oldToNew);
2179  reorderPatchFields<surfaceSymmTensorField>(mesh, oldToNew);
2180  reorderPatchFields<surfaceTensorField>(mesh, oldToNew);
2181 
2182  return insertPatchI;
2183 }
2184 
2185 
2188  const word& name,
2189  const dictionary& patchInfo
2190 )
2191 {
2192  label meshedI = findIndex(meshedPatches_, name);
2193 
2194  if (meshedI != -1)
2195  {
2196  // Already there. Get corresponding polypatch
2197  return mesh_.boundaryMesh().findPatchID(name);
2198  }
2199  else
2200  {
2201  // Add patch
2202  label patchI = addPatch(mesh_, name, patchInfo);
2203 
2204 // dictionary patchDict(patchInfo);
2205 // patchDict.set("nFaces", 0);
2206 // patchDict.set("startFace", 0);
2207 // autoPtr<polyPatch> ppPtr
2208 // (
2209 // polyPatch::New
2210 // (
2211 // name,
2212 // patchDict,
2213 // 0,
2214 // mesh_.boundaryMesh()
2215 // )
2216 // );
2217 // label patchI = fvMeshTools::addPatch
2218 // (
2219 // mesh_,
2220 // ppPtr(),
2221 // dictionary(), // optional field values
2222 // calculatedFvPatchField<scalar>::typeName,
2223 // true
2224 // );
2225 
2226  // Store
2227  meshedPatches_.append(name);
2228 
2229  return patchI;
2230  }
2231 }
2232 
2233 
2235 {
2236  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
2237 
2238  DynamicList<label> patchIDs(meshedPatches_.size());
2239  forAll(meshedPatches_, i)
2240  {
2241  label patchI = patches.findPatchID(meshedPatches_[i]);
2242 
2243  if (patchI == -1)
2244  {
2245  FatalErrorIn("meshRefinement::meshedPatches() const")
2246  << "Problem : did not find patch " << meshedPatches_[i]
2247  << endl << "Valid patches are " << patches.names()
2248  << abort(FatalError);
2249  }
2250  if (!polyPatch::constraintType(patches[patchI].type()))
2251  {
2252  patchIDs.append(patchI);
2253  }
2254  }
2255 
2256  return patchIDs;
2257 }
2258 
2259 
2261 {
2262  const polyBoundaryMesh& patches = mesh_.boundaryMesh();
2263 
2264  forAll(patches, patchI)
2265  {
2266  // Check all coupled. Avoid using .coupled() so we also pick up AMI.
2267  if (isA<coupledPolyPatch>(patches[patchI]))
2268  {
2269  const coupledPolyPatch& cpp = refCast<const coupledPolyPatch>
2270  (
2271  patches[patchI]
2272  );
2273 
2274  if (cpp.separated() || !cpp.parallel())
2275  {
2276  forAll(cpp, i)
2277  {
2278  selected[cpp.start()+i] = true;
2279  }
2280  }
2281  }
2282  }
2283 }
2284 
2285 
2288  const polyMesh& mesh,
2289  const labelList& cellToRegion,
2290  const vector& perturbVec,
2291  const point& p
2292 )
2293 {
2294  label regionI = -1;
2295  label cellI = mesh.findCell(p);
2296  if (cellI != -1)
2297  {
2298  regionI = cellToRegion[cellI];
2299  }
2300  reduce(regionI, maxOp<label>());
2301 
2302  if (regionI == -1)
2303  {
2304  // See if we can perturb a bit
2305  cellI = mesh.findCell(p+perturbVec);
2306  if (cellI != -1)
2307  {
2308  regionI = cellToRegion[cellI];
2309  }
2310  reduce(regionI, maxOp<label>());
2311  }
2312  return regionI;
2313 }
2314 
2315 
2318  const labelList& globalToMasterPatch,
2319  const labelList& globalToSlavePatch,
2320  const point& keepPoint
2321 )
2322 {
2323  // Force calculation of face decomposition (used in findCell)
2324  (void)mesh_.tetBasePtIs();
2325 
2326  // Determine connected regions. regionSplit is the labelList with the
2327  // region per cell.
2328 
2329  boolList blockedFace(mesh_.nFaces(), false);
2330  selectSeparatedCoupledFaces(blockedFace);
2331 
2332  regionSplit cellRegion(mesh_, blockedFace);
2333 
2334  label regionI = findRegion
2335  (
2336  mesh_,
2337  cellRegion,
2338  mergeDistance_*vector(1,1,1), // note:1,1,1 should really be normalised
2339  keepPoint
2340  );
2341 
2342  if (regionI == -1)
2343  {
2344  FatalErrorIn
2345  (
2346  "meshRefinement::splitMeshRegions(const point&)"
2347  ) << "Point " << keepPoint
2348  << " is not inside the mesh." << nl
2349  << "Bounding box of the mesh:" << mesh_.bounds()
2350  << exit(FatalError);
2351  }
2352 
2353  // Subset
2354  // ~~~~~~
2355 
2356  // Get cells to remove
2357  DynamicList<label> cellsToRemove(mesh_.nCells());
2358  forAll(cellRegion, cellI)
2359  {
2360  if (cellRegion[cellI] != regionI)
2361  {
2362  cellsToRemove.append(cellI);
2363  }
2364  }
2365  cellsToRemove.shrink();
2366 
2367  label nCellsToKeep = mesh_.nCells() - cellsToRemove.size();
2368  reduce(nCellsToKeep, sumOp<label>());
2369 
2370  Info<< "Keeping all cells in region " << regionI
2371  << " containing point " << keepPoint << endl
2372  << "Selected for keeping : "
2373  << nCellsToKeep
2374  << " cells." << endl;
2375 
2376 
2377  // Remove cells
2378  removeCells cellRemover(mesh_);
2379 
2380  labelList exposedFaces(cellRemover.getExposedFaces(cellsToRemove));
2381  labelList exposedPatch;
2382 
2383  label nExposedFaces = returnReduce(exposedFaces.size(), sumOp<label>());
2384  if (nExposedFaces)
2385  {
2386  //FatalErrorIn
2387  //(
2388  // "meshRefinement::splitMeshRegions(const point&)"
2389  //) << "Removing non-reachable cells should only expose"
2390  // << " boundary faces" << nl
2391  // << "ExposedFaces:" << exposedFaces << abort(FatalError);
2392 
2393  // Patch for exposed faces for lack of anything sensible.
2394  label defaultPatch = 0;
2395  if (globalToMasterPatch.size())
2396  {
2397  defaultPatch = globalToMasterPatch[0];
2398  }
2399 
2400  WarningIn
2401  (
2402  "meshRefinement::splitMeshRegions(const point&)"
2403  ) << "Removing non-reachable cells exposes "
2404  << nExposedFaces << " internal or coupled faces." << endl
2405  << " These get put into patch " << defaultPatch << endl;
2406  exposedPatch.setSize(exposedFaces.size(), defaultPatch);
2407  }
2408 
2409  return doRemoveCells
2410  (
2411  cellsToRemove,
2412  exposedFaces,
2413  exposedPatch,
2414  cellRemover
2415  );
2416 }
2417 
2418 
2420 {
2421  // mesh_ already distributed; distribute my member data
2422 
2423  // surfaceQueries_ ok.
2424 
2425  // refinement
2426  meshCutter_.distribute(map);
2427 
2428  // surfaceIndex is face data.
2429  map.distributeFaceData(surfaceIndex_);
2430 
2431  // maintainedFaces are indices of faces.
2432  forAll(userFaceData_, i)
2433  {
2434  map.distributeFaceData(userFaceData_[i].second());
2435  }
2436 
2437  // Redistribute surface and any fields on it.
2438  {
2439  Random rndGen(653213);
2440 
2441  // Get local mesh bounding box. Single box for now.
2443  treeBoundBox& bb = meshBb[0];
2444  bb = treeBoundBox(mesh_.points());
2445  bb = bb.extend(rndGen, 1e-4);
2446 
2447  // Distribute all geometry (so refinementSurfaces and shellSurfaces)
2448  searchableSurfaces& geometry =
2449  const_cast<searchableSurfaces&>(surfaces_.geometry());
2450 
2451  forAll(geometry, i)
2452  {
2454  autoPtr<mapDistribute> pointMap;
2455  geometry[i].distribute
2456  (
2457  meshBb,
2458  false, // do not keep outside triangles
2459  faceMap,
2460  pointMap
2461  );
2462 
2463  if (faceMap.valid())
2464  {
2465  // (ab)use the instance() to signal current modification time
2466  geometry[i].instance() = geometry[i].time().timeName();
2467  }
2468 
2469  faceMap.clear();
2470  pointMap.clear();
2471  }
2472  }
2473 }
2474 
2475 
2476 // Update local data for a mesh change
2479  const mapPolyMesh& map,
2480  const labelList& changedFaces
2481 )
2482 {
2483  Map<label> dummyMap(0);
2484 
2485  updateMesh(map, changedFaces, dummyMap, dummyMap, dummyMap);
2486 }
2487 
2488 
2491  const labelList& pointsToStore,
2492  const labelList& facesToStore,
2493  const labelList& cellsToStore
2494 )
2495 {
2496  // For now only meshCutter has storable/retrievable data.
2497  meshCutter_.storeData
2498  (
2499  pointsToStore,
2500  facesToStore,
2501  cellsToStore
2502  );
2503 }
2504 
2505 
2508  const mapPolyMesh& map,
2509  const labelList& changedFaces,
2510  const Map<label>& pointsToRestore,
2511  const Map<label>& facesToRestore,
2512  const Map<label>& cellsToRestore
2513 )
2514 {
2515  // For now only meshCutter has storable/retrievable data.
2516 
2517  // Update numbering of cells/vertices.
2518  meshCutter_.updateMesh
2519  (
2520  map,
2521  pointsToRestore,
2522  facesToRestore,
2523  cellsToRestore
2524  );
2525 
2526  // Update surfaceIndex
2527  updateList(map.faceMap(), label(-1), surfaceIndex_);
2528 
2529  // Update cached intersection information
2530  updateIntersections(changedFaces);
2531 
2532  // Update maintained faces
2533  forAll(userFaceData_, i)
2534  {
2535  labelList& data = userFaceData_[i].second();
2536 
2537  if (userFaceData_[i].first() == KEEPALL)
2538  {
2539  // extend list with face-from-face data
2540  updateList(map.faceMap(), label(-1), data);
2541  }
2542  else if (userFaceData_[i].first() == MASTERONLY)
2543  {
2544  // keep master only
2545  labelList newFaceData(map.faceMap().size(), -1);
2546 
2547  forAll(newFaceData, faceI)
2548  {
2549  label oldFaceI = map.faceMap()[faceI];
2550 
2551  if (oldFaceI >= 0 && map.reverseFaceMap()[oldFaceI] == faceI)
2552  {
2553  newFaceData[faceI] = data[oldFaceI];
2554  }
2555  }
2556  data.transfer(newFaceData);
2557  }
2558  else
2559  {
2560  // remove any face that has been refined i.e. referenced more than
2561  // once.
2562 
2563  // 1. Determine all old faces that get referenced more than once.
2564  // These get marked with -1 in reverseFaceMap
2565  labelList reverseFaceMap(map.reverseFaceMap());
2566 
2567  forAll(map.faceMap(), faceI)
2568  {
2569  label oldFaceI = map.faceMap()[faceI];
2570 
2571  if (oldFaceI >= 0)
2572  {
2573  if (reverseFaceMap[oldFaceI] != faceI)
2574  {
2575  // faceI is slave face. Mark old face.
2576  reverseFaceMap[oldFaceI] = -1;
2577  }
2578  }
2579  }
2580 
2581  // 2. Map only faces with intact reverseFaceMap
2582  labelList newFaceData(map.faceMap().size(), -1);
2583  forAll(newFaceData, faceI)
2584  {
2585  label oldFaceI = map.faceMap()[faceI];
2586 
2587  if (oldFaceI >= 0)
2588  {
2589  if (reverseFaceMap[oldFaceI] == faceI)
2590  {
2591  newFaceData[faceI] = data[oldFaceI];
2592  }
2593  }
2594  }
2595  data.transfer(newFaceData);
2596  }
2597  }
2598 }
2599 
2600 
2602 {
2603  bool writeOk =
2604  mesh_.write()
2605  && meshCutter_.write()
2606  && surfaceIndex_.write();
2607 
2608 
2609  // Make sure that any distributed surfaces (so ones which probably have
2610  // been changed) get written as well.
2611  // Note: should ideally have some 'modified' flag to say whether it
2612  // has been changed or not.
2613  searchableSurfaces& geometry =
2614  const_cast<searchableSurfaces&>(surfaces_.geometry());
2615 
2616  forAll(geometry, i)
2617  {
2618  searchableSurface& s = geometry[i];
2619 
2620  // Check if instance() of surface is not constant or system.
2621  // Is good hint that surface is distributed.
2622  if
2623  (
2624  s.instance() != s.time().system()
2625  && s.instance() != s.time().caseSystem()
2626  && s.instance() != s.time().constant()
2627  && s.instance() != s.time().caseConstant()
2628  )
2629  {
2630  // Make sure it gets written to current time, not constant.
2631  s.instance() = s.time().timeName();
2632  writeOk = writeOk && s.write();
2633  }
2634  }
2635 
2636  return writeOk;
2637 }
2638 
2639 
2642  const polyMesh& mesh,
2643  const labelList& meshPoints
2644 )
2645 {
2646  const globalIndex globalPoints(meshPoints.size());
2647 
2648  labelList myPoints(meshPoints.size());
2649  forAll(meshPoints, pointI)
2650  {
2651  myPoints[pointI] = globalPoints.toGlobal(pointI);
2652  }
2653 
2655  (
2656  mesh,
2657  meshPoints,
2658  myPoints,
2659  minEqOp<label>(),
2660  labelMax
2661  );
2662 
2663 
2664  PackedBoolList isPatchMasterPoint(meshPoints.size());
2665  forAll(meshPoints, pointI)
2666  {
2667  if (myPoints[pointI] == globalPoints.toGlobal(pointI))
2668  {
2669  isPatchMasterPoint[pointI] = true;
2670  }
2671  }
2672 
2673  return isPatchMasterPoint;
2674 }
2675 
2676 
2679  const polyMesh& mesh,
2680  const labelList& meshEdges
2681 )
2682 {
2683  const globalIndex globalEdges(meshEdges.size());
2684 
2685  labelList myEdges(meshEdges.size());
2686  forAll(meshEdges, edgeI)
2687  {
2688  myEdges[edgeI] = globalEdges.toGlobal(edgeI);
2689  }
2690 
2692  (
2693  mesh,
2694  meshEdges,
2695  myEdges,
2696  minEqOp<label>(),
2697  labelMax
2698  );
2699 
2700 
2701  PackedBoolList isMasterEdge(meshEdges.size());
2702  forAll(meshEdges, edgeI)
2703  {
2704  if (myEdges[edgeI] == globalEdges.toGlobal(edgeI))
2705  {
2706  isMasterEdge[edgeI] = true;
2707  }
2708  }
2709 
2710  return isMasterEdge;
2711 }
2712 
2713 
2714 void Foam::meshRefinement::printMeshInfo(const bool debug, const string& msg)
2715 const
2716 {
2717  const globalMeshData& pData = mesh_.globalData();
2718 
2719  if (debug)
2720  {
2721  Pout<< msg.c_str()
2722  << " : cells(local):" << mesh_.nCells()
2723  << " faces(local):" << mesh_.nFaces()
2724  << " points(local):" << mesh_.nPoints()
2725  << endl;
2726  }
2727 
2728  {
2729  PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh_));
2730  label nMasterFaces = 0;
2731  forAll(isMasterFace, i)
2732  {
2733  if (isMasterFace[i])
2734  {
2735  nMasterFaces++;
2736  }
2737  }
2738 
2739  PackedBoolList isMeshMasterPoint(syncTools::getMasterPoints(mesh_));
2740  label nMasterPoints = 0;
2741  forAll(isMeshMasterPoint, i)
2742  {
2743  if (isMeshMasterPoint[i])
2744  {
2745  nMasterPoints++;
2746  }
2747  }
2748 
2749  Info<< msg.c_str()
2750  << " : cells:" << pData.nTotalCells()
2751  << " faces:" << returnReduce(nMasterFaces, sumOp<label>())
2752  << " points:" << returnReduce(nMasterPoints, sumOp<label>())
2753  << endl;
2754  }
2755 
2756 
2757  //if (debug)
2758  {
2759  const labelList& cellLevel = meshCutter_.cellLevel();
2760 
2761  labelList nCells(gMax(cellLevel)+1, 0);
2762 
2763  forAll(cellLevel, cellI)
2764  {
2765  nCells[cellLevel[cellI]]++;
2766  }
2767 
2770 
2771  Info<< "Cells per refinement level:" << endl;
2772  forAll(nCells, levelI)
2773  {
2774  Info<< " " << levelI << '\t' << nCells[levelI]
2775  << endl;
2776  }
2777  }
2778 }
2779 
2780 
2781 //- Return either time().constant() or oldInstance
2783 {
2784  if (overwrite_ && mesh_.time().timeIndex() == 0)
2785  {
2786  return oldInstance_;
2787  }
2788  else
2789  {
2790  return mesh_.time().timeName();
2791  }
2792 }
2793 
2794 
2796 {
2797  // Note: use time().timeName(), not meshRefinement::timeName()
2798  // so as to dump the fields to 0, not to constant.
2799  {
2800  volScalarField volRefLevel
2801  (
2802  IOobject
2803  (
2804  "cellLevel",
2805  mesh_.time().timeName(),
2806  mesh_,
2809  false
2810  ),
2811  mesh_,
2812  dimensionedScalar("zero", dimless, 0),
2813  zeroGradientFvPatchScalarField::typeName
2814  );
2815 
2816  const labelList& cellLevel = meshCutter_.cellLevel();
2817 
2818  forAll(volRefLevel, cellI)
2819  {
2820  volRefLevel[cellI] = cellLevel[cellI];
2821  }
2822 
2823  volRefLevel.write();
2824  }
2825 
2826  // Dump pointLevel
2827  {
2828  const pointMesh& pMesh = pointMesh::New(mesh_);
2829 
2830  pointScalarField pointRefLevel
2831  (
2832  IOobject
2833  (
2834  "pointLevel",
2835  mesh_.time().timeName(),
2836  mesh_,
2839  false
2840  ),
2841  pMesh,
2842  dimensionedScalar("zero", dimless, 0)
2843  );
2844 
2845  const labelList& pointLevel = meshCutter_.pointLevel();
2846 
2847  forAll(pointRefLevel, pointI)
2848  {
2849  pointRefLevel[pointI] = pointLevel[pointI];
2850  }
2851 
2852  pointRefLevel.write();
2853  }
2854 }
2855 
2856 
2858 {
2859  {
2860  const pointField& cellCentres = mesh_.cellCentres();
2861 
2862  OFstream str(prefix + "_edges.obj");
2863  label vertI = 0;
2864  Pout<< "meshRefinement::dumpIntersections :"
2865  << " Writing cellcentre-cellcentre intersections to file "
2866  << str.name() << endl;
2867 
2868 
2869  // Redo all intersections
2870  // ~~~~~~~~~~~~~~~~~~~~~~
2871 
2872  // Get boundary face centre and level. Coupled aware.
2873  labelList neiLevel(mesh_.nFaces()-mesh_.nInternalFaces());
2874  pointField neiCc(mesh_.nFaces()-mesh_.nInternalFaces());
2875  calcNeighbourData(neiLevel, neiCc);
2876 
2877  labelList intersectionFaces(intersectedFaces());
2878 
2879  // Collect segments we want to test for
2880  pointField start(intersectionFaces.size());
2881  pointField end(intersectionFaces.size());
2882 
2883  forAll(intersectionFaces, i)
2884  {
2885  label faceI = intersectionFaces[i];
2886  start[i] = cellCentres[mesh_.faceOwner()[faceI]];
2887 
2888  if (mesh_.isInternalFace(faceI))
2889  {
2890  end[i] = cellCentres[mesh_.faceNeighbour()[faceI]];
2891  }
2892  else
2893  {
2894  end[i] = neiCc[faceI-mesh_.nInternalFaces()];
2895  }
2896  }
2897 
2898  // Extend segments a bit
2899  {
2900  const vectorField smallVec(ROOTSMALL*(end-start));
2901  start -= smallVec;
2902  end += smallVec;
2903  }
2904 
2905 
2906  // Do tests in one go
2907  labelList surfaceHit;
2908  List<pointIndexHit> surfaceHitInfo;
2909  surfaces_.findAnyIntersection
2910  (
2911  start,
2912  end,
2913  surfaceHit,
2914  surfaceHitInfo
2915  );
2916 
2917  forAll(intersectionFaces, i)
2918  {
2919  if (surfaceHit[i] != -1)
2920  {
2921  meshTools::writeOBJ(str, start[i]);
2922  vertI++;
2923  meshTools::writeOBJ(str, surfaceHitInfo[i].hitPoint());
2924  vertI++;
2925  meshTools::writeOBJ(str, end[i]);
2926  vertI++;
2927  str << "l " << vertI-2 << ' ' << vertI-1 << nl
2928  << "l " << vertI-1 << ' ' << vertI << nl;
2929  }
2930  }
2931  }
2932 
2933  Pout<< endl;
2934 }
2935 
2936 
2939  const debugType debugFlags,
2940  const writeType writeFlags,
2941  const fileName& prefix
2942 ) const
2943 {
2944  if (writeFlags & WRITEMESH)
2945  {
2946  write();
2947  }
2948  if (writeFlags & WRITELEVELS)
2949  {
2950  dumpRefinementLevel();
2951  }
2952  if (debugFlags & OBJINTERSECTIONS && prefix.size())
2953  {
2954  dumpIntersections(prefix);
2955  }
2956 }
2957 
2958 
2960 {
2961  return writeLevel_;
2962 }
2963 
2964 
2966 {
2967  writeLevel_ = flags;
2968 }
2969 
2970 
2972 {
2973  return outputLevel_;
2974 }
2975 
2976 
2978 {
2979  outputLevel_ = flags;
2980 }
2981 
2982 
2983 // ************************************************************************* //
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
void storeData(const labelList &pointsToStore, const labelList &facesToStore, const labelList &cellsToStore)
Signal points/face/cells for which to store data.
labelList getExposedFaces(const labelList &cellsToRemove) const
Get labels of exposed faces.
Definition: removeCells.C:73
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:309
Output to file stream.
Definition: OFstream.H:81
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:380
A List with indirect addressing.
Definition: IndirectList.H:102
fileName caseConstant() const
Return constant name for the case.
Definition: TimePaths.C:123
label countHits() const
Count number of intersections (local)
const boolList & flipMap() const
Return face flip map.
Definition: faceZone.H:249
Simple random number generator.
Definition: Random.H:49
const faceZoneMesh & faceZones() const
Return face zone mesh.
Definition: polyMesh.H:463
Pre-declare related SubField type.
Definition: Field.H:61
cachedRandom rndGen(label(0),-1)
void setSize(const label)
Reset size of PtrList. If extending the PtrList, new entries are.
Definition: PtrList.C:142
label addFace(const face &f, const label own, const label nei, const label masterPointID, const label masterEdgeID, const label masterFaceID, const bool flipFaceFlux, const label patchID, const label zoneID, const bool zoneFlip)
Add face to cells. Return new face label.
static PackedBoolList getMasterFaces(const polyMesh &)
Get per face whether it is uncoupled or a master of a.
Definition: syncTools.C:156
static autoPtr< fvPatch > New(const polyPatch &, const fvBoundaryMesh &)
Return a pointer to a new patch created on freestore from polyPatch.
Definition: fvPatchNew.C:33
void selectSeparatedCoupledFaces(boolList &) const
Select coupled faces that are not collocated.
This boundary condition is not designed to be evaluated; it is assmued that the value is assigned via...
bool write() const
Write mesh and all data.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
Container for data on surfaces used for surface-driven refinement. Contains all the data about the le...
label size() const
Return the number of elements in the PtrList.
Definition: PtrListI.H:32
label nFaces() const
virtual bool separated() const
Are the planes separated.
const labelList & reverseFaceMap() const
Reverse face map.
Definition: mapPolyMesh.H:497
bool set(const label) const
Is element set.
Definition: PtrListI.H:107
static label findRegion(const polyMesh &, const labelList &cellRegion, const vector &perturbVec, const point &p)
Find region point is in. Uses optional perturbation to re-test.
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
virtual bool coupled() const
Return true if this patch is geometrically coupled (i.e. faces and.
Definition: polyPatch.H:310
vector point
Point is a vector.
Definition: point.H:41
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
Definition: removeCells.H:115
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: contiguous.H:49
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject( name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE ))
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
A templated 1D list of pointers to objects of type <T>, where the size of the array is known and used...
Definition: List.H:61
const vectorField::subField faceAreas() const
Return face normals.
Definition: polyPatch.C:290
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:390
Base class of (analytical or triangulated) surface. Encapsulates all the search routines. WIP.
dimensioned< scalar > mag(const dimensioned< Type > &)
void clear()
Delete object (if the pointer is valid) and set pointer to NULL.
Definition: autoPtrI.H:126
labelList f(nPoints)
labelList intersectedPoints() const
Get points on surfaces with intersection and boundary faces.
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:158
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
virtual labelList decompose(const pointField &points, const scalarField &pointWeights)
Return for every coordinate the wanted processor number.
static const pointMesh & New(const polyMesh &mesh)
static const NamedEnum< IOdebugType, 5 > IOdebugTypeNames
bool valid() const
Return true if the autoPtr valid (ie, the pointer is set).
Definition: autoPtrI.H:83
Definition: ops.H:70
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
const labelUList & faceCells() const
Return face-cell addressing.
Definition: polyPatch.C:316
static outputType outputLevel()
Get/set output level.
Foam::fvBoundaryMesh.
scalar f1
Definition: createFields.H:28
const Type & second() const
Return second.
Definition: Pair.H:99
A bit-packed bool list.
Calculates a unique integer (label so might not have enough room - 2G max) for processor + local inde...
Definition: globalIndex.H:63
A class for handling words, derived from string.
Definition: word.H:59
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
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:741
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:75
void updateMesh(const mapPolyMesh &, const labelList &changedFaces)
Update for external change to mesh. changedFaces are in new mesh.
static labelList findDuplicateFaces(const primitiveMesh &, const labelList &)
Helper routine to find baffles (two boundary faces using the.
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
static const NamedEnum< IOwriteType, 4 > IOwriteTypeNames
Given list of cells to remove insert all the topology changes.
Definition: removeCells.H:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
void setRefinement(const labelList &cellsToRemove, const labelList &facesToExpose, const labelList &patchIDs, polyTopoChange &) const
Play commands into polyTopoChange to remove cells.
Definition: removeCells.C:179
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: UListI.H:58
const fileName & instance() const
Definition: IOobject.H:337
void dumpRefinementLevel() const
Write refinement level as volScalarFields for postprocessing.
Database for solution data, solver performance and other reduced data.
Definition: data.H:52
autoPtr< mapPolyMesh > splitMeshRegions(const labelList &globalToMasterPatch, const labelList &globalToSlavePatch, const point &keepPoint)
Split mesh. Keep part containing point.
static autoPtr< indirectPrimitivePatch > makePatch(const polyMesh &, const labelList &)
Create patch from set of patches.
fileName caseSystem() const
Return system name for the case.
Definition: TimePaths.C:110
PrimitivePatch< face, IndirectList, const pointField & > indirectPrimitivePatch
Foam::indirectPrimitivePatch.
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
label size() const
Number of entries.
Definition: PackedListI.H:722
static void syncEdgeList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh edges.
static PackedBoolList getMasterPoints(const polyMesh &)
Get per point whether it is uncoupled or a master of a.
Definition: syncTools.C:68
void setConstraints(const polyMesh &mesh, boolList &blockedFace, PtrList< labelList > &specifiedProcessorFaces, labelList &specifiedProcessor, List< labelPair > &explicitConnections)
Helper: extract constraints:
messageStream Info
Accumulating histogram of values. Specified bin resolution automatic generation of bins...
Definition: distribution.H:51
Mesh representing a set of points created from polyMesh.
Definition: pointMesh.H:48
dynamicFvMesh & mesh
void printMeshInfo(const bool, const string &) const
Print some mesh stats.
const fileName & pointsInstance() const
Return the current instance directory for points.
Definition: polyMesh.C:818
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
void distribute(const mapDistributePolyMesh &)
Update local numbering for mesh redistribution.
Sends/receives parts of mesh+fvfields to neighbouring processors. Used in load balancing.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
static void syncFaceList(const polyMesh &mesh, UList< T > &l, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:380
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
autoPtr< mapDistributePolyMesh > balance(const bool keepZoneFaces, const bool keepBaffles, const scalarField &cellWeights, decompositionMethod &decomposer, fvMeshDistribute &distributor)
Redecompose according to cell count.
const word & constant() const
Return constant name.
Definition: TimePaths.H:124
Namespace for OpenFOAM.
runTime write()
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
label whichFace(const label globalCellID) const
Helper function to re-direct to zone::localID(...)
Definition: faceZone.C:317
void setInstance(const fileName &)
Set instance of all local IOobjects.
patches[0]
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
static labelPairList findDuplicateFacePairs(const polyMesh &)
Helper routine to find all baffles (two boundary faces.
const vectorField::subField faceCentres() const
Return face centres.
Definition: polyPatch.C:284
wordList names() const
Return a list of patch names.
virtual bool write() const
Write using setting from DB.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
static void checkCoupledFaceZones(const polyMesh &)
Helper function: check that face zones are synced.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:386
static const char nl
Definition: Ostream.H:260
const double e
Elementary charge.
Definition: doubleFloat.H:78
Calculates points shared by more than two processor patches or cyclic patches.
Definition: globalPoints.H:100
void setSize(const label)
Reset size of List.
Definition: List.C:318
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
virtual bool parallel() const
Are the cyclic planes parallel.
autoPtr< mapPolyMesh > splitFaces(const labelList &splitFaces, const labelPairList &splits)
Split faces into two.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
#define WarningIn(functionName)
Report a warning using Foam::Warning.
static tmp< pointVectorField > makeDisplacementField(const pointMesh &pMesh, const labelList &adaptPatchIDs)
Helper function to make a pointVectorField with correct.
treeBoundBox extend(Random &, const scalar s) const
Return slightly wider bounding box.
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1035
Foam::polyBoundaryMesh.
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
static void testSyncPointList(const string &msg, const polyMesh &mesh, const List< scalar > &fld)
Abstract base class for decomposition.
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:118
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
#define forAll(list, i)
Definition: UList.H:421
static bool constraintType(const word &pt)
Return true if the given type is a constraint type.
Definition: polyPatch.C:246
const pointBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: pointMesh.H:106
static PackedBoolList getMasterEdges(const polyMesh &mesh, const labelList &meshEdges)
Determine master edge for subset of edges. If coupled.
static PackedBoolList getMasterPoints(const polyMesh &mesh, const labelList &meshPoints)
Determine master point for subset of points. If coupled.
ListType renumber(const labelUList &oldToNew, const ListType &)
Renumber the values (not the indices) of a list.
label nTotalCells() const
Return total number of cells in decomposed mesh.
const labelList & faceMap() const
Old face map.
Definition: mapPolyMesh.H:406
label findCell(const point &p, const cellDecomposition=CELL_TETS) const
Find cell enclosing this location and return index.
Definition: polyMesh.C:1476
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &l)
Swap coupled boundary face values.
Definition: syncTools.H:429
label whichPatch(const label faceIndex) const
Return patch index for a given face label.
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
List< treeBoundBox > meshBb(1, treeBoundBox( boundBox(coarseMesh.points(), false) ).extend(rndGen, 1e-3))
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
static label appendPatch(fvMesh &, const label insertPatchI, const word &, const dictionary &)
Helper:append patch to end of mesh.
Class containing mesh-to-mesh mapping information after a mesh distribution where we send parts of me...
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const word & name() const
Return name.
Definition: IOobject.H:260
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:404
const word & name() const
Return name.
Definition: zone.H:150
static void syncPointList(const polyMesh &, List< T > &, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
IOwriteType
Enumeration for what to write.
fileName::Type type(const fileName &)
Return the file type: DIRECTORY or FILE.
Definition: POSIX.C:589
static autoPtr< polyPatch > New(const word &patchType, const word &name, const label size, const label start, const label index, const polyBoundaryMesh &bm)
Return a pointer to a new patch created on freestore from.
Definition: polyPatchNew.C:32
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:421
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:52
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
Encapsulates queries for features.
static labelList countCells(const labelList &)
Helper function: count cells per processor in wanted distribution.
static writeType writeLevel()
Get/set write level.
Various mesh related information for a parallel run. Upon construction, constructs all info using par...
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:300
autoPtr< mapDistributePolyMesh > distribute(const labelList &dist)
Send cells to neighbours according to distribution.
label nInternalFaces() const
void modifyFace(const face &f, const label faceI, const label own, const label nei, const bool flipFaceFlux, const label patchID, const label zoneID, const bool zoneFlip)
Modify vertices or cell of face.
static const NamedEnum< IOoutputType, 1 > IOoutputTypeNames
static void calculateEdgeWeights(const polyMesh &mesh, const PackedBoolList &isMasterEdge, const labelList &meshPoints, const edgeList &edges, scalarField &edgeWeights, scalarField &invSumWeight)
Helper: calculate edge weights (1/length)
labelList intersectedFaces() const
Get faces with intersection.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
void set(entry *)
Assign a new entry, overwrite any existing entry.
Definition: dictionary.C:866
error FatalError
const PtrList< surfaceZonesInfo > & surfZones() const
List< label > labelList
A List of labels.
Definition: labelList.H:56
void clearOut()
Clear all geometry and addressing.
Definition: fvMesh.C:231
A class for handling file names.
Definition: fileName.H:69
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
static const Vector zero
Definition: Vector.H:80
Pair< label > labelPair
Label pair.
Definition: labelPair.H:48
const Type & first() const
Return first.
Definition: Pair.H:87
IOoutputType
Enumeration for what to output.
const Time & time() const
Return time.
Definition: IOobject.C:251
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
Direct mesh changes based on v1.3 polyTopoChange syntax.
A List obtained as a section of another List.
Definition: SubList.H:53
IOdebugType
Enumeration for what to debug.
Container for searchableSurfaces.
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:47
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:97
word timeName() const
Replacement for Time::timeName() : return oldInstance (if.
const Time & time() const
Return time.
void checkData()
Debugging: check that all faces still obey start()>end()
void reorder(const labelUList &)
Reorders elements. Ordering does not have to be done in.
Definition: PtrList.C:208
labelList meshedPatches() const
Get patchIDs for patches added in addMeshedPatch.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1060
wordList names() const
Return a list of zone names.
Definition: ZoneMesh.C:269
Foam::pointBoundaryMesh.
label addMeshedPatch(const word &name, const dictionary &)
Add patch originating from meshing. Update meshedPatches_.
static void swapBoundaryFacePositions(const polyMesh &mesh, UList< point > &l)
Swap coupled positions.
Definition: syncTools.H:445
static void syncBoundaryFacePositions(const polyMesh &mesh, UList< point > &l, const CombineOp &cop)
Synchronize locations on boundary faces only.
Definition: syncTools.H:362
static label addPatch(fvMesh &, const word &name, const dictionary &)
Helper:add patch to mesh. Update all registered fields.
void reorder(const labelUList &, const bool validBoundary)
Reorders patches. Ordering does not have to be done in.
The coupledPolyPatch is an abstract base class for patches that couple regions of the computational d...
void distributeFaceData(List< T > &lst) const
Distribute list of face data.
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:209
label findPatchID(const word &patchName) const
Find patch index given a name.
Type gMax(const FieldField< Field, Type > &f)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:117
bool found(const Key &) const
Return true if hashedEntry is found in table.
Definition: HashTable.C:109
A class for managing temporary objects.
Definition: PtrList.H:118
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.
void dumpIntersections(const fileName &prefix) const
Debug: Write intersection information to OBJ format.
This class separates the mesh into distinct unconnected regions, each of which is then given a label ...
Definition: regionSplit.H:116
label nPoints() const
defineTypeNameAndDebug(combustionModel, 0)
word timeName
Definition: getTimeIndex.H:3
prefixOSstream Pout(cout,"Pout")
Definition: IOstreams.H:53
unsigned int get(const label) const
Get value at index I.
Definition: PackedListI.H:972
Encapsulates queries for volume refinement (&#39;refine all cells within shell&#39;).
Definition: shellSurfaces.H:52
static const label labelMax
Definition: label.H:62
const word & system() const
Return system name.
Definition: TimePaths.H:114
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:552