dynamicRefineFvMesh.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2021 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "dynamicRefineFvMesh.H"
27 #include "surfaceInterpolate.H"
28 #include "polyTopoChange.H"
29 #include "syncTools.H"
30 #include "pointFields.H"
31 #include "sigFpe.H"
32 #include "cellSet.H"
34 
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39  defineTypeNameAndDebug(dynamicRefineFvMesh, 0);
40  addToRunTimeSelectionTable(dynamicFvMesh, dynamicRefineFvMesh, IOobject);
41 }
42 
43 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
44 
45 Foam::label Foam::dynamicRefineFvMesh::count
46 (
47  const PackedBoolList& l,
48  const unsigned int val
49 )
50 {
51  label n = 0;
52  forAll(l, i)
53  {
54  if (l.get(i) == val)
55  {
56  n++;
57  }
58 
59  // Debug also serves to get-around Clang compiler trying to optimise
60  // out this forAll loop under O3 optimisation
61  if (debug)
62  {
63  Info<< "n=" << n << endl;
64  }
65  }
66 
67  return n;
68 }
69 
70 
71 void Foam::dynamicRefineFvMesh::calculateProtectedCells
72 (
73  PackedBoolList& unrefineableCells
74 ) const
75 {
76  if (protectedCells_.empty())
77  {
78  unrefineableCells.clear();
79  return;
80  }
81 
82  const labelList& cellLevel = meshCutter_.cellLevel();
83 
84  unrefineableCells = protectedCells_;
85 
86  // Get neighbouring cell level
87  labelList neiLevel(nFaces()-nInternalFaces());
88 
89  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
90  {
91  neiLevel[facei-nInternalFaces()] = cellLevel[faceOwner()[facei]];
92  }
93  syncTools::swapBoundaryFaceList(*this, neiLevel);
94 
95 
96  while (true)
97  {
98  // Pick up faces on border of protected cells
99  boolList seedFace(nFaces(), false);
100 
101  forAll(faceNeighbour(), facei)
102  {
103  label own = faceOwner()[facei];
104  bool ownProtected = unrefineableCells.get(own);
105  label nei = faceNeighbour()[facei];
106  bool neiProtected = unrefineableCells.get(nei);
107 
108  if (ownProtected && (cellLevel[nei] > cellLevel[own]))
109  {
110  seedFace[facei] = true;
111  }
112  else if (neiProtected && (cellLevel[own] > cellLevel[nei]))
113  {
114  seedFace[facei] = true;
115  }
116  }
117  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
118  {
119  label own = faceOwner()[facei];
120  bool ownProtected = unrefineableCells.get(own);
121  if
122  (
123  ownProtected
124  && (neiLevel[facei-nInternalFaces()] > cellLevel[own])
125  )
126  {
127  seedFace[facei] = true;
128  }
129  }
130 
131  syncTools::syncFaceList(*this, seedFace, orEqOp<bool>());
132 
133 
134  // Extend unrefineableCells
135  bool hasExtended = false;
136 
137  for (label facei = 0; facei < nInternalFaces(); facei++)
138  {
139  if (seedFace[facei])
140  {
141  label own = faceOwner()[facei];
142  if (unrefineableCells.get(own) == 0)
143  {
144  unrefineableCells.set(own, 1);
145  hasExtended = true;
146  }
147 
148  label nei = faceNeighbour()[facei];
149  if (unrefineableCells.get(nei) == 0)
150  {
151  unrefineableCells.set(nei, 1);
152  hasExtended = true;
153  }
154  }
155  }
156  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
157  {
158  if (seedFace[facei])
159  {
160  label own = faceOwner()[facei];
161  if (unrefineableCells.get(own) == 0)
162  {
163  unrefineableCells.set(own, 1);
164  hasExtended = true;
165  }
166  }
167  }
168 
169  if (!returnReduce(hasExtended, orOp<bool>()))
170  {
171  break;
172  }
173  }
174 }
175 
176 
177 void Foam::dynamicRefineFvMesh::readDict()
178 {
179  const dictionary refineDict
180  (
181  dynamicMeshDict().optionalSubDict(typeName + "Coeffs")
182  );
183 
184  List<Pair<word>> fluxVelocities = List<Pair<word>>
185  (
186  refineDict.lookup("correctFluxes")
187  );
188  // Rework into hashtable.
189  correctFluxes_.resize(fluxVelocities.size());
190  forAll(fluxVelocities, i)
191  {
192  correctFluxes_.insert(fluxVelocities[i][0], fluxVelocities[i][1]);
193  }
194 
195  dumpLevel_ = Switch(refineDict.lookup("dumpLevel"));
196 }
197 
198 
199 // Refines cells, maps fields and recalculates (an approximate) flux
201 Foam::dynamicRefineFvMesh::refine
202 (
203  const labelList& cellsToRefine
204 )
205 {
206  // Mesh changing engine.
207  polyTopoChange meshMod(*this);
208 
209  // Play refinement commands into mesh changer.
210  meshCutter_.setRefinement(cellsToRefine, meshMod);
211 
212  // Create mesh (with inflation), return map from old to new mesh.
213  // autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
214  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
215 
216  Info<< "Refined from "
217  << returnReduce(map().nOldCells(), sumOp<label>())
218  << " to " << globalData().nTotalCells() << " cells." << endl;
219 
220  if (debug)
221  {
222  // Check map.
223  for (label facei = 0; facei < nInternalFaces(); facei++)
224  {
225  label oldFacei = map().faceMap()[facei];
226 
227  if (oldFacei >= nInternalFaces())
228  {
230  << "New internal face:" << facei
231  << " fc:" << faceCentres()[facei]
232  << " originates from boundary oldFace:" << oldFacei
233  << abort(FatalError);
234  }
235  }
236  }
237 
238  // Update fields
239  updateMesh(map);
240 
241  // Correct the flux for modified/added faces. All the faces which only
242  // have been renumbered will already have been handled by the mapping.
243  {
244  const labelList& faceMap = map().faceMap();
245  const labelList& reverseFaceMap = map().reverseFaceMap();
246 
247  // Storage for any master faces. These will be the original faces
248  // on the coarse cell that get split into four (or rather the
249  // master face gets modified and three faces get added from the master)
250  labelHashSet masterFaces(4*cellsToRefine.size());
251 
252  forAll(faceMap, facei)
253  {
254  label oldFacei = faceMap[facei];
255 
256  if (oldFacei >= 0)
257  {
258  label masterFacei = reverseFaceMap[oldFacei];
259 
260  if (masterFacei < 0)
261  {
263  << "Problem: should not have removed faces"
264  << " when refining."
265  << nl << "face:" << facei << abort(FatalError);
266  }
267  else if (masterFacei != facei)
268  {
269  masterFaces.insert(masterFacei);
270  }
271  }
272  }
273  if (debug)
274  {
275  Pout<< "Found " << masterFaces.size() << " split faces " << endl;
276  }
277 
278  HashTable<surfaceScalarField*> fluxes
279  (
280  lookupClass<surfaceScalarField>()
281  );
282  forAllIter(HashTable<surfaceScalarField*>, fluxes, iter)
283  {
284  if (!correctFluxes_.found(iter.key()))
285  {
287  << "Cannot find surfaceScalarField " << iter.key()
288  << " in user-provided flux mapping table "
289  << correctFluxes_ << endl
290  << " The flux mapping table is used to recreate the"
291  << " flux on newly created faces." << endl
292  << " Either add the entry if it is a flux or use ("
293  << iter.key() << " none) to suppress this warning."
294  << endl;
295  continue;
296  }
297 
298  const word& UName = correctFluxes_[iter.key()];
299 
300  if (UName == "none")
301  {
302  continue;
303  }
304 
305  if (UName == "NaN")
306  {
307  Pout<< "Setting surfaceScalarField " << iter.key()
308  << " to NaN" << endl;
309 
310  surfaceScalarField& phi = *iter();
311 
312  sigFpe::fillNan(phi.primitiveFieldRef());
313 
314  continue;
315  }
316 
317  if (debug)
318  {
319  Pout<< "Mapping flux " << iter.key()
320  << " using interpolated flux " << UName
321  << endl;
322  }
323 
324  surfaceScalarField& phi = *iter();
325  const surfaceScalarField phiU
326  (
328  (
329  lookupObject<volVectorField>(UName)
330  )
331  & Sf()
332  );
333 
334  // Recalculate new internal faces.
335  for (label facei = 0; facei < nInternalFaces(); facei++)
336  {
337  label oldFacei = faceMap[facei];
338 
339  if (oldFacei == -1)
340  {
341  // Inflated/appended
342  phi[facei] = phiU[facei];
343  }
344  else if (reverseFaceMap[oldFacei] != facei)
345  {
346  // face-from-masterface
347  phi[facei] = phiU[facei];
348  }
349  }
350 
351  // Recalculate new boundary faces.
352  surfaceScalarField::Boundary& phiBf =
353  phi.boundaryFieldRef();
354  forAll(phiBf, patchi)
355  {
356  fvsPatchScalarField& patchPhi = phiBf[patchi];
357  const fvsPatchScalarField& patchPhiU =
358  phiU.boundaryField()[patchi];
359 
360  label facei = patchPhi.patch().start();
361 
362  forAll(patchPhi, i)
363  {
364  label oldFacei = faceMap[facei];
365 
366  if (oldFacei == -1)
367  {
368  // Inflated/appended
369  patchPhi[i] = patchPhiU[i];
370  }
371  else if (reverseFaceMap[oldFacei] != facei)
372  {
373  // face-from-masterface
374  patchPhi[i] = patchPhiU[i];
375  }
376 
377  facei++;
378  }
379  }
380 
381  // Update master faces
382  forAllConstIter(labelHashSet, masterFaces, iter)
383  {
384  label facei = iter.key();
385 
386  if (isInternalFace(facei))
387  {
388  phi[facei] = phiU[facei];
389  }
390  else
391  {
392  label patchi = boundaryMesh().whichPatch(facei);
393  label i = facei - boundaryMesh()[patchi].start();
394 
395  const fvsPatchScalarField& patchPhiU =
396  phiU.boundaryField()[patchi];
397 
398  fvsPatchScalarField& patchPhi = phiBf[patchi];
399 
400  patchPhi[i] = patchPhiU[i];
401  }
402  }
403  }
404  }
405 
406 
407  // Update numbering of cells/vertices.
408  meshCutter_.updateMesh(map);
409 
410  // Update numbering of protectedCells_
411  if (protectedCells_.size())
412  {
413  PackedBoolList newProtectedCell(nCells());
414 
415  forAll(newProtectedCell, celli)
416  {
417  label oldCelli = map().cellMap()[celli];
418  newProtectedCell.set(celli, protectedCells_.get(oldCelli));
419  }
420  protectedCells_.transfer(newProtectedCell);
421  }
422 
423  // Debug: Check refinement levels (across faces only)
424  meshCutter_.checkRefinementLevels(-1, labelList(0));
425 
426  return map;
427 }
428 
429 
431 Foam::dynamicRefineFvMesh::unrefine
432 (
433  const labelList& splitPoints
434 )
435 {
436  polyTopoChange meshMod(*this);
437 
438  // Play refinement commands into mesh changer.
439  meshCutter_.setUnrefinement(splitPoints, meshMod);
440 
441 
442  // Save information on faces that will be combined
443  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
444 
445  // Find the faceMidPoints on cells to be combined.
446  // for each face resulting of split of face into four store the
447  // midpoint
448  Map<label> faceToSplitPoint(3*splitPoints.size());
449 
450  {
451  forAll(splitPoints, i)
452  {
453  label pointi = splitPoints[i];
454 
455  const labelList& pEdges = pointEdges()[pointi];
456 
457  forAll(pEdges, j)
458  {
459  label otherPointi = edges()[pEdges[j]].otherVertex(pointi);
460 
461  const labelList& pFaces = pointFaces()[otherPointi];
462 
463  forAll(pFaces, pFacei)
464  {
465  faceToSplitPoint.insert(pFaces[pFacei], otherPointi);
466  }
467  }
468  }
469  }
470 
471 
472  // Change mesh and generate map.
473  // autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
474  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
475 
476  Info<< "Unrefined from "
477  << returnReduce(map().nOldCells(), sumOp<label>())
478  << " to " << globalData().nTotalCells() << " cells."
479  << endl;
480 
481  // Update fields
482  updateMesh(map);
483 
484  // Correct the flux for modified faces.
485  {
486  const labelList& reversePointMap = map().reversePointMap();
487  const labelList& reverseFaceMap = map().reverseFaceMap();
488 
489  HashTable<surfaceScalarField*> fluxes
490  (
491  lookupClass<surfaceScalarField>()
492  );
493  forAllIter(HashTable<surfaceScalarField*>, fluxes, iter)
494  {
495  if (!correctFluxes_.found(iter.key()))
496  {
498  << "Cannot find surfaceScalarField " << iter.key()
499  << " in user-provided flux mapping table "
500  << correctFluxes_ << endl
501  << " The flux mapping table is used to recreate the"
502  << " flux on newly created faces." << endl
503  << " Either add the entry if it is a flux or use ("
504  << iter.key() << " none) to suppress this warning."
505  << endl;
506  continue;
507  }
508 
509  const word& UName = correctFluxes_[iter.key()];
510 
511  if (UName == "none")
512  {
513  continue;
514  }
515 
516  if (debug)
517  {
518  Info<< "Mapping flux " << iter.key()
519  << " using interpolated flux " << UName
520  << endl;
521  }
522 
523  surfaceScalarField& phi = *iter();
524  surfaceScalarField::Boundary& phiBf =
525  phi.boundaryFieldRef();
526 
527  const surfaceScalarField phiU
528  (
530  (
531  lookupObject<volVectorField>(UName)
532  )
533  & Sf()
534  );
535 
536 
537  forAllConstIter(Map<label>, faceToSplitPoint, iter)
538  {
539  label oldFacei = iter.key();
540  label oldPointi = iter();
541 
542  if (reversePointMap[oldPointi] < 0)
543  {
544  // midpoint was removed. See if face still exists.
545  label facei = reverseFaceMap[oldFacei];
546 
547  if (facei >= 0)
548  {
549  if (isInternalFace(facei))
550  {
551  phi[facei] = phiU[facei];
552  }
553  else
554  {
555  label patchi = boundaryMesh().whichPatch(facei);
556  label i = facei - boundaryMesh()[patchi].start();
557 
558  const fvsPatchScalarField& patchPhiU =
559  phiU.boundaryField()[patchi];
560  fvsPatchScalarField& patchPhi = phiBf[patchi];
561  patchPhi[i] = patchPhiU[i];
562  }
563  }
564  }
565  }
566  }
567  }
568 
569 
570  // Update numbering of cells/vertices.
571  meshCutter_.updateMesh(map);
572 
573  // Update numbering of protectedCells_
574  if (protectedCells_.size())
575  {
576  PackedBoolList newProtectedCell(nCells());
577 
578  forAll(newProtectedCell, celli)
579  {
580  label oldCelli = map().cellMap()[celli];
581  if (oldCelli >= 0)
582  {
583  newProtectedCell.set(celli, protectedCells_.get(oldCelli));
584  }
585  }
586  protectedCells_.transfer(newProtectedCell);
587  }
588 
589  // Debug: Check refinement levels (across faces only)
590  meshCutter_.checkRefinementLevels(-1, labelList(0));
591 
592  return map;
593 }
594 
595 
596 const Foam::cellZone& Foam::dynamicRefineFvMesh::findCellZone
597 (
598  const word& cellZoneName
599 ) const
600 {
601  const label cellZoneID = cellZones().findZoneID(cellZoneName);
602  bool cellZoneFound = (cellZoneID != -1);
603  reduce(cellZoneFound, orOp<bool>());
604  if (!cellZoneFound)
605  {
607  << "cannot find cellZone " << cellZoneName
608  << exit(FatalError);
609  }
610 
611  return cellZones()[cellZoneID];
612 }
613 
614 
616 Foam::dynamicRefineFvMesh::cellToPoint(const scalarField& vFld) const
617 {
618  scalarField pFld(nPoints());
619 
620  forAll(pointCells(), pointi)
621  {
622  const labelList& pCells = pointCells()[pointi];
623 
624  scalar sum = 0.0;
625  forAll(pCells, i)
626  {
627  sum += vFld[pCells[i]];
628  }
629  pFld[pointi] = sum/pCells.size();
630  }
631  return pFld;
632 }
633 
634 
635 Foam::scalarField Foam::dynamicRefineFvMesh::error
636 (
637  const scalarField& fld,
638  const scalar minLevel,
639  const scalar maxLevel
640 ) const
641 {
642  scalarField c(fld.size(), -1);
643 
644  forAll(c, celli)
645  {
646  scalar err = min(fld[celli] - minLevel, maxLevel - fld[celli]);
647 
648  if (err >= 0)
649  {
650  c[celli] = err;
651  }
652  }
653 
654  return c;
655 }
656 
657 
658 Foam::scalarField Foam::dynamicRefineFvMesh::error
659 (
660  const scalarField& fld,
661  const labelList& cells,
662  const scalar minLevel,
663  const scalar maxLevel
664 ) const
665 {
666  scalarField c(fld.size(), -1);
667 
668  forAll(cells, i)
669  {
670  const label celli = cells[i];
671 
672  scalar err = min(fld[celli] - minLevel, maxLevel - fld[celli]);
673 
674  if (err >= 0)
675  {
676  c[celli] = err;
677  }
678  }
679 
680  return c;
681 }
682 
683 
684 void Foam::dynamicRefineFvMesh::selectRefineCandidates
685 (
686  PackedBoolList& candidateCells,
687  const scalar lowerRefineLevel,
688  const scalar upperRefineLevel,
689  const scalar maxRefinement,
690  const scalarField& vFld
691 ) const
692 {
693  // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
694  // higher more desirable to be refined).
695  const scalarField cellError
696  (
697  error(vFld, lowerRefineLevel, upperRefineLevel)
698  );
699 
700  const labelList& cellLevel = meshCutter_.cellLevel();
701 
702  // Mark cells that are candidates for refinement.
703  forAll(cellError, celli)
704  {
705  if
706  (
707  cellLevel[celli] < maxRefinement
708  && cellError[celli] > 0
709  )
710  {
711  candidateCells.set(celli, 1);
712  }
713  }
714 }
715 
716 
717 void Foam::dynamicRefineFvMesh::selectRefineCandidates
718 (
719  PackedBoolList& candidateCells,
720  const scalar lowerRefineLevel,
721  const scalar upperRefineLevel,
722  const scalar maxRefinement,
723  const scalarField& vFld,
724  const labelList& cells
725 ) const
726 {
727  // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
728  // higher more desirable to be refined).
729  const scalarField cellError
730  (
731  error(vFld, cells, lowerRefineLevel, upperRefineLevel)
732  );
733 
734  const labelList& cellLevel = meshCutter_.cellLevel();
735 
736  // Mark cells that are candidates for refinement.
737  forAll(cellError, celli)
738  {
739  if
740  (
741  cellLevel[celli] < maxRefinement
742  && cellError[celli] > 0
743  )
744  {
745  candidateCells.set(celli, 1);
746  }
747  }
748 }
749 
750 
751 Foam::scalar Foam::dynamicRefineFvMesh::selectRefineCandidates
752 (
753  PackedBoolList& candidateCells,
754  const dictionary& refineDict
755 ) const
756 {
757  const word fieldName(refineDict.lookup("field"));
758 
759  const volScalarField& vFld = lookupObject<volScalarField>(fieldName);
760 
761  const scalar lowerRefineLevel =
762  refineDict.lookup<scalar>("lowerRefineLevel");
763  const scalar upperRefineLevel =
764  refineDict.lookup<scalar>("upperRefineLevel");
765 
766  const label maxRefinement = refineDict.lookup<label>("maxRefinement");
767 
768  if (maxRefinement <= 0)
769  {
771  << "Illegal maximum refinement level " << maxRefinement << nl
772  << "The maxCells setting in the dynamicMeshDict should"
773  << " be > 0." << nl
774  << exit(FatalError);
775  }
776 
777  if (refineDict.found("cellZone"))
778  {
779  // Determine candidates for refinement (looking at field only)
780  selectRefineCandidates
781  (
782  candidateCells,
783  lowerRefineLevel,
784  upperRefineLevel,
785  maxRefinement,
786  vFld,
787  findCellZone(refineDict.lookup("cellZone"))
788  );
789  }
790  else
791  {
792  // Determine candidates for refinement (looking at field only)
793  selectRefineCandidates
794  (
795  candidateCells,
796  lowerRefineLevel,
797  upperRefineLevel,
798  maxRefinement,
799  vFld
800  );
801  }
802 
803  return maxRefinement;
804 }
805 
806 
807 Foam::labelList Foam::dynamicRefineFvMesh::selectRefineCells
808 (
809  const label maxCells,
810  const label maxRefinement,
811  const PackedBoolList& candidateCells
812 ) const
813 {
814  // Every refined cell causes 7 extra cells
815  label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
816 
817  const labelList& cellLevel = meshCutter_.cellLevel();
818 
819  // Mark cells that cannot be refined since they would trigger refinement
820  // of protected cells (since 2:1 cascade)
821  PackedBoolList unrefineableCells;
822  calculateProtectedCells(unrefineableCells);
823 
824  // Count current selection
825  label nLocalCandidates = count(candidateCells, 1);
826  label nCandidates = returnReduce(nLocalCandidates, sumOp<label>());
827 
828  // Collect all cells
829  DynamicList<label> candidates(nLocalCandidates);
830 
831  if (nCandidates < nTotToRefine)
832  {
833  forAll(candidateCells, celli)
834  {
835  if
836  (
837  candidateCells.get(celli)
838  && (
839  unrefineableCells.empty()
840  || !unrefineableCells.get(celli)
841  )
842  )
843  {
844  candidates.append(celli);
845  }
846  }
847  }
848  else
849  {
850  // Sort by error? For now just truncate.
851  for (label level = 0; level < maxRefinement; level++)
852  {
853  forAll(candidateCells, celli)
854  {
855  if
856  (
857  cellLevel[celli] == level
858  && candidateCells.get(celli)
859  && (
860  unrefineableCells.empty()
861  || !unrefineableCells.get(celli)
862  )
863  )
864  {
865  candidates.append(celli);
866  }
867  }
868 
869  if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine)
870  {
871  break;
872  }
873  }
874  }
875 
876  // Guarantee 2:1 refinement after refinement
877  labelList consistentSet
878  (
879  meshCutter_.consistentRefinement
880  (
881  candidates.shrink(),
882  true // Add to set to guarantee 2:1
883  )
884  );
885 
886  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
887  << " cells for refinement out of " << globalData().nTotalCells()
888  << "." << endl;
889 
890  return consistentSet;
891 }
892 
893 
894 void Foam::dynamicRefineFvMesh::selectUnrefineCandidates
895 (
896  boolList& unrefineCandidates,
897  const volScalarField& vFld,
898  const scalar unrefineLevel
899 ) const
900 {
901  forAll(pointCells(), pointi)
902  {
903  const labelList& pCells = pointCells()[pointi];
904 
905  scalar maxVal = -great;
906  forAll(pCells, i)
907  {
908  maxVal = max(maxVal, vFld[pCells[i]]);
909  }
910 
911  unrefineCandidates[pointi] =
912  unrefineCandidates[pointi] && maxVal < unrefineLevel;
913  }
914 }
915 
916 
917 void Foam::dynamicRefineFvMesh::selectUnrefineCandidates
918 (
919  boolList& unrefineCandidates,
920  const volScalarField& vFld,
921  const cellZone& cZone,
922  const scalar unrefineLevel
923 ) const
924 {
925  const Map<label>& zoneMap(cZone.lookupMap());
926 
927  forAll(pointCells(), pointi)
928  {
929  const labelList& pCells = pointCells()[pointi];
930 
931  scalar maxVal = -great;
932  forAll(pCells, i)
933  {
934  if (zoneMap.found(pCells[i]))
935  {
936  maxVal = max(maxVal, vFld[pCells[i]]);
937  }
938  }
939 
940  unrefineCandidates[pointi] =
941  unrefineCandidates[pointi] && maxVal < unrefineLevel;
942  }
943 }
944 
945 
946 void Foam::dynamicRefineFvMesh::selectUnrefineCandidates
947 (
948  boolList& unrefineCandidates,
949  const dictionary& refineDict
950 ) const
951 {
952  if (refineDict.found("unrefineLevel"))
953  {
954  const word fieldName(refineDict.lookup("field"));
955  const volScalarField& vFld
956  (
957  lookupObject<volScalarField>(fieldName)
958  );
959 
960  const scalar unrefineLevel =
961  refineDict.lookup<scalar>("unrefineLevel");
962 
963  if (refineDict.found("cellZone"))
964  {
965  selectUnrefineCandidates
966  (
967  unrefineCandidates,
968  vFld,
969  findCellZone(refineDict.lookup("cellZone")),
970  unrefineLevel
971  );
972  }
973  else
974  {
975  selectUnrefineCandidates
976  (
977  unrefineCandidates,
978  vFld,
979  unrefineLevel
980  );
981  }
982  }
983 }
984 
985 
986 Foam::labelList Foam::dynamicRefineFvMesh::selectUnrefinePoints
987 (
988  const PackedBoolList& markedCell,
989  const boolList& unrefineCandidates
990 ) const
991 {
992  // All points that can be unrefined
993  const labelList splitPoints(meshCutter_.getSplitPoints());
994 
995  DynamicList<label> newSplitPoints(splitPoints.size());
996 
997  forAll(splitPoints, i)
998  {
999  label pointi = splitPoints[i];
1000 
1001  if (unrefineCandidates[pointi])
1002  {
1003  // Check that all cells are not marked
1004  const labelList& pCells = pointCells()[pointi];
1005 
1006  bool hasMarked = false;
1007 
1008  forAll(pCells, pCelli)
1009  {
1010  if (markedCell.get(pCells[pCelli]))
1011  {
1012  hasMarked = true;
1013  break;
1014  }
1015  }
1016 
1017  if (!hasMarked)
1018  {
1019  newSplitPoints.append(pointi);
1020  }
1021  }
1022  }
1023 
1024 
1025  newSplitPoints.shrink();
1026 
1027  // Guarantee 2:1 refinement after unrefinement
1028  labelList consistentSet
1029  (
1030  meshCutter_.consistentUnrefinement
1031  (
1032  newSplitPoints,
1033  false
1034  )
1035  );
1036  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
1037  << " split points out of a possible "
1038  << returnReduce(splitPoints.size(), sumOp<label>())
1039  << "." << endl;
1040 
1041  return consistentSet;
1042 }
1043 
1044 
1045 void Foam::dynamicRefineFvMesh::extendMarkedCells
1046 (
1047  PackedBoolList& markedCell
1048 ) const
1049 {
1050  // Mark faces using any marked cell
1051  boolList markedFace(nFaces(), false);
1052 
1053  forAll(markedCell, celli)
1054  {
1055  if (markedCell.get(celli))
1056  {
1057  const cell& cFaces = cells()[celli];
1058 
1059  forAll(cFaces, i)
1060  {
1061  markedFace[cFaces[i]] = true;
1062  }
1063  }
1064  }
1065 
1066  syncTools::syncFaceList(*this, markedFace, orEqOp<bool>());
1067 
1068  // Update cells using any markedFace
1069  for (label facei = 0; facei < nInternalFaces(); facei++)
1070  {
1071  if (markedFace[facei])
1072  {
1073  markedCell.set(faceOwner()[facei], 1);
1074  markedCell.set(faceNeighbour()[facei], 1);
1075  }
1076  }
1077  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
1078  {
1079  if (markedFace[facei])
1080  {
1081  markedCell.set(faceOwner()[facei], 1);
1082  }
1083  }
1084 }
1085 
1086 
1087 void Foam::dynamicRefineFvMesh::checkEightAnchorPoints
1088 (
1089  PackedBoolList& protectedCell,
1090  label& nProtected
1091 ) const
1092 {
1093  const labelList& cellLevel = meshCutter_.cellLevel();
1094  const labelList& pointLevel = meshCutter_.pointLevel();
1095 
1096  labelList nAnchorPoints(nCells(), 0);
1097 
1098  forAll(pointLevel, pointi)
1099  {
1100  const labelList& pCells = pointCells(pointi);
1101 
1102  forAll(pCells, pCelli)
1103  {
1104  label celli = pCells[pCelli];
1105 
1106  if (pointLevel[pointi] <= cellLevel[celli])
1107  {
1108  // Check if cell has already 8 anchor points -> protect cell
1109  if (nAnchorPoints[celli] == 8)
1110  {
1111  if (protectedCell.set(celli, true))
1112  {
1113  nProtected++;
1114  }
1115  }
1116 
1117  if (!protectedCell[celli])
1118  {
1119  nAnchorPoints[celli]++;
1120  }
1121  }
1122  }
1123  }
1124 
1125 
1126  forAll(protectedCell, celli)
1127  {
1128  if (!protectedCell[celli] && nAnchorPoints[celli] != 8)
1129  {
1130  protectedCell.set(celli, true);
1131  nProtected++;
1132  }
1133  }
1134 }
1135 
1136 
1137 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1138 
1140 :
1141  dynamicFvMesh(io),
1142  meshCutter_(*this),
1143  dumpLevel_(false),
1144  nRefinementIterations_(0),
1145  protectedCells_(nCells(), 0)
1146 {
1147  // Read static part of dictionary
1148  readDict();
1149 
1150  const labelList& cellLevel = meshCutter_.cellLevel();
1151  const labelList& pointLevel = meshCutter_.pointLevel();
1152 
1153  // Set cells that should not be refined.
1154  // This is currently any cell which does not have 8 anchor points or
1155  // uses any face which does not have 4 anchor points.
1156  // Note: do not use cellPoint addressing
1157 
1158  // Count number of points <= cellLevel
1159  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1160 
1161  labelList nAnchors(nCells(), 0);
1162 
1163  label nProtected = 0;
1164 
1165  forAll(pointCells(), pointi)
1166  {
1167  const labelList& pCells = pointCells()[pointi];
1168 
1169  forAll(pCells, i)
1170  {
1171  label celli = pCells[i];
1172 
1173  if (!protectedCells_.get(celli))
1174  {
1175  if (pointLevel[pointi] <= cellLevel[celli])
1176  {
1177  nAnchors[celli]++;
1178 
1179  if (nAnchors[celli] > 8)
1180  {
1181  protectedCells_.set(celli, 1);
1182  nProtected++;
1183  }
1184  }
1185  }
1186  }
1187  }
1188 
1189 
1190  // Count number of points <= faceLevel
1191  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1192  // Bit tricky since proc face might be one more refined than the owner since
1193  // the coupled one is refined.
1194 
1195  {
1196  labelList neiLevel(nFaces());
1197 
1198  for (label facei = 0; facei < nInternalFaces(); facei++)
1199  {
1200  neiLevel[facei] = cellLevel[faceNeighbour()[facei]];
1201  }
1202  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
1203  {
1204  neiLevel[facei] = cellLevel[faceOwner()[facei]];
1205  }
1206  syncTools::swapFaceList(*this, neiLevel);
1207 
1208 
1209  boolList protectedFace(nFaces(), false);
1210 
1211  forAll(faceOwner(), facei)
1212  {
1213  label faceLevel = max
1214  (
1215  cellLevel[faceOwner()[facei]],
1216  neiLevel[facei]
1217  );
1218 
1219  const face& f = faces()[facei];
1220 
1221  label nAnchors = 0;
1222 
1223  forAll(f, fp)
1224  {
1225  if (pointLevel[f[fp]] <= faceLevel)
1226  {
1227  nAnchors++;
1228 
1229  if (nAnchors > 4)
1230  {
1231  protectedFace[facei] = true;
1232  break;
1233  }
1234  }
1235  }
1236  }
1237 
1238  syncTools::syncFaceList(*this, protectedFace, orEqOp<bool>());
1239 
1240  for (label facei = 0; facei < nInternalFaces(); facei++)
1241  {
1242  if (protectedFace[facei])
1243  {
1244  protectedCells_.set(faceOwner()[facei], 1);
1245  nProtected++;
1246  protectedCells_.set(faceNeighbour()[facei], 1);
1247  nProtected++;
1248  }
1249  }
1250  for (label facei = nInternalFaces(); facei < nFaces(); facei++)
1251  {
1252  if (protectedFace[facei])
1253  {
1254  protectedCells_.set(faceOwner()[facei], 1);
1255  nProtected++;
1256  }
1257  }
1258 
1259  // Also protect any cells that are less than hex
1260  forAll(cells(), celli)
1261  {
1262  const cell& cFaces = cells()[celli];
1263 
1264  if (cFaces.size() < 6)
1265  {
1266  if (protectedCells_.set(celli, 1))
1267  {
1268  nProtected++;
1269  }
1270  }
1271  else
1272  {
1273  forAll(cFaces, cFacei)
1274  {
1275  if (faces()[cFaces[cFacei]].size() < 4)
1276  {
1277  if (protectedCells_.set(celli, 1))
1278  {
1279  nProtected++;
1280  }
1281  break;
1282  }
1283  }
1284  }
1285  }
1286 
1287  // Check cells for 8 corner points
1288  checkEightAnchorPoints(protectedCells_, nProtected);
1289  }
1290 
1291  if (returnReduce(nProtected, sumOp<label>()) == 0)
1292  {
1293  protectedCells_.clear();
1294  }
1295  else
1296  {
1297 
1298  cellSet protectedCells(*this, "protectedCells", nProtected);
1299  forAll(protectedCells_, celli)
1300  {
1301  if (protectedCells_[celli])
1302  {
1303  protectedCells.insert(celli);
1304  }
1305  }
1306 
1307  Info<< "Detected " << returnReduce(nProtected, sumOp<label>())
1308  << " cells that are protected from refinement."
1309  << " Writing these to cellSet "
1310  << protectedCells.name()
1311  << "." << endl;
1312 
1313  protectedCells.write();
1314  }
1315 }
1316 
1317 
1318 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1319 
1321 {}
1322 
1323 
1324 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1325 
1327 {
1328  // Re-read dictionary. Chosen since usually -small so trivial amount
1329  // of time compared to actual refinement. Also very useful to be able
1330  // to modify on-the-fly.
1331  const dictionary refineDict
1332  (
1333  dynamicMeshDict().optionalSubDict(typeName + "Coeffs")
1334  );
1335 
1336  label refineInterval = refineDict.lookup<label>("refineInterval");
1337 
1338  bool hasChanged = false;
1339 
1340  if (refineInterval == 0)
1341  {
1342  topoChanging(hasChanged);
1343 
1344  return false;
1345  }
1346  else if (refineInterval < 0)
1347  {
1349  << "Illegal refineInterval " << refineInterval << nl
1350  << "The refineInterval setting in the dynamicMeshDict should"
1351  << " be >= 1." << nl
1352  << exit(FatalError);
1353  }
1354 
1355  // Note: cannot refine at time 0 since no V0 present since mesh not
1356  // moved yet.
1357 
1358  if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0)
1359  {
1360  label maxCells = refineDict.lookup<label>("maxCells");
1361 
1362  if (maxCells <= 0)
1363  {
1365  << "Illegal maximum number of cells " << maxCells << nl
1366  << "The maxCells setting in the dynamicMeshDict should"
1367  << " be > 0." << nl
1368  << exit(FatalError);
1369  }
1370 
1371  const label nBufferLayers =
1372  refineDict.lookup<label>("nBufferLayers");
1373 
1374  // Cells marked for refinement or otherwise protected from unrefinement.
1375  PackedBoolList refineCells(nCells());
1376 
1377  label maxRefinement = 0;
1378 
1379  if (refineDict.isDict("refinementRegions"))
1380  {
1382  (
1383  refineDict.subDict("refinementRegions")
1384  );
1385 
1387  {
1388  maxRefinement = max
1389  (
1390  selectRefineCandidates
1391  (
1392  refineCells,
1393  refinementRegions.subDict(iter().keyword())
1394  ),
1395  maxRefinement
1396  );
1397  }
1398  }
1399  else
1400  {
1401  maxRefinement = selectRefineCandidates(refineCells, refineDict);
1402  }
1403 
1404  if (globalData().nTotalCells() < maxCells)
1405  {
1406  // Select subset of candidates. Take into account max allowable
1407  // cells, refinement level, protected cells.
1408  labelList cellsToRefine
1409  (
1410  selectRefineCells
1411  (
1412  maxCells,
1413  maxRefinement,
1414  refineCells
1415  )
1416  );
1417 
1418  label nCellsToRefine = returnReduce
1419  (
1420  cellsToRefine.size(), sumOp<label>()
1421  );
1422 
1423  if (nCellsToRefine > 0)
1424  {
1425  // Refine/update mesh and map fields
1426  autoPtr<mapPolyMesh> map = refine(cellsToRefine);
1427 
1428  // Update refineCells. Note that some of the marked ones have
1429  // not been refined due to constraints.
1430  {
1431  const labelList& cellMap = map().cellMap();
1432  const labelList& reverseCellMap = map().reverseCellMap();
1433 
1434  PackedBoolList newRefineCell(cellMap.size());
1435 
1436  forAll(cellMap, celli)
1437  {
1438  label oldCelli = cellMap[celli];
1439 
1440  if (oldCelli < 0)
1441  {
1442  newRefineCell.set(celli, 1);
1443  }
1444  else if (reverseCellMap[oldCelli] != celli)
1445  {
1446  newRefineCell.set(celli, 1);
1447  }
1448  else
1449  {
1450  newRefineCell.set(celli, refineCells.get(oldCelli));
1451  }
1452  }
1453  refineCells.transfer(newRefineCell);
1454  }
1455 
1456  // Extend with a buffer layer to prevent neighbouring points
1457  // being unrefined.
1458  for (label i = 0; i < nBufferLayers; i++)
1459  {
1460  extendMarkedCells(refineCells);
1461  }
1462 
1463  hasChanged = true;
1464  }
1465  }
1466 
1467  boolList unrefineCandidates(nPoints(), true);
1468 
1469  if (refineDict.isDict("refinementRegions"))
1470  {
1472  (
1473  refineDict.subDict("refinementRegions")
1474  );
1475 
1477  {
1478  selectUnrefineCandidates
1479  (
1480  unrefineCandidates,
1481  refinementRegions.subDict(iter().keyword())
1482  );
1483  }
1484  }
1485  else
1486  {
1487  selectUnrefineCandidates
1488  (
1489  unrefineCandidates,
1490  refineDict
1491  );
1492  }
1493 
1494  {
1495  // Select unrefineable points that are not marked in refineCells
1496  labelList pointsToUnrefine
1497  (
1498  selectUnrefinePoints
1499  (
1500  refineCells,
1501  unrefineCandidates
1502  )
1503  );
1504 
1505  label nSplitPoints = returnReduce
1506  (
1507  pointsToUnrefine.size(),
1508  sumOp<label>()
1509  );
1510 
1511  if (nSplitPoints > 0)
1512  {
1513  // Refine/update mesh
1514  unrefine(pointsToUnrefine);
1515 
1516  hasChanged = true;
1517  }
1518  }
1519 
1520 
1521  if ((nRefinementIterations_ % 10) == 0)
1522  {
1523  // Compact refinement history occasionally (how often?).
1524  // Unrefinement causes holes in the refinementHistory.
1525  const_cast<refinementHistory&>(meshCutter().history()).compact();
1526  }
1527  nRefinementIterations_++;
1528  }
1529 
1530  topoChanging(hasChanged);
1531  if (hasChanged)
1532  {
1533  // Reset moving flag (if any). If not using inflation we'll not move,
1534  // if are using inflation any follow on movePoints will set it.
1535  moving(false);
1536  }
1537 
1538  return hasChanged;
1539 }
1540 
1541 
1547  const bool write
1548 ) const
1549 {
1550  // Force refinement data to go to the current time directory.
1551  const_cast<hexRef8&>(meshCutter_).setInstance(time().timeName());
1552 
1553  bool writeOk =
1554  (
1555  dynamicFvMesh::writeObject(fmt, ver, cmp, write)
1556  && meshCutter_.write(write)
1557  );
1558 
1559  if (dumpLevel_)
1560  {
1561  volScalarField scalarCellLevel
1562  (
1563  IOobject
1564  (
1565  "cellLevel",
1566  time().timeName(),
1567  *this,
1570  false
1571  ),
1572  *this,
1574  );
1575 
1576  const labelList& cellLevel = meshCutter_.cellLevel();
1577 
1578  forAll(cellLevel, celli)
1579  {
1580  scalarCellLevel[celli] = cellLevel[celli];
1581  }
1582 
1583  writeOk = writeOk && scalarCellLevel.write();
1584  }
1585 
1586  return writeOk;
1587 }
1588 
1589 
1590 // ************************************************************************* //
fvsPatchField< scalar > fvsPatchScalarField
const refinementHistory & history() const
Definition: hexRef8.H:395
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
const word & name() const
Return name.
Definition: IOobject.H:303
bool moving() const
Is mesh moving.
Definition: polyMesh.H:512
const hexRef8 & meshCutter() const
Direct access to the refinement engine.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
unsigned int get(const label) const
Get value at index I.
Definition: PackedListI.H:954
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
const labelIOList & pointLevel() const
Definition: hexRef8.H:390
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:323
label nInternalFaces() const
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1175
label nFaces() const
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:459
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
label nCells() const
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
label count(const ListType &l, typename ListType::const_reference x)
Count the number of occurrences of a value in a list.
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write=true) const
Write using given format, version and compression.
Encapsulates queries for volume refinement (&#39;refine all cells within shell&#39;).
const cellList & cells() const
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:636
const dimensionSet dimless
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:239
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:111
const dimensionedScalar c
Speed of light in a vacuum.
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Macros for easy insertion into run-time selection tables.
bool isDict(const word &) const
Check if entry is a sub-dictionary.
Definition: dictionary.C:936
virtual bool writeObject(IOstream::streamFormat fmt, IOstream::versionNumber ver, IOstream::compressionType cmp, const bool write=true) const
Write the underlying polyMesh and other data.
Definition: fvMesh.C:1070
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
DynamicID< meshCellZones > cellZoneID
Foam::cellZoneID.
Definition: ZoneIDs.H:41
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:982
List< bool > boolList
Bool container classes.
Definition: boolList.H:50
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:57
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys.
Definition: HashSet.H:211
virtual bool update()
Update the mesh for both mesh motion and topology change.
const cellShapeList & cells
void set(const PackedList< 1 > &)
Set specified bits.
const dictionary & optionalSubDict(const word &) const
Find and return a sub-dictionary if found.
Definition: dictionary.C:1040
Pre-declare SubField and related Field type.
Definition: Field.H:56
Refinement of (split) hexes using polyTopoChange.
Definition: hexRef8.H:64
label nPoints
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
bool write(const bool write=true) const
Force writing refinement+history to polyMesh directory.
Definition: hexRef8.C:5746
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1169
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:86
const globalMeshData & globalData() const
Return parallel info.
Definition: polyMesh.C:1394
word timeName
Definition: getTimeIndex.H:3
List< label > labelList
A List of labels.
Definition: labelList.H:56
static void swapFaceList(const polyMesh &mesh, UList< T > &l)
Swap coupled face values.
Definition: syncTools.H:463
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1156
static void fillNan(UList< scalar > &)
Fill block of data with NaN.
Definition: sigFpe.C:46
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
errorManip< error > abort(error &err)
Definition: errorManip.H:131
void clear()
Clear the list, i.e. set addressable size to zero.
Definition: PackedListI.H:889
const labelListList & pointCells() const
Info<< "Finished reading KIVA file"<< endl;cellShapeList cellShapes(nPoints);labelList cellZoning(nPoints, -1);const cellModel &hex=*(cellModeller::lookup("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, &mergedCyclicPolyPatch::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
compressionType
Enumeration for the format of data in the stream.
Definition: IOstream.H:193
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
static const char nl
Definition: Ostream.H:260
defineTypeNameAndDebug(combustionModel, 0)
labelList f(nPoints)
dimensioned< Type > min(const dimensioned< Type > &, const dimensioned< Type > &)
A subset of mesh cells.
Definition: cellZone.H:61
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
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.
void setInstance(const fileName &)
Set the instance for mesh files.
Definition: polyMeshIO.C:32
static void syncFaceList(const polyMesh &mesh, UList< T > &l, const CombineOp &cop)
Synchronise values on all mesh faces.
Definition: syncTools.H:381
A bit-packed bool list.
label patchi
#define WarningInFunction
Report a warning using Foam::Warning.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
dynamicRefineFvMesh(const IOobject &io)
Construct from IOobject.
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:56
Abstract base class for geometry and/or topology changing fvMesh.
Definition: dynamicFvMesh.H:49
A collection of cell labels.
Definition: cellSet.H:48
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
bool topoChanging() const
Is mesh topology changing.
Definition: polyMesh.H:526
label timeIndex
Definition: getTimeIndex.H:4
Version number type.
Definition: IOstream.H:96
virtual ~dynamicRefineFvMesh()
Destructor.
messageStream Info
label n
label nPoints() const
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: PtrList.H:52
static void swapBoundaryFaceList(const polyMesh &mesh, UList< T > &l)
Swap coupled boundary face values.
Definition: syncTools.H:430
virtual bool write(const bool write=true) const
Write using setting from DB.
All refinement history. Used in unrefinement.
GeometricField< scalar, fvsPatchField, surfaceMesh > surfaceScalarField
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
const labelIOList & cellLevel() const
Definition: hexRef8.H:385
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:844
const dictionary & dynamicMeshDict() const
Return the dynamicMeshDict.