dynamicRefineFvMesh.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2018-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "dynamicRefineFvMesh.H"
31 #include "surfaceInterpolate.H"
32 #include "volFields.H"
33 #include "polyTopoChange.H"
34 #include "surfaceFields.H"
35 #include "syncTools.H"
36 #include "pointFields.H"
37 #include "sigFpe.H"
38 #include "cellSet.H"
39 #include "HashOps.H"
40 
41 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 
43 namespace Foam
44 {
45  defineTypeNameAndDebug(dynamicRefineFvMesh, 0);
46  addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineFvMesh, IOobject);
47  addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineFvMesh, doInit);
48 }
49 
50 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
51 
53 (
54  bitSet& unrefineableCell
55 ) const
56 {
57  if (protectedCell_.empty())
58  {
59  unrefineableCell.clear();
60  return;
61  }
62 
63  const labelList& cellLevel = meshCutter_.cellLevel();
64 
65  unrefineableCell = protectedCell_;
66 
67  // Get neighbouring cell level
68  labelList neiLevel(nFaces()-nInternalFaces());
69 
70  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
71  {
72  neiLevel[facei-nInternalFaces()] = cellLevel[faceOwner()[facei]];
73  }
74  syncTools::swapBoundaryFaceList(*this, neiLevel);
75 
76 
77  bitSet seedFace;
78 
79  while (true)
80  {
81  // Pick up faces on border of protected cells
82  seedFace.reset();
83  seedFace.resize(nFaces());
84 
85  for (label facei = 0; facei < nInternalFaces(); ++facei)
86  {
87  const label own = faceOwner()[facei];
88  const label nei = faceNeighbour()[facei];
89 
90  if
91  (
92  // Protected owner
93  (
94  unrefineableCell.test(own)
95  && (cellLevel[nei] > cellLevel[own])
96  )
97  ||
98  // Protected neighbour
99  (
100  unrefineableCell.test(nei)
101  && (cellLevel[own] > cellLevel[nei])
102  )
103  )
104  {
105  seedFace.set(facei);
106  }
107  }
108  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
109  {
110  const label own = faceOwner()[facei];
111 
112  if
113  (
114  // Protected owner
115  (
116  unrefineableCell.test(own)
117  && (neiLevel[facei-nInternalFaces()] > cellLevel[own])
118  )
119  )
120  {
121  seedFace.set(facei);
122  }
123  }
124 
125  syncTools::syncFaceList(*this, seedFace, orEqOp<unsigned int>());
126 
127 
128  // Extend unrefineableCell
129  bool hasExtended = false;
130 
131  for (label facei = 0; facei < nInternalFaces(); ++facei)
132  {
133  if (seedFace.test(facei))
134  {
135  if (unrefineableCell.set(faceOwner()[facei]))
136  {
137  hasExtended = true;
138  }
139  if (unrefineableCell.set(faceNeighbour()[facei]))
140  {
141  hasExtended = true;
142  }
143  }
144  }
145  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
146  {
147  if (seedFace.test(facei))
148  {
149  const label own = faceOwner()[facei];
150 
151  if (unrefineableCell.set(own))
152  {
153  hasExtended = true;
154  }
155  }
156  }
157 
158  if (!returnReduce(hasExtended, orOp<bool>()))
159  {
160  break;
161  }
162  }
163 }
164 
165 
167 {
168  dictionary refineDict
169  (
171  (
172  IOobject
173  (
174  "dynamicMeshDict",
175  time().constant(),
176  *this,
179  false
180  )
181  ).optionalSubDict(typeName + "Coeffs")
182  );
183 
184  auto fluxVelocities = refineDict.get<List<Pair<word>>>("correctFluxes");
185 
186  // Rework into hashtable.
187  correctFluxes_.resize(fluxVelocities.size());
188  for (const auto& pr : fluxVelocities)
189  {
190  correctFluxes_.insert(pr.first(), pr.second());
191  }
192 
193  refineDict.readEntry("dumpLevel", dumpLevel_);
194 }
195 
196 
198 {
200 
201  // Correct the flux for modified/added faces. All the faces which only
202  // have been renumbered will already have been handled by the mapping.
203  {
204  const labelList& faceMap = mpm.faceMap();
205  const labelList& reverseFaceMap = mpm.reverseFaceMap();
206 
207  // Storage for any master faces. These will be the original faces
208  // on the coarse cell that get split into four (or rather the
209  // master face gets modified and three faces get added from the master)
210  // Estimate number of faces created
211 
212  bitSet masterFaces(nFaces());
213 
214  forAll(faceMap, facei)
215  {
216  const label oldFacei = faceMap[facei];
217 
218  if (oldFacei >= 0)
219  {
220  const label masterFacei = reverseFaceMap[oldFacei];
221 
222  if (masterFacei < 0)
223  {
225  << "Problem: should not have removed faces"
226  << " when refining."
227  << nl << "face:" << facei << endl
228  << abort(FatalError);
229  }
230  else if (masterFacei != facei)
231  {
232  masterFaces.set(masterFacei);
233  }
234  }
235  }
236 
237  if (debug)
238  {
239  Pout<< "Found " << masterFaces.count() << " split faces " << endl;
240  }
241 
243  (
244  lookupClass<surfaceScalarField>()
245  );
246  forAllIters(fluxes, iter)
247  {
248  if (!correctFluxes_.found(iter.key()))
249  {
251  << "Cannot find surfaceScalarField " << iter.key()
252  << " in user-provided flux mapping table "
253  << correctFluxes_ << endl
254  << " The flux mapping table is used to recreate the"
255  << " flux on newly created faces." << endl
256  << " Either add the entry if it is a flux or use ("
257  << iter.key() << " none) to suppress this warning."
258  << endl;
259  continue;
260  }
261 
262  const word& UName = correctFluxes_[iter.key()];
263 
264  if (UName == "none")
265  {
266  continue;
267  }
268 
269  surfaceScalarField& phi = *iter();
270 
271  if (UName == "NaN")
272  {
273  Pout<< "Setting surfaceScalarField " << iter.key()
274  << " to NaN" << endl;
275 
277 
278  continue;
279  }
280 
281  if (debug)
282  {
283  Pout<< "Mapping flux " << iter.key()
284  << " using interpolated flux " << UName
285  << endl;
286  }
287 
288  const surfaceScalarField phiU
289  (
291  (
292  lookupObject<volVectorField>(UName)
293  )
294  & Sf()
295  );
296 
297  // Recalculate new internal faces.
298  for (label facei = 0; facei < nInternalFaces(); ++facei)
299  {
300  const label oldFacei = faceMap[facei];
301 
302  if (oldFacei == -1)
303  {
304  // Inflated/appended
305  phi[facei] = phiU[facei];
306  }
307  else if (reverseFaceMap[oldFacei] != facei)
308  {
309  // face-from-masterface
310  phi[facei] = phiU[facei];
311  }
312  }
313 
314  // Recalculate new boundary faces.
315  surfaceScalarField::Boundary& phiBf = phi.boundaryFieldRef();
316 
317  forAll(phiBf, patchi)
318  {
319  fvsPatchScalarField& patchPhi = phiBf[patchi];
320  const fvsPatchScalarField& patchPhiU =
321  phiU.boundaryField()[patchi];
322 
323  label facei = patchPhi.patch().start();
324 
325  forAll(patchPhi, i)
326  {
327  const label oldFacei = faceMap[facei];
328 
329  if (oldFacei == -1)
330  {
331  // Inflated/appended
332  patchPhi[i] = patchPhiU[i];
333  }
334  else if (reverseFaceMap[oldFacei] != facei)
335  {
336  // face-from-masterface
337  patchPhi[i] = patchPhiU[i];
338  }
339 
340  ++facei;
341  }
342  }
343 
344  // Update master faces
345  for (const label facei : masterFaces)
346  {
347  if (isInternalFace(facei))
348  {
349  phi[facei] = phiU[facei];
350  }
351  else
352  {
353  const label patchi = boundaryMesh().whichPatch(facei);
354  const label i = facei - boundaryMesh()[patchi].start();
355 
356  const fvsPatchScalarField& patchPhiU =
357  phiU.boundaryField()[patchi];
358 
359  fvsPatchScalarField& patchPhi = phiBf[patchi];
360 
361  patchPhi[i] = patchPhiU[i];
362  }
363  }
364  }
365  }
366 
367  // Correct the flux for injected faces - these are the faces which have
368  // no correspondence to the old mesh (i.e. added without a masterFace, edge
369  // or point). An example is the internal faces from hexRef8.
370  {
371  const labelList& faceMap = mpm.faceMap();
372 
373  mapNewInternalFaces<scalar>(this->Sf(), this->magSf(), faceMap);
374  mapNewInternalFaces<vector>(this->Sf(), this->magSf(), faceMap);
375 
376  // No oriented fields of more complex type
377  mapNewInternalFaces<sphericalTensor>(faceMap);
378  mapNewInternalFaces<symmTensor>(faceMap);
379  mapNewInternalFaces<tensor>(faceMap);
380  }
381 }
382 
383 
384 // Refines cells, maps fields and recalculates (an approximate) flux
387 (
388  const labelList& cellsToRefine
389 )
390 {
391  // Mesh changing engine.
392  polyTopoChange meshMod(*this);
393 
394  // Play refinement commands into mesh changer.
395  meshCutter_.setRefinement(cellsToRefine, meshMod);
396 
397  // Create mesh (with inflation), return map from old to new mesh.
398  //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
399  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
400 
401  Info<< "Refined from "
402  << returnReduce(map().nOldCells(), sumOp<label>())
403  << " to " << globalData().nTotalCells() << " cells." << endl;
404 
405  if (debug)
406  {
407  // Check map.
408  for (label facei = 0; facei < nInternalFaces(); ++facei)
409  {
410  const label oldFacei = map().faceMap()[facei];
411 
412  if (oldFacei >= nInternalFaces())
413  {
415  << "New internal face:" << facei
416  << " fc:" << faceCentres()[facei]
417  << " originates from boundary oldFace:" << oldFacei
418  << abort(FatalError);
419  }
420  }
421  }
422 
423  // // Remove the stored tet base points
424  // tetBasePtIsPtr_.clear();
425  // // Remove the cell tree
426  // cellTreePtr_.clear();
427 
428  // Update fields
429  updateMesh(*map);
430 
431 
432  // Move mesh
433  /*
434  pointField newPoints;
435  if (map().hasMotionPoints())
436  {
437  newPoints = map().preMotionPoints();
438  }
439  else
440  {
441  newPoints = points();
442  }
443  movePoints(newPoints);
444  */
445 
446 
447 
448  // Update numbering of cells/vertices.
449  meshCutter_.updateMesh(*map);
450 
451  // Update numbering of protectedCell_
452  if (protectedCell_.size())
453  {
454  bitSet newProtectedCell(nCells());
455 
456  forAll(newProtectedCell, celli)
457  {
458  const label oldCelli = map().cellMap()[celli];
459  if (protectedCell_.test(oldCelli))
460  {
461  newProtectedCell.set(celli);
462  }
463  }
464  protectedCell_.transfer(newProtectedCell);
465  }
466 
467  // Debug: Check refinement levels (across faces only)
468  meshCutter_.checkRefinementLevels(-1, labelList());
469 
470  return map;
471 }
472 
473 
476 (
477  const labelList& splitPoints
478 )
479 {
480  polyTopoChange meshMod(*this);
481 
482  // Play refinement commands into mesh changer.
483  meshCutter_.setUnrefinement(splitPoints, meshMod);
484 
485 
486  // Save information on faces that will be combined
487  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
488 
489  // Find the faceMidPoints on cells to be combined.
490  // for each face resulting of split of face into four store the
491  // midpoint
492  Map<label> faceToSplitPoint(3*splitPoints.size());
493 
494  {
495  for (const label pointi : splitPoints)
496  {
497  const labelList& pEdges = pointEdges()[pointi];
498 
499  for (const label edgei : pEdges)
500  {
501  const label otherPointi = edges()[edgei].otherVertex(pointi);
502 
503  const labelList& pFaces = pointFaces()[otherPointi];
504 
505  for (const label facei : pFaces)
506  {
507  faceToSplitPoint.insert(facei, otherPointi);
508  }
509  }
510  }
511  }
512 
513 
514  // Change mesh and generate map.
515  //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
516  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
517 
518  Info<< "Unrefined from "
519  << returnReduce(map().nOldCells(), sumOp<label>())
520  << " to " << globalData().nTotalCells() << " cells."
521  << endl;
522 
523  // Update fields
524  updateMesh(*map);
525 
526 
527  // Move mesh
528  /*
529  pointField newPoints;
530  if (map().hasMotionPoints())
531  {
532  newPoints = map().preMotionPoints();
533  }
534  else
535  {
536  newPoints = points();
537  }
538  movePoints(newPoints);
539  */
540 
541  // Correct the flux for modified faces.
542  {
543  const labelList& reversePointMap = map().reversePointMap();
544  const labelList& reverseFaceMap = map().reverseFaceMap();
545 
547  (
548  lookupClass<surfaceScalarField>()
549  );
550  forAllIters(fluxes, iter)
551  {
552  if (!correctFluxes_.found(iter.key()))
553  {
555  << "Cannot find surfaceScalarField " << iter.key()
556  << " in user-provided flux mapping table "
557  << correctFluxes_ << endl
558  << " The flux mapping table is used to recreate the"
559  << " flux on newly created faces." << endl
560  << " Either add the entry if it is a flux or use ("
561  << iter.key() << " none) to suppress this warning."
562  << endl;
563  continue;
564  }
565 
566  const word& UName = correctFluxes_[iter.key()];
567 
568  if (UName == "none")
569  {
570  continue;
571  }
572 
573  DebugInfo
574  << "Mapping flux " << iter.key()
575  << " using interpolated flux " << UName
576  << endl;
577 
578 
579  surfaceScalarField& phi = *iter();
580  surfaceScalarField::Boundary& phiBf =
582 
583  const surfaceScalarField phiU
584  (
586  (
587  lookupObject<volVectorField>(UName)
588  )
589  & Sf()
590  );
591 
592 
593  forAllConstIters(faceToSplitPoint, iter)
594  {
595  const label oldFacei = iter.key();
596  const label oldPointi = iter.val();
597 
598  if (reversePointMap[oldPointi] < 0)
599  {
600  // midpoint was removed. See if face still exists.
601  const label facei = reverseFaceMap[oldFacei];
602 
603  if (facei >= 0)
604  {
605  if (isInternalFace(facei))
606  {
607  phi[facei] = phiU[facei];
608  }
609  else
610  {
611  label patchi = boundaryMesh().whichPatch(facei);
612  label i = facei - boundaryMesh()[patchi].start();
613 
614  const fvsPatchScalarField& patchPhiU =
615  phiU.boundaryField()[patchi];
616  fvsPatchScalarField& patchPhi = phiBf[patchi];
617  patchPhi[i] = patchPhiU[i];
618  }
619  }
620  }
621  }
622  }
623  }
624 
625 
626  // Update numbering of cells/vertices.
627  meshCutter_.updateMesh(*map);
628 
629  // Update numbering of protectedCell_
630  if (protectedCell_.size())
631  {
632  bitSet newProtectedCell(nCells());
633 
634  forAll(newProtectedCell, celli)
635  {
636  const label oldCelli = map().cellMap()[celli];
637  if (protectedCell_.test(oldCelli))
638  {
639  newProtectedCell.set(celli);
640  }
641  }
642  protectedCell_.transfer(newProtectedCell);
643  }
644 
645  // Debug: Check refinement levels (across faces only)
646  meshCutter_.checkRefinementLevels(-1, labelList());
647 
648  return map;
649 }
650 
651 
654 {
655  scalarField vFld(nCells(), -GREAT);
656 
657  forAll(pointCells(), pointi)
658  {
659  const labelList& pCells = pointCells()[pointi];
660 
661  for (const label celli : pCells)
662  {
663  vFld[celli] = max(vFld[celli], pFld[pointi]);
664  }
665  }
666  return vFld;
667 }
668 
669 
672 {
673  scalarField pFld(nPoints(), -GREAT);
674 
675  forAll(pointCells(), pointi)
676  {
677  const labelList& pCells = pointCells()[pointi];
678 
679  for (const label celli : pCells)
680  {
681  pFld[pointi] = max(pFld[pointi], vFld[celli]);
682  }
683  }
684  return pFld;
685 }
686 
687 
690 {
691  scalarField pFld(nPoints());
692 
693  forAll(pointCells(), pointi)
694  {
695  const labelList& pCells = pointCells()[pointi];
696 
697  scalar sum = 0.0;
698  for (const label celli : pCells)
699  {
700  sum += vFld[celli];
701  }
702  pFld[pointi] = sum/pCells.size();
703  }
704  return pFld;
705 }
706 
707 
709 (
710  const scalarField& fld,
711  const scalar minLevel,
712  const scalar maxLevel
713 ) const
714 {
715  scalarField c(fld.size(), scalar(-1));
716 
717  forAll(fld, i)
718  {
719  scalar err = min(fld[i]-minLevel, maxLevel-fld[i]);
720 
721  if (err >= 0)
722  {
723  c[i] = err;
724  }
725  }
726  return c;
727 }
728 
729 
731 (
732  const scalar lowerRefineLevel,
733  const scalar upperRefineLevel,
734  const scalarField& vFld,
735  bitSet& candidateCell
736 ) const
737 {
738  // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
739  // higher more desirable to be refined).
740  scalarField cellError
741  (
742  maxPointField
743  (
744  error
745  (
746  cellToPoint(vFld),
747  lowerRefineLevel,
748  upperRefineLevel
749  )
750  )
751  );
752 
753  // Mark cells that are candidates for refinement.
754  forAll(cellError, celli)
755  {
756  if (cellError[celli] > 0)
757  {
758  candidateCell.set(celli);
759  }
760  }
761 }
762 
763 
765 (
766  const label maxCells,
767  const label maxRefinement,
768  const bitSet& candidateCell
769 ) const
770 {
771  // Every refined cell causes 7 extra cells
772  label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
773 
774  const labelList& cellLevel = meshCutter_.cellLevel();
775 
776  // Mark cells that cannot be refined since they would trigger refinement
777  // of protected cells (since 2:1 cascade)
778  bitSet unrefineableCell;
779  calculateProtectedCells(unrefineableCell);
780 
781  // Count current selection
782  label nLocalCandidates = candidateCell.count();
783  label nCandidates = returnReduce(nLocalCandidates, sumOp<label>());
784 
785  // Collect all cells
786  DynamicList<label> candidates(nLocalCandidates);
787 
788  if (nCandidates < nTotToRefine)
789  {
790  for (const label celli : candidateCell)
791  {
792  if
793  (
794  (!unrefineableCell.test(celli))
795  && cellLevel[celli] < maxRefinement
796  )
797  {
798  candidates.append(celli);
799  }
800  }
801  }
802  else
803  {
804  // Sort by error? For now just truncate.
805  for (label level = 0; level < maxRefinement; ++level)
806  {
807  for (const label celli : candidateCell)
808  {
809  if
810  (
811  (!unrefineableCell.test(celli))
812  && cellLevel[celli] == level
813  )
814  {
815  candidates.append(celli);
816  }
817  }
818 
819  if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine)
820  {
821  break;
822  }
823  }
824  }
825 
826  // Guarantee 2:1 refinement after refinement
827  labelList consistentSet
828  (
829  meshCutter_.consistentRefinement
830  (
831  candidates.shrink(),
832  true // Add to set to guarantee 2:1
833  )
834  );
835 
836  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
837  << " cells for refinement out of " << globalData().nTotalCells()
838  << "." << endl;
839 
840  return consistentSet;
841 }
842 
843 
845 (
846  const scalar unrefineLevel,
847  const bitSet& markedCell,
848  const scalarField& pFld
849 ) const
850 {
851  // All points that can be unrefined
852  const labelList splitPoints(meshCutter_.getSplitPoints());
853 
854 
855  const labelListList& pointCells = this->pointCells();
856 
857  // If we have any protected cells make sure they also are not being
858  // unrefined
859 
860  bitSet protectedPoint(nPoints());
861 
862  if (protectedCell_.size())
863  {
864  // Get all points on a protected cell
865  forAll(pointCells, pointi)
866  {
867  for (const label celli : pointCells[pointi])
868  {
869  if (protectedCell_.test(celli))
870  {
871  protectedPoint.set(pointi);
872  break;
873  }
874  }
875  }
876 
878  (
879  *this,
880  protectedPoint,
882  0u
883  );
884 
885  DebugInfo<< "From "
886  << returnReduce(protectedCell_.count(), sumOp<label>())
887  << " protected cells found "
888  << returnReduce(protectedPoint.count(), sumOp<label>())
889  << " protected points." << endl;
890  }
891 
892 
893  DynamicList<label> newSplitPoints(splitPoints.size());
894 
895  for (const label pointi : splitPoints)
896  {
897  if (!protectedPoint[pointi] && pFld[pointi] < unrefineLevel)
898  {
899  // Check that all cells are not marked
900  bool hasMarked = false;
901 
902  for (const label celli : pointCells[pointi])
903  {
904  if (markedCell.test(celli))
905  {
906  hasMarked = true;
907  break;
908  }
909  }
910 
911  if (!hasMarked)
912  {
913  newSplitPoints.append(pointi);
914  }
915  }
916  }
917 
918 
919  newSplitPoints.shrink();
920 
921  // Guarantee 2:1 refinement after unrefinement
922  labelList consistentSet
923  (
924  meshCutter_.consistentUnrefinement
925  (
926  newSplitPoints,
927  false
928  )
929  );
930  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
931  << " split points out of a possible "
932  << returnReduce(splitPoints.size(), sumOp<label>())
933  << "." << endl;
934 
935  return consistentSet;
936 }
937 
938 
940 (
941  bitSet& markedCell
942 ) const
943 {
944  // Mark faces using any marked cell
945  bitSet markedFace(nFaces());
946 
947  for (const label celli : markedCell)
948  {
949  markedFace.set(cells()[celli]); // set multiple faces
950  }
951 
952  syncTools::syncFaceList(*this, markedFace, orEqOp<unsigned int>());
953 
954  // Update cells using any markedFace
955  for (label facei = 0; facei < nInternalFaces(); ++facei)
956  {
957  if (markedFace.test(facei))
958  {
959  markedCell.set(faceOwner()[facei]);
960  markedCell.set(faceNeighbour()[facei]);
961  }
962  }
963  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
964  {
965  if (markedFace.test(facei))
966  {
967  markedCell.set(faceOwner()[facei]);
968  }
969  }
970 }
971 
972 
974 (
975  bitSet& protectedCell
976 ) const
977 {
978  const labelList& cellLevel = meshCutter_.cellLevel();
979  const labelList& pointLevel = meshCutter_.pointLevel();
980 
981  labelList nAnchorPoints(nCells(), Zero);
982 
983  forAll(pointLevel, pointi)
984  {
985  const labelList& pCells = pointCells(pointi);
986 
987  for (const label celli : pCells)
988  {
989  if (pointLevel[pointi] <= cellLevel[celli])
990  {
991  // Check if cell has already 8 anchor points -> protect cell
992  if (nAnchorPoints[celli] == 8)
993  {
994  protectedCell.set(celli);
995  }
996 
997  if (!protectedCell.test(celli))
998  {
999  ++nAnchorPoints[celli];
1000  }
1001  }
1002  }
1003  }
1004 
1005 
1006  forAll(protectedCell, celli)
1007  {
1008  if (nAnchorPoints[celli] != 8)
1009  {
1010  protectedCell.set(celli);
1011  }
1012  }
1013 }
1014 
1015 
1016 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1017 
1018 Foam::dynamicRefineFvMesh::dynamicRefineFvMesh
1020  const IOobject& io,
1021  const bool doInit
1022 )
1023 :
1024  dynamicFvMesh(io, doInit),
1025  meshCutter_(*this)
1026 {
1027  if (doInit)
1028  {
1029  init(false); // do not initialise lower levels
1030  }
1031 }
1032 
1033 
1034 bool Foam::dynamicRefineFvMesh::init(const bool doInit)
1035 {
1036  if (doInit)
1037  {
1038  dynamicFvMesh::init(doInit);
1039  }
1040 
1041  protectedCell_.setSize(nCells());
1042  nRefinementIterations_ = 0;
1043  dumpLevel_ = false;
1044 
1045  // Read static part of dictionary
1046  readDict();
1047 
1048 
1049  const labelList& cellLevel = meshCutter_.cellLevel();
1050  const labelList& pointLevel = meshCutter_.pointLevel();
1051 
1052  // Set cells that should not be refined.
1053  // This is currently any cell which does not have 8 anchor points or
1054  // uses any face which does not have 4 anchor points.
1055  // Note: do not use cellPoint addressing
1056 
1057  // Count number of points <= cellLevel
1058  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1059 
1060  labelList nAnchors(nCells(), Zero);
1061 
1062  forAll(pointCells(), pointi)
1063  {
1064  const labelList& pCells = pointCells()[pointi];
1065 
1066  for (const label celli : pCells)
1067  {
1068  if (!protectedCell_.test(celli))
1069  {
1070  if (pointLevel[pointi] <= cellLevel[celli])
1071  {
1072  ++nAnchors[celli];
1073 
1074  if (nAnchors[celli] > 8)
1075  {
1076  protectedCell_.set(celli);
1077  }
1078  }
1079  }
1080  }
1081  }
1082 
1083 
1084  // Count number of points <= faceLevel
1085  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1086  // Bit tricky since proc face might be one more refined than the owner since
1087  // the coupled one is refined.
1088 
1089  {
1090  labelList neiLevel(nFaces());
1091 
1092  for (label facei = 0; facei < nInternalFaces(); ++facei)
1093  {
1094  neiLevel[facei] = cellLevel[faceNeighbour()[facei]];
1095  }
1096  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
1097  {
1098  neiLevel[facei] = cellLevel[faceOwner()[facei]];
1099  }
1100  syncTools::swapFaceList(*this, neiLevel);
1101 
1102 
1103  bitSet protectedFace(nFaces());
1104 
1105  forAll(faceOwner(), facei)
1106  {
1107  const label faceLevel = max
1108  (
1109  cellLevel[faceOwner()[facei]],
1110  neiLevel[facei]
1111  );
1112 
1113  const face& f = faces()[facei];
1114 
1115  label nAnchors = 0;
1116 
1117  for (const label pointi : f)
1118  {
1119  if (pointLevel[pointi] <= faceLevel)
1120  {
1121  ++nAnchors;
1122 
1123  if (nAnchors > 4)
1124  {
1125  protectedFace.set(facei);
1126  break;
1127  }
1128  }
1129  }
1130  }
1131 
1132  syncTools::syncFaceList(*this, protectedFace, orEqOp<unsigned int>());
1133 
1134  for (label facei = 0; facei < nInternalFaces(); ++facei)
1135  {
1136  if (protectedFace.test(facei))
1137  {
1138  protectedCell_.set(faceOwner()[facei]);
1139  protectedCell_.set(faceNeighbour()[facei]);
1140  }
1141  }
1142  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
1143  {
1144  if (protectedFace.test(facei))
1145  {
1146  protectedCell_.set(faceOwner()[facei]);
1147  }
1148  }
1149 
1150  // Also protect any cells that are less than hex
1151  forAll(cells(), celli)
1152  {
1153  const cell& cFaces = cells()[celli];
1154 
1155  if (cFaces.size() < 6)
1156  {
1157  protectedCell_.set(celli);
1158  }
1159  else
1160  {
1161  for (const label cfacei : cFaces)
1162  {
1163  if (faces()[cfacei].size() < 4)
1164  {
1165  protectedCell_.set(celli);
1166  break;
1167  }
1168  }
1169  }
1170  }
1171 
1172  // Check cells for 8 corner points
1173  checkEightAnchorPoints(protectedCell_);
1174  }
1175 
1176  if (!returnReduce(protectedCell_.any(), orOp<bool>()))
1177  {
1178  protectedCell_.clear();
1179  }
1180  else
1181  {
1182  cellSet protectedCells
1183  (
1184  *this,
1185  "protectedCells",
1186  HashSetOps::used(protectedCell_)
1187  );
1188 
1189  Info<< "Detected "
1190  << returnReduce(protectedCells.size(), sumOp<label>())
1191  << " cells that are protected from refinement."
1192  << " Writing these to cellSet "
1193  << protectedCells.name()
1194  << "." << endl;
1195 
1196  protectedCells.write();
1197  }
1198 
1199  return true;
1200 }
1201 
1202 
1203 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1204 
1206 {
1207  // Re-read dictionary. Chosen since usually -small so trivial amount
1208  // of time compared to actual refinement. Also very useful to be able
1209  // to modify on-the-fly.
1210  dictionary refineDict
1211  (
1212  IOdictionary
1213  (
1214  IOobject
1215  (
1216  "dynamicMeshDict",
1217  time().constant(),
1218  *this,
1221  false
1222  )
1223  ).optionalSubDict(typeName + "Coeffs")
1224  );
1225 
1226  const label refineInterval = refineDict.get<label>("refineInterval");
1227 
1228  bool hasChanged = false;
1229 
1230  if (refineInterval == 0)
1231  {
1232  topoChanging(hasChanged);
1233 
1234  return false;
1235  }
1236  else if (refineInterval < 0)
1237  {
1239  << "Illegal refineInterval " << refineInterval << nl
1240  << "The refineInterval setting in the dynamicMeshDict should"
1241  << " be >= 1." << nl
1242  << exit(FatalError);
1243  }
1244 
1245 
1246  // Note: cannot refine at time 0 since no V0 present since mesh not
1247  // moved yet.
1248 
1249  if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0)
1250  {
1251  const label maxCells = refineDict.get<label>("maxCells");
1252 
1253  if (maxCells <= 0)
1254  {
1256  << "Illegal maximum number of cells " << maxCells << nl
1257  << "The maxCells setting in the dynamicMeshDict should"
1258  << " be > 0." << nl
1259  << exit(FatalError);
1260  }
1261 
1262  const label maxRefinement = refineDict.get<label>("maxRefinement");
1263 
1264  if (maxRefinement <= 0)
1265  {
1267  << "Illegal maximum refinement level " << maxRefinement << nl
1268  << "The maxCells setting in the dynamicMeshDict should"
1269  << " be > 0." << nl
1270  << exit(FatalError);
1271  }
1272 
1273  const word fieldName(refineDict.get<word>("field"));
1274 
1275  const volScalarField& vFld = lookupObject<volScalarField>(fieldName);
1276 
1277  const scalar lowerRefineLevel =
1278  refineDict.get<scalar>("lowerRefineLevel");
1279  const scalar upperRefineLevel =
1280  refineDict.get<scalar>("upperRefineLevel");
1281  const scalar unrefineLevel = refineDict.getOrDefault<scalar>
1282  (
1283  "unrefineLevel",
1284  GREAT
1285  );
1286  const label nBufferLayers = refineDict.get<label>("nBufferLayers");
1287 
1288  // Cells marked for refinement or otherwise protected from unrefinement.
1289  bitSet refineCell(nCells());
1290 
1291  // Determine candidates for refinement (looking at field only)
1292  selectRefineCandidates
1293  (
1294  lowerRefineLevel,
1295  upperRefineLevel,
1296  vFld,
1297  refineCell
1298  );
1299 
1300  if (globalData().nTotalCells() < maxCells)
1301  {
1302  // Select subset of candidates. Take into account max allowable
1303  // cells, refinement level, protected cells.
1304  labelList cellsToRefine
1305  (
1306  selectRefineCells
1307  (
1308  maxCells,
1309  maxRefinement,
1310  refineCell
1311  )
1312  );
1313 
1314  const label nCellsToRefine = returnReduce
1315  (
1316  cellsToRefine.size(), sumOp<label>()
1317  );
1318 
1319  if (nCellsToRefine > 0)
1320  {
1321  // Refine/update mesh and map fields
1322  autoPtr<mapPolyMesh> map = refine(cellsToRefine);
1323 
1324  // Update refineCell. Note that some of the marked ones have
1325  // not been refined due to constraints.
1326  {
1327  const labelList& cellMap = map().cellMap();
1328  const labelList& reverseCellMap = map().reverseCellMap();
1329 
1330  bitSet newRefineCell(cellMap.size());
1331 
1332  forAll(cellMap, celli)
1333  {
1334  const label oldCelli = cellMap[celli];
1335 
1336  if
1337  (
1338  (oldCelli < 0)
1339  || (reverseCellMap[oldCelli] != celli)
1340  || (refineCell.test(oldCelli))
1341  )
1342  {
1343  newRefineCell.set(celli);
1344  }
1345  }
1346  refineCell.transfer(newRefineCell);
1347  }
1348 
1349  // Extend with a buffer layer to prevent neighbouring points
1350  // being unrefined.
1351  for (label i = 0; i < nBufferLayers; ++i)
1352  {
1353  extendMarkedCells(refineCell);
1354  }
1355 
1356  hasChanged = true;
1357  }
1358  }
1359 
1360 
1361  {
1362  // Select unrefineable points that are not marked in refineCell
1363  labelList pointsToUnrefine
1364  (
1365  selectUnrefinePoints
1366  (
1367  unrefineLevel,
1368  refineCell,
1369  maxCellField(vFld)
1370  )
1371  );
1372 
1373  const label nSplitPoints = returnReduce
1374  (
1375  pointsToUnrefine.size(),
1376  sumOp<label>()
1377  );
1378 
1379  if (nSplitPoints > 0)
1380  {
1381  // Refine/update mesh
1382  unrefine(pointsToUnrefine);
1383 
1384  hasChanged = true;
1385  }
1386  }
1387 
1388 
1389  if ((nRefinementIterations_ % 10) == 0)
1390  {
1391  // Compact refinement history occasionally (how often?).
1392  // Unrefinement causes holes in the refinementHistory.
1393  const_cast<refinementHistory&>(meshCutter().history()).compact();
1394  }
1395  nRefinementIterations_++;
1396  }
1397 
1398  topoChanging(hasChanged);
1399  if (hasChanged)
1400  {
1401  // Reset moving flag (if any). If not using inflation we'll not move,
1402  // if are using inflation any follow on movePoints will set it.
1403  moving(false);
1404  }
1405 
1406  return hasChanged;
1407 }
1408 
1409 
1412  IOstreamOption streamOpt,
1413  const bool valid
1414 ) const
1415 {
1416  // Force refinement data to go to the current time directory.
1417  const_cast<hexRef8&>(meshCutter_).setInstance(time().timeName());
1418 
1419  bool writeOk =
1420  (
1421  dynamicFvMesh::writeObject(streamOpt, valid)
1422  && meshCutter_.write(valid)
1423  );
1424 
1425  if (dumpLevel_)
1426  {
1427  volScalarField scalarCellLevel
1428  (
1429  IOobject
1430  (
1431  "cellLevel",
1432  time().timeName(),
1433  *this,
1436  false
1437  ),
1438  *this,
1440  );
1441 
1442  const labelList& cellLevel = meshCutter_.cellLevel();
1443 
1444  forAll(cellLevel, celli)
1445  {
1446  scalarCellLevel[celli] = cellLevel[celli];
1447  }
1448 
1449  writeOk = writeOk && scalarCellLevel.write();
1450  }
1451 
1452  return writeOk;
1453 }
1454 
1455 
1456 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::IOobject::NO_WRITE
Definition: IOobject.H:130
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:71
volFields.H
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:54
Foam::HashTable::size
label size() const noexcept
The number of elements in table.
Definition: HashTableI.H:52
Foam::PackedList::reset
void reset()
Clear all bits but do not adjust the addressable size.
Definition: PackedListI.H:495
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:104
Foam::meshCutter
Cuts (splits) cells.
Definition: meshCutter.H:138
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:129
Foam::dynamicRefineFvMesh::error
scalarField error(const scalarField &fld, const scalar minLevel, const scalar maxLevel) const
Definition: dynamicRefineFvMesh.C:709
Foam::dimless
const dimensionSet dimless(0, 0, 0, 0, 0, 0, 0)
Dimensionless.
Definition: dimensionSets.H:50
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::IOobject::name
const word & name() const
Return name.
Definition: IOobjectI.H:70
Foam::dynamicRefineFvMesh::extendMarkedCells
void extendMarkedCells(bitSet &markedCell) const
Extend markedCell with cell-face-cell.
Definition: dynamicRefineFvMesh.C:940
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::polyTopoChange::changeMesh
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
Definition: polyTopoChange.C:2959
Foam::DynamicList< label >
Foam::fvPatch::start
virtual label start() const
Return start label of this patch in the polyMesh face list.
Definition: fvPatch.H:173
Foam::dynamicRefineFvMesh::init
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Definition: dynamicRefineFvMesh.C:1034
polyTopoChange.H
Foam::fvMesh::mapFields
virtual void mapFields(const mapPolyMesh &mpm)
Map all fields in time using given map.
Definition: fvMesh.C:700
Foam::fvsPatchField
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
Definition: fvsPatchField.H:68
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:99
Foam::dynamicFvMesh::init
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Definition: dynamicFvMesh.C:90
Foam::dynamicFvMesh
Abstract base class for geometry and/or topology changing fvMesh.
Definition: dynamicFvMesh.H:78
Foam::dynamicRefineFvMesh::mapFields
virtual void mapFields(const mapPolyMesh &mpm)
Map all fields in time using given map.
Definition: dynamicRefineFvMesh.C:197
Foam::dynamicRefineFvMesh::update
virtual bool update()
Update the mesh for both mesh motion and topology change.
Definition: dynamicRefineFvMesh.C:1205
Foam::dynamicRefineFvMesh::selectRefineCells
virtual labelList selectRefineCells(const label maxCells, const label maxRefinement, const bitSet &candidateCell) const
Subset candidate cells for refinement.
Definition: dynamicRefineFvMesh.C:765
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:574
Foam::Map< label >
Foam::orEqOp
Definition: ops.H:86
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:350
surfaceFields.H
Foam::surfaceFields.
Foam::dynamicRefineFvMesh::correctFluxes_
HashTable< word > correctFluxes_
Fluxes to map.
Definition: dynamicRefineFvMesh.H:100
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:81
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:520
Foam::DynamicList::shrink
DynamicList< T, SizeMin > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:376
Foam::PackedList::resize
void resize(const label nElem, const unsigned int val=0u)
Reset addressable list size, does not shrink the allocated size.
Definition: PackedListI.H:399
syncTools.H
Foam::bitSet::count
unsigned int count(const bool on=true) const
Count number of bits set.
Definition: bitSetI.H:499
Foam::dynamicRefineFvMesh::readDict
void readDict()
Read the projection parameters from dictionary.
Definition: dynamicRefineFvMesh.C:166
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::syncTools::syncPointList
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
Definition: syncToolsTemplates.C:724
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::dynamicRefineFvMesh::writeObject
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write using stream options.
Definition: dynamicRefineFvMesh.C:1411
nPoints
label nPoints
Definition: gmvOutputHeader.H:2
Foam::refinementHistory
All refinement history. Used in unrefinement.
Definition: refinementHistory.H:102
Foam::syncTools::syncFaceList
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:390
Foam::dynamicRefineFvMesh::checkEightAnchorPoints
void checkEightAnchorPoints(bitSet &protectedCell) const
Check all cells have 8 anchor points.
Definition: dynamicRefineFvMesh.C:974
pFaces
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=cellModel::ref(cellModel::HEX);labelList hexLabels(8);label activeCells=0;labelList pointMap(nPoints);forAll(pointMap, i){ pointMap[i]=i;}for(label i=0;i< nPoints;i++){ if(f[i] > 0.0) { hexLabels[0]=i;hexLabels[1]=i1tab[i];hexLabels[2]=i3tab[i1tab[i]];hexLabels[3]=i3tab[i];hexLabels[4]=i8tab[i];hexLabels[5]=i1tab[i8tab[i]];hexLabels[6]=i3tab[i1tab[i8tab[i]]];hexLabels[7]=i3tab[i8tab[i]];cellShapes[activeCells]=cellShape(hex, hexLabels);edgeList edges=cellShapes[activeCells].edges();forAll(edges, ei) { if(edges[ei].mag(points)< SMALL) { label start=pointMap[edges[ei].start()];while(start !=pointMap[start]) { start=pointMap[start];} label end=pointMap[edges[ei].end()];while(end !=pointMap[end]) { end=pointMap[end];} label minLabel=min(start, end);pointMap[start]=pointMap[end]=minLabel;} } cellZoning[activeCells]=idreg[i];activeCells++;}}cellShapes.setSize(activeCells);cellZoning.setSize(activeCells);forAll(cellShapes, celli){ cellShape &cs=cellShapes[celli];forAll(cs, i) { cs[i]=pointMap[cs[i]];} cs.collapse();}label bcIDs[11]={-1, 0, 2, 4, -1, 5, -1, 6, 7, 8, 9};const label nBCs=12;const word *kivaPatchTypes[nBCs]={ &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &wallPolyPatch::typeName, &symmetryPolyPatch::typeName, &wedgePolyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &polyPatch::typeName, &symmetryPolyPatch::typeName, &oldCyclicPolyPatch::typeName};enum patchTypeNames{ PISTON, VALVE, LINER, CYLINDERHEAD, AXIS, WEDGE, INFLOW, OUTFLOW, PRESIN, PRESOUT, SYMMETRYPLANE, CYCLIC};const char *kivaPatchNames[nBCs]={ "piston", "valve", "liner", "cylinderHead", "axis", "wedge", "inflow", "outflow", "presin", "presout", "symmetryPlane", "cyclic"};List< SLList< face > > pFaces[nBCs]
Definition: readKivaGrid.H:235
Foam::Field< scalar >
Foam::regIOobject::write
virtual bool write(const bool valid=true) const
Write using setting from DB.
Definition: regIOobjectWrite.C:165
Foam::sigFpe::fillNan
static void fillNan(UList< scalar > &list)
Fill data block with NaN values.
Definition: sigFpe.C:225
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:474
Foam::dynamicRefineFvMesh::selectRefineCandidates
virtual void selectRefineCandidates(const scalar lowerRefineLevel, const scalar upperRefineLevel, const scalarField &vFld, bitSet &candidateCell) const
Select candidate cells for refinement.
Definition: dynamicRefineFvMesh.C:731
init
mesh init(true)
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
Foam::dictionary::readEntry
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Definition: dictionaryTemplates.C:314
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:43
phi
surfaceScalarField & phi
Definition: setRegionFluidFields.H:8
Foam::dynamicRefineFvMesh::maxCellField
scalarField maxCellField(const volScalarField &) const
Get point max of connected cell.
Definition: dynamicRefineFvMesh.C:671
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
fld
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< ' ';}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< ' ';}gmvFile<< nl;for(const word &name :lagrangianScalarNames){ IOField< scalar > fld(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Definition: gmvOutputLagrangian.H:23
forAllIters
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:223
Foam::dynamicRefineFvMesh::refine
virtual autoPtr< mapPolyMesh > refine(const labelList &)
Refine cells. Update mesh and fields.
Definition: dynamicRefineFvMesh.C:387
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
dynamicRefineFvMesh.H
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::fvc::interpolate
static tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > interpolate(const GeometricField< Type, fvPatchField, volMesh > &tvf, const surfaceScalarField &faceFlux, Istream &schemeData)
Interpolate field onto faces using scheme given by Istream.
Foam::cellSet
A collection of cell labels.
Definition: cellSet.H:51
Foam::dynamicRefineFvMesh::selectUnrefinePoints
virtual labelList selectUnrefinePoints(const scalar unrefineLevel, const bitSet &markedCell, const scalarField &pFld) const
Select points that can be unrefined.
Definition: dynamicRefineFvMesh.C:845
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::GeometricField::primitiveFieldRef
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field.
Definition: GeometricField.C:766
Foam::HashTable
A HashTable similar to std::unordered_map.
Definition: HashTable.H:105
Foam::mapPolyMesh::reverseFaceMap
const labelList & reverseFaceMap() const
Reverse face map.
Definition: mapPolyMesh.H:501
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::dynamicRefineFvMesh::calculateProtectedCells
void calculateProtectedCells(bitSet &unrefineableCell) const
Calculate cells that cannot be refined since would trigger.
Definition: dynamicRefineFvMesh.C:53
Foam::refineCell
Container with cells to refine. Refinement given as single direction.
Definition: refineCell.H:56
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:359
Foam::nl
constexpr char nl
Definition: Ostream.H:385
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::fvsPatchField::patch
const fvPatch & patch() const
Return patch.
Definition: fvsPatchField.H:281
Foam::hexRef8
Refinement of (split) hexes using polyTopoChange.
Definition: hexRef8.H:67
f
labelList f(nPoints)
Foam::GeometricField::boundaryFieldRef
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Definition: GeometricField.C:783
Foam::syncTools::swapFaceList
static void swapFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled face values. Uses eqOp.
Definition: syncTools.H:472
Foam::List< label >
Foam::HashSetOps::used
labelHashSet used(const bitSet &select)
Convert a bitset to a labelHashSet of the indices used.
Definition: HashOps.C:35
Foam::dynamicRefineFvMesh::dumpLevel_
bool dumpLevel_
Dump cellLevel for post-processing.
Definition: dynamicRefineFvMesh.H:109
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::IOobject::MUST_READ_IF_MODIFIED
Definition: IOobject.H:121
Foam::mapPolyMesh::faceMap
const labelList & faceMap() const
Old face map.
Definition: mapPolyMesh.H:410
Foam::dictionary::optionalSubDict
const dictionary & optionalSubDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary, otherwise return this dictionary.
Definition: dictionary.C:645
Foam::List::set
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
Definition: List.H:325
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:161
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:275
Foam::boundaryMesh
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface....
Definition: boundaryMesh.H:62
Foam::dynamicRefineFvMesh::unrefine
virtual autoPtr< mapPolyMesh > unrefine(const labelList &)
Unrefine cells. Gets passed in centre points of cells to combine.
Definition: dynamicRefineFvMesh.C:476
Foam::dynamicRefineFvMesh::cellToPoint
scalarField cellToPoint(const scalarField &vFld) const
Definition: dynamicRefineFvMesh.C:689
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
timeIndex
label timeIndex
Definition: getTimeIndex.H:4
Foam::pointCells
Smooth ATC in cells having a point to a set of patches supplied by type.
Definition: pointCells.H:56
cells
const cellShapeList & cells
Definition: gmvOutputHeader.H:3
cellSet.H
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:122
Foam::GeometricField< scalar, fvsPatchField, surfaceMesh >
Foam::IOobject::NO_READ
Definition: IOobject.H:123
Foam::orOp
Definition: ops.H:234
constant
constant condensation/saturation model.
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::dynamicRefineFvMesh::maxPointField
scalarField maxPointField(const scalarField &) const
Get per cell max of connected point.
Definition: dynamicRefineFvMesh.C:653
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:303
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::error
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:70
pointFields.H
Foam::PackedList::clear
void clear()
Clear the list, i.e. set addressable size to zero.
Definition: PackedListI.H:502
HashOps.H
Foam::GeometricField::boundaryField
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Definition: GeometricFieldI.H:62
Foam::fvMesh::writeObject
virtual bool writeObject(IOstreamOption streamOpt, const bool valid) const
Write the underlying polyMesh and other data.
Definition: fvMesh.C:1004