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-2023 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);
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(nBoundaryFaces());
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 (!returnReduceOr(hasExtended))
159  {
160  break;
161  }
162  }
163 }
164 
165 
167 {
168  const dictionary refineDict
169  (
170  IOdictionary
171  (
172  IOobject
173  (
174  "dynamicMeshDict",
175  time().constant(),
176  *this,
180  )
181  ).optionalSubDict(typeName + "Coeffs")
182  );
183 
184  auto fluxVelocities = refineDict.get<List<Pair<word>>>("correctFluxes");
185 
186  // Rework into hashtable.
187  correctFluxes_.reserve(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 
197 void Foam::dynamicRefineFvMesh::mapFields(const mapPolyMesh& mpm)
198 {
199  //dynamicFvMesh::mapFields(mpm);
201 
202 
203  // Correct old-time volumes for refined/unrefined cells. We know at this
204  // point that the points have not moved and the cells have only been split
205  // or merged. We hope that dynamicMotionSolverListFvMesh::mapFields
206  // does not use old-time volumes ...
207  {
208  const labelList& cellMap = mpm.cellMap();
209  const labelList& reverseCellMap = mpm.reverseCellMap();
210 
211  // Each split cell becomes original + 7 additional
212  labelList nSubCells(mpm.nOldCells(), 0);
213 
214  forAll(cellMap, celli)
215  {
216  const label oldCelli = cellMap[celli];
217  if (oldCelli >= 0 && reverseCellMap[oldCelli] >= 0)
218  {
219  // Found master cell.
220  nSubCells[oldCelli]++;
221  }
222  }
223 
224  // Start off from mapped old volumes
225  scalarField correctedV0(this->V0());
226 
227  // Correct any split cells
228  const auto& V = this->V();
229  forAll(cellMap, celli)
230  {
231  const label oldCelli = cellMap[celli];
232  if (oldCelli >= 0 && nSubCells[oldCelli] == 8)
233  {
234  // Found split cell. Use current volume instead of mapped
235  // old one
236  correctedV0[celli] = V[celli];
237  }
238  }
239 
240  const auto& cellsFromCells = mpm.cellsFromCellsMap();
241  for (const auto& s : cellsFromCells)
242  {
243  // Reset unsplit cell
244  const label celli = s.index();
245  correctedV0[celli] = V[celli];
246  //? Or sum up old volumes?
247  //const labelList& oldCells = s.masterObjects();
248  //for (const label oldCelli : oldCells)
249  //{
250  //}
251  }
252 
253  setV0().field() = correctedV0;
254  }
255 
256 
257  // Correct the flux for modified/added faces. All the faces which only
258  // have been renumbered will already have been handled by the mapping.
259  {
260  const labelList& faceMap = mpm.faceMap();
261  const labelList& reverseFaceMap = mpm.reverseFaceMap();
262 
263  // Storage for any master faces. These will be the original faces
264  // on the coarse cell that get split into four (or rather the
265  // master face gets modified and three faces get added from the master)
266  // Estimate number of faces created
267 
268  bitSet masterFaces(nFaces());
269 
270  forAll(faceMap, facei)
271  {
272  const label oldFacei = faceMap[facei];
273 
274  if (oldFacei >= 0)
275  {
276  const label masterFacei = reverseFaceMap[oldFacei];
277 
278  if (masterFacei < 0)
279  {
281  << "Problem: should not have removed faces"
282  << " when refining."
283  << nl << "face:" << facei << endl
284  << abort(FatalError);
285  }
286  else if (masterFacei != facei)
287  {
288  masterFaces.set(masterFacei);
289  }
290  }
291  }
292 
293  if (debug)
294  {
295  Pout<< "Found " << masterFaces.count() << " split faces " << endl;
296  }
297 
298  UPtrList<surfaceScalarField> fluxes
299  (
300  this->objectRegistry::sorted<surfaceScalarField>()
301  );
302 
303  // Remove surfaceInterpolation to allow re-calculation on demand
304  // This could be done in fvMesh::updateMesh but some dynamicFvMesh
305  // might need the old interpolation fields (weights, etc).
307 
308  for (surfaceScalarField& phi : fluxes)
309  {
310  const word& UName = correctFluxes_.lookup(phi.name(), word::null);
311 
312  if (UName.empty())
313  {
315  << "Cannot find surfaceScalarField " << phi.name()
316  << " in user-provided flux mapping table "
317  << correctFluxes_ << endl
318  << " The flux mapping table is used to recreate the"
319  << " flux on newly created faces." << endl
320  << " Either add the entry if it is a flux or use ("
321  << phi.name() << " none) to suppress this warning."
322  << endl;
323  continue;
324  }
325  if (UName == "none")
326  {
327  continue;
328  }
329  if (UName == "NaN")
330  {
331  Pout<< "Setting surfaceScalarField " << phi.name()
332  << " to NaN" << endl;
333 
334  sigFpe::fillNan(phi.primitiveFieldRef());
335  continue;
336  }
337 
338  if (debug)
339  {
340  Pout<< "Mapping flux " << phi.name()
341  << " using interpolated flux " << UName
342  << endl;
343  }
344 
345  const surfaceScalarField phiU
346  (
348  (
349  lookupObject<volVectorField>(UName)
350  )
351  & Sf()
352  );
353 
354  // Recalculate new internal faces.
355  for (label facei = 0; facei < nInternalFaces(); ++facei)
356  {
357  const label oldFacei = faceMap[facei];
358 
359  if (oldFacei == -1)
360  {
361  // Inflated/appended
362  phi[facei] = phiU[facei];
363  }
364  else if (reverseFaceMap[oldFacei] != facei)
365  {
366  // face-from-masterface
367  phi[facei] = phiU[facei];
368  }
369  }
370 
371  // Recalculate new boundary faces.
372  auto& phiBf = phi.boundaryFieldRef();
373 
374  forAll(phiBf, patchi)
375  {
376  fvsPatchScalarField& patchPhi = phiBf[patchi];
377  const fvsPatchScalarField& patchPhiU =
378  phiU.boundaryField()[patchi];
379 
380  label facei = patchPhi.patch().start();
381 
382  forAll(patchPhi, i)
383  {
384  const label oldFacei = faceMap[facei];
385 
386  if (oldFacei == -1)
387  {
388  // Inflated/appended
389  patchPhi[i] = patchPhiU[i];
390  }
391  else if (reverseFaceMap[oldFacei] != facei)
392  {
393  // face-from-masterface
394  patchPhi[i] = patchPhiU[i];
395  }
396 
397  ++facei;
398  }
399  }
400 
401  // Update master faces
402  for (const label facei : masterFaces)
403  {
404  if (isInternalFace(facei))
405  {
406  phi[facei] = phiU[facei];
407  }
408  else
409  {
410  const label patchi = boundaryMesh().whichPatch(facei);
411  const label i = facei - boundaryMesh()[patchi].start();
412 
413  const fvsPatchScalarField& patchPhiU =
414  phiU.boundaryField()[patchi];
415 
416  fvsPatchScalarField& patchPhi = phiBf[patchi];
417 
418  patchPhi[i] = patchPhiU[i];
419  }
420  }
421  }
422  }
423 
424  // Correct the flux for injected faces - these are the faces which have
425  // no correspondence to the old mesh (i.e. added without a masterFace, edge
426  // or point). An example is the internal faces from hexRef8.
427  {
428  const labelList& faceMap = mpm.faceMap();
429 
430  mapNewInternalFaces<scalar>(this->Sf(), this->magSf(), faceMap);
431  mapNewInternalFaces<vector>(this->Sf(), this->magSf(), faceMap);
432 
433  // No oriented fields of more complex type
434  mapNewInternalFaces<sphericalTensor>(faceMap);
435  mapNewInternalFaces<symmTensor>(faceMap);
436  mapNewInternalFaces<tensor>(faceMap);
437  }
438 }
439 
440 
441 // Refines cells, maps fields and recalculates (an approximate) flux
444 (
445  const labelList& cellsToRefine
446 )
447 {
448  // Mesh changing engine.
449  polyTopoChange meshMod(*this);
450 
451  // Play refinement commands into mesh changer.
452  meshCutter_.setRefinement(cellsToRefine, meshMod);
453 
454  // Create mesh (with inflation), return map from old to new mesh.
455  //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
456 
457  // Clear moving flag. This is currently required since geometry calculation
458  // might get triggered when doing processor patches.
459  // (TBD: should be in changeMesh if no inflation?)
460  moving(false);
461  // Create mesh (no inflation), return map from old to new mesh.
462  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
463 
464  Info<< "Refined from "
465  << returnReduce(map().nOldCells(), sumOp<label>())
466  << " to " << globalData().nTotalCells() << " cells." << endl;
467 
468  if (debug)
469  {
470  // Check map.
471  for (label facei = 0; facei < nInternalFaces(); ++facei)
472  {
473  const label oldFacei = map().faceMap()[facei];
474 
475  if (oldFacei >= nInternalFaces())
476  {
478  << "New internal face:" << facei
479  << " fc:" << faceCentres()[facei]
480  << " originates from boundary oldFace:" << oldFacei
481  << abort(FatalError);
482  }
483  }
484  }
485 
486  // // Remove the stored tet base points
487  // tetBasePtIsPtr_.clear();
488  // // Remove the cell tree
489  // cellTreePtr_.clear();
490 
491  // Update fields
492  updateMesh(*map);
493 
494 
495  // Move mesh
496  /*
497  pointField newPoints;
498  if (map().hasMotionPoints())
499  {
500  newPoints = map().preMotionPoints();
501  }
502  else
503  {
504  newPoints = points();
505  }
506  movePoints(newPoints);
507  */
508 
509 
510 
511  // Update numbering of cells/vertices.
512  meshCutter_.updateMesh(*map);
513 
514  // Update numbering of protectedCell_
515  if (protectedCell_.size())
516  {
517  bitSet newProtectedCell(nCells());
518 
519  forAll(newProtectedCell, celli)
520  {
521  const label oldCelli = map().cellMap()[celli];
522  if (protectedCell_.test(oldCelli))
523  {
524  newProtectedCell.set(celli);
525  }
526  }
527  protectedCell_.transfer(newProtectedCell);
528  }
529 
530  // Debug: Check refinement levels (across faces only)
531  meshCutter_.checkRefinementLevels(-1, labelList());
533  return map;
534 }
535 
536 
539 (
540  const labelList& splitPoints
541 )
542 {
543  polyTopoChange meshMod(*this);
544 
545  // Play refinement commands into mesh changer.
546  meshCutter_.setUnrefinement(splitPoints, meshMod);
547 
548 
549  // Save information on faces that will be combined
550  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
551 
552  // Find the faceMidPoints on cells to be combined.
553  // for each face resulting of split of face into four store the
554  // midpoint
555  Map<label> faceToSplitPoint(3*splitPoints.size());
556 
557  {
558  for (const label pointi : splitPoints)
559  {
560  const labelList& pEdges = pointEdges()[pointi];
561 
562  for (const label edgei : pEdges)
563  {
564  const label otherPointi = edges()[edgei].otherVertex(pointi);
565 
566  const labelList& pFaces = pointFaces()[otherPointi];
567 
568  for (const label facei : pFaces)
569  {
570  faceToSplitPoint.insert(facei, otherPointi);
571  }
572  }
573  }
574  }
575 
576 
577  // Change mesh and generate map.
578  //autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
579 
580  // Clear moving flag. This is currently required since geometry calculation
581  // might get triggered when doing processor patches.
582  // (TBD: should be in changeMesh if no inflation?)
583  moving(false);
584  // Create mesh (no inflation), return map from old to new mesh.
585  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
586 
587  Info<< "Unrefined from "
588  << returnReduce(map().nOldCells(), sumOp<label>())
589  << " to " << globalData().nTotalCells() << " cells."
590  << endl;
591 
592  // Update fields
593  updateMesh(*map);
594 
595 
596  // Move mesh
597  /*
598  pointField newPoints;
599  if (map().hasMotionPoints())
600  {
601  newPoints = map().preMotionPoints();
602  }
603  else
604  {
605  newPoints = points();
606  }
607  movePoints(newPoints);
608  */
609 
610  // Correct the flux for modified faces.
611  {
612  const labelList& reversePointMap = map().reversePointMap();
613  const labelList& reverseFaceMap = map().reverseFaceMap();
614 
615  UPtrList<surfaceScalarField> fluxes
616  (
617  this->objectRegistry::sorted<surfaceScalarField>()
618  );
619 
620  for (surfaceScalarField& phi : fluxes)
621  {
622  const word& UName = correctFluxes_.lookup(phi.name(), word::null);
623 
624  if (UName.empty())
625  {
627  << "Cannot find surfaceScalarField " << phi.name()
628  << " in user-provided flux mapping table "
629  << correctFluxes_ << endl
630  << " The flux mapping table is used to recreate the"
631  << " flux on newly created faces." << endl
632  << " Either add the entry if it is a flux or use ("
633  << phi.name() << " none) to suppress this warning."
634  << endl;
635  continue;
636  }
637  if (UName == "none")
638  {
639  continue;
640  }
641 
642  DebugInfo
643  << "Mapping flux " << phi.name()
644  << " using interpolated flux " << UName
645  << endl;
646 
647  auto& phiBf = phi.boundaryFieldRef();
648 
649  const surfaceScalarField phiU
650  (
652  (
653  lookupObject<volVectorField>(UName)
654  )
655  & Sf()
656  );
657 
658 
659  forAllConstIters(faceToSplitPoint, iter)
660  {
661  const label oldFacei = iter.key();
662  const label oldPointi = iter.val();
663 
664  if (reversePointMap[oldPointi] < 0)
665  {
666  // midpoint was removed. See if face still exists.
667  const label facei = reverseFaceMap[oldFacei];
668 
669  if (facei >= 0)
670  {
671  if (isInternalFace(facei))
672  {
673  phi[facei] = phiU[facei];
674  }
675  else
676  {
677  label patchi = boundaryMesh().whichPatch(facei);
678  label i = facei - boundaryMesh()[patchi].start();
679 
680  const fvsPatchScalarField& patchPhiU =
681  phiU.boundaryField()[patchi];
682  fvsPatchScalarField& patchPhi = phiBf[patchi];
683  patchPhi[i] = patchPhiU[i];
684  }
685  }
686  }
687  }
688  }
689  }
690 
691 
692  // Update numbering of cells/vertices.
693  meshCutter_.updateMesh(*map);
694 
695  // Update numbering of protectedCell_
696  if (protectedCell_.size())
697  {
698  bitSet newProtectedCell(nCells());
699 
700  forAll(newProtectedCell, celli)
701  {
702  const label oldCelli = map().cellMap()[celli];
703  if (protectedCell_.test(oldCelli))
704  {
705  newProtectedCell.set(celli);
706  }
707  }
708  protectedCell_.transfer(newProtectedCell);
709  }
710 
711  // Debug: Check refinement levels (across faces only)
712  meshCutter_.checkRefinementLevels(-1, labelList());
713 
714  return map;
715 }
716 
717 
720 {
721  scalarField vFld(nCells(), -GREAT);
722 
723  forAll(pointCells(), pointi)
724  {
725  const labelList& pCells = pointCells()[pointi];
726 
727  for (const label celli : pCells)
728  {
729  vFld[celli] = max(vFld[celli], pFld[pointi]);
730  }
731  }
732  return vFld;
733 }
734 
735 
738 {
739  scalarField pFld(nPoints(), -GREAT);
740 
741  forAll(pointCells(), pointi)
742  {
743  const labelList& pCells = pointCells()[pointi];
744 
745  for (const label celli : pCells)
746  {
747  pFld[pointi] = max(pFld[pointi], vFld[celli]);
748  }
749  }
750  return pFld;
751 }
752 
753 
756 {
757  scalarField pFld(nPoints());
758 
759  forAll(pointCells(), pointi)
760  {
761  const labelList& pCells = pointCells()[pointi];
762 
763  scalar sum = 0.0;
764  for (const label celli : pCells)
765  {
766  sum += vFld[celli];
767  }
768  pFld[pointi] = sum/pCells.size();
769  }
770  return pFld;
771 }
772 
773 
775 (
776  const scalarField& fld,
777  const scalar minLevel,
778  const scalar maxLevel
779 ) const
780 {
781  scalarField c(fld.size(), scalar(-1));
782 
783  forAll(fld, i)
784  {
785  scalar err = min(fld[i]-minLevel, maxLevel-fld[i]);
786 
787  if (err >= 0)
788  {
789  c[i] = err;
790  }
791  }
792  return c;
793 }
794 
795 
797 (
798  const scalar lowerRefineLevel,
799  const scalar upperRefineLevel,
800  const scalarField& vFld,
801  bitSet& candidateCell
802 ) const
803 {
804  // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
805  // higher more desirable to be refined).
806  scalarField cellError
807  (
808  maxPointField
809  (
810  error
811  (
812  cellToPoint(vFld),
813  lowerRefineLevel,
814  upperRefineLevel
815  )
816  )
817  );
818 
819  // Mark cells that are candidates for refinement.
820  forAll(cellError, celli)
821  {
822  if (cellError[celli] > 0)
823  {
824  candidateCell.set(celli);
825  }
826  }
827 }
828 
829 
831 (
832  const label maxCells,
833  const label maxRefinement,
834  const bitSet& candidateCell
835 ) const
836 {
837  // Every refined cell causes 7 extra cells
838  label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
839 
840  const labelList& cellLevel = meshCutter_.cellLevel();
841 
842  // Mark cells that cannot be refined since they would trigger refinement
843  // of protected cells (since 2:1 cascade)
844  bitSet unrefineableCell;
845  calculateProtectedCells(unrefineableCell);
846 
847  // Count current selection
848  label nLocalCandidates = candidateCell.count();
849  label nCandidates = returnReduce(nLocalCandidates, sumOp<label>());
850 
851  // Collect all cells
852  DynamicList<label> candidates(nLocalCandidates);
853 
854  if (nCandidates < nTotToRefine)
855  {
856  for (const label celli : candidateCell)
857  {
858  if
859  (
860  (!unrefineableCell.test(celli))
861  && cellLevel[celli] < maxRefinement
862  )
863  {
864  candidates.append(celli);
865  }
866  }
867  }
868  else
869  {
870  // Sort by error? For now just truncate.
871  for (label level = 0; level < maxRefinement; ++level)
872  {
873  for (const label celli : candidateCell)
874  {
875  if
876  (
877  (!unrefineableCell.test(celli))
878  && cellLevel[celli] == level
879  )
880  {
881  candidates.append(celli);
882  }
883  }
884 
885  if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine)
886  {
887  break;
888  }
889  }
890  }
891 
892  // Guarantee 2:1 refinement after refinement
893  labelList consistentSet
894  (
895  meshCutter_.consistentRefinement
896  (
897  candidates.shrink(),
898  true // Add to set to guarantee 2:1
899  )
900  );
901 
902  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
903  << " cells for refinement out of " << globalData().nTotalCells()
904  << "." << endl;
905 
906  return consistentSet;
907 }
908 
909 
911 (
912  const scalar unrefineLevel,
913  const bitSet& markedCell,
914  const scalarField& pFld
915 ) const
916 {
917  // All points that can be unrefined
918  const labelList splitPoints(meshCutter_.getSplitPoints());
919 
920 
921  const labelListList& pointCells = this->pointCells();
922 
923  // If we have any protected cells make sure they also are not being
924  // unrefined
925 
926  bitSet protectedPoint(nPoints());
927 
928  if (protectedCell_.size())
929  {
930  // Get all points on a protected cell
931  forAll(pointCells, pointi)
932  {
933  for (const label celli : pointCells[pointi])
934  {
935  if (protectedCell_.test(celli))
936  {
937  protectedPoint.set(pointi);
938  break;
939  }
940  }
941  }
942 
944  (
945  *this,
946  protectedPoint,
948  0u
949  );
950 
951  DebugInfo<< "From "
952  << returnReduce(protectedCell_.count(), sumOp<label>())
953  << " protected cells found "
954  << returnReduce(protectedPoint.count(), sumOp<label>())
955  << " protected points." << endl;
956  }
957 
958 
959  DynamicList<label> newSplitPoints(splitPoints.size());
960 
961  for (const label pointi : splitPoints)
962  {
963  if (!protectedPoint[pointi] && pFld[pointi] < unrefineLevel)
964  {
965  // Check that all cells are not marked
966  bool hasMarked = false;
967 
968  for (const label celli : pointCells[pointi])
969  {
970  if (markedCell.test(celli))
971  {
972  hasMarked = true;
973  break;
974  }
975  }
976 
977  if (!hasMarked)
978  {
979  newSplitPoints.append(pointi);
980  }
981  }
982  }
983 
984 
985  newSplitPoints.shrink();
986 
987  // Guarantee 2:1 refinement after unrefinement
988  labelList consistentSet
989  (
990  meshCutter_.consistentUnrefinement
991  (
992  newSplitPoints,
993  false
994  )
995  );
996  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
997  << " split points out of a possible "
998  << returnReduce(splitPoints.size(), sumOp<label>())
999  << "." << endl;
1000 
1001  return consistentSet;
1002 }
1003 
1004 
1006 (
1007  bitSet& markedCell
1008 ) const
1009 {
1010  // Mark faces using any marked cell
1011  bitSet markedFace(nFaces());
1012 
1013  for (const label celli : markedCell)
1014  {
1015  markedFace.set(cells()[celli]); // set multiple faces
1016  }
1017 
1018  syncTools::syncFaceList(*this, markedFace, orEqOp<unsigned int>());
1019 
1020  // Update cells using any markedFace
1021  for (label facei = 0; facei < nInternalFaces(); ++facei)
1022  {
1023  if (markedFace.test(facei))
1024  {
1025  markedCell.set(faceOwner()[facei]);
1026  markedCell.set(faceNeighbour()[facei]);
1027  }
1028  }
1029  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
1030  {
1031  if (markedFace.test(facei))
1032  {
1033  markedCell.set(faceOwner()[facei]);
1034  }
1035  }
1036 }
1037 
1038 
1040 (
1041  bitSet& protectedCell
1042 ) const
1043 {
1044  const labelList& cellLevel = meshCutter_.cellLevel();
1045  const labelList& pointLevel = meshCutter_.pointLevel();
1046 
1047  labelList nAnchorPoints(nCells(), Zero);
1048 
1049  forAll(pointLevel, pointi)
1050  {
1051  const labelList& pCells = pointCells(pointi);
1052 
1053  for (const label celli : pCells)
1054  {
1055  if (pointLevel[pointi] <= cellLevel[celli])
1056  {
1057  // Check if cell has already 8 anchor points -> protect cell
1058  if (nAnchorPoints[celli] == 8)
1059  {
1060  protectedCell.set(celli);
1061  }
1062 
1063  if (!protectedCell.test(celli))
1064  {
1065  ++nAnchorPoints[celli];
1066  }
1067  }
1068  }
1069  }
1070 
1071 
1072  forAll(protectedCell, celli)
1073  {
1074  if (nAnchorPoints[celli] != 8)
1075  {
1076  protectedCell.set(celli);
1077  }
1078  }
1079 }
1080 
1081 
1082 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1083 
1084 Foam::dynamicRefineFvMesh::dynamicRefineFvMesh
1085 (
1086  const IOobject& io,
1087  const bool doInit
1088 )
1089 :
1090  //dynamicFvMesh(io, doInit),
1091  dynamicMotionSolverListFvMesh(io, doInit),
1092  meshCutter_(*this)
1093 {
1094  if (doInit)
1095  {
1096  init(false); // do not initialise lower levels
1097  }
1098 }
1099 
1100 
1101 bool Foam::dynamicRefineFvMesh::init(const bool doInit)
1102 {
1103  if (doInit)
1104  {
1105  //dynamicFvMesh::init(doInit);
1106  // Note: allow zero motion solvers
1107  dynamicMotionSolverListFvMesh::init(doInit, false);
1108  }
1109 
1110  protectedCell_.setSize(nCells());
1111  nRefinementIterations_ = 0;
1112  dumpLevel_ = false;
1113 
1114  // Read static part of dictionary
1115  readDict();
1116 
1117 
1118  const labelList& cellLevel = meshCutter_.cellLevel();
1119  const labelList& pointLevel = meshCutter_.pointLevel();
1120 
1121  // Set cells that should not be refined.
1122  // This is currently any cell which does not have 8 anchor points or
1123  // uses any face which does not have 4 anchor points.
1124  // Note: do not use cellPoint addressing
1125 
1126  // Count number of points <= cellLevel
1127  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1128 
1129  labelList nAnchors(nCells(), Zero);
1130 
1131  forAll(pointCells(), pointi)
1132  {
1133  const labelList& pCells = pointCells()[pointi];
1134 
1135  for (const label celli : pCells)
1136  {
1137  if (!protectedCell_.test(celli))
1138  {
1139  if (pointLevel[pointi] <= cellLevel[celli])
1140  {
1141  ++nAnchors[celli];
1142 
1143  if (nAnchors[celli] > 8)
1144  {
1145  protectedCell_.set(celli);
1146  }
1147  }
1148  }
1149  }
1150  }
1151 
1152 
1153  // Count number of points <= faceLevel
1154  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1155  // Bit tricky since proc face might be one more refined than the owner since
1156  // the coupled one is refined.
1157 
1158  {
1159  labelList neiLevel(nFaces());
1160 
1161  for (label facei = 0; facei < nInternalFaces(); ++facei)
1162  {
1163  neiLevel[facei] = cellLevel[faceNeighbour()[facei]];
1164  }
1165  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
1166  {
1167  neiLevel[facei] = cellLevel[faceOwner()[facei]];
1168  }
1169  syncTools::swapFaceList(*this, neiLevel);
1170 
1171 
1172  bitSet protectedFace(nFaces());
1173 
1174  forAll(faceOwner(), facei)
1175  {
1176  const label faceLevel = max
1177  (
1178  cellLevel[faceOwner()[facei]],
1179  neiLevel[facei]
1180  );
1181 
1182  const face& f = faces()[facei];
1183 
1184  label nAnchors = 0;
1185 
1186  for (const label pointi : f)
1187  {
1188  if (pointLevel[pointi] <= faceLevel)
1189  {
1190  ++nAnchors;
1191 
1192  if (nAnchors > 4)
1193  {
1194  protectedFace.set(facei);
1195  break;
1196  }
1197  }
1198  }
1199  }
1200 
1201  syncTools::syncFaceList(*this, protectedFace, orEqOp<unsigned int>());
1202 
1203  for (label facei = 0; facei < nInternalFaces(); ++facei)
1204  {
1205  if (protectedFace.test(facei))
1206  {
1207  protectedCell_.set(faceOwner()[facei]);
1208  protectedCell_.set(faceNeighbour()[facei]);
1209  }
1210  }
1211  for (label facei = nInternalFaces(); facei < nFaces(); ++facei)
1212  {
1213  if (protectedFace.test(facei))
1214  {
1215  protectedCell_.set(faceOwner()[facei]);
1216  }
1217  }
1218 
1219  // Also protect any cells that are less than hex
1220  forAll(cells(), celli)
1221  {
1222  const cell& cFaces = cells()[celli];
1223 
1224  if (cFaces.size() < 6)
1225  {
1226  protectedCell_.set(celli);
1227  }
1228  else
1229  {
1230  for (const label cfacei : cFaces)
1231  {
1232  if (faces()[cfacei].size() < 4)
1233  {
1234  protectedCell_.set(celli);
1235  break;
1236  }
1237  }
1238  }
1239  }
1240 
1241  // Check cells for 8 corner points
1242  checkEightAnchorPoints(protectedCell_);
1243  }
1244 
1245  if (!returnReduceOr(protectedCell_.any()))
1246  {
1247  protectedCell_.clear();
1248  }
1249  else
1250  {
1251  cellSet protectedCells
1252  (
1253  *this,
1254  "protectedCells",
1255  HashSetOps::used(protectedCell_)
1256  );
1257 
1258  Info<< "Detected "
1259  << returnReduce(protectedCells.size(), sumOp<label>())
1260  << " cells that are protected from refinement."
1261  << " Writing these to cellSet "
1262  << protectedCells.name()
1263  << "." << endl;
1264 
1265  protectedCells.write();
1266  }
1268  return true;
1269 }
1270 
1271 
1272 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1273 
1275 {
1276  // Re-read dictionary. Chosen since usually -small so trivial amount
1277  // of time compared to actual refinement. Also very useful to be able
1278  // to modify on-the-fly.
1279  dictionary refineDict
1280  (
1281  IOdictionary
1282  (
1283  IOobject
1284  (
1285  "dynamicMeshDict",
1286  time().constant(),
1287  *this,
1291  )
1292  ).optionalSubDict(typeName + "Coeffs")
1293  );
1294 
1295  const label refineInterval = refineDict.get<label>("refineInterval");
1296 
1297  bool hasChanged = false;
1298 
1299  if (refineInterval == 0)
1300  {
1301  topoChanging(hasChanged);
1302 
1303  return false;
1304  }
1305  else if (refineInterval < 0)
1306  {
1308  << "Illegal refineInterval " << refineInterval << nl
1309  << "The refineInterval setting in the dynamicMeshDict should"
1310  << " be >= 1." << nl
1311  << exit(FatalError);
1312  }
1313 
1314 
1315  // Note: cannot refine at time 0 since no V0 present since mesh not
1316  // moved yet.
1317 
1318  if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0)
1319  {
1320  const label maxCells = refineDict.get<label>("maxCells");
1321 
1322  if (maxCells <= 0)
1323  {
1325  << "Illegal maximum number of cells " << maxCells << nl
1326  << "The maxCells setting in the dynamicMeshDict should"
1327  << " be > 0." << nl
1328  << exit(FatalError);
1329  }
1330 
1331  const label maxRefinement = refineDict.get<label>("maxRefinement");
1332 
1333  if (maxRefinement <= 0)
1334  {
1336  << "Illegal maximum refinement level " << maxRefinement << nl
1337  << "The maxCells setting in the dynamicMeshDict should"
1338  << " be > 0." << nl
1339  << exit(FatalError);
1340  }
1341 
1342  const word fieldName(refineDict.get<word>("field"));
1343 
1344  const volScalarField& vFld = lookupObject<volScalarField>(fieldName);
1345 
1346  const scalar lowerRefineLevel =
1347  refineDict.get<scalar>("lowerRefineLevel");
1348  const scalar upperRefineLevel =
1349  refineDict.get<scalar>("upperRefineLevel");
1350  const scalar unrefineLevel = refineDict.getOrDefault<scalar>
1351  (
1352  "unrefineLevel",
1353  GREAT
1354  );
1355  const label nBufferLayers = refineDict.get<label>("nBufferLayers");
1356 
1357  // Cells marked for refinement or otherwise protected from unrefinement.
1358  bitSet refineCell(nCells());
1359 
1360  // Determine candidates for refinement (looking at field only)
1361  selectRefineCandidates
1362  (
1363  lowerRefineLevel,
1364  upperRefineLevel,
1365  vFld,
1366  refineCell
1367  );
1368 
1369  if (globalData().nTotalCells() < maxCells)
1370  {
1371  // Select subset of candidates. Take into account max allowable
1372  // cells, refinement level, protected cells.
1373  labelList cellsToRefine
1374  (
1375  selectRefineCells
1376  (
1377  maxCells,
1378  maxRefinement,
1379  refineCell
1380  )
1381  );
1382 
1383  if (returnReduceOr(cellsToRefine.size()))
1384  {
1385  // Refine/update mesh and map fields
1386  autoPtr<mapPolyMesh> map = refine(cellsToRefine);
1387 
1388  // Update refineCell. Note that some of the marked ones have
1389  // not been refined due to constraints.
1390  {
1391  const labelList& cellMap = map().cellMap();
1392  const labelList& reverseCellMap = map().reverseCellMap();
1393 
1394  bitSet newRefineCell(cellMap.size());
1395 
1396  forAll(cellMap, celli)
1397  {
1398  const label oldCelli = cellMap[celli];
1399 
1400  if
1401  (
1402  (oldCelli < 0)
1403  || (reverseCellMap[oldCelli] != celli)
1404  || (refineCell.test(oldCelli))
1405  )
1406  {
1407  newRefineCell.set(celli);
1408  }
1409  }
1410  refineCell.transfer(newRefineCell);
1411  }
1412 
1413  // Extend with a buffer layer to prevent neighbouring points
1414  // being unrefined.
1415  for (label i = 0; i < nBufferLayers; ++i)
1416  {
1417  extendMarkedCells(refineCell);
1418  }
1419 
1420  hasChanged = true;
1421  }
1422  }
1423 
1424 
1425  {
1426  // Select unrefineable points that are not marked in refineCell
1427  labelList pointsToUnrefine
1428  (
1429  selectUnrefinePoints
1430  (
1431  unrefineLevel,
1432  refineCell,
1433  maxCellField(vFld)
1434  )
1435  );
1436 
1437  if (returnReduceOr(pointsToUnrefine.size()))
1438  {
1439  // Refine/update mesh
1440  unrefine(pointsToUnrefine);
1441 
1442  hasChanged = true;
1443  }
1444  }
1445 
1446 
1447  if ((nRefinementIterations_ % 10) == 0)
1448  {
1449  // Compact refinement history occasionally (how often?).
1450  // Unrefinement causes holes in the refinementHistory.
1451  const_cast<refinementHistory&>(meshCutter().history()).compact();
1452  }
1453  nRefinementIterations_++;
1454  }
1455 
1456  topoChanging(hasChanged);
1457  if (hasChanged)
1458  {
1459  // Reset moving flag (if any). If not using inflation we'll not move,
1460  // if are using inflation any follow on movePoints will set it.
1461  moving(false);
1462  }
1463 
1464  return hasChanged;
1465 }
1466 
1467 
1469 {
1470  bool hasChanged = updateTopology();
1471  // Do any mesh motion (resets mesh.moving() if it does any mesh motion)
1472  hasChanged = dynamicMotionSolverListFvMesh::update() && hasChanged;
1473 
1474  return hasChanged;
1475 }
1476 
1477 
1479 (
1480  IOstreamOption streamOpt,
1481  const bool writeOnProc
1482 ) const
1483 {
1484  // Force refinement data to go to the current time directory.
1485  const_cast<hexRef8&>(meshCutter_).setInstance(time().timeName());
1486 
1487  bool writeOk =
1488  (
1489  //dynamicFvMesh::writeObject(streamOpt, writeOnProc)
1490  dynamicMotionSolverListFvMesh::writeObject(streamOpt, writeOnProc)
1491  && meshCutter_.write(writeOnProc)
1492  );
1493 
1494  if (dumpLevel_)
1495  {
1496  volScalarField scalarCellLevel
1497  (
1498  IOobject
1499  (
1500  "cellLevel",
1501  time().timeName(),
1502  *this,
1506  ),
1507  *this,
1509  );
1510 
1511  const labelList& cellLevel = meshCutter_.cellLevel();
1512 
1513  forAll(cellLevel, celli)
1514  {
1515  scalarCellLevel[celli] = cellLevel[celli];
1516  }
1517 
1518  writeOk = writeOk && scalarCellLevel.write();
1519  }
1520 
1521  return writeOk;
1522 }
1523 
1524 
1525 // ************************************************************************* //
Foam::surfaceFields.
void calculateProtectedCells(bitSet &unrefineableCell) const
Calculate cells that cannot be refined since would trigger.
fvsPatchField< scalar > fvsPatchScalarField
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
unsigned int count(const bool on=true) const
Count number of bits set.
Definition: bitSetI.H:426
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &f1)
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:504
bool updateTopology()
Update topology (refinement, unrefinement)
scalarField maxPointField(const scalarField &) const
Get per cell max of connected point.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write the underlying polyMesh and other data.
Definition: fvMesh.C:1079
labelHashSet used(const bitSet &select)
Convert a bitset to a labelHashSet of the indices used.
Definition: HashOps.C:26
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
const word UName(propsDict.getOrDefault< word >("U", "U"))
void checkEightAnchorPoints(bitSet &protectedCell) const
Check all cells have 8 anchor points.
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1122
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
scalarField cellToPoint(const scalarField &vFld) const
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:489
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
virtual bool update()
Update the mesh for both mesh motion and topology change.
static void syncFaceList(const polyMesh &mesh, UList< T > &faceValues, const CombineOp &cop)
Synchronize values on all mesh faces.
Definition: syncTools.H:432
bitSet protectedCell_
Protected cells (usually since not hexes)
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
Smooth ATC in cells having a point to a set of patches supplied by type.
Definition: pointCells.H:52
A simple container for options an IOstream can normally have.
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
label nFaces() const noexcept
Number of mesh faces.
autoPtr< mapPolyMesh > changeMesh(polyMesh &mesh, const labelUList &patchMap, const bool inflate, const bool syncParallel=true, const bool orderCells=false, const bool orderPoints=false)
Inplace changes mesh without change of patches.
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
A fvMesh with built-in refinement.
Macros for easy insertion into run-time selection tables.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
virtual labelList selectUnrefinePoints(const scalar unrefineLevel, const bitSet &markedCell, const scalarField &pFld) const
Select points that can be unrefined.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:81
virtual bool update()
Update the mesh for both mesh motion and topology change.
virtual bool writeObject(IOstreamOption streamOpt, const bool writeOnProc) const
Write using stream options.
word timeName
Definition: getTimeIndex.H:3
const cellShapeList & cells
virtual autoPtr< mapPolyMesh > unrefine(const labelList &)
Unrefine cells. Gets passed in centre points of cells to combine.
virtual void selectRefineCandidates(const scalar lowerRefineLevel, const scalar upperRefineLevel, const scalarField &vFld, bitSet &candidateCell) const
Select candidate cells for refinement.
virtual void mapFields(const mapPolyMesh &mpm)
Map all fields in time using given map. Triggered by topo change.
Refinement of (split) hexes using polyTopoChange.
Definition: hexRef8.H:62
label nPoints
hexRef8 meshCutter_
Mesh cutting engine.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
virtual labelList selectRefineCells(const label maxCells, const label maxRefinement, const bitSet &candidateCell) const
Subset candidate cells for refinement.
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1116
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
static const word null
An empty word.
Definition: word.H:84
virtual autoPtr< mapPolyMesh > refine(const labelList &)
Refine cells. Update mesh and fields.
virtual bool write(const token &tok)=0
Write token to stream or otherwise handle it.
label nInternalFaces() const noexcept
Number of internal faces.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void clear()
Clear the list, i.e. set addressable size to zero.
Definition: PackedListI.H:558
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
bool test(const label pos) const
Test for True value at specified position, never auto-vivify entries.
Definition: bitSet.H:326
virtual bool init(const bool doInit)
Initialise all non-demand-driven data.
#define DebugInfo
Report an information message using Foam::Info.
static void swapFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled face values. Uses eqOp.
Definition: syncTools.H:522
virtual void mapFields(const mapPolyMesh &mpm)
Map all fields in time using given map.
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
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].reset(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
void extendMarkedCells(bitSet &markedCell) const
Extend markedCell with cell-face-cell.
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.
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))
void readDict()
Read the projection parameters from dictionary.
static void fillNan(char *buf, size_t count)
Fill data block with signaling_NaN values.
Definition: sigFpe.C:244
bool empty() const noexcept
True if the list is empty (ie, size() is zero).
Definition: PackedList.H:366
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:59
#define WarningInFunction
Report a warning using Foam::Warning.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
void clearOut()
Clear all geometry and addressing.
Abstract base class for geometry and/or topology changing fvMesh.
Definition: dynamicFvMesh.H:74
Direct mesh changes based on v1.3 polyTopoChange syntax.
const dimensionedScalar c
Speed of light in a vacuum.
Nothing to be read.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
List< label > labelList
A List of labels.
Definition: List.H:62
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
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;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
label nBoundaryFaces() const noexcept
Number of boundary faces (== nFaces - nInternalFaces)
bool returnReduceOr(const bool value, const label comm=UPstream::worldComm)
Perform logical (or) MPI Allreduce on a copy. Uses UPstream::reduceOr.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
scalarField error(const scalarField &fld, const scalar minLevel, const scalar maxLevel) const
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
Do not request registration (bool: false)
const labelIOList & cellLevel() const
Definition: hexRef8.H:481
Namespace for OpenFOAM.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
label timeIndex
Definition: getTimeIndex.H:24
scalarField maxCellField(const volScalarField &) const
Get point max of connected cell.
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &faceValues)
Swap coupled boundary face values. Uses eqOp.
Definition: syncTools.H:485
addToRunTimeSelectionTable(functionObject, pointHistory, dictionary)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127