1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 Cell layer addition/removal mesh modifier
28 \*---------------------------------------------------------------------------*/
30 #include "layerAdditionRemoval.H"
31 #include "polyTopoChanger.H"
34 #include "primitiveMesh.H"
35 #include "polyTopoChange.H"
36 #include "addToRunTimeSelectionTable.H"
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 defineTypeNameAndDebug(layerAdditionRemoval, 0);
43 addToRunTimeSelectionTable
52 const Foam::scalar Foam::layerAdditionRemoval::addDelta_ = 0.3;
53 const Foam::scalar Foam::layerAdditionRemoval::removeDelta_ = 0.1;
56 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
58 void Foam::layerAdditionRemoval::checkDefinition()
60 if (!faceZoneID_.active())
64 "void Foam::layerAdditionRemoval::checkDefinition()"
65 ) << "Master face zone named " << faceZoneID_.name()
66 << " cannot be found."
72 minLayerThickness_ < VSMALL
73 || maxLayerThickness_ < minLayerThickness_
78 "void Foam::layerAdditionRemoval::checkDefinition()"
79 ) << "Incorrect layer thickness definition."
83 if (topoChanger().mesh().faceZones()[faceZoneID_.index()].size() == 0)
87 "void Foam::layerAdditionRemoval::checkDefinition()"
88 ) << "Face extrusion zone contains no faces. Please check your "
95 Pout<< "Cell layer addition/removal object " << name() << " :" << nl
96 << " faceZoneID: " << faceZoneID_ << endl;
100 Foam::scalar Foam::layerAdditionRemoval::readOldThickness
102 const dictionary& dict
105 if (dict.found("oldLayerThickness"))
107 return readScalar(dict.lookup("oldLayerThickness"));
116 void Foam::layerAdditionRemoval::clearAddressing() const
118 // Layer removal data
119 deleteDemandDrivenData(pointsPairingPtr_);
120 deleteDemandDrivenData(facesPairingPtr_);
124 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
126 // Construct from components
127 Foam::layerAdditionRemoval::layerAdditionRemoval
131 const polyTopoChanger& mme,
132 const word& zoneName,
133 const scalar minThickness,
134 const scalar maxThickness
137 polyMeshModifier(name, index, mme, true),
138 faceZoneID_(zoneName, mme.mesh().faceZones()),
139 minLayerThickness_(minThickness),
140 maxLayerThickness_(maxThickness),
141 oldLayerThickness_(-1.0),
142 pointsPairingPtr_(NULL),
143 facesPairingPtr_(NULL),
151 // Construct from dictionary
152 Foam::layerAdditionRemoval::layerAdditionRemoval
155 const dictionary& dict,
157 const polyTopoChanger& mme
160 polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
161 faceZoneID_(dict.lookup("faceZoneName"), mme.mesh().faceZones()),
162 minLayerThickness_(readScalar(dict.lookup("minLayerThickness"))),
163 maxLayerThickness_(readScalar(dict.lookup("maxLayerThickness"))),
164 oldLayerThickness_(readOldThickness(dict)),
165 pointsPairingPtr_(NULL),
166 facesPairingPtr_(NULL),
174 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
176 Foam::layerAdditionRemoval::~layerAdditionRemoval()
182 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
184 bool Foam::layerAdditionRemoval::changeTopology() const
186 // Protect from multiple calculation in the same time-step
187 if (triggerRemoval_ > -1 || triggerAddition_ > -1)
192 // Go through all the cells in the master layer and calculate
193 // approximate layer thickness as the ratio of the cell volume and
194 // face area in the face zone.
196 // When the max thickness exceeds the threshold, trigger refinement.
198 // When the min thickness falls below the threshold, trigger removal.
200 const faceZone& fz = topoChanger().mesh().faceZones()[faceZoneID_.index()];
201 const labelList& mc = fz.masterCells();
203 const scalarField& V = topoChanger().mesh().cellVolumes();
204 const vectorField& S = topoChanger().mesh().faceAreas();
206 if (min(V) < -VSMALL)
208 FatalErrorIn("bool layerAdditionRemoval::changeTopology() const")
209 << "negative cell volume. Error in mesh motion before "
210 << "topological change."
211 << abort(FatalError);
215 scalar minDelta = GREAT;
220 scalar curDelta = V[mc[faceI]]/mag(S[fz[faceI]]);
221 avgDelta += curDelta;
222 minDelta = min(minDelta, curDelta);
223 maxDelta = max(maxDelta, curDelta);
226 avgDelta /= fz.size();
228 ////MJ Alternative thickness determination
230 // // Edges on layer.
231 // const Map<label>& zoneMeshPointMap = fz().meshPointMap();
235 // // Edges with only one point on zone
236 // const polyMesh& mesh = topoChanger().mesh();
240 // const cell& cFaces = mesh.cells()[mc[faceI]];
241 // const edgeList cellEdges(cFaces.edges(mesh.faces()));
243 // forAll(cellEdges, i)
245 // const edge& e = cellEdges[i];
247 // if (zoneMeshPointMap.found(e[0]))
249 // if (!zoneMeshPointMap.found(e[1]))
251 // scalar curDelta = e.mag(mesh.points());
252 // avgDelta += curDelta;
254 // minDelta = min(minDelta, curDelta);
255 // maxDelta = max(maxDelta, curDelta);
260 // if (zoneMeshPointMap.found(e[1]))
262 // scalar curDelta = e.mag(mesh.points());
263 // avgDelta += curDelta;
265 // minDelta = min(minDelta, curDelta);
266 // maxDelta = max(maxDelta, curDelta);
272 // avgDelta /= nDelta;
277 Pout<< "bool layerAdditionRemoval::changeTopology() const "
278 << " for object " << name() << " : " << nl
279 << "Layer thickness: min: " << minDelta
280 << " max: " << maxDelta << " avg: " << avgDelta
281 << " old thickness: " << oldLayerThickness_ << nl
282 << "Removal threshold: " << minLayerThickness_
283 << " addition threshold: " << maxLayerThickness_ << endl;
286 bool topologicalChange = false;
288 // If the thickness is decreasing and crosses the min thickness,
290 if (oldLayerThickness_ < 0)
294 Pout << "First step. No addition/removal" << endl;
297 // No topological changes allowed before first mesh motion
299 oldLayerThickness_ = avgDelta;
301 topologicalChange = false;
303 else if (avgDelta < oldLayerThickness_)
305 // Layers moving towards removal
306 if (minDelta < minLayerThickness_)
308 // Check layer pairing
309 if (setLayerPairing())
311 // A mesh layer detected. Check that collapse is valid
314 // At this point, info about moving the old mesh
315 // in a way to collapse the cells in the removed
316 // layer is available. Not sure what to do with
321 Pout<< "bool layerAdditionRemoval::changeTopology() "
322 << " const for object " << name() << " : "
323 << "Triggering layer removal" << endl;
326 triggerRemoval_ = topoChanger().morphIndex();
328 // Old thickness looses meaning.
329 // Set it up to indicate layer removal
330 oldLayerThickness_ = GREAT;
332 topologicalChange = true;
336 // No removal, clear addressing
343 oldLayerThickness_ = avgDelta;
348 // Layers moving towards addition
349 if (maxDelta > maxLayerThickness_)
353 Pout<< "bool layerAdditionRemoval::changeTopology() const "
354 << " for object " << name() << " : "
355 << "Triggering layer addition" << endl;
358 triggerAddition_ = topoChanger().morphIndex();
360 // Old thickness looses meaning.
361 // Set it up to indicate layer removal
362 oldLayerThickness_ = 0;
364 topologicalChange = true;
368 oldLayerThickness_ = avgDelta;
372 return topologicalChange;
376 void Foam::layerAdditionRemoval::setRefinement(polyTopoChange& ref) const
378 // Insert the layer addition/removal instructions
379 // into the topological change
381 if (triggerRemoval_ == topoChanger().morphIndex())
383 removeCellLayer(ref);
385 // Clear addressing. This also resets the addition/removal data
388 Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
389 << " for object " << name() << " : "
390 << "Clearing addressing after layer removal. " << endl;
393 triggerRemoval_ = -1;
397 if (triggerAddition_ == topoChanger().morphIndex())
401 // Clear addressing. This also resets the addition/removal data
404 Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
405 << " for object " << name() << " : "
406 << "Clearing addressing after layer addition. " << endl;
409 triggerAddition_ = -1;
415 void Foam::layerAdditionRemoval::updateMesh(const mapPolyMesh&)
419 Pout<< "layerAdditionRemoval::updateMesh(const mapPolyMesh&) "
420 << " for object " << name() << " : "
421 << "Clearing addressing on external request. ";
423 if (pointsPairingPtr_ || facesPairingPtr_)
425 Pout << "Pointers set." << endl;
429 Pout << "Pointers not set." << endl;
433 // Mesh has changed topologically. Update local topological data
434 faceZoneID_.update(topoChanger().mesh().faceZones());
440 void Foam::layerAdditionRemoval::setMinLayerThickness(const scalar t) const
445 || maxLayerThickness_ < t
450 "void layerAdditionRemoval::setMinLayerThickness("
451 "const scalar t) const"
452 ) << "Incorrect layer thickness definition."
453 << abort(FatalError);
456 minLayerThickness_ = t;
460 void Foam::layerAdditionRemoval::setMaxLayerThickness(const scalar t) const
462 if (t < minLayerThickness_)
466 "void layerAdditionRemoval::setMaxLayerThickness("
467 "const scalar t) const"
468 ) << "Incorrect layer thickness definition."
469 << abort(FatalError);
472 maxLayerThickness_ = t;
476 void Foam::layerAdditionRemoval::write(Ostream& os) const
478 os << nl << type() << nl
481 << minLayerThickness_ << nl
482 << oldLayerThickness_ << nl
483 << maxLayerThickness_ << endl;
487 void Foam::layerAdditionRemoval::writeDict(Ostream& os) const
489 os << nl << name() << nl << token::BEGIN_BLOCK << nl
490 << " type " << type()
491 << token::END_STATEMENT << nl
492 << " faceZoneName " << faceZoneID_.name()
493 << token::END_STATEMENT << nl
494 << " minLayerThickness " << minLayerThickness_
495 << token::END_STATEMENT << nl
496 << " maxLayerThickness " << maxLayerThickness_
497 << token::END_STATEMENT << nl
498 << " oldLayerThickness " << oldLayerThickness_
499 << token::END_STATEMENT << nl
500 << " active " << active()
501 << token::END_STATEMENT << nl
502 << token::END_BLOCK << endl;
506 // ************************************************************************* //