layerAdditionRemoval.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "layerAdditionRemoval.H"
30 #include "polyTopoChanger.H"
31 #include "polyMesh.H"
32 #include "Time.H"
33 #include "primitiveMesh.H"
34 #include "polyTopoChange.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41  defineTypeNameAndDebug(layerAdditionRemoval, 0);
43  (
44  polyMeshModifier,
45  layerAdditionRemoval,
46  dictionary
47  );
48 }
49 
50 
51 const Foam::scalar Foam::layerAdditionRemoval::addDelta_ = 0.3;
52 const Foam::scalar Foam::layerAdditionRemoval::removeDelta_ = 0.1;
53 
54 
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
56 
57 void Foam::layerAdditionRemoval::checkDefinition()
58 {
59  if (!faceZoneID_.active())
60  {
62  << "Master face zone named " << faceZoneID_.name()
63  << " cannot be found."
64  << abort(FatalError);
65  }
66 
67  if
68  (
69  minLayerThickness_ < VSMALL
70  || maxLayerThickness_ < minLayerThickness_
71  )
72  {
74  << "Incorrect layer thickness definition."
75  << abort(FatalError);
76  }
77 
78  label nFaces = topoChanger().mesh().faceZones()[faceZoneID_.index()].size();
79 
80  reduce(nFaces, sumOp<label>());
81 
82  if (nFaces == 0)
83  {
85  << "Face extrusion zone contains no faces. "
86  << "Please check your mesh definition."
87  << abort(FatalError);
88  }
89 
90  if (debug)
91  {
92  Pout<< "Cell layer addition/removal object " << name() << " :" << nl
93  << " faceZoneID: " << faceZoneID_ << endl;
94  }
95 }
96 
97 
98 void Foam::layerAdditionRemoval::clearAddressing() const
99 {
100  pointsPairingPtr_.reset(nullptr);
101  facesPairingPtr_.reset(nullptr);
102 }
103 
104 
105 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
106 
107 Foam::layerAdditionRemoval::layerAdditionRemoval
108 (
109  const word& name,
110  const label index,
111  const polyTopoChanger& ptc,
112  const word& zoneName,
113  const scalar minThickness,
114  const scalar maxThickness,
115  const bool thicknessFromVolume
116 )
117 :
118  polyMeshModifier(name, index, ptc, true),
119  faceZoneID_(zoneName, ptc.mesh().faceZones()),
120  minLayerThickness_(minThickness),
121  maxLayerThickness_(maxThickness),
122  thicknessFromVolume_(thicknessFromVolume),
123  oldLayerThickness_(-1.0),
124  pointsPairingPtr_(nullptr),
125  facesPairingPtr_(nullptr),
126  triggerRemoval_(-1),
127  triggerAddition_(-1)
128 {
129  checkDefinition();
130 }
131 
132 
133 Foam::layerAdditionRemoval::layerAdditionRemoval
134 (
135  const word& name,
136  const dictionary& dict,
137  const label index,
138  const polyTopoChanger& ptc
139 )
140 :
141  polyMeshModifier(name, index, ptc, dict.get<bool>("active")),
142  faceZoneID_(dict.lookup("faceZoneName"), ptc.mesh().faceZones()),
143  minLayerThickness_(dict.get<scalar>("minLayerThickness")),
144  maxLayerThickness_(dict.get<scalar>("maxLayerThickness")),
145  thicknessFromVolume_(dict.getOrDefault("thicknessFromVolume", true)),
146  oldLayerThickness_(dict.getOrDefault<scalar>("oldLayerThickness", -1)),
147  pointsPairingPtr_(nullptr),
148  facesPairingPtr_(nullptr),
149  triggerRemoval_(-1),
150  triggerAddition_(-1)
151 {
152  checkDefinition();
153 }
154 
155 
156 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
157 
159 {
160  // Protect from multiple calculation in the same time-step
161  if (triggerRemoval_ > -1 || triggerAddition_ > -1)
162  {
163  return true;
164  }
165 
166  // Go through all the cells in the master layer and calculate
167  // approximate layer thickness as the ratio of the cell volume and
168  // face area in the face zone.
169  // Layer addition:
170  // When the max thickness exceeds the threshold, trigger refinement.
171  // Layer removal:
172  // When the min thickness falls below the threshold, trigger removal.
173 
174  const polyMesh& mesh = topoChanger().mesh();
175 
176  const faceZone& fz = mesh.faceZones()[faceZoneID_.index()];
177  const labelList& mc = fz.masterCells();
178 
179  const scalarField& V = mesh.cellVolumes();
180  const vectorField& S = mesh.faceAreas();
181 
182  if (min(V) < -VSMALL)
183  {
185  << "negative cell volume. Error in mesh motion before "
186  << "topological change.\n V: " << V
187  << abort(FatalError);
188  }
189 
190  scalar avgDelta = 0;
191  scalar minDelta = GREAT;
192  scalar maxDelta = 0;
193  label nDelta = 0;
194 
195  if (thicknessFromVolume_)
196  {
197  // Thickness calculated from cell volume/face area
198  forAll(fz, facei)
199  {
200  scalar curDelta = V[mc[facei]]/mag(S[fz[facei]]);
201  avgDelta += curDelta;
202  minDelta = min(minDelta, curDelta);
203  maxDelta = max(maxDelta, curDelta);
204  }
205 
206  nDelta = fz.size();
207  }
208  else
209  {
210  // Thickness calculated from edges on layer
211  const Map<label>& zoneMeshPointMap = fz().meshPointMap();
212 
213  // Edges with only one point on zone
214  forAll(mc, facei)
215  {
216  const cell& cFaces = mesh.cells()[mc[facei]];
217  const edgeList cellEdges(cFaces.edges(mesh.faces()));
218 
219  forAll(cellEdges, i)
220  {
221  const edge& e = cellEdges[i];
222 
223  if (zoneMeshPointMap.found(e[0]))
224  {
225  if (!zoneMeshPointMap.found(e[1]))
226  {
227  scalar curDelta = e.mag(mesh.points());
228  avgDelta += curDelta;
229  nDelta++;
230  minDelta = min(minDelta, curDelta);
231  maxDelta = max(maxDelta, curDelta);
232  }
233  }
234  else
235  {
236  if (zoneMeshPointMap.found(e[1]))
237  {
238  scalar curDelta = e.mag(mesh.points());
239  avgDelta += curDelta;
240  nDelta++;
241  minDelta = min(minDelta, curDelta);
242  maxDelta = max(maxDelta, curDelta);
243  }
244  }
245  }
246  }
247  }
248 
249  reduce(minDelta, minOp<scalar>());
250  reduce(maxDelta, maxOp<scalar>());
251  reduce(avgDelta, sumOp<scalar>());
252  reduce(nDelta, sumOp<label>());
253 
254  avgDelta /= nDelta;
255 
256  if (debug)
257  {
258  Pout<< "bool layerAdditionRemoval::changeTopology() const "
259  << " for object " << name() << " : " << nl
260  << "Layer thickness: min: " << minDelta
261  << " max: " << maxDelta << " avg: " << avgDelta
262  << " old thickness: " << oldLayerThickness_ << nl
263  << "Removal threshold: " << minLayerThickness_
264  << " addition threshold: " << maxLayerThickness_ << endl;
265  }
266 
267  bool topologicalChange = false;
268 
269  // If the thickness is decreasing and crosses the min thickness,
270  // trigger removal
271  if (oldLayerThickness_ < 0)
272  {
273  if (debug)
274  {
275  Pout<< "First step. No addition/removal" << endl;
276  }
277 
278  // No topological changes allowed before first mesh motion
279  oldLayerThickness_ = avgDelta;
280 
281  topologicalChange = false;
282  }
283  else if (avgDelta < oldLayerThickness_)
284  {
285  // Layers moving towards removal
286  if (minDelta < minLayerThickness_)
287  {
288  // Check layer pairing
289  if (setLayerPairing())
290  {
291  // A mesh layer detected. Check that collapse is valid
292  if (validCollapse())
293  {
294  // At this point, info about moving the old mesh
295  // in a way to collapse the cells in the removed
296  // layer is available. Not sure what to do with
297  // it.
298 
299  if (debug)
300  {
301  Pout<< "bool layerAdditionRemoval::changeTopology() "
302  << " const for object " << name() << " : "
303  << "Triggering layer removal" << endl;
304  }
305 
306  triggerRemoval_ = mesh.time().timeIndex();
307 
308  // Old thickness looses meaning.
309  // Set it up to indicate layer removal
310  oldLayerThickness_ = GREAT;
311 
312  topologicalChange = true;
313  }
314  else
315  {
316  // No removal, clear addressing
317  clearAddressing();
318  }
319  }
320  }
321  else
322  {
323  oldLayerThickness_ = avgDelta;
324  }
325  }
326  else
327  {
328  // Layers moving towards addition
329  if (maxDelta > maxLayerThickness_)
330  {
331  if (debug)
332  {
333  Pout<< "bool layerAdditionRemoval::changeTopology() const "
334  << " for object " << name() << " : "
335  << "Triggering layer addition" << endl;
336  }
337 
338  triggerAddition_ = mesh.time().timeIndex();
339 
340  // Old thickness looses meaning.
341  // Set it up to indicate layer removal
342  oldLayerThickness_ = 0;
343 
344  topologicalChange = true;
345  }
346  else
347  {
348  oldLayerThickness_ = avgDelta;
349  }
350  }
351 
352  return topologicalChange;
353 }
354 
355 
357 {
358  // Insert the layer addition/removal instructions
359  // into the topological change
360 
361  if (triggerRemoval_ == topoChanger().mesh().time().timeIndex())
362  {
363  removeCellLayer(ref);
364 
365  // Clear addressing. This also resets the addition/removal data
366  if (debug)
367  {
368  Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange&) "
369  << "for object " << name() << " : "
370  << "Clearing addressing after layer removal" << endl;
371  }
372 
373  triggerRemoval_ = -1;
374  clearAddressing();
375  }
376 
377  if (triggerAddition_ == topoChanger().mesh().time().timeIndex())
378  {
379  addCellLayer(ref);
380 
381  // Clear addressing. This also resets the addition/removal data
382  if (debug)
383  {
384  Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange&) "
385  << "for object " << name() << " : "
386  << "Clearing addressing after layer addition" << endl;
387  }
388 
389  triggerAddition_ = -1;
390  clearAddressing();
391  }
392 }
393 
394 
396 {
397  if (debug)
398  {
399  Pout<< "layerAdditionRemoval::updateMesh(const mapPolyMesh&) "
400  << "for object " << name() << " : "
401  << "Clearing addressing on external request";
402 
403  if (pointsPairingPtr_ || facesPairingPtr_)
404  {
405  Pout<< "Pointers set." << endl;
406  }
407  else
408  {
409  Pout<< "Pointers not set." << endl;
410  }
411  }
412 
413  // Mesh has changed topologically. Update local topological data
414  faceZoneID_.update(topoChanger().mesh().faceZones());
415 
416  clearAddressing();
417 }
418 
419 
421 {
422  if (t < VSMALL || maxLayerThickness_ < t)
423  {
425  << "Incorrect layer thickness definition."
426  << abort(FatalError);
427  }
428 
429  minLayerThickness_ = t;
430 }
431 
432 
434 {
435  if (t < minLayerThickness_)
436  {
438  << "Incorrect layer thickness definition."
439  << abort(FatalError);
440  }
441 
442  maxLayerThickness_ = t;
443 }
444 
445 
447 {
448  os << nl << type() << nl
449  << name()<< nl
450  << faceZoneID_ << nl
451  << minLayerThickness_ << nl
452  << oldLayerThickness_ << nl
453  << maxLayerThickness_ << nl
454  << thicknessFromVolume_ << endl;
455 }
456 
457 
459 {
460  os << nl << name() << nl << token::BEGIN_BLOCK << nl
461  << " type " << type()
463  << " faceZoneName " << faceZoneID_.name()
465  << " minLayerThickness " << minLayerThickness_
467  << " maxLayerThickness " << maxLayerThickness_
469  << " thicknessFromVolume " << thicknessFromVolume_
471  << " oldLayerThickness " << oldLayerThickness_
473  << " active " << active()
475  << token::END_BLOCK << endl;
476 }
477 
478 
479 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
Foam::maxOp
Definition: ops.H:223
Foam::polyMesh::points
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1069
Foam::layerAdditionRemoval::changeTopology
virtual bool changeTopology() const
Check for topology change.
Definition: layerAdditionRemoval.C:158
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::layerAdditionRemoval::updateMesh
virtual void updateMesh(const mapPolyMesh &)
Force recalculation of locally stored data on topological change.
Definition: layerAdditionRemoval.C:395
Foam::polyMeshModifier::topoChanger
const polyTopoChanger & topoChanger() const
Return reference to morph engine.
Definition: polyMeshModifier.C:63
Foam::minOp
Definition: ops.H:224
Foam::polyTopoChanger
List of mesh modifiers defining the mesh dynamics.
Definition: polyTopoChanger.H:62
polyTopoChanger.H
polyTopoChange.H
Foam::primitiveMesh::cells
const cellList & cells() const
Definition: primitiveMeshCells.C:138
Foam::polyTopoChange
Direct mesh changes based on v1.3 polyTopoChange syntax.
Definition: polyTopoChange.H:99
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:63
Foam::layerAdditionRemoval::setRefinement
virtual void setRefinement(polyTopoChange &) const
Insert the layer addition/removal instructions.
Definition: layerAdditionRemoval.C:356
Foam::Map< label >
primitiveMesh.H
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:107
ref
rDeltaT ref()
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
polyMesh.H
layerAdditionRemoval.H
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::layerAdditionRemoval::setMaxLayerThickness
void setMaxLayerThickness(const scalar t) const
Set max layer thickness which triggers removal.
Definition: layerAdditionRemoval.C:433
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::TimeState::timeIndex
label timeIndex() const noexcept
Return current time index.
Definition: TimeStateI.H:37
Foam::Field< scalar >
Foam::DynamicID::name
const wordRe & name() const noexcept
The selector name.
Definition: DynamicID.H:111
Foam::faceZone
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:64
Foam::layerAdditionRemoval::setMinLayerThickness
void setMinLayerThickness(const scalar t) const
Set min layer thickness which triggers removal.
Definition: layerAdditionRemoval.C:420
Foam::cell::edges
edgeList edges(const faceUList &meshFaces) const
Return cell edges.
Definition: cell.C:111
Foam::polyMesh::faceZones
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:486
Foam::token::END_STATEMENT
End entry [isseparator].
Definition: token.H:154
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::token::END_BLOCK
End block [isseparator].
Definition: token.H:160
Foam::dictionary::lookup
ITstream & lookup(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.C:386
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::primitiveMesh::cellVolumes
const scalarField & cellVolumes() const
Definition: primitiveMeshCellCentresAndVols.C:96
Foam::token::BEGIN_BLOCK
Begin block [isseparator].
Definition: token.H:159
Foam::polyMeshModifier
Virtual base class for mesh modifiers.
Definition: polyMeshModifier.H:68
Foam::polyMeshModifier::name
const word & name() const
Return name of this modifier.
Definition: polyMeshModifier.H:150
Time.H
Foam::faceZone::masterCells
const labelList & masterCells() const
Definition: faceZone.C:389
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::polyTopoChanger::mesh
const polyMesh & mesh() const
Return the mesh reference.
Definition: polyTopoChanger.H:111
Foam::List< label >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::DynamicID::active
bool active() const noexcept
Has the zone been found.
Definition: DynamicID.H:129
Foam::mapPolyMesh
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:161
Foam::layerAdditionRemoval::write
virtual void write(Ostream &) const
Write.
Definition: layerAdditionRemoval.C:446
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::fvMesh::time
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:280
timeIndex
label timeIndex
Definition: getTimeIndex.H:30
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:148
Foam::layerAdditionRemoval::writeDict
virtual void writeDict(Ostream &) const
Write dictionary.
Definition: layerAdditionRemoval.C:458
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54
Foam::DynamicID::index
label index() const
The index of the first matching items, -1 if no matches.
Definition: DynamicID.H:123
Foam::primitiveMesh::faceAreas
const vectorField & faceAreas() const
Definition: primitiveMeshFaceCentresAndAreas.C:89