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