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