NEMoSys  0.63.0
A modular, extensible resource with robust automated mesh generation, mesh quality analysis, adaptive mesh refinement, and data transfer between arbitrary meshes.
Foam::AMRFoam Class Reference

AMRFoam class is a standalone adaptive mesh refinement application that uses polyMesh as its base and provides useful interface for use of different solvers and mesh formats. More...

Detailed Description

Initially the supported refinement criterias would be size field defined over mesh as well as a gradient field of any simulation quantity.

Any object/pointer created for this class in C++ runtime will act as finiteVolume mesh of OpenFOAM.

Definition at line 52 of file AMRFoam.H.

Public Member Functions

 AMRFoam (const Foam::IOobject &iomesh)
 Standard constructor. More...
 
 ~AMRFoam ()
 Class destructor. More...
 
bool updateAMR (const int &refineInterval, const int &maxRefinement, volScalarField &vFld, const double &lowerRefineLevel, const double &upperRefineLevel, const double &unrefineAbove, const double &unrefineBelow, const int &nBufferLayers, const int &maxCells)
 updateAMR is a master method for this process. More...
 
bool updateAMRML (const int &refineInterval, const int &maxRefinement, const int &nBufferLayers, const int &maxCells, volScalarField &vFld)
 New method for machine learning ML. More...
 
void solveMotion ()
 A mesh motion solver. More...
 
Foam::scalarField cell2Pt (const scalarField &vFld)
 Converts volume field to point field. More...
 
void writeHistory ()
 Writes refinement history in current time directory. More...
 
const polyMesh & getMesh ()
 Access to current mesh at every time step. More...
 
void writeMesh ()
 Ability to write current mesh into current time directory. More...
 
void disableMotion ()
 Ability to explicitely disable motion. More...
 
pointScalarField readIncomingPtField (const std::string &inName, const std::string &outName)
 Converts incoming size-field/solution-field into pointScalarField defined over all points of mesh. More...
 
volScalarField pF2vF (const pointScalarField &pntF, const std::string &outName)
 Converts pointScalarField to volScalarField. More...
 
volScalarField readInitialField (const std::string &fldName)
 Reads the refinement field and registers it. More...
 
pointScalarField initPntSField (const std::string &fldName)
 Creates an empty pointScalarField based on current mesh. More...
 
volScalarField initScalarField (const std::string &fldName)
 Creates an empty volScalarField based on current mesh. More...
 
volScalarField initGradientField (const std::string &fldName)
 Creates an empty volScalarField for gradient magnitude. More...
 
volScalarField assignToVolScalarField (const std::vector< int > &vec)
 Converts vector to volScalarField for refinement/unrefinement. More...
 
void enableUpdatedField ()
 Access to updated field at every time step. More...
 
void enableRefHistoryData ()
 Access to refinement history data. More...
 
void enableMeshWriting ()
 Access to mesh data. More...
 
volScalarField readIncomingCellField (const std::string &inName, const std::string &outName)
 reads incoming field and converts to volScalarField More...
 
void transformField (volScalarField &inField)
 Transforms incoming scalar field into refinement levels understood by OpenFOAM environement. More...
 
volScalarField getGradient (const volScalarField &fldGrd)
 Returns a gradient of scalar field over mesh param fldGrd Scalar Field for Gradient Calculation. More...
 
virtual bool update ()
 
const hexRef8 & meshCutter () const
 
const bitSet & protectedCell () const
 
bitSet & protectedCell ()
 
bool writeObjectAMR (const bool valid) const
 
virtual void mapFields (const mapPolyMesh &mpm)
 

Public Attributes

std::vector< double > lowerRefLvl
 Vector to store lower refinement levels. More...
 
std::vector< double > upperRefLvl
 Vector to store upper refinement levels. More...
 
std::vector< double > unrefAboveLvl
 Vector to store unrefine levels. More...
 
std::vector< double > unrefBelowLvl
 Vector to store unrefine levels. More...
 
int stepSz = 1
 Step size for one time refinement. More...
 
bool enableMotion {false}
 Boolean to check if mesh motion is needed. More...
 
autoPtr< motionSolver > motionPtr_
 

Protected Member Functions

void checkForMotion ()
 Checks for availability of mesh motion keywords in dictionary. More...
 
void calcProtectedCells ()
 Calculates and stores non-hex cells in protected cells catagory to avoid their refinement. More...
 
virtual Foam::autoPtr< Foam::mapPolyMesh > refine (const labelList &)
 Unrefines selected cells in a mesh. More...
 
virtual Foam::autoPtr< Foam::mapPolyMesh > unrefine (const labelList &)
 Refines selected cells in a mesh. More...
 
void calculateProtectedCells (bitSet &unrefineableCell) const
 
void readDict ()
 
scalar getRefineLevel (const label maxCells, const label maxRefinement, const scalar refineLevel, const scalarField &) const
 
scalarField maxPointField (const scalarField &) const
 
scalarField maxCellField (const volScalarField &) const
 
scalarField cellToPoint (const scalarField &vFld) const
 
scalarField error (const scalarField &fld, const scalar minLevel, const scalar maxLevel) const
 
virtual void selectRefineCandidates (const scalar lowerRefineLevel, const scalar upperRefineLevel, const scalarField &vFld, bitSet &candidateCell) const
 
virtual labelList selectRefineCells (const label maxCells, const label maxRefinement, const bitSet &candidateCell) const
 
virtual labelList selectUnrefinePoints (const scalar unrefineAbove, const scalar unrefineBelow, const bitSet &markedCell, const scalarField &pFld) const
 Marked the cells to unrefine based on user defined levels. More...
 
void extendMarkedCells (bitSet &markedCell) const
 
void checkEightAnchorPoints (bitSet &protectedCell) const
 
template<class T >
void mapNewInternalFaces (const labelList &faceMap, GeometricField< T, fvsPatchField, surfaceMesh > &)
 
template<class T >
void mapNewInternalFaces (const labelList &faceMap)
 
template<class T >
void mapNewInternalFaces (const surfaceVectorField &Sf, const surfaceScalarField &magSf, const labelList &faceMap)
 

Protected Attributes

hexRef8 meshCutter_
 
bool dumpLevel_
 
HashTable< word > correctFluxes_
 
label nRefinementIterations_
 
bitSet protectedCell_
 

Private Attributes

bool writeField {false}
 Boolean to enable writing of updated solution field every timestep. More...
 
bool writeRefHistory {false}
 Boolean to enable writing of refinement history. More...
 
bool writeMeshData {false}
 Boolean to enable writing of mesh. More...
 
std::vector< double > incomingField
 Vector to store user defined vector. More...
 

Inherits dynamicFvMesh.

Constructor & Destructor Documentation

◆ AMRFoam()

Foam::AMRFoam::AMRFoam ( const Foam::IOobject &  iomesh)

Accepts polyMesh object for initialization. It needs dynamicMeshDict present in constant folder. Method for same is available in MeshManipulationFoam class as "createDynamicMeshDict"

Parameters
iomeshA polyMesh input object

Definition at line 62 of file AMRFoam.C.

References calcProtectedCells(), and checkForMotion().

63  : dynamicFvMesh(iomesh),
64  meshCutter_(*this),
65  dumpLevel_(true),
67  protectedCell_(nCells()) {
70 }
bitSet protectedCell_
Definition: AMRFoam.H:265
void checkForMotion()
Checks for availability of mesh motion keywords in dictionary.
Definition: AMRFoam.C:72
label nRefinementIterations_
Definition: AMRFoam.H:262
void calcProtectedCells()
Calculates and stores non-hex cells in protected cells catagory to avoid their refinement.
Definition: AMRFoam.C:86
hexRef8 meshCutter_
Definition: AMRFoam.H:253
bool dumpLevel_
Definition: AMRFoam.H:256

◆ ~AMRFoam()

Member Function Documentation

◆ assignToVolScalarField()

volScalarField Foam::AMRFoam::assignToVolScalarField ( const std::vector< int > &  vec)
Parameters
vecIncoming vector
Returns
volScalarField

Definition at line 750 of file AMRFoam.C.

References initScalarField().

Referenced by NEM::DRV::FoamRefineDriver::execute(), and ~AMRFoam().

750  {
751  volScalarField vFld = initScalarField("vFld");
752  for (int i = 0; i < (int)vec.size(); i++) vFld[i] = vec[i];
753  return vFld;
754 }
volScalarField initScalarField(const std::string &fldName)
Creates an empty volScalarField based on current mesh.
Definition: AMRFoam.C:798

◆ calcProtectedCells()

void Foam::AMRFoam::calcProtectedCells ( )
protected

Definition at line 86 of file AMRFoam.C.

References checkEightAnchorPoints(), enableMotion, meshCutter_, and protectedCell_.

Referenced by AMRFoam().

86  {
87  const labelList &cellLevel = meshCutter_.cellLevel();
88  const labelList &pointLevel = meshCutter_.pointLevel();
89 
90  // Set cells that should not be refined.
91  // This is currently any cell which does not have 8 anchor points or
92  // uses any face which does not have 4 anchor points.
93  // Note: do not use cellPoint addressing
94 
95  // Count number of points <= cellLevel
96  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
97 
98  labelList nAnchors(nCells(), Zero);
99 
100  label nProtected = 0;
101 
102  forAll (pointCells(), pointi) {
103  const labelList &pCells = pointCells()[pointi];
104 
105  for (const label celli : pCells) {
106  if (!protectedCell_.test(celli)) {
107  if (pointLevel[pointi] <= cellLevel[celli]) {
108  ++nAnchors[celli];
109 
110  if (nAnchors[celli] > 8) {
111  protectedCell_.set(celli);
112  nProtected++;
113  }
114  }
115  }
116  }
117  }
118 
119  // Count number of points <= faceLevel
120  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
121  // Bit tricky since proc face might be one more refined than the owner since
122  // the coupled one is refined.
123 
124  {
125  labelList neiLevel(nFaces());
126 
127  for (label facei = 0; facei < nInternalFaces(); ++facei) {
128  neiLevel[facei] = cellLevel[faceNeighbour()[facei]];
129  }
130  for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
131  neiLevel[facei] = cellLevel[faceOwner()[facei]];
132  }
133  syncTools::swapFaceList(*this, neiLevel);
134 
135  bitSet protectedFace(nFaces());
136 
137  forAll (faceOwner(), facei) {
138  const label faceLevel =
139  max(cellLevel[faceOwner()[facei]], neiLevel[facei]);
140 
141  const face &f = faces()[facei];
142 
143  label nnAnchors = 0;
144 
145  for (const label pointi : f) {
146  if (pointLevel[pointi] <= faceLevel) {
147  ++nnAnchors;
148 
149  if (nnAnchors > 4) {
150  protectedFace.set(facei);
151  break;
152  }
153  }
154  }
155  }
156 
157  syncTools::syncFaceList(*this, protectedFace, orEqOp<unsigned int>());
158 
159  for (label facei = 0; facei < nInternalFaces(); ++facei) {
160  if (protectedFace.test(facei)) {
161  protectedCell_.set(faceOwner()[facei]);
162  nProtected++;
163  protectedCell_.set(faceNeighbour()[facei]);
164  nProtected++;
165  }
166  }
167  for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
168  if (protectedFace.test(facei)) {
169  protectedCell_.set(faceOwner()[facei]);
170  nProtected++;
171  }
172  }
173 
174  // Also protect any cells that are less than hex
175  forAll (cells(), celli) {
176  const cell &cFaces = cells()[celli];
177 
178  if (cFaces.size() < 6) {
179  if (protectedCell_.set(celli)) { nProtected++; }
180 
181  } else {
182  for (const label cfacei : cFaces) {
183  if (faces()[cfacei].size() < 4) {
184  if (protectedCell_.set(celli)) { nProtected++; }
185  break;
186  }
187  }
188  }
189  }
190 
191  // Check cells for 8 corner points
193 
194  if (enableMotion) {
195  // Block boundary cells from refinement
196  const polyBoundaryMesh &patches = boundaryMesh();
197  wordList ptchTypes = patches.types();
198 
199  labelList assignedScore(nCells(), 0);
200 
201  forAll (patches, patchI) {
202  if (ptchTypes[patchI] != "empty") {
203  auto allCells = patches[patchI].faceCells();
204  forAll (allCells, cellI) {
205  assignedScore[allCells[cellI]] += 1;
206  // Find all neighbours and assign the score of one
207  auto neiCells = cellCells()[allCells[cellI]];
208  forAll (neiCells, nCellI) { assignedScore[neiCells[nCellI]] += 1; }
209  }
210  }
211  }
212 
213  forAll (assignedScore, scoreI) {
214  if (assignedScore[scoreI] >= 2) { protectedCell_.set(scoreI); }
215  }
216  }
217  }
218 
219  if (!returnReduce(protectedCell_.any(), orOp<bool>())) {
220  protectedCell_.clear();
221  } else {
222  cellSet protectedCells(*this, "protectedCells",
223  HashSetOps::used(protectedCell_));
224  Info << "Detected " << returnReduce(protectedCells.size(), sumOp<label>())
225  << " cells that are protected from refinement."
226  << " Writing these to cellSet " << protectedCells.name() << "."
227  << endl;
228 
229  protectedCells.write();
230  }
231 }
bitSet protectedCell_
Definition: AMRFoam.H:265
bool enableMotion
Boolean to check if mesh motion is needed.
Definition: AMRFoam.H:231
hexRef8 meshCutter_
Definition: AMRFoam.H:253
void checkEightAnchorPoints(bitSet &protectedCell) const
Definition: AMRFoam.C:1401

◆ calculateProtectedCells()

void Foam::AMRFoam::calculateProtectedCells ( bitSet &  unrefineableCell) const
protected

Definition at line 847 of file AMRFoam.C.

References meshCutter_, and protectedCell_.

Referenced by selectRefineCells().

847  {
848  if (protectedCell_.empty()) {
849  unrefineableCell.clear();
850  return;
851  }
852 
853  const labelList &cellLevel = meshCutter_.cellLevel();
854 
855  unrefineableCell = protectedCell_;
856 
857  // Get neighbouring cell level
858  labelList neiLevel(nFaces() - nInternalFaces());
859 
860  for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
861  neiLevel[facei - nInternalFaces()] = cellLevel[faceOwner()[facei]];
862  }
863  syncTools::swapBoundaryFaceList(*this, neiLevel);
864 
865  bitSet seedFace;
866 
867  while (true) {
868  // Pick up faces on border of protected cells
869  seedFace.reset();
870  seedFace.resize(nFaces());
871 
872  for (label facei = 0; facei < nInternalFaces(); ++facei) {
873  const label own = faceOwner()[facei];
874  const label nei = faceNeighbour()[facei];
875 
876  if (
877  // Protected owner
878  (unrefineableCell.test(own) && (cellLevel[nei] > cellLevel[own])) ||
879  // Protected neighbour
880  (unrefineableCell.test(nei) && (cellLevel[own] > cellLevel[nei]))) {
881  seedFace.set(facei);
882  }
883  }
884  for (label facei = nInternalFaces(); facei < nFaces(); facei++) {
885  const label own = faceOwner()[facei];
886 
887  if (
888  // Protected owner
889  (unrefineableCell.test(own) &&
890  (neiLevel[facei - nInternalFaces()] > cellLevel[own]))) {
891  seedFace.set(facei);
892  }
893  }
894 
895  syncTools::syncFaceList(*this, seedFace, orEqOp<unsigned int>());
896 
897  // Extend unrefineableCell
898  bool hasExtended = false;
899 
900  for (label facei = 0; facei < nInternalFaces(); ++facei) {
901  if (seedFace.test(facei)) {
902  if (unrefineableCell.set(faceOwner()[facei])) { hasExtended = true; }
903  if (unrefineableCell.set(faceNeighbour()[facei])) {
904  hasExtended = true;
905  }
906  }
907  }
908  for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
909  if (seedFace.test(facei)) {
910  const label own = faceOwner()[facei];
911 
912  if (unrefineableCell.set(own)) { hasExtended = true; }
913  }
914  }
915 
916  if (!returnReduce(hasExtended, orOp<bool>())) { break; }
917  }
918 }
bitSet protectedCell_
Definition: AMRFoam.H:265
hexRef8 meshCutter_
Definition: AMRFoam.H:253

◆ cell2Pt()

scalarField Foam::AMRFoam::cell2Pt ( const scalarField &  vFld)
Parameters
vFldVolume Field.
Returns
Point Field.

Definition at line 680 of file AMRFoam.C.

Referenced by ~AMRFoam().

680  {
681  scalarField pFld(nPoints());
682 
683  forAll (pointCells(), pointi) {
684  const labelList &pCells = pointCells()[pointi];
685 
686  scalar sum = 0.0;
687  forAll (pCells, i)
688  sum += vFld[pCells[i]];
689 
690  pFld[pointi] = sum / pCells.size();
691  }
692 
693  return pFld;
694 }

◆ cellToPoint()

scalarField Foam::AMRFoam::cellToPoint ( const scalarField &  vFld) const
protected

Definition at line 1286 of file AMRFoam.C.

Referenced by selectRefineCandidates().

1286  {
1287  scalarField pFld(nPoints());
1288 
1289  forAll (pointCells(), pointi) {
1290  const labelList &pCells = pointCells()[pointi];
1291 
1292  scalar sum = 0.0;
1293  for (const label celli : pCells) { sum += vFld[celli]; }
1294  pFld[pointi] = sum / pCells.size();
1295  }
1296  return pFld;
1297 }

◆ checkEightAnchorPoints()

void Foam::AMRFoam::checkEightAnchorPoints ( bitSet &  protectedCell) const
protected

Definition at line 1401 of file AMRFoam.C.

References meshCutter_.

Referenced by calcProtectedCells().

1401  {
1402  const labelList &cellLevel = meshCutter_.cellLevel();
1403  const labelList &pointLevel = meshCutter_.pointLevel();
1404 
1405  labelList nAnchorPoints(nCells(), Zero);
1406 
1407  forAll (pointLevel, pointi) {
1408  const labelList &pCells = pointCells(pointi);
1409 
1410  for (const label celli : pCells) {
1411  if (pointLevel[pointi] <= cellLevel[celli]) {
1412  // Check if cell has already 8 anchor points -> protect cell
1413  if (nAnchorPoints[celli] == 8) { protectedCell.set(celli); }
1414 
1415  if (!protectedCell.test(celli)) { ++nAnchorPoints[celli]; }
1416  }
1417  }
1418  }
1419 
1420  forAll (protectedCell, celli) {
1421  if (nAnchorPoints[celli] != 8) { protectedCell.set(celli); }
1422  }
1423 }
hexRef8 meshCutter_
Definition: AMRFoam.H:253
const bitSet & protectedCell() const
Definition: AMRFoam.H:373

◆ checkForMotion()

void Foam::AMRFoam::checkForMotion ( )
protected

Definition at line 72 of file AMRFoam.C.

References enableMotion, motionPtr_, and NEM::MSH::New().

Referenced by AMRFoam().

72  {
73  // Check if motion needs to be enabled
74  dictionary refineDict(IOdictionary(
75  IOobject("dynamicMeshDict", time().constant(), *this,
76  IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE, false)));
77 
78  word subType = word(refineDict.lookup("dynamicFvMesh"));
79  if (subType == "dynamicMotionSolverFvMesh") { enableMotion = true; }
80 
81  if (enableMotion) { motionPtr_ = motionSolver::New(*this); }
82 }
bool enableMotion
Boolean to check if mesh motion is needed.
Definition: AMRFoam.H:231
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
autoPtr< motionSolver > motionPtr_
Definition: AMRFoam.H:365

◆ disableMotion()

void Foam::AMRFoam::disableMotion ( )

Definition at line 84 of file AMRFoam.C.

References enableMotion.

Referenced by ~AMRFoam().

84 { enableMotion = false; }
bool enableMotion
Boolean to check if mesh motion is needed.
Definition: AMRFoam.H:231

◆ enableMeshWriting()

void Foam::AMRFoam::enableMeshWriting ( )

Definition at line 832 of file AMRFoam.C.

References writeMeshData.

Referenced by ~AMRFoam().

832 { writeMeshData = true; }
bool writeMeshData
Boolean to enable writing of mesh.
Definition: AMRFoam.H:245

◆ enableRefHistoryData()

void Foam::AMRFoam::enableRefHistoryData ( )

Definition at line 828 of file AMRFoam.C.

References writeRefHistory.

Referenced by ~AMRFoam().

828 { writeRefHistory = true; }
bool writeRefHistory
Boolean to enable writing of refinement history.
Definition: AMRFoam.H:241

◆ enableUpdatedField()

void Foam::AMRFoam::enableUpdatedField ( )

Definition at line 830 of file AMRFoam.C.

References writeField.

Referenced by ~AMRFoam().

830 { writeField = true; }
bool writeField
Boolean to enable writing of updated solution field every timestep.
Definition: AMRFoam.H:237

◆ error()

scalarField Foam::AMRFoam::error ( const scalarField &  fld,
const scalar  minLevel,
const scalar  maxLevel 
) const
protected

Definition at line 1299 of file AMRFoam.C.

Referenced by selectRefineCandidates().

1300  {
1301  scalarField c(fld.size(), scalar(-1));
1302  forAll (fld, i) {
1303  scalar err = min(fld[i] - minLevel, maxLevel - fld[i]);
1304 
1305  if (err >= 0) { c[i] = err; }
1306  }
1307  return c;
1308 }

◆ extendMarkedCells()

void Foam::AMRFoam::extendMarkedCells ( bitSet &  markedCell) const
protected

Definition at line 1379 of file AMRFoam.C.

Referenced by update(), updateAMR(), and updateAMRML().

1379  {
1380  // Mark faces using any marked cell
1381  bitSet markedFace(nFaces());
1382 
1383  for (const label celli : markedCell) {
1384  markedFace.set(cells()[celli]); // set multiple faces
1385  }
1386 
1387  syncTools::syncFaceList(*this, markedFace, orEqOp<unsigned int>());
1388 
1389  // Update cells using any markedFace
1390  for (label facei = 0; facei < nInternalFaces(); ++facei) {
1391  if (markedFace.test(facei)) {
1392  markedCell.set(faceOwner()[facei]);
1393  markedCell.set(faceNeighbour()[facei]);
1394  }
1395  }
1396  for (label facei = nInternalFaces(); facei < nFaces(); ++facei) {
1397  if (markedFace.test(facei)) { markedCell.set(faceOwner()[facei]); }
1398  }
1399 }

◆ getGradient()

volScalarField Foam::AMRFoam::getGradient ( const volScalarField &  fldGrd)
Returns
scalar field of gradient over mesh

Definition at line 834 of file AMRFoam.C.

References initGradientField().

Referenced by ~AMRFoam().

834  {
835  volVectorField returnGrad(IOobject("fldName", time().timeName(), *this,
836  IOobject::NO_READ, IOobject::NO_WRITE),
837  *this, dimensionedVector("vector", dimless, Zero));
838 
839  returnGrad = Foam::fvc::grad(fldGrd);
840  returnGrad.write();
841  volScalarField returnScalar = initGradientField("gradient");
842  returnScalar = mag(returnGrad);
843 
844  return returnScalar;
845 }
volScalarField initGradientField(const std::string &fldName)
Creates an empty volScalarField for gradient magnitude.
Definition: AMRFoam.C:806

◆ getMesh()

const polyMesh & Foam::AMRFoam::getMesh ( )
Returns
A polyMesh object

Definition at line 702 of file AMRFoam.C.

References meshCutter_.

Referenced by ~AMRFoam().

702 { return meshCutter_.mesh(); }
hexRef8 meshCutter_
Definition: AMRFoam.H:253

◆ getRefineLevel()

scalar Foam::AMRFoam::getRefineLevel ( const label  maxCells,
const label  maxRefinement,
const scalar  refineLevel,
const scalarField &   
) const
protected

◆ initGradientField()

volScalarField Foam::AMRFoam::initGradientField ( const std::string &  fldName)
Parameters
fldNameName of field to create in current runTime directory

Definition at line 806 of file AMRFoam.C.

Referenced by getGradient(), and ~AMRFoam().

806  {
807  volScalarField emptyScalar(IOobject(fldName, time().timeName(), *this,
808  IOobject::NO_READ, IOobject::AUTO_WRITE),
809  *this, dimensionedScalar("scalar", dimless, 0));
810 
811  return emptyScalar;
812 }

◆ initPntSField()

pointScalarField Foam::AMRFoam::initPntSField ( const std::string &  fldName)
Parameters
fldNameName of field to create in current runTime directory

Definition at line 814 of file AMRFoam.C.

Referenced by readIncomingPtField(), and ~AMRFoam().

814  {
815  // Initialize a pointMesh object
816  pointMesh pMesh(*this);
817 
818  // Zero pointScalarField declaration. InternalField contains all mesh
819  // points. Can be overwritten with incoming stream.
820  pointScalarField initFieldZero(
821  IOobject(fldName, time().timeName(), *this, IOobject::NO_READ,
822  IOobject::AUTO_WRITE),
823  pMesh, dimensionedScalar("scalar", dimLength, 0));
824 
825  return initFieldZero;
826 }

◆ initScalarField()

volScalarField Foam::AMRFoam::initScalarField ( const std::string &  fldName)
Parameters
fldNameName of field to create in current runTime directory

Definition at line 798 of file AMRFoam.C.

Referenced by assignToVolScalarField(), pF2vF(), readIncomingCellField(), and ~AMRFoam().

798  {
799  volScalarField emptyScalar(IOobject(fldName, time().timeName(), *this,
800  IOobject::NO_READ, IOobject::AUTO_WRITE),
801  *this, dimensionedScalar("scalar", dimLength, 0));
802 
803  return emptyScalar;
804 }

◆ mapFields()

void Foam::AMRFoam::mapFields ( const mapPolyMesh &  mpm)
virtual

Definition at line 937 of file AMRFoam.C.

References correctFluxes_.

Referenced by protectedCell().

937  {
938  dynamicFvMesh::mapFields(mpm);
939 
940  // Correct the flux for modified/added faces. All the faces which only
941  // have been renumbered will already have been handled by the mapping.
942  {
943  const labelList &faceMap = mpm.faceMap();
944  const labelList &reverseFaceMap = mpm.reverseFaceMap();
945 
946  // Storage for any master faces. These will be the original faces
947  // on the coarse cell that get split into four (or rather the
948  // master face gets modified and three faces get added from the master)
949  // Estimate number of faces created
950 
951  bitSet masterFaces(nFaces());
952 
953  forAll (faceMap, facei) {
954  const label oldFacei = faceMap[facei];
955 
956  if (oldFacei >= 0) {
957  const label masterFacei = reverseFaceMap[oldFacei];
958 
959  if (masterFacei < 0) {
960  FatalErrorInFunction << "Problem: should not have removed faces"
961  << " when refining." << nl << "face:" << facei
962  << endl
963  << abort(FatalError);
964  } else if (masterFacei != facei) {
965  masterFaces.set(masterFacei);
966  }
967  }
968  }
969 
970  if (debug) {
971  Pout << "Found " << masterFaces.count() << " split faces " << endl;
972  }
973 
974  HashTable<surfaceScalarField *> fluxes(lookupClass<surfaceScalarField>());
975  forAllIters(fluxes, iter) {
976  if (!correctFluxes_.found(iter.key())) {
977  WarningInFunction
978  << "Cannot find surfaceScalarField " << iter.key()
979  << " in user-provided flux mapping table " << correctFluxes_ << endl
980  << " The flux mapping table is used to recreate the"
981  << " flux on newly created faces." << endl
982  << " Either add the entry if it is a flux or use (" << iter.key()
983  << " none) to suppress this warning." << endl;
984  continue;
985  }
986 
987  const word &UName = correctFluxes_[iter.key()];
988 
989  if (UName == "none") { continue; }
990 
991  surfaceScalarField &phi = *iter();
992 
993  if (UName == "NaN") {
994  Pout << "Setting surfaceScalarField " << iter.key() << " to NaN"
995  << endl;
996 
997  sigFpe::fillNan(phi.primitiveFieldRef());
998 
999  continue;
1000  }
1001 
1002  if (debug) {
1003  Pout << "Mapping flux " << iter.key() << " using interpolated flux "
1004  << UName << endl;
1005  }
1006 
1007  const surfaceScalarField phiU(
1008  fvc::interpolate(lookupObject<volVectorField>(UName)) & Sf());
1009 
1010  // Recalculate new internal faces.
1011  for (label facei = 0; facei < nInternalFaces(); ++facei) {
1012  const label oldFacei = faceMap[facei];
1013 
1014  if (oldFacei == -1) {
1015  // Inflated/appended
1016  phi[facei] = phiU[facei];
1017  } else if (reverseFaceMap[oldFacei] != facei) {
1018  // face-from-masterface
1019  phi[facei] = phiU[facei];
1020  }
1021  }
1022 
1023  // Recalculate new boundary faces.
1024  surfaceScalarField::Boundary &phiBf = phi.boundaryFieldRef();
1025 
1026  forAll (phiBf, patchi) {
1027  fvsPatchScalarField &patchPhi = phiBf[patchi];
1028  const fvsPatchScalarField &patchPhiU = phiU.boundaryField()[patchi];
1029 
1030  label facei = patchPhi.patch().start();
1031 
1032  forAll (patchPhi, i) {
1033  const label oldFacei = faceMap[facei];
1034 
1035  if (oldFacei == -1) {
1036  // Inflated/appended
1037  patchPhi[i] = patchPhiU[i];
1038  } else if (reverseFaceMap[oldFacei] != facei) {
1039  // face-from-masterface
1040  patchPhi[i] = patchPhiU[i];
1041  }
1042 
1043  ++facei;
1044  }
1045  }
1046 
1047  // Update master faces
1048  for (const label facei : masterFaces) {
1049  if (isInternalFace(facei)) {
1050  phi[facei] = phiU[facei];
1051  } else {
1052  const label patchi = boundaryMesh().whichPatch(facei);
1053  const label i = facei - boundaryMesh()[patchi].start();
1054 
1055  const fvsPatchScalarField &patchPhiU = phiU.boundaryField()[patchi];
1056 
1057  fvsPatchScalarField &patchPhi = phiBf[patchi];
1058 
1059  patchPhi[i] = patchPhiU[i];
1060  }
1061  }
1062  }
1063  }
1064 
1065  // Correct the flux for injected faces - these are the faces which have
1066  // no correspondence to the old mesh (i.e. added without a masterFace, edge
1067  // or point). An example is the internal faces from hexRef8.
1068  {
1069  const labelList &faceMap = mpm.faceMap();
1070 
1071  mapNewInternalFaces<scalar>(this->Sf(), this->magSf(), faceMap);
1072  mapNewInternalFaces<vector>(this->Sf(), this->magSf(), faceMap);
1073 
1074  // No oriented fields of more complex type
1075  mapNewInternalFaces<sphericalTensor>(faceMap);
1076  mapNewInternalFaces<symmTensor>(faceMap);
1077  mapNewInternalFaces<tensor>(faceMap);
1078  }
1079 }
HashTable< word > correctFluxes_
Definition: AMRFoam.H:259

◆ mapNewInternalFaces() [1/3]

template<class T >
void Foam::AMRFoam::mapNewInternalFaces ( const labelList &  faceMap,
GeometricField< T, fvsPatchField, surfaceMesh > &  sFld 
)
protected

Definition at line 1458 of file AMRFoam.C.

Referenced by mapNewInternalFaces().

1460  {
1461  using GeoField = GeometricField<T, fvsPatchField, surfaceMesh>;
1462 
1463  //- Make flat field for ease of looping
1464  Field<T> tsFld(this->nFaces(), Zero);
1465  SubField<T>(tsFld, this->nInternalFaces()) = sFld.internalField();
1466 
1467  const typename GeoField::Boundary &bFld = sFld.boundaryField();
1468  forAll (bFld, patchi) {
1469  label facei = this->boundaryMesh()[patchi].start();
1470  for (const T &val : bFld[patchi]) { tsFld[facei++] = val; }
1471  }
1472 
1473  const labelUList &owner = this->faceOwner();
1474  const labelUList &neighbour = this->faceNeighbour();
1475  const cellList &cells = this->cells();
1476 
1477  for (label facei = 0; facei < nInternalFaces(); facei++) {
1478  label oldFacei = faceMap[facei];
1479 
1480  // Map surface field on newly generated faces by obtaining the
1481  // hull of the outside faces
1482  if (oldFacei == -1) {
1483  // Loop over all owner/neighbour cell faces
1484  // and find already mapped ones (master-faces):
1485  T tmpValue(pTraits<T>::zero);
1486  label counter = 0;
1487 
1488  const cell &ownFaces = cells[owner[facei]];
1489  for (auto ownFacei : ownFaces) {
1490  if (faceMap[ownFacei] != -1) {
1491  tmpValue += tsFld[ownFacei];
1492  counter++;
1493  }
1494  }
1495 
1496  const cell &neiFaces = cells[neighbour[facei]];
1497  for (auto neiFacei : neiFaces) {
1498  if (faceMap[neiFacei] != -1) {
1499  tmpValue += tsFld[neiFacei];
1500  counter++;
1501  }
1502  }
1503 
1504  if (counter > 0) { sFld[facei] = tmpValue / counter; }
1505  }
1506  }
1507 }

◆ mapNewInternalFaces() [2/3]

template<class T >
void Foam::AMRFoam::mapNewInternalFaces ( const labelList &  faceMap)
protected

Definition at line 1510 of file AMRFoam.C.

References mapNewInternalFaces().

1510  {
1511  using GeoField = GeometricField<T, fvsPatchField, surfaceMesh>;
1512  HashTable<GeoField *> sFlds(this->objectRegistry::lookupClass<GeoField>());
1513 
1514  forAllIters(sFlds, iter) {
1515  // if (mapSurfaceFields_.found(iter.key()))
1516  {
1517  DebugInfo << "dynamicRefineMotionFvMesh::mapNewInternalFaces():"
1518  << " Mapping new internal faces by interpolation on "
1519  << iter.key() << endl;
1520 
1521  GeoField &sFld = *iter();
1522 
1523  if (sFld.oriented()()) {
1524  WarningInFunction << "Ignoring mapping oriented field " << sFld.name()
1525  << " since of type " << sFld.type() << endl;
1526  } else {
1527  mapNewInternalFaces(faceMap, sFld);
1528  }
1529  }
1530  }
1531 }
void mapNewInternalFaces(const labelList &faceMap, GeometricField< T, fvsPatchField, surfaceMesh > &)
Definition: AMRFoam.C:1458

◆ mapNewInternalFaces() [3/3]

template<class T >
void Foam::AMRFoam::mapNewInternalFaces ( const surfaceVectorField &  Sf,
const surfaceScalarField &  magSf,
const labelList &  faceMap 
)
protected

Definition at line 1534 of file AMRFoam.C.

References mapNewInternalFaces().

1536  {
1537  using GeoField = GeometricField<T, fvsPatchField, surfaceMesh>;
1538  HashTable<GeoField *> sFlds(this->objectRegistry::lookupClass<GeoField>());
1539 
1540  forAllIters(sFlds, iter) {
1541  // if (mapSurfaceFields_.found(iter.key()))
1542  {
1543  DebugInfo << "dynamicRefineMotionFvMesh::mapNewInternalFaces():"
1544  << " Mapping new internal faces by interpolation on "
1545  << iter.key() << endl;
1546 
1547  GeoField &sFld = *iter();
1548 
1549  if (sFld.oriented()()) {
1550  DebugInfo << "dynamicRefineMotionFvMesh::mapNewInternalFaces(): "
1551  << "Converting oriented field " << iter.key()
1552  << " to intensive field and mapping" << endl;
1553 
1554  // Assume any oriented field is face area weighted (i.e. a flux)
1555  // Convert to intensive (& oriented) before mapping. Untested.
1556 
1557  using NormalGeoField =
1558  GeometricField<typename outerProduct<vector, T>::type,
1559  fvsPatchField, surfaceMesh>;
1560 
1561  // Convert to intensive and non oriented
1562  NormalGeoField fFld(sFld * Sf / Foam::sqr(magSf));
1563 
1564  // Interpolate
1565  mapNewInternalFaces(faceMap, fFld);
1566 
1567  // Convert back to extensive and oriented
1568  sFld = (fFld & Sf);
1569  } else {
1570  mapNewInternalFaces(faceMap, sFld);
1571  }
1572  }
1573  }
1574 }
void mapNewInternalFaces(const labelList &faceMap, GeometricField< T, fvsPatchField, surfaceMesh > &)
Definition: AMRFoam.C:1458

◆ maxCellField()

scalarField Foam::AMRFoam::maxCellField ( const volScalarField &  vFld) const
protected

Definition at line 1273 of file AMRFoam.C.

Referenced by update(), updateAMR(), and updateAMRML().

1273  {
1274  scalarField pFld(nPoints(), -GREAT);
1275 
1276  forAll (pointCells(), pointi) {
1277  const labelList &pCells = pointCells()[pointi];
1278 
1279  for (const label celli : pCells) {
1280  pFld[pointi] = max(pFld[pointi], vFld[celli]);
1281  }
1282  }
1283  return pFld;
1284 }

◆ maxPointField()

scalarField Foam::AMRFoam::maxPointField ( const scalarField &  pFld) const
protected

Definition at line 1260 of file AMRFoam.C.

Referenced by selectRefineCandidates().

1260  {
1261  scalarField vFld(nCells(), -GREAT);
1262 
1263  forAll (pointCells(), pointi) {
1264  const labelList &pCells = pointCells()[pointi];
1265 
1266  for (const label celli : pCells) {
1267  vFld[celli] = max(vFld[celli], pFld[pointi]);
1268  }
1269  }
1270  return vFld;
1271 }

◆ meshCutter()

const hexRef8& Foam::AMRFoam::meshCutter ( ) const
inline

Definition at line 370 of file AMRFoam.H.

References meshCutter_.

Referenced by update(), updateAMR(), and updateAMRML().

370 { return meshCutter_; }
hexRef8 meshCutter_
Definition: AMRFoam.H:253

◆ pF2vF()

volScalarField Foam::AMRFoam::pF2vF ( const pointScalarField &  pntF,
const std::string &  outName 
)
Parameters
pntFA point field defined on mesh points
outNameObject name for output scalar
Returns
A Scalar Field defined on cells

Definition at line 792 of file AMRFoam.C.

References initScalarField().

Referenced by ~AMRFoam().

793  {
794  volScalarField returnFld = initScalarField(outName);
795  return returnFld;
796 }
volScalarField initScalarField(const std::string &fldName)
Creates an empty volScalarField based on current mesh.
Definition: AMRFoam.C:798

◆ protectedCell() [1/2]

const bitSet& Foam::AMRFoam::protectedCell ( ) const
inline

Definition at line 373 of file AMRFoam.H.

References protectedCell_.

373 { return protectedCell_; }
bitSet protectedCell_
Definition: AMRFoam.H:265

◆ protectedCell() [2/2]

bitSet& Foam::AMRFoam::protectedCell ( )
inline

Definition at line 376 of file AMRFoam.H.

References mapFields(), protectedCell_, and writeObjectAMR().

376 { return protectedCell_; }
bitSet protectedCell_
Definition: AMRFoam.H:265

◆ readDict()

void Foam::AMRFoam::readDict ( )
protected

Definition at line 920 of file AMRFoam.C.

References correctFluxes_, and dumpLevel_.

920  {
921  dictionary refineDict(
922  IOdictionary(IOobject("dynamicMeshDict", time().constant(), *this,
923  IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE,
924  false))
925  .optionalSubDict("dynamicRefineMotionFvMeshCoeffs"));
926 
927  List<Pair<word>> fluxVelocities =
928  List<Pair<word>>(refineDict.lookup("correctFluxes"));
929  // Rework into hashtable.
930  correctFluxes_.resize(fluxVelocities.size());
931  forAll (fluxVelocities, i)
932  correctFluxes_.insert(fluxVelocities[i][0], fluxVelocities[i][1]);
933 
934  dumpLevel_ = Switch(refineDict.lookup("dumpLevel"));
935 }
HashTable< word > correctFluxes_
Definition: AMRFoam.H:259
bool dumpLevel_
Definition: AMRFoam.H:256

◆ readIncomingCellField()

volScalarField Foam::AMRFoam::readIncomingCellField ( const std::string &  inName,
const std::string &  outName 
)
Parameters
inNameInput file name
outNameObject name for volScalarField
Returns
Scalar Field

Definition at line 723 of file AMRFoam.C.

References incomingField, initScalarField(), and nemAux::strToChar().

Referenced by ~AMRFoam().

724  {
725  std::cout << " - Parsing Input file ... " << std::endl;
726  std::ifstream inFld(inName);
727  if (inFld.is_open()) {
728  std::string linesOut; // Temporary string for multiple uses
729  std::vector<std::string> myLines; // Stores whole file line by line
730  while (std::getline(inFld, linesOut)) myLines.push_back(linesOut);
731 
732  incomingField.clear();
733  incomingField.resize(myLines.size());
734 
735  for (int i = 0; i < (int)myLines.size(); i++)
736  incomingField[i] =
737  std::strtod(nemAux::strToChar(myLines[i]).get(), nullptr);
738 
739  volScalarField returnFld = initScalarField(outName);
740 
741  for (int i = 0; i < returnFld.size(); i++) returnFld[i] = incomingField[i];
742 
743  return returnFld;
744  } else {
745  std::cerr << "Cannot open/find " << inName << " file!" << std::endl;
746  throw;
747  }
748 }
std::vector< double > incomingField
Vector to store user defined vector.
Definition: AMRFoam.H:249
std::shared_ptr< char > strToChar(const std::string &strng)
volScalarField initScalarField(const std::string &fldName)
Creates an empty volScalarField based on current mesh.
Definition: AMRFoam.C:798

◆ readIncomingPtField()

pointScalarField Foam::AMRFoam::readIncomingPtField ( const std::string &  inName,
const std::string &  outName 
)
Parameters
inName
Returns
A pointScalarField with appended incoming values

Definition at line 756 of file AMRFoam.C.

References incomingField, initPntSField(), and nemAux::strToChar().

Referenced by ~AMRFoam().

757  {
758  std::cout << " - Parsing Input file ... " << std::endl;
759  std::ifstream inFld(inName);
760  if (inFld.is_open()) {
761  std::string linesOut; // Temporary string for multiple uses
762  std::vector<std::string> myLines; // Stores whole file line by line
763  while (std::getline(inFld, linesOut)) myLines.push_back(linesOut);
764 
765  incomingField.clear();
766  incomingField.resize(myLines.size());
767 
768  for (int i = 0; i < (int)myLines.size(); i++) {
769  incomingField[i] =
770  std::strtod(nemAux::strToChar(myLines[i]).get(), nullptr);
771  }
772 
773  pointScalarField returnFld = initPntSField(outName);
774 
775  for (int i = 0; i < returnFld.size(); i++) returnFld[i] = incomingField[i];
776 
777  return returnFld;
778  } else {
779  std::cerr << "Cannot open/find " << inName << " file!" << std::endl;
780  throw;
781  }
782 }
pointScalarField initPntSField(const std::string &fldName)
Creates an empty pointScalarField based on current mesh.
Definition: AMRFoam.C:814
std::vector< double > incomingField
Vector to store user defined vector.
Definition: AMRFoam.H:249
std::shared_ptr< char > strToChar(const std::string &strng)

◆ readInitialField()

volScalarField Foam::AMRFoam::readInitialField ( const std::string &  fldName)
Parameters
fldNameName of field present in current runTime directory

Definition at line 784 of file AMRFoam.C.

Referenced by ~AMRFoam().

784  {
785  volScalarField meshFieldXY(IOobject(fldName, time().timeName(), *this,
786  IOobject::NO_READ, IOobject::AUTO_WRITE),
787  *this);
788 
789  return meshFieldXY;
790 }

◆ refine()

autoPtr< mapPolyMesh > Foam::AMRFoam::refine ( const labelList &  cellsToRefine)
protectedvirtual
Parameters
splitPointsSelected hanging nodes that can be erased to unrefine previously refined cells. Selection is performed using criteria and protected cells are excluded.
Returns
Mapped Polymesh.

Definition at line 1082 of file AMRFoam.C.

References enableMotion, meshCutter_, motionPtr_, and protectedCell_.

Referenced by update(), updateAMR(), and updateAMRML().

1082  {
1083  // Mesh changing engine.
1084  polyTopoChange meshMod(*this);
1085 
1086  // Play refinement commands into mesh changer.
1087  meshCutter_.setRefinement(cellsToRefine, meshMod);
1088 
1089  // Create mesh (with inflation), return map from old to new mesh.
1090  // autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
1091  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
1092 
1093  Info << "Refined from " << returnReduce(map().nOldCells(), sumOp<label>())
1094  << " to " << globalData().nTotalCells() << " cells." << endl;
1095 
1096  if (debug) {
1097  // Check map.
1098  for (label facei = 0; facei < nInternalFaces(); ++facei) {
1099  const label oldFacei = map().faceMap()[facei];
1100 
1101  if (oldFacei >= nInternalFaces()) {
1102  FatalErrorInFunction << "New internal face:" << facei
1103  << " fc:" << faceCentres()[facei]
1104  << " originates from boundary oldFace:" << oldFacei
1105  << abort(FatalError);
1106  }
1107  }
1108  }
1109 
1110  // Update fields
1111  updateMesh(*map);
1112 
1113  if (enableMotion) {
1114  // Solve for mesh motion and move points
1115  motionPtr_->updateMesh(*map);
1116  movePoints(motionPtr_->newPoints());
1117  }
1118 
1119  // Update numbering of cells/vertices.
1120  meshCutter_.updateMesh(*map);
1121 
1122  // Update numbering of protectedCell_
1123  if (!protectedCell_.empty()) {
1124  bitSet newProtectedCell(nCells());
1125  forAll (newProtectedCell, celli) {
1126  const label oldCelli = map().cellMap()[celli];
1127  if (protectedCell_.test(oldCelli)) { newProtectedCell.set(celli); }
1128  }
1129  protectedCell_.transfer(newProtectedCell);
1130  }
1131 
1132  // Debug: Check refinement levels (across faces only)
1133  meshCutter_.checkRefinementLevels(-1, labelList());
1134 
1135  return map;
1136 }
bitSet protectedCell_
Definition: AMRFoam.H:265
bool enableMotion
Boolean to check if mesh motion is needed.
Definition: AMRFoam.H:231
hexRef8 meshCutter_
Definition: AMRFoam.H:253
autoPtr< motionSolver > motionPtr_
Definition: AMRFoam.H:365
std::vector< bool > cellsToRefine(const std::vector< T > &values, T tol)

◆ selectRefineCandidates()

void Foam::AMRFoam::selectRefineCandidates ( const scalar  lowerRefineLevel,
const scalar  upperRefineLevel,
const scalarField &  vFld,
bitSet &  candidateCell 
) const
protectedvirtual

Definition at line 1310 of file AMRFoam.C.

References cellToPoint(), error(), and maxPointField().

Referenced by update(), updateAMR(), and updateAMRML().

1313  {
1314  // Get error per cell. Is -1 (not to be refined) to >0 (to be refined,
1315  // higher more desirable to be refined).
1316  scalarField cellError(maxPointField(
1317  error(cellToPoint(vFld), lowerRefineLevel, upperRefineLevel)));
1318 
1319  // Mark cells that are candidates for refinement.
1320  forAll (cellError, celli) {
1321  if (cellError[celli] > 0) { candidateCell.set(celli); }
1322  }
1323 }
scalarField error(const scalarField &fld, const scalar minLevel, const scalar maxLevel) const
Definition: AMRFoam.C:1299
scalarField maxPointField(const scalarField &) const
Definition: AMRFoam.C:1260
scalarField cellToPoint(const scalarField &vFld) const
Definition: AMRFoam.C:1286

◆ selectRefineCells()

labelList Foam::AMRFoam::selectRefineCells ( const label  maxCells,
const label  maxRefinement,
const bitSet &  candidateCell 
) const
protectedvirtual

Definition at line 1325 of file AMRFoam.C.

References calculateProtectedCells(), and meshCutter_.

Referenced by update(), updateAMR(), and updateAMRML().

1327  {
1328  // Every refined cell causes 7 extra cells
1329  label nTotToRefine = (maxCells - globalData().nTotalCells()) / 7;
1330 
1331  const labelList &cellLevel = meshCutter_.cellLevel();
1332 
1333  // Mark cells that cannot be refined since they would trigger refinement
1334  // of protected cells (since 2:1 cascade)
1335  bitSet unrefineableCell;
1336  calculateProtectedCells(unrefineableCell);
1337 
1338  // Count current selection
1339  label nLocalCandidates = candidateCell.count();
1340  label nCandidates = returnReduce(nLocalCandidates, sumOp<label>());
1341 
1342  // Collect all cells
1343  DynamicList<label> candidates(nLocalCandidates);
1344 
1345  if (nCandidates < nTotToRefine) {
1346  for (const label celli : candidateCell) {
1347  if ((!unrefineableCell.test(celli)) && cellLevel[celli] < maxRefinement) {
1348  candidates.append(celli);
1349  }
1350  }
1351  } else {
1352  // Sort by error? For now just truncate.
1353  for (label level = 0; level < maxRefinement; ++level) {
1354  for (const label celli : candidateCell) {
1355  if ((!unrefineableCell.test(celli)) && cellLevel[celli] == level) {
1356  candidates.append(celli);
1357  }
1358  }
1359 
1360  if (returnReduce(candidates.size(), sumOp<label>()) > nTotToRefine) {
1361  break;
1362  }
1363  }
1364  }
1365 
1366  // Guarantee 2:1 refinement after refinement
1367  labelList consistentSet(meshCutter_.consistentRefinement(
1368  candidates.shrink(),
1369  true // Add to set to guarantee 2:1
1370  ));
1371 
1372  Info << "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
1373  << " cells for refinement out of " << globalData().nTotalCells() << "."
1374  << endl;
1375 
1376  return consistentSet;
1377 }
void calculateProtectedCells(bitSet &unrefineableCell) const
Definition: AMRFoam.C:847
hexRef8 meshCutter_
Definition: AMRFoam.H:253

◆ selectUnrefinePoints()

labelList Foam::AMRFoam::selectUnrefinePoints ( const scalar  unrefineAbove,
const scalar  unrefineBelow,
const bitSet &  markedCell,
const scalarField &  pFld 
) const
protectedvirtual
Parameters
unrefineAboveUnrefine cells above this thresold.
unrefineBelowUnrefine cells below this thresold.
markedCellUnrefinable cells list
pFldPointField at current runTime
Returns
List of cells/points to unrefine.

Definition at line 616 of file AMRFoam.C.

References meshCutter_, and protectedCell_.

Referenced by update(), updateAMR(), and updateAMRML().

619  {
620  // All points that can be unrefined
621  const labelList splitPoints(meshCutter_.getSplitPoints());
622 
623  const labelListList &pointCells = this->pointCells();
624 
625  // If we have any protected cells make sure they also are not being
626  // unrefined
627 
628  bitSet protectedPoint(nPoints());
629 
630  if (!protectedCell_.empty()) {
631  // Get all points on a protected cell
632  forAll (pointCells, pointi) {
633  for (const label celli : pointCells[pointi]) {
634  if (protectedCell_.test(celli)) {
635  protectedPoint.set(pointi);
636  break;
637  }
638  }
639  }
640 
641  syncTools::syncPointList(*this, protectedPoint, orEqOp<unsigned int>(), 0u);
642 
643  DebugInfo << "From " << returnReduce(protectedCell_.count(), sumOp<label>())
644  << " protected cells found "
645  << returnReduce(protectedPoint.count(), sumOp<label>())
646  << " protected points." << endl;
647  }
648 
649  DynamicList<label> newSplitPoints(splitPoints.size());
650 
651  for (const label pointi : splitPoints) {
652  if ((!protectedPoint[pointi] && pFld[pointi] < unrefineBelow) ||
653  (!protectedPoint[pointi] && pFld[pointi] > unrefineAbove)) {
654  // Check that all cells are not marked
655  bool hasMarked = false;
656 
657  for (const label celli : pointCells[pointi]) {
658  if (markedCell.test(celli)) {
659  hasMarked = true;
660  break;
661  }
662  }
663 
664  if (!hasMarked) { newSplitPoints.append(pointi); }
665  }
666  }
667 
668  newSplitPoints.shrink();
669 
670  // Guarantee 2:1 refinement after unrefinement
671  labelList consistentSet(
672  meshCutter_.consistentUnrefinement(newSplitPoints, false));
673  Info << "Selected " << returnReduce(consistentSet.size(), sumOp<label>())
674  << " split points out of a possible "
675  << returnReduce(splitPoints.size(), sumOp<label>()) << "." << endl;
676 
677  return consistentSet;
678 }
bitSet protectedCell_
Definition: AMRFoam.H:265
hexRef8 meshCutter_
Definition: AMRFoam.H:253

◆ solveMotion()

void Foam::AMRFoam::solveMotion ( )

This method allows solving of mesh motion along with mesh refinment. Flux correction takes place after motion and refinement operations are performed. Experimental method.

Definition at line 1449 of file AMRFoam.C.

References motionPtr_.

Referenced by update(), updateAMR(), and ~AMRFoam().

1449  {
1450  movePoints(motionPtr_->newPoints());
1451 
1452  if (foundObject<volVectorField>("U")) {
1453  lookupObjectRef<volVectorField>("U").correctBoundaryConditions();
1454  }
1455 }
autoPtr< motionSolver > motionPtr_
Definition: AMRFoam.H:365

◆ transformField()

void Foam::AMRFoam::transformField ( volScalarField &  inField)

Appends this information to lower, upper and unrefine level vectors for AMR

Definition at line 708 of file AMRFoam.C.

Referenced by ~AMRFoam().

708  {
709  double maxNum = 0;
710  for (int i = 0; i < inField.size(); i++) {
711  if (inField[i] < 0) {
712  // Do Nothing
713  } else if (inField[i] > maxNum) {
714  maxNum = inField[i];
715  } else {
716  // Do Nothing
717  }
718  }
719 
720  for (int i = 0; i < inField.size(); i++) inField[i] = inField[i] / maxNum;
721 }

◆ unrefine()

autoPtr< mapPolyMesh > Foam::AMRFoam::unrefine ( const labelList &  splitPoints)
protectedvirtual
Parameters
cellsToRefineCell list selected for refinement.
Returns
Mapped Polymesh.

Definition at line 1138 of file AMRFoam.C.

References correctFluxes_, enableMotion, meshCutter_, motionPtr_, and protectedCell_.

Referenced by update(), updateAMR(), and updateAMRML().

1138  {
1139  polyTopoChange meshMod(*this);
1140 
1141  // Play refinement commands into mesh changer.
1142  meshCutter_.setUnrefinement(splitPoints, meshMod);
1143 
1144  // Save information on faces that will be combined
1145  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1146 
1147  // Find the faceMidPoints on cells to be combined.
1148  // for each face resulting of split of face into four store the
1149  // midpoint
1150  Map<label> faceToSplitPoint(3 * splitPoints.size());
1151 
1152  {
1153  for (const label pointi : splitPoints) {
1154  const labelList &pEdges = pointEdges()[pointi];
1155 
1156  for (const label edgei : pEdges) {
1157  const label otherPointi = edges()[edgei].otherVertex(pointi);
1158 
1159  const labelList &pFaces = pointFaces()[otherPointi];
1160 
1161  for (const label facei : pFaces) {
1162  faceToSplitPoint.insert(facei, otherPointi);
1163  }
1164  }
1165  }
1166  }
1167 
1168  // Change mesh and generate map.
1169  // autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, true);
1170  autoPtr<mapPolyMesh> map = meshMod.changeMesh(*this, false);
1171 
1172  Info << "Unrefined from " << returnReduce(map().nOldCells(), sumOp<label>())
1173  << " to " << globalData().nTotalCells() << " cells." << endl;
1174 
1175  // Update fields
1176  updateMesh(*map);
1177 
1178  if (enableMotion) {
1179  // Solve for mesh motion and move points
1180  motionPtr_->updateMesh(*map);
1181  movePoints(motionPtr_->newPoints());
1182  }
1183 
1184  // Correct the flux for modified faces.
1185  {
1186  const labelList &reversePointMap = map().reversePointMap();
1187  const labelList &reverseFaceMap = map().reverseFaceMap();
1188 
1189  HashTable<surfaceScalarField *> fluxes(lookupClass<surfaceScalarField>());
1190  forAllIters(fluxes, iter) {
1191  if (!correctFluxes_.found(iter.key())) {
1192  WarningInFunction
1193  << "Cannot find surfaceScalarField " << iter.key()
1194  << " in user-provided flux mapping table " << correctFluxes_ << endl
1195  << " The flux mapping table is used to recreate the"
1196  << " flux on newly created faces." << endl
1197  << " Either add the entry if it is a flux or use (" << iter.key()
1198  << " none) to suppress this warning." << endl;
1199  continue;
1200  }
1201 
1202  const word &UName = correctFluxes_[iter.key()];
1203 
1204  if (UName == "none") { continue; }
1205 
1206  DebugInfo << "Mapping flux " << iter.key() << " using interpolated flux "
1207  << UName << endl;
1208 
1209  surfaceScalarField &phi = *iter();
1210  surfaceScalarField::Boundary &phiBf = phi.boundaryFieldRef();
1211 
1212  const surfaceScalarField phiU(
1213  fvc::interpolate(lookupObject<volVectorField>(UName)) & Sf());
1214 
1215  forAllConstIters(faceToSplitPoint, iter2) {
1216  const label oldFacei = iter2.key();
1217  const label oldPointi = iter2.val();
1218  if (reversePointMap[oldPointi] < 0) {
1219  // midpoint was removed. See if face still exists.
1220  const label facei = reverseFaceMap[oldFacei];
1221 
1222  if (facei >= 0) {
1223  if (isInternalFace(facei)) {
1224  phi[facei] = phiU[facei];
1225  } else {
1226  label patchi = boundaryMesh().whichPatch(facei);
1227  label i = facei - boundaryMesh()[patchi].start();
1228 
1229  const fvsPatchScalarField &patchPhiU =
1230  phiU.boundaryField()[patchi];
1231  fvsPatchScalarField &patchPhi = phiBf[patchi];
1232  patchPhi[i] = patchPhiU[i];
1233  }
1234  }
1235  }
1236  }
1237  }
1238  }
1239 
1240  // Update numbering of cells/vertices.
1241  meshCutter_.updateMesh(*map);
1242 
1243  // Update numbering of protectedCell_
1244  if (!protectedCell_.empty()) {
1245  bitSet newProtectedCell(nCells());
1246 
1247  forAll (newProtectedCell, celli) {
1248  const label oldCelli = map().cellMap()[celli];
1249  if (protectedCell_.test(oldCelli)) { newProtectedCell.set(celli); }
1250  }
1251  protectedCell_.transfer(newProtectedCell);
1252  }
1253 
1254  // Debug: Check refinement levels (across faces only)
1255  meshCutter_.checkRefinementLevels(-1, labelList());
1256 
1257  return map;
1258 }
bitSet protectedCell_
Definition: AMRFoam.H:265
bool enableMotion
Boolean to check if mesh motion is needed.
Definition: AMRFoam.H:231
HashTable< word > correctFluxes_
Definition: AMRFoam.H:259
hexRef8 meshCutter_
Definition: AMRFoam.H:253
autoPtr< motionSolver > motionPtr_
Definition: AMRFoam.H:365

◆ update()

bool Foam::AMRFoam::update ( )
virtual

Definition at line 233 of file AMRFoam.C.

References nemAux::cellsToRefine(), correctFluxes_, dumpLevel_, enableMotion, extendMarkedCells(), maxCellField(), meshCutter(), nRefinementIterations_, refine(), selectRefineCandidates(), selectRefineCells(), selectUnrefinePoints(), solveMotion(), unrefine(), writeHistory(), and writeMesh().

233  {
234  // Re-read dictionary. Chosen since usually -small so trivial amount
235  // of time compared to actual refinement. Also very useful to be able
236  // to modify on-the-fly.
237  dictionary refineDict(
238  IOdictionary(IOobject("dynamicMeshDict", time().constant(), *this,
239  IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE,
240  false))
241  .optionalSubDict("dynamicRefineMotionFvMeshCoeffs"));
242 
243  auto fluxVelocities = refineDict.get<List<Pair<word>>>("correctFluxes");
244 
245  // Rework into hashtable.
246  correctFluxes_.resize(fluxVelocities.size());
247  for (const auto &pr : fluxVelocities) {
248  correctFluxes_.insert(pr.first(), pr.second());
249  }
250 
251  refineDict.readEntry("dumpLevel", dumpLevel_);
252  const label refineInterval = refineDict.get<label>("refineInterval");
253 
254  bool hasChanged = false;
255 
256  if (refineInterval == 0) {
257  polyMesh::topoChanging(hasChanged);
258  return hasChanged;
259  } else if (refineInterval < 0) {
260  FatalErrorInFunction << "Illegal refineInterval " << refineInterval << nl
261  << "The refineInterval value should"
262  << " be >= 1." << nl << exit(FatalError);
263  }
264 
265  if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0) {
266  label maxCells = refineDict.get<label>("maxCells");
267 
268  if (maxCells < 0) maxCells = 500000;
269 
270  if (maxCells <= 0) {
271  FatalErrorInFunction
272  << "Illegal maximum number of cells " << maxCells << nl
273  << "The maxCells setting in the dynamicMeshDict should"
274  << " be > 0." << nl << exit(FatalError);
275  }
276 
277  const label maxRefinement = refineDict.get<label>("maxRefinement");
278 
279  if (maxRefinement <= 0) {
280  FatalErrorInFunction
281  << "Illegal maximum refinement level " << maxRefinement << nl
282  << "The maxCells setting in the dynamicMeshDict should"
283  << " be > 0." << nl << exit(FatalError);
284  }
285 
286  const word fieldName(refineDict.get<word>("field"));
287 
288  const volScalarField &vFld = lookupObject<volScalarField>(fieldName);
289 
290  const scalar lowerRefineLevel = refineDict.get<scalar>("lowerRefineLevel");
291  const scalar upperRefineLevel = refineDict.get<scalar>("upperRefineLevel");
292  const scalar unrefineBelow =
293  refineDict.getOrDefault<scalar>("unrefineLevel", GREAT);
294  const scalar unrefineAbove =
295  refineDict.getOrDefault<scalar>("unrefineAbove", 50000);
296  const label nBufferLayers = refineDict.get<label>("nBufferLayers");
297 
298  // Cells marked for refinement or otherwise protected from unrefinement.
299  bitSet refineCell(nCells());
300 
301  // Determine candidates for refinement (looking at field only)
302  selectRefineCandidates(lowerRefineLevel, upperRefineLevel, vFld,
303  refineCell);
304 
305  if (globalData().nTotalCells() < maxCells) {
306  // Select subset of candidates. Take into account max allowable
307  // cells, refinement level, protected cells.
308  labelList cellsToRefine(
309  selectRefineCells(maxCells, maxRefinement, refineCell));
310 
311  const label nCellsToRefine =
312  returnReduce(cellsToRefine.size(), sumOp<label>());
313 
314  if (nCellsToRefine > 0) {
315  // Refine/update mesh and map fields
316  autoPtr<mapPolyMesh> map = refine(cellsToRefine);
317 
318  // Update refineCell. Note that some of the marked ones have
319  // not been refined due to constraints.
320  {
321  const labelList &cellMap = map().cellMap();
322  const labelList &reverseCellMap = map().reverseCellMap();
323 
324  bitSet newRefineCell(cellMap.size());
325 
326  forAll (cellMap, celli) {
327  const label oldCelli = cellMap[celli];
328  if ((oldCelli < 0) || (reverseCellMap[oldCelli] != celli) ||
329  (refineCell.test(oldCelli))) {
330  newRefineCell.set(celli);
331  }
332  }
333  refineCell.transfer(newRefineCell);
334  }
335 
336  // Extend with a buffer layer to prevent neighbouring points
337  // being unrefined.
338  for (label i = 0; i < nBufferLayers; ++i) {
339  extendMarkedCells(refineCell);
340  }
341 
342  hasChanged = true;
343  }
344  }
345 
346  {
347  // Select unrefineable points that are not marked in refineCell
348  labelList pointsToUnrefine(selectUnrefinePoints(
349  unrefineAbove, unrefineBelow, refineCell, maxCellField(vFld)));
350 
351  const label nSplitPoints =
352  returnReduce(pointsToUnrefine.size(), sumOp<label>());
353 
354  if (nSplitPoints > 0) {
355  // Refine/update mesh
356  unrefine(pointsToUnrefine);
357 
358  hasChanged = true;
359  }
360  }
361 
362  if ((nRefinementIterations_ % 1) == 0) {
363  // Compact refinement history occasionally (how often?).
364  // Unrefinement causes holes in the refinementHistory.
365  const_cast<refinementHistory &>(meshCutter().history()).compact();
366  }
368  }
369 
370  writeHistory();
371 
372  writeMesh();
373 
374  topoChanging(hasChanged);
375 
376  if (hasChanged) {
377  // Reset moving flag (if any). If not using inflation we'll not move,
378  // if are using inflation any follow on movePoints will set it.
379  moving(false);
380  } else {
381  if (enableMotion) solveMotion();
382  }
383  return hasChanged;
384 }
virtual Foam::autoPtr< Foam::mapPolyMesh > unrefine(const labelList &)
Refines selected cells in a mesh.
Definition: AMRFoam.C:1138
virtual labelList selectUnrefinePoints(const scalar unrefineAbove, const scalar unrefineBelow, const bitSet &markedCell, const scalarField &pFld) const
Marked the cells to unrefine based on user defined levels.
Definition: AMRFoam.C:616
bool enableMotion
Boolean to check if mesh motion is needed.
Definition: AMRFoam.H:231
void solveMotion()
A mesh motion solver.
Definition: AMRFoam.C:1449
label nRefinementIterations_
Definition: AMRFoam.H:262
const hexRef8 & meshCutter() const
Definition: AMRFoam.H:370
void writeHistory()
Writes refinement history in current time directory.
Definition: AMRFoam.C:696
HashTable< word > correctFluxes_
Definition: AMRFoam.H:259
scalarField maxCellField(const volScalarField &) const
Definition: AMRFoam.C:1273
virtual void selectRefineCandidates(const scalar lowerRefineLevel, const scalar upperRefineLevel, const scalarField &vFld, bitSet &candidateCell) const
Definition: AMRFoam.C:1310
void extendMarkedCells(bitSet &markedCell) const
Definition: AMRFoam.C:1379
void writeMesh()
Ability to write current mesh into current time directory.
Definition: AMRFoam.C:704
bool dumpLevel_
Definition: AMRFoam.H:256
virtual Foam::autoPtr< Foam::mapPolyMesh > refine(const labelList &)
Unrefines selected cells in a mesh.
Definition: AMRFoam.C:1082
std::vector< bool > cellsToRefine(const std::vector< T > &values, T tol)
virtual labelList selectRefineCells(const label maxCells, const label maxRefinement, const bitSet &candidateCell) const
Definition: AMRFoam.C:1325

◆ updateAMR()

bool Foam::AMRFoam::updateAMR ( const int &  refineInterval,
const int &  maxRefinement,
volScalarField &  vFld,
const double &  lowerRefineLevel,
const double &  upperRefineLevel,
const double &  unrefineAbove,
const double &  unrefineBelow,
const int &  nBufferLayers,
const int &  maxCells 
)

It drives the refinement and unrefinement procedure between any two given timesteps.

Parameters
refineIntervalRefinement interval/frequency
maxRefinementMaximum refinement allowed by user
vFldA scalar field of refinement criteria quantity
lowerRefineLevelLower refinement level (Based on vFld)
upperRefineLevelUpper refinement level (Based on vFld)
unrefineAboveCriteria for unrefinement above this value
unrefineBelowCriteria for unrefinement below this value
nBufferLayersBuffer layers for slower than 2:1 refinement
maxCellsMaximum number of cells allowed in mesh. Once this level is reached, refinement will be stopped.
Returns
A boolean indicating mesh change

Definition at line 386 of file AMRFoam.C.

References nemAux::cellsToRefine(), enableMotion, extendMarkedCells(), maxCellField(), meshCutter(), nRefinementIterations_, refine(), selectRefineCandidates(), selectRefineCells(), selectUnrefinePoints(), solveMotion(), unrefine(), writeField, writeHistory(), writeMesh(), writeMeshData, and writeRefHistory.

Referenced by ~AMRFoam().

391  {
392  bool hasChanged = false;
393 
394  if (refineInterval == 0) {
395  polyMesh::topoChanging(hasChanged);
396  return hasChanged;
397  } else if (refineInterval < 0) {
398  FatalErrorInFunction << "Illegal refineInterval " << refineInterval << nl
399  << "The refineInterval value should"
400  << " be >= 1." << nl << exit(FatalError);
401  }
402 
403  if (time().timeIndex() > 0 && time().timeIndex() % refineInterval == 0) {
404  if (maxCells <= 0) {
405  FatalErrorInFunction
406  << "Illegal maximum number of cells " << maxCells << nl
407  << "The maxCells setting in the dynamicMeshDict should"
408  << " be > 0." << nl << exit(FatalError);
409  }
410 
411  if (maxRefinement <= 0) {
412  FatalErrorInFunction
413  << "Illegal maximum refinement level " << maxRefinement << nl
414  << "The maxCells setting in the dynamicMeshDict should"
415  << " be > 0." << nl << exit(FatalError);
416  }
417 
418  // Cells marked for refinement or otherwise protected from unrefinement.
419  bitSet refineCell(nCells());
420 
421  // Determine candidates for refinement (looking at field only)
422  selectRefineCandidates(lowerRefineLevel, upperRefineLevel, vFld,
423  refineCell);
424 
425  if (globalData().nTotalCells() < maxCells) {
426  // Select subset of candidates. Take into account max allowable
427  // cells, refinement level, protected cells.
428  labelList cellsToRefine(
429  selectRefineCells(maxCells, maxRefinement, refineCell));
430 
431  const label nCellsToRefine =
432  returnReduce(cellsToRefine.size(), sumOp<label>());
433 
434  if (nCellsToRefine > 0) {
435  // Refine/update mesh and map fields
436  autoPtr<mapPolyMesh> map = refine(cellsToRefine);
437 
438  // Update refineCell. Note that some of the marked ones have
439  // not been refined due to constraints.
440  {
441  const labelList &cellMap = map().cellMap();
442  const labelList &reverseCellMap = map().reverseCellMap();
443 
444  bitSet newRefineCell(cellMap.size());
445 
446  forAll (cellMap, celli) {
447  const label oldCelli = cellMap[celli];
448  if ((oldCelli < 0) || (reverseCellMap[oldCelli] != celli) ||
449  (refineCell.test(oldCelli))) {
450  newRefineCell.set(celli);
451  }
452  }
453  refineCell.transfer(newRefineCell);
454  }
455 
456  // Extend with a buffer layer to prevent neighbouring points
457  // being unrefined.
458  for (label i = 0; i < nBufferLayers; ++i) {
459  extendMarkedCells(refineCell);
460  }
461 
462  hasChanged = true;
463  }
464  }
465 
466  {
467  // Select unrefineable points that are not marked in refineCell
468  labelList pointsToUnrefine(selectUnrefinePoints(
469  unrefineAbove, unrefineBelow, refineCell, maxCellField(vFld)));
470 
471  const label nSplitPoints =
472  returnReduce(pointsToUnrefine.size(), sumOp<label>());
473 
474  if (nSplitPoints > 0) {
475  // Refine/update mesh
476  unrefine(pointsToUnrefine);
477 
478  hasChanged = true;
479  }
480  }
481 
482  if ((nRefinementIterations_ % 10) == 0) {
483  // Compact refinement history occasionally (how often?).
484  // Unrefinement causes holes in the refinementHistory.
485  const_cast<refinementHistory &>(meshCutter().history()).compact();
486  }
488  }
489 
490  topoChanging(hasChanged);
491 
492  if (hasChanged) {
493  // Reset moving flag (if any). If not using inflation we'll not move,
494  // if are using inflation any follow on movePoints will set it.
495  moving(false);
496  } else {
497  if (enableMotion) solveMotion();
498  }
499 
500  if (writeField) vFld.write();
501 
503 
504  if (writeMeshData) writeMesh();
505 
506  return hasChanged;
507 }
virtual Foam::autoPtr< Foam::mapPolyMesh > unrefine(const labelList &)
Refines selected cells in a mesh.
Definition: AMRFoam.C:1138
virtual labelList selectUnrefinePoints(const scalar unrefineAbove, const scalar unrefineBelow, const bitSet &markedCell, const scalarField &pFld) const
Marked the cells to unrefine based on user defined levels.
Definition: AMRFoam.C:616
bool enableMotion
Boolean to check if mesh motion is needed.
Definition: AMRFoam.H:231
void solveMotion()
A mesh motion solver.
Definition: AMRFoam.C:1449
label nRefinementIterations_
Definition: AMRFoam.H:262
const hexRef8 & meshCutter() const
Definition: AMRFoam.H:370
void writeHistory()
Writes refinement history in current time directory.
Definition: AMRFoam.C:696
bool writeRefHistory
Boolean to enable writing of refinement history.
Definition: AMRFoam.H:241
scalarField maxCellField(const volScalarField &) const
Definition: AMRFoam.C:1273
virtual void selectRefineCandidates(const scalar lowerRefineLevel, const scalar upperRefineLevel, const scalarField &vFld, bitSet &candidateCell) const
Definition: AMRFoam.C:1310
void extendMarkedCells(bitSet &markedCell) const
Definition: AMRFoam.C:1379
void writeMesh()
Ability to write current mesh into current time directory.
Definition: AMRFoam.C:704
bool writeMeshData
Boolean to enable writing of mesh.
Definition: AMRFoam.H:245
bool writeField
Boolean to enable writing of updated solution field every timestep.
Definition: AMRFoam.H:237
virtual Foam::autoPtr< Foam::mapPolyMesh > refine(const labelList &)
Unrefines selected cells in a mesh.
Definition: AMRFoam.C:1082
std::vector< bool > cellsToRefine(const std::vector< T > &values, T tol)
virtual labelList selectRefineCells(const label maxCells, const label maxRefinement, const bitSet &candidateCell) const
Definition: AMRFoam.C:1325

◆ updateAMRML()

bool Foam::AMRFoam::updateAMRML ( const int &  refineInterval,
const int &  maxRefinement,
const int &  nBufferLayers,
const int &  maxCells,
volScalarField &  vFld 
)

Takes output from ML model and performs refinement/unrefinement.

Parameters
refineIntervalRefinement interval/frequency
maxRefinementMaximum refinement allowed by user
nBufferLayersBuffer layers for slower than 2:1 refinement
maxCellsMaximum number of cells allowed in mesh. Once this level is reached, refinement will be stopped.
vFldMachine learning model output vector
Returns
A boolean indicating mesh change

Definition at line 510 of file AMRFoam.C.

References nemAux::cellsToRefine(), extendMarkedCells(), maxCellField(), meshCutter(), nRefinementIterations_, refine(), selectRefineCandidates(), selectRefineCells(), selectUnrefinePoints(), and unrefine().

Referenced by NEM::DRV::FoamRefineDriver::execute(), and ~AMRFoam().

512  {
513  bool hasChanged = false;
514  if (refineInterval == 0) {
515  polyMesh::topoChanging(hasChanged);
516  return hasChanged;
517  } else if (refineInterval < 0) {
518  FatalErrorInFunction << "Illegal refineInterval " << refineInterval << nl
519  << "The refineInterval value should"
520  << " be >= 1." << nl << exit(FatalError);
521  }
522 
523  // if (maxCells < 0)
524  // maxCells = 500000;
525 
526  // Cannot refine at time = 0;
527  if (fvMesh::time().timeIndex() > 0 &&
528  fvMesh::time().timeIndex() % refineInterval == 0) {
529  if (maxCells <= 0) {
530  FatalErrorInFunction << "Illegal maximum number of cells " << maxCells
531  << nl << "The maxCells value should"
532  << " be > 0." << nl << exit(FatalError);
533  }
534 
535  if (maxRefinement <= 0) {
536  FatalErrorInFunction << "Illegal maximum refinement level "
537  << maxRefinement << nl << "The maxCells value should"
538  << " be > 0." << nl << exit(FatalError);
539  }
540 
541  // Cells marked for refinement or otherwise protected from unrefinement.
542  bitSet refineCell(primitiveMesh::nCells());
543 
544  // Selecting refinement candidates based on lower and upper refinement
545  // levels in scalar field
546  selectRefineCandidates(0.5, 1.5, vFld, refineCell);
547 
548  // Refinement Procedure Loop
549  if (polyMesh::globalData().nTotalCells() < maxCells) {
550  // Select subset of candidates. Take into account max allowable
551  // cells, refinement level, protected cells.
552  labelList cellsToRefine(
553  selectRefineCells(maxCells, maxRefinement, refineCell));
554 
555  label nCellsToRefine = returnReduce(cellsToRefine.size(), sumOp<label>());
556 
557  if (nCellsToRefine > 0) {
558  // Refine/update mesh and map fields
559  autoPtr<mapPolyMesh> map = refine(cellsToRefine);
560 
561  // Update refineCell. Note that some of the marked ones have not been
562  // refined due to constraints.
563  const labelList &cellMap = map().cellMap();
564  const labelList &reverseCellMap = map().reverseCellMap();
565 
566  bitSet newRefineCell(cellMap.size());
567 
568  forAll (cellMap, celli) {
569  label oldCelli = cellMap[celli];
570 
571  if (oldCelli < 0)
572  newRefineCell.set(celli, 1);
573  else if (reverseCellMap[oldCelli] != celli)
574  newRefineCell.set(celli, 1);
575  else
576  newRefineCell.set(celli, refineCell.get(oldCelli));
577  }
578  refineCell.transfer(newRefineCell);
579 
580  // Extended with a buffer layer to prevent neighbouring points
581  // being unrefined
582  for (label i = 0; i < nBufferLayers; i++) {
583  extendMarkedCells(refineCell);
584  }
585 
586  hasChanged = true;
587  }
588  }
589 
590  // Select unrefinable points that are not marked in refineCell
591  labelList pointsToUnrefine(
592  selectUnrefinePoints(-1, 0.5, refineCell, maxCellField(vFld)));
593 
594  label nSplitPoints = returnReduce(pointsToUnrefine.size(), sumOp<label>());
595  autoPtr<mapPolyMesh> mapUnrefine;
596 
597  if (nSplitPoints > 0) {
598  // Refine/update mesh
599  unrefine(pointsToUnrefine);
600  hasChanged = true;
601  }
602 
603  if ((nRefinementIterations_ % 10) == 0) {
604  // Unrefinement causes holes in the refinementHistory
605  const_cast<refinementHistory &>(meshCutter().history()).compact();
606  }
608  }
609 
610  polyMesh::topoChanging(hasChanged);
611  if (hasChanged) { polyMesh::moving(false); }
612 
613  return hasChanged;
614 }
virtual Foam::autoPtr< Foam::mapPolyMesh > unrefine(const labelList &)
Refines selected cells in a mesh.
Definition: AMRFoam.C:1138
virtual labelList selectUnrefinePoints(const scalar unrefineAbove, const scalar unrefineBelow, const bitSet &markedCell, const scalarField &pFld) const
Marked the cells to unrefine based on user defined levels.
Definition: AMRFoam.C:616
label nRefinementIterations_
Definition: AMRFoam.H:262
const hexRef8 & meshCutter() const
Definition: AMRFoam.H:370
scalarField maxCellField(const volScalarField &) const
Definition: AMRFoam.C:1273
virtual void selectRefineCandidates(const scalar lowerRefineLevel, const scalar upperRefineLevel, const scalarField &vFld, bitSet &candidateCell) const
Definition: AMRFoam.C:1310
void extendMarkedCells(bitSet &markedCell) const
Definition: AMRFoam.C:1379
virtual Foam::autoPtr< Foam::mapPolyMesh > refine(const labelList &)
Unrefines selected cells in a mesh.
Definition: AMRFoam.C:1082
std::vector< bool > cellsToRefine(const std::vector< T > &values, T tol)
virtual labelList selectRefineCells(const label maxCells, const label maxRefinement, const bitSet &candidateCell) const
Definition: AMRFoam.C:1325

◆ writeHistory()

void Foam::AMRFoam::writeHistory ( )

Definition at line 696 of file AMRFoam.C.

References meshCutter_.

Referenced by update(), updateAMR(), and ~AMRFoam().

696  {
697  // Just write refiment history in current time
698  const_cast<hexRef8 &>(meshCutter_).setInstance(time().timeName());
699  meshCutter_.write(true);
700 }
hexRef8 meshCutter_
Definition: AMRFoam.H:253

◆ writeMesh()

void Foam::AMRFoam::writeMesh ( )

Definition at line 704 of file AMRFoam.C.

References writeObjectAMR().

Referenced by update(), updateAMR(), and ~AMRFoam().

704  {
705  writeObjectAMR(true);
706 }
bool writeObjectAMR(const bool valid) const
Definition: AMRFoam.C:1425

◆ writeObjectAMR()

bool Foam::AMRFoam::writeObjectAMR ( const bool  valid) const

Definition at line 1425 of file AMRFoam.C.

References dumpLevel_, and meshCutter_.

Referenced by protectedCell(), and writeMesh().

1425  {
1426  // Force refinement data to go to the current time directory.
1427  const_cast<hexRef8 &>(meshCutter_).setInstance(time().timeName());
1428  auto strmOpt =
1429  IOstreamOption(time().writeFormat(), time().writeCompression());
1430  bool writeOk =
1431  (dynamicFvMesh::writeObject(strmOpt, true) && meshCutter_.write(valid));
1432 
1433  if (dumpLevel_) {
1434  volScalarField scalarCellLevel(
1435  IOobject("cellLevel", time().timeName(), *this, IOobject::NO_READ,
1436  IOobject::AUTO_WRITE, false),
1437  *this, dimensionedScalar("level", dimless, 0));
1438 
1439  const labelList &cellLevel = meshCutter_.cellLevel();
1440 
1441  forAll (cellLevel, celli) { scalarCellLevel[celli] = cellLevel[celli]; }
1442 
1443  writeOk = writeOk && scalarCellLevel.write();
1444  }
1445 
1446  return writeOk;
1447 }
hexRef8 meshCutter_
Definition: AMRFoam.H:253
bool dumpLevel_
Definition: AMRFoam.H:256

Member Data Documentation

◆ correctFluxes_

HashTable<word> Foam::AMRFoam::correctFluxes_
protected

Definition at line 259 of file AMRFoam.H.

Referenced by mapFields(), readDict(), unrefine(), and update().

◆ dumpLevel_

bool Foam::AMRFoam::dumpLevel_
protected

Definition at line 256 of file AMRFoam.H.

Referenced by readDict(), update(), and writeObjectAMR().

◆ enableMotion

bool Foam::AMRFoam::enableMotion {false}

◆ incomingField

std::vector<double> Foam::AMRFoam::incomingField
private

Definition at line 249 of file AMRFoam.H.

Referenced by readIncomingCellField(), and readIncomingPtField().

◆ lowerRefLvl

std::vector<double> Foam::AMRFoam::lowerRefLvl

Definition at line 211 of file AMRFoam.H.

◆ meshCutter_

◆ motionPtr_

autoPtr<motionSolver> Foam::AMRFoam::motionPtr_

Definition at line 365 of file AMRFoam.H.

Referenced by checkForMotion(), refine(), solveMotion(), and unrefine().

◆ nRefinementIterations_

label Foam::AMRFoam::nRefinementIterations_
protected

Definition at line 262 of file AMRFoam.H.

Referenced by update(), updateAMR(), and updateAMRML().

◆ protectedCell_

bitSet Foam::AMRFoam::protectedCell_
protected

◆ stepSz

int Foam::AMRFoam::stepSz = 1

Definition at line 227 of file AMRFoam.H.

◆ unrefAboveLvl

std::vector<double> Foam::AMRFoam::unrefAboveLvl

Definition at line 219 of file AMRFoam.H.

◆ unrefBelowLvl

std::vector<double> Foam::AMRFoam::unrefBelowLvl

Definition at line 223 of file AMRFoam.H.

◆ upperRefLvl

std::vector<double> Foam::AMRFoam::upperRefLvl

Definition at line 215 of file AMRFoam.H.

◆ writeField

bool Foam::AMRFoam::writeField {false}
private

Definition at line 237 of file AMRFoam.H.

Referenced by enableUpdatedField(), and updateAMR().

◆ writeMeshData

bool Foam::AMRFoam::writeMeshData {false}
private

Definition at line 245 of file AMRFoam.H.

Referenced by enableMeshWriting(), and updateAMR().

◆ writeRefHistory

bool Foam::AMRFoam::writeRefHistory {false}
private

Definition at line 241 of file AMRFoam.H.

Referenced by enableRefHistoryData(), and updateAMR().


The documentation for this class was generated from the following files: