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-2024 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
259  // return map from old to new mesh.
260  autoPtr<polyTopoChangeMap> map = meshMod.changeMesh(mesh());
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());
392 
393  Info<< "Unrefined from "
394  << returnReduce(map().nOldCells(), sumOp<label>())
395  << " to " << mesh().globalData().nTotalCells() << " cells."
396  << endl;
397 
398  // Update fields
399  mesh().topoChange(map);
400 
401  // Correct the fluxes for modified faces
402  unrefineFluxes(faceToSplitPoint, map());
403 
404  // Correct the face velocities for modified faces
405  unrefineUfs(faceToSplitPoint, map());
406 
407  // Update numbering of protectedCells_
408  if (protectedCells_.size())
409  {
410  PackedBoolList newProtectedCell(mesh().nCells());
411 
412  forAll(newProtectedCell, celli)
413  {
414  const label oldCelli = map().cellMap()[celli];
415  if (oldCelli >= 0)
416  {
417  newProtectedCell.set(celli, protectedCells_.get(oldCelli));
418  }
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 
430 Foam::word Foam::fvMeshTopoChangers::refiner::Uname
431 (
432  const surfaceVectorField& Uf
433 ) const
434 {
435  const word UfName(Uf.member());
436 
437  return
439  (
440  UfName.back() == 'f'
441  ? word(UfName(UfName.size() - 1))
442  : UfName.compare(UfName.size() - 3, 3, "f_0") == 0
443  ? word(UfName(UfName.size() - 3) + "_0")
444  : word::null,
445  Uf.group()
446  );
447 }
448 
449 
450 void Foam::fvMeshTopoChangers::refiner::refineFluxes
451 (
452  const labelHashSet& masterFaces,
453  const polyTopoChangeMap& map
454 )
455 {
456  if (correctFluxes_.size())
457  {
458  UPtrList<surfaceScalarField> fluxes
459  (
460  mesh().fields<surfaceScalarField>()
461  );
462 
463  forAll(fluxes, i)
464  {
465  surfaceScalarField& flux = fluxes[i];
466 
467  if (!correctFluxes_.found(flux.name()))
468  {
470  << "Cannot find surfaceScalarField " << flux.name()
471  << " in user-provided flux mapping table "
472  << correctFluxes_ << endl
473  << " The flux mapping table is used to recreate the"
474  << " flux on newly created faces." << endl
475  << " Either add the entry if it is a flux or use ("
476  << flux.name() << " none) to suppress this warning."
477  << endl;
478  }
479  else
480  {
481  const word& method = correctFluxes_[flux.name()];
482 
483  if (method == "none")
484  {}
485  else if (method == "NaN")
486  {
487  Pout<< "Setting surfaceScalarField " << flux.name()
488  << " to NaN" << endl;
489 
490  sigFpe::fillNan(flux.primitiveFieldRef());
491  }
492  else
493  {
495  << "Unknown refinement method " << method
496  << " for surfaceScalarField " << flux.name()
497  << " in user-provided flux mapping table "
498  << correctFluxes_
499  << exit(FatalError);
500  }
501  }
502  }
503  }
504 }
505 
506 
507 void Foam::fvMeshTopoChangers::refiner::unrefineFluxes
508 (
509  const Map<label>& faceToSplitPoint,
510  const polyTopoChangeMap& map
511 )
512 {
513  if (correctFluxes_.size())
514  {
515  UPtrList<surfaceScalarField> fluxes
516  (
517  mesh().fields<surfaceScalarField>()
518  );
519 
520  forAll(fluxes, i)
521  {
522  surfaceScalarField& flux = fluxes[i];
523 
524  if (!correctFluxes_.found(flux.name()))
525  {
527  << "Cannot find surfaceScalarField " << flux.name()
528  << " in user-provided flux mapping table "
529  << correctFluxes_ << endl
530  << " The flux mapping table is used to recreate the"
531  << " flux on newly created faces." << endl
532  << " Either add the entry if it is a flux or use ("
533  << flux.name() << " none) to suppress this warning."
534  << endl;
535  }
536  else
537  {
538  const word& method = correctFluxes_[flux.name()];
539 
540  if (method != "none")
541  {
543  << "Unknown unrefinement method " << method
544  << " for surfaceScalarField " << flux.name()
545  << " in user-provided flux mapping table "
546  << correctFluxes_
547  << exit(FatalError);
548  }
549  }
550  }
551  }
552 }
553 
554 
555 void Foam::fvMeshTopoChangers::refiner::refineUfs
556 (
557  const labelHashSet& masterFaces,
558  const polyTopoChangeMap& map
559 )
560 {
561  const labelList& faceMap = map.faceMap();
562  const labelList& reverseFaceMap = map.reverseFaceMap();
563 
564  // Interpolate U to Uf for added faces
565  UPtrList<surfaceVectorField> Ufs(mesh().fields<surfaceVectorField>());
566 
567  forAll(Ufs, i)
568  {
569  surfaceVectorField& Uf = Ufs[i];
570 
571  const word Uname(this->Uname(Uf));
572 
573  if (Uname != word::null)
574  {
575  const surfaceVectorField UfU
576  (
577  fvc::interpolate(mesh().lookupObject<volVectorField>(Uname))
578  );
579 
580  // Recalculate new internal faces.
581  for (label facei = 0; facei < mesh().nInternalFaces(); facei++)
582  {
583  label oldFacei = faceMap[facei];
584 
585  if (oldFacei == -1)
586  {
587  // Inserted
588  Uf[facei] = UfU[facei];
589  }
590  else if (reverseFaceMap[oldFacei] != facei)
591  {
592  // face-from-masterface
593  Uf[facei] = UfU[facei];
594  }
595  }
596 
597  // Recalculate new boundary faces.
598  surfaceVectorField::Boundary& UfBf = Uf.boundaryFieldRef();
599  forAll(UfBf, patchi)
600  {
601  fvsPatchVectorField& patchUf = UfBf[patchi];
602  const fvsPatchVectorField& patchUfU =
603  UfU.boundaryField()[patchi];
604 
605  label facei = patchUf.patch().start();
606 
607  forAll(patchUf, i)
608  {
609  label oldFacei = faceMap[facei];
610 
611  if (oldFacei == -1)
612  {
613  // Inserted/appended
614  patchUf[i] = patchUfU[i];
615  }
616  else if (reverseFaceMap[oldFacei] != facei)
617  {
618  // face-from-master-face
619  patchUf[i] = patchUfU[i];
620  }
621 
622  facei++;
623  }
624  }
625 
626  // Update master faces
627  forAllConstIter(labelHashSet, masterFaces, iter)
628  {
629  label facei = iter.key();
630 
631  if (mesh().isInternalFace(facei))
632  {
633  Uf[facei] = UfU[facei];
634  }
635  else
636  {
637  const label patchi =
638  mesh().boundaryMesh().whichPatch(facei);
639  const label i =
640  facei - mesh().boundaryMesh()[patchi].start();
641 
642  const fvsPatchVectorField& patchUfU =
643  UfU.boundaryField()[patchi];
644 
645  fvsPatchVectorField& patchUf = UfBf[patchi];
646 
647  patchUf[i] = patchUfU[i];
648  }
649  }
650  }
651  }
652 }
653 
654 
655 void Foam::fvMeshTopoChangers::refiner::unrefineUfs
656 (
657  const Map<label>& faceToSplitPoint,
658  const polyTopoChangeMap& map
659 )
660 {
661  const labelList& reversePointMap = map.reversePointMap();
662  const labelList& reverseFaceMap = map.reverseFaceMap();
663 
664  // Interpolate U to Uf for added faces
665  UPtrList<surfaceVectorField> Ufs(mesh().fields<surfaceVectorField>());
666 
667  forAll(Ufs, i)
668  {
669  surfaceVectorField& Uf = Ufs[i];
670 
671  const word Uname(this->Uname(Uf));
672 
673  if (Uname != word::null)
674  {
675  surfaceVectorField::Boundary& UfBf = Uf.boundaryFieldRef();
676 
677  const surfaceVectorField UfU
678  (
679  fvc::interpolate(mesh().lookupObject<volVectorField>(Uname))
680  );
681 
682  forAllConstIter(Map<label>, faceToSplitPoint, iter)
683  {
684  const label oldFacei = iter.key();
685  const label oldPointi = iter();
686 
687  if (reversePointMap[oldPointi] < 0)
688  {
689  // midpoint was removed. See if face still exists.
690  const label facei = reverseFaceMap[oldFacei];
691 
692  if (facei >= 0)
693  {
694  if (mesh().isInternalFace(facei))
695  {
696  Uf[facei] = UfU[facei];
697  }
698  else
699  {
700  const label patchi =
701  mesh().boundaryMesh().whichPatch(facei);
702  const label i =
703  facei - mesh().boundaryMesh()[patchi].start();
704 
705  UfBf[patchi][i] = UfU.boundaryField()[patchi][i];
706  }
707  }
708  }
709  }
710  }
711  }
712 }
713 
714 
715 const Foam::cellZone& Foam::fvMeshTopoChangers::refiner::findCellZone
716 (
717  const word& cellZoneName
718 ) const
719 {
720  const label cellZoneID = mesh().cellZones().findIndex(cellZoneName);
721 
722  bool cellZoneFound = (cellZoneID != -1);
723  reduce(cellZoneFound, orOp<bool>());
724 
725  if (!cellZoneFound)
726  {
728  << "cannot find cellZone " << cellZoneName
729  << exit(FatalError);
730  }
731 
732  return mesh().cellZones()[cellZoneID];
733 }
734 
735 
737 Foam::fvMeshTopoChangers::refiner::cellToPoint(const scalarField& vFld) const
738 {
739  scalarField pFld(mesh().nPoints());
740 
741  forAll(mesh().pointCells(), pointi)
742  {
743  const labelList& pCells = mesh().pointCells()[pointi];
744 
745  scalar sum = 0.0;
746  forAll(pCells, i)
747  {
748  sum += vFld[pCells[i]];
749  }
750  pFld[pointi] = sum/pCells.size();
751  }
752 
753  return pFld;
754 }
755 
756 
757 Foam::scalarField Foam::fvMeshTopoChangers::refiner::error
758 (
759  const scalarField& fld,
760  const scalar minLevel,
761  const scalar maxLevel
762 ) const
763 {
764  scalarField c(fld.size(), -1);
765 
766  forAll(c, celli)
767  {
768  scalar err = min(fld[celli] - minLevel, maxLevel - fld[celli]);
769 
770  if (err >= 0)
771  {
772  c[celli] = err;
773  }
774  }
775 
776  return c;
777 }
778 
779 
780 Foam::scalarField Foam::fvMeshTopoChangers::refiner::error
781 (
782  const scalarField& fld,
783  const labelList& cells,
784  const scalar minLevel,
785  const scalar maxLevel
786 ) const
787 {
788  scalarField c(fld.size(), -1);
789 
790  forAll(cells, i)
791  {
792  const label celli = cells[i];
793 
794  scalar err = min(fld[celli] - minLevel, maxLevel - fld[celli]);
795 
796  if (err >= 0)
797  {
798  c[celli] = err;
799  }
800  }
801 
802  return c;
803 }
804 
805 
806 void Foam::fvMeshTopoChangers::refiner::selectRefineCandidates
807 (
808  PackedBoolList& candidateCells,
809  const scalar lowerRefineLevel,
810  const scalar upperRefineLevel,
811  const scalar maxRefinement,
812  const scalarField& vFld
813 ) const
814 {
815  // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
816  // higher more desirable to be refined).
817  const scalarField cellError
818  (
819  error(vFld, lowerRefineLevel, upperRefineLevel)
820  );
821 
822  // Mark cells that are candidates for refinement.
823  forAll(cellError, celli)
824  {
825  if (cellError[celli] > 0)
826  {
827  candidateCells.set(celli, 1);
828  }
829  }
830 }
831 
832 
833 void Foam::fvMeshTopoChangers::refiner::selectRefineCandidates
834 (
835  PackedBoolList& candidateCells,
836  const scalar lowerRefineLevel,
837  const scalar upperRefineLevel,
838  const scalar maxRefinement,
839  const scalarField& vFld,
840  const labelList& cells
841 ) const
842 {
843  // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
844  // higher more desirable to be refined).
845  const scalarField cellError
846  (
847  error(vFld, cells, lowerRefineLevel, upperRefineLevel)
848  );
849 
850  // Mark cells that are candidates for refinement.
851  forAll(cellError, celli)
852  {
853  if (cellError[celli] > 0)
854  {
855  candidateCells.set(celli, 1);
856  }
857  }
858 }
859 
860 
861 Foam::scalar Foam::fvMeshTopoChangers::refiner::selectRefineCandidates
862 (
863  PackedBoolList& candidateCells,
864  const dictionary& refineDict
865 ) const
866 {
867  const word fieldName(refineDict.lookup("field"));
868 
869  const volScalarField& vFld = mesh().lookupObject<volScalarField>(fieldName);
870 
871  const scalar lowerRefineLevel =
872  refineDict.lookup<scalar>("lowerRefineLevel");
873  const scalar upperRefineLevel =
874  refineDict.lookup<scalar>("upperRefineLevel");
875 
876  const label maxRefinement = refineDict.lookup<label>("maxRefinement");
877 
878  if (maxRefinement <= 0)
879  {
881  << "Illegal maximum refinement level " << maxRefinement << nl
882  << "The maxCells setting in the dynamicMeshDict should"
883  << " be > 0." << nl
884  << exit(FatalError);
885  }
886 
887  if (refineDict.found("cellZone"))
888  {
889  // Determine candidates for refinement (looking at field only)
890  selectRefineCandidates
891  (
892  candidateCells,
893  lowerRefineLevel,
894  upperRefineLevel,
895  maxRefinement,
896  vFld,
897  findCellZone(refineDict.lookup("cellZone"))
898  );
899  }
900  else
901  {
902  // Determine candidates for refinement (looking at field only)
903  selectRefineCandidates
904  (
905  candidateCells,
906  lowerRefineLevel,
907  upperRefineLevel,
908  maxRefinement,
909  vFld
910  );
911  }
912 
913  return maxRefinement;
914 }
915 
916 
917 Foam::labelList Foam::fvMeshTopoChangers::refiner::selectRefineCells
918 (
919  const label maxCells,
920  const label maxRefinement,
921  const PackedBoolList& candidateCells
922 ) const
923 {
924  // Every refined cell causes 7 extra cells
925  const label nTotToRefine = (maxCells - mesh().globalData().nTotalCells())/7;
926 
927  const labelList& cellLevel = meshCutter_.cellLevel();
928 
929  // Mark cells that cannot be refined since they would trigger refinement
930  // of protected cells (since 2:1 cascade)
931  PackedBoolList unrefineableCells;
932  calculateProtectedCells(unrefineableCells);
933 
934  // Count current selection
935  const label nLocalCandidates = count(candidateCells, 1);
936  const label nCandidates = returnReduce(nLocalCandidates, sumOp<label>());
937 
938  // Collect all cells
939  DynamicList<label> candidates(nLocalCandidates);
940 
941  if (nCandidates < nTotToRefine)
942  {
943  forAll(candidateCells, celli)
944  {
945  if
946  (
947  candidateCells.get(celli)
948  && (
949  unrefineableCells.empty()
950  || !unrefineableCells.get(celli)
951  )
952  )
953  {
954  candidates.append(celli);
955  }
956  }
957  }
958  else
959  {
960  // Sort by error? For now just truncate.
961  for (label level = 0; level < maxRefinement; level++)
962  {
963  forAll(candidateCells, celli)
964  {
965  if
966  (
967  cellLevel[celli] == level
968  && candidateCells.get(celli)
969  && (
970  unrefineableCells.empty()
971  || !unrefineableCells.get(celli)
972  )
973  )
974  {
975  candidates.append(celli);
976  }
977  }
978 
979  if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine)
980  {
981  break;
982  }
983  }
984  }
985 
986  // Guarantee 2:1 refinement after refinement
987  labelList consistentSet
988  (
989  meshCutter_.consistentRefinement
990  (
991  candidates.shrink(),
992  true // Add to set to guarantee 2:1
993  )
994  );
995 
996  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
997  << " cells for refinement out of " << mesh().globalData().nTotalCells()
998  << "." << endl;
999 
1000  return consistentSet;
1001 }
1002 
1003 
1004 Foam::labelList Foam::fvMeshTopoChangers::refiner::selectUnrefinePoints
1005 (
1006  const PackedBoolList& markedCell
1007 ) const
1008 {
1009  // All points that can be unrefined
1010  const labelList splitPoints(meshCutter_.getSplitPoints());
1011 
1012  DynamicList<label> newSplitPoints(splitPoints.size());
1013 
1014  forAll(splitPoints, i)
1015  {
1016  const label pointi = splitPoints[i];
1017 
1018  // Check that all cells are not marked
1019  const labelList& pCells = mesh().pointCells()[pointi];
1020 
1021  bool hasMarked = false;
1022 
1023  forAll(pCells, pCelli)
1024  {
1025  if (markedCell.get(pCells[pCelli]))
1026  {
1027  hasMarked = true;
1028  break;
1029  }
1030  }
1031 
1032  if (!hasMarked)
1033  {
1034  newSplitPoints.append(pointi);
1035  }
1036  }
1037 
1038 
1039  newSplitPoints.shrink();
1040 
1041  // Guarantee 2:1 refinement after unrefinement
1042  labelList consistentSet
1043  (
1044  meshCutter_.consistentUnrefinement
1045  (
1046  newSplitPoints,
1047  false
1048  )
1049  );
1050 
1051  Info<< "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
1052  << " split points out of a possible "
1053  << returnReduce(splitPoints.size(), sumOp<label>())
1054  << "." << endl;
1055 
1056  return consistentSet;
1057 }
1058 
1059 
1060 void Foam::fvMeshTopoChangers::refiner::extendMarkedCells
1061 (
1062  PackedBoolList& markedCell
1063 ) const
1064 {
1065  // Mark faces using any marked cell
1066  boolList markedFace(mesh().nFaces(), false);
1067 
1068  forAll(markedCell, celli)
1069  {
1070  if (markedCell.get(celli))
1071  {
1072  const cell& cFaces = mesh().cells()[celli];
1073 
1074  forAll(cFaces, i)
1075  {
1076  markedFace[cFaces[i]] = true;
1077  }
1078  }
1079  }
1080 
1081  syncTools::syncFaceList(mesh(), markedFace, orEqOp<bool>());
1082 
1083  // Update cells using any markedFace
1084  for (label facei = 0; facei < mesh().nInternalFaces(); facei++)
1085  {
1086  if (markedFace[facei])
1087  {
1088  markedCell.set(mesh().faceOwner()[facei], 1);
1089  markedCell.set(mesh().faceNeighbour()[facei], 1);
1090  }
1091  }
1092 
1093  for
1094  (
1095  label facei = mesh().nInternalFaces();
1096  facei < mesh().nFaces();
1097  facei++
1098  )
1099  {
1100  if (markedFace[facei])
1101  {
1102  markedCell.set(mesh().faceOwner()[facei], 1);
1103  }
1104  }
1105 }
1106 
1107 
1108 void Foam::fvMeshTopoChangers::refiner::checkEightAnchorPoints
1109 (
1110  PackedBoolList& protectedCell,
1111  label& nProtected
1112 ) const
1113 {
1114  const labelList& cellLevel = meshCutter_.cellLevel();
1115  const labelList& pointLevel = meshCutter_.pointLevel();
1116 
1117  labelList nAnchorPoints(mesh().nCells(), 0);
1118 
1119  forAll(pointLevel, pointi)
1120  {
1121  const labelList& pCells = mesh().pointCells(pointi);
1122 
1123  forAll(pCells, pCelli)
1124  {
1125  const label celli = pCells[pCelli];
1126 
1127  if (pointLevel[pointi] <= cellLevel[celli])
1128  {
1129  // Check if cell has already 8 anchor points -> protect cell
1130  if (nAnchorPoints[celli] == 8)
1131  {
1132  if (protectedCell.set(celli, true))
1133  {
1134  nProtected++;
1135  }
1136  }
1137 
1138  if (!protectedCell[celli])
1139  {
1140  nAnchorPoints[celli]++;
1141  }
1142  }
1143  }
1144  }
1145 
1146  forAll(protectedCell, celli)
1147  {
1148  if (!protectedCell[celli] && nAnchorPoints[celli] != 8)
1149  {
1150  protectedCell.set(celli, true);
1151  nProtected++;
1152  }
1153  }
1154 }
1155 
1156 
1157 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1158 
1160 :
1161  fvMeshTopoChanger(mesh),
1162  dict_(dict),
1163  meshCutter_(mesh),
1164  dumpLevel_(false),
1165  nRefinementIterations_(0),
1166  protectedCells_(mesh.nCells(), 0),
1167  changedSinceWrite_(false),
1168  timeIndex_(-1)
1169 {
1170  // Read static part of dictionary
1171  readDict();
1172 
1173  const labelList& cellLevel = meshCutter_.cellLevel();
1174  const labelList& pointLevel = meshCutter_.pointLevel();
1175 
1176  // Set cells that should not be refined.
1177  // This is currently any cell which does not have 8 anchor points or
1178  // uses any face which does not have 4 anchor points.
1179  // Note: do not use cellPoint addressing
1180 
1181  // Count number of points <= cellLevel
1182  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1183 
1184  labelList nAnchors(mesh.nCells(), 0);
1185 
1186  label nProtected = 0;
1187 
1188  forAll(mesh.pointCells(), pointi)
1189  {
1190  const labelList& pCells = mesh.pointCells()[pointi];
1191 
1192  forAll(pCells, i)
1193  {
1194  const label celli = pCells[i];
1195 
1196  if (!protectedCells_.get(celli))
1197  {
1198  if (pointLevel[pointi] <= cellLevel[celli])
1199  {
1200  nAnchors[celli]++;
1201 
1202  if (nAnchors[celli] > 8)
1203  {
1204  protectedCells_.set(celli, 1);
1205  nProtected++;
1206  }
1207  }
1208  }
1209  }
1210  }
1211 
1212 
1213  // Count number of points <= faceLevel
1214  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1215  // Bit tricky since proc face might be one more refined than the owner since
1216  // the coupled one is refined.
1217 
1218  {
1219  labelList neiLevel(mesh.nFaces());
1220 
1221  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
1222  {
1223  neiLevel[facei] = cellLevel[mesh.faceNeighbour()[facei]];
1224  }
1225 
1226  for
1227  (
1228  label facei = mesh.nInternalFaces();
1229  facei < mesh.nFaces();
1230  facei++
1231  )
1232  {
1233  neiLevel[facei] = cellLevel[mesh.faceOwner()[facei]];
1234  }
1235  syncTools::swapFaceList(mesh, neiLevel);
1236 
1237 
1238  boolList protectedFace(mesh.nFaces(), false);
1239 
1240  forAll(mesh.faceOwner(), facei)
1241  {
1242  const label faceLevel = max
1243  (
1244  cellLevel[mesh.faceOwner()[facei]],
1245  neiLevel[facei]
1246  );
1247 
1248  const face& f = mesh.faces()[facei];
1249 
1250  label nAnchors = 0;
1251 
1252  forAll(f, fp)
1253  {
1254  if (pointLevel[f[fp]] <= faceLevel)
1255  {
1256  nAnchors++;
1257 
1258  if (nAnchors > 4)
1259  {
1260  protectedFace[facei] = true;
1261  break;
1262  }
1263  }
1264  }
1265  }
1266 
1267  syncTools::syncFaceList(mesh, protectedFace, orEqOp<bool>());
1268 
1269  for (label facei = 0; facei < mesh.nInternalFaces(); facei++)
1270  {
1271  if (protectedFace[facei])
1272  {
1273  protectedCells_.set(mesh.faceOwner()[facei], 1);
1274  nProtected++;
1275  protectedCells_.set(mesh.faceNeighbour()[facei], 1);
1276  nProtected++;
1277  }
1278  }
1279 
1280  for
1281  (
1282  label facei = mesh.nInternalFaces();
1283  facei < mesh.nFaces();
1284  facei++
1285  )
1286  {
1287  if (protectedFace[facei])
1288  {
1289  protectedCells_.set(mesh.faceOwner()[facei], 1);
1290  nProtected++;
1291  }
1292  }
1293 
1294  // Also protect any cells that are less than hex
1295  forAll(mesh.cells(), celli)
1296  {
1297  const cell& cFaces = mesh.cells()[celli];
1298 
1299  if (cFaces.size() < 6)
1300  {
1301  if (protectedCells_.set(celli, 1))
1302  {
1303  nProtected++;
1304  }
1305  }
1306  else
1307  {
1308  forAll(cFaces, cFacei)
1309  {
1310  if (mesh.faces()[cFaces[cFacei]].size() < 4)
1311  {
1312  if (protectedCells_.set(celli, 1))
1313  {
1314  nProtected++;
1315  }
1316  break;
1317  }
1318  }
1319  }
1320  }
1321 
1322  // Check cells for 8 corner points
1323  checkEightAnchorPoints(protectedCells_, nProtected);
1324  }
1325 
1326  if (returnReduce(nProtected, sumOp<label>()) == 0)
1327  {
1328  protectedCells_.clear();
1329  }
1330  else
1331  {
1332  cellSet protectedCells(mesh, "protectedCells", nProtected);
1333  forAll(protectedCells_, celli)
1334  {
1335  if (protectedCells_[celli])
1336  {
1337  protectedCells.insert(celli);
1338  }
1339  }
1340 
1341  Info<< "Detected " << returnReduce(nProtected, sumOp<label>())
1342  << " cells that are protected from refinement."
1343  << " Writing these to cellSet "
1344  << protectedCells.name()
1345  << "." << endl;
1346 
1347  protectedCells.write();
1348  }
1349 }
1350 
1351 
1352 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
1353 
1355 {}
1356 
1357 
1358 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1359 
1361 {
1362  // Only refine on the first call in a time-step
1363  if (timeIndex_ != mesh().time().timeIndex())
1364  {
1365  timeIndex_ = mesh().time().timeIndex();
1366  }
1367  else
1368  {
1369  return false;
1370  }
1371 
1372  bool hasChanged = false;
1373 
1374  if (refineInterval_ == 0)
1375  {
1376  return hasChanged;
1377  }
1378 
1379  // Note: cannot refine at time 0 since no V0 present since mesh not
1380  // moved yet.
1381 
1382  if
1383  (
1384  mesh().time().timeIndex() > 0
1385  && mesh().time().timeIndex() % refineInterval_ == 0
1386  )
1387  {
1388  // Cells marked for refinement or otherwise protected from unrefinement.
1389  PackedBoolList refineCells(mesh().nCells());
1390 
1391  label maxRefinement = 0;
1392 
1393  if (dict_.isDict("refinementRegions"))
1394  {
1396  (
1397  dict_.subDict("refinementRegions")
1398  );
1399 
1401  {
1402  maxRefinement = max
1403  (
1404  selectRefineCandidates
1405  (
1406  refineCells,
1407  refinementRegions.subDict(iter().keyword())
1408  ),
1409  maxRefinement
1410  );
1411  }
1412  }
1413  else
1414  {
1415  maxRefinement = selectRefineCandidates(refineCells, dict_);
1416  }
1417 
1418  // Extend with a buffer layer to prevent neighbouring points
1419  // being unrefined.
1420  for (label i = 0; i < nBufferLayers_; i++)
1421  {
1422  extendMarkedCells(refineCells);
1423  }
1424 
1425  PackedBoolList refinableCells(refineCells);
1426 
1427  {
1428  const labelList& cellLevel = meshCutter_.cellLevel();
1429 
1430  // Mark cells that are candidates for refinement.
1431  forAll(cellLevel, celli)
1432  {
1433  if (cellLevel[celli] >= maxRefinement)
1434  {
1435  refinableCells.unset(celli);
1436  }
1437  }
1438  }
1439 
1440  if (mesh().globalData().nTotalCells() < maxCells_)
1441  {
1442  // Select subset of candidates. Take into account max allowable
1443  // cells, refinement level, protected cells.
1444  const labelList cellsToRefine
1445  (
1446  selectRefineCells
1447  (
1448  maxCells_,
1449  maxRefinement,
1450  refinableCells
1451  )
1452  );
1453 
1454  const label nCellsToRefine = returnReduce
1455  (
1456  cellsToRefine.size(), sumOp<label>()
1457  );
1458 
1459  if (nCellsToRefine > 0)
1460  {
1461  // Refine/update mesh and map fields
1462  autoPtr<polyTopoChangeMap> map = refine(cellsToRefine);
1463 
1464  // Update refinableCells. Note that some of the marked ones have
1465  // not been refined due to constraints.
1466  {
1467  const labelList& cellMap = map().cellMap();
1468  const labelList& reverseCellMap = map().reverseCellMap();
1469 
1470  PackedBoolList newRefineCell(cellMap.size());
1471 
1472  forAll(cellMap, celli)
1473  {
1474  const label oldCelli = cellMap[celli];
1475 
1476  if (oldCelli < 0)
1477  {
1478  newRefineCell.set(celli, 1);
1479  }
1480  else if (reverseCellMap[oldCelli] != celli)
1481  {
1482  newRefineCell.set(celli, 1);
1483  }
1484  else
1485  {
1486  newRefineCell.set
1487  (
1488  celli,
1489  refinableCells.get(oldCelli)
1490  );
1491  }
1492  }
1493  refinableCells.transfer(newRefineCell);
1494  }
1495 
1496  hasChanged = true;
1497  }
1498  }
1499 
1500  {
1501  // Select unrefineable points that are not marked in refineCells
1502  const labelList pointsToUnrefine(selectUnrefinePoints(refineCells));
1503 
1504  const label nSplitPoints = returnReduce
1505  (
1506  pointsToUnrefine.size(),
1507  sumOp<label>()
1508  );
1509 
1510  if (nSplitPoints > 0)
1511  {
1512  // Refine/update mesh
1513  unrefine(pointsToUnrefine);
1514 
1515  hasChanged = true;
1516  }
1517  }
1518 
1519 
1520  if ((nRefinementIterations_ % 10) == 0)
1521  {
1522  // Compact refinement history occasionally (how often?).
1523  // Unrefinement causes holes in the refinementHistory.
1524  const_cast<refinementHistory&>(meshCutter().history()).compact();
1525  }
1526  nRefinementIterations_++;
1527  }
1528 
1529  if (hasChanged)
1530  {
1531  changedSinceWrite_ = true;
1532  }
1533 
1534  return hasChanged;
1535 }
1536 
1537 
1539 {
1540  // Update numbering of cells/vertices.
1541  meshCutter_.topoChange(map);
1542 }
1543 
1544 
1546 {
1547  // meshCutter_ will need to be re-constructed from the new mesh
1548  // and protectedCells_ updated.
1549  // The constructor should be refactored for the protectedCells_ update.
1551 }
1552 
1553 
1555 (
1556  const polyDistributionMap& map
1557 )
1558 {
1559  // Redistribute the mesh cutting engine
1560  meshCutter_.distribute(map);
1561 }
1562 
1563 
1565 {
1566  if (changedSinceWrite_)
1567  {
1568  // Force refinement data to go to the current time directory.
1569  const_cast<hexRef8&>(meshCutter_).setInstance(mesh().time().name());
1570 
1571  bool writeOk = meshCutter_.write(write);
1572 
1573  if (dumpLevel_)
1574  {
1575  volScalarField scalarCellLevel
1576  (
1577  IOobject
1578  (
1579  "cellLevel",
1580  mesh().time().name(),
1581  mesh(),
1584  false
1585  ),
1586  mesh(),
1588  );
1589 
1590  const labelList& cellLevel = meshCutter_.cellLevel();
1591 
1592  forAll(cellLevel, celli)
1593  {
1594  scalarCellLevel[celli] = cellLevel[celli];
1595  }
1596 
1597  writeOk = writeOk && scalarCellLevel.write();
1598  }
1599 
1600  changedSinceWrite_ = false;
1601 
1602  return writeOk;
1603  }
1604  else
1605  {
1606  return true;
1607  }
1608 }
1609 
1610 
1611 // ************************************************************************* //
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:109
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:58
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:162
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:99
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:5472
const labelIOList & cellLevel() const
Definition: hexRef8.H:397
const labelIOList & pointLevel() const
Definition: hexRef8.H:402
Cuts (splits) cells.
Definition: meshCutter.H:131
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:1326
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1339
virtual const labelList & faceNeighbour() const
Return face neighbour.
Definition: polyMesh.C:1345
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:381
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:346
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
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
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:257
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
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:64
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:213
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:266
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
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