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