1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
25 Cell layer addition/removal mesh modifier
27 \*---------------------------------------------------------------------------*/
29 #include "layerAdditionRemoval.H"
30 #include "polyTopoChanger.H"
33 #include "primitiveMesh.H"
34 #include "polyTopoChange.H"
35 #include "addToRunTimeSelectionTable.H"
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
41 defineTypeNameAndDebug(layerAdditionRemoval, 0);
42 addToRunTimeSelectionTable
51 const Foam::scalar Foam::layerAdditionRemoval::addDelta_ = 0.3;
52 const Foam::scalar Foam::layerAdditionRemoval::removeDelta_ = 0.1;
55 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
57 void Foam::layerAdditionRemoval::checkDefinition()
59 if (!faceZoneID_.active())
63 "void Foam::layerAdditionRemoval::checkDefinition()"
64 ) << "Master face zone named " << faceZoneID_.name()
65 << " cannot be found."
71 minLayerThickness_ < VSMALL
72 || maxLayerThickness_ < minLayerThickness_
77 "void Foam::layerAdditionRemoval::checkDefinition()"
78 ) << "Incorrect layer thickness definition."
82 if (topoChanger().mesh().faceZones()[faceZoneID_.index()].empty())
86 "void Foam::layerAdditionRemoval::checkDefinition()"
87 ) << "Face extrusion zone contains no faces. "
88 << " Please check your mesh definition."
94 Pout<< "Cell layer addition/removal object " << name() << " :" << nl
95 << " faceZoneID: " << faceZoneID_ << endl;
99 Foam::scalar Foam::layerAdditionRemoval::readOldThickness
101 const dictionary& dict
104 return dict.lookupOrDefault("oldLayerThickness", -1.0);
108 void Foam::layerAdditionRemoval::clearAddressing() const
110 // Layer removal data
111 deleteDemandDrivenData(pointsPairingPtr_);
112 deleteDemandDrivenData(facesPairingPtr_);
116 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
118 // Construct from components
119 Foam::layerAdditionRemoval::layerAdditionRemoval
123 const polyTopoChanger& mme,
124 const word& zoneName,
125 const scalar minThickness,
126 const scalar maxThickness
129 polyMeshModifier(name, index, mme, true),
130 faceZoneID_(zoneName, mme.mesh().faceZones()),
131 minLayerThickness_(minThickness),
132 maxLayerThickness_(maxThickness),
133 oldLayerThickness_(-1.0),
134 pointsPairingPtr_(NULL),
135 facesPairingPtr_(NULL),
143 // Construct from dictionary
144 Foam::layerAdditionRemoval::layerAdditionRemoval
147 const dictionary& dict,
149 const polyTopoChanger& mme
152 polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
153 faceZoneID_(dict.lookup("faceZoneName"), mme.mesh().faceZones()),
154 minLayerThickness_(readScalar(dict.lookup("minLayerThickness"))),
155 maxLayerThickness_(readScalar(dict.lookup("maxLayerThickness"))),
156 oldLayerThickness_(readOldThickness(dict)),
157 pointsPairingPtr_(NULL),
158 facesPairingPtr_(NULL),
166 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
168 Foam::layerAdditionRemoval::~layerAdditionRemoval()
174 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
176 bool Foam::layerAdditionRemoval::changeTopology() const
178 // Protect from multiple calculation in the same time-step
179 if (triggerRemoval_ > -1 || triggerAddition_ > -1)
184 // Go through all the cells in the master layer and calculate
185 // approximate layer thickness as the ratio of the cell volume and
186 // face area in the face zone.
188 // When the max thickness exceeds the threshold, trigger refinement.
190 // When the min thickness falls below the threshold, trigger removal.
192 const faceZone& fz = topoChanger().mesh().faceZones()[faceZoneID_.index()];
193 const labelList& mc = fz.masterCells();
195 const scalarField& V = topoChanger().mesh().cellVolumes();
196 const vectorField& S = topoChanger().mesh().faceAreas();
198 if (min(V) < -VSMALL)
200 FatalErrorIn("bool layerAdditionRemoval::changeTopology() const")
201 << "negative cell volume. Error in mesh motion before "
202 << "topological change.\n V: " << V
203 << abort(FatalError);
207 scalar minDelta = GREAT;
212 scalar curDelta = V[mc[faceI]]/mag(S[fz[faceI]]);
213 avgDelta += curDelta;
214 minDelta = min(minDelta, curDelta);
215 maxDelta = max(maxDelta, curDelta);
218 avgDelta /= fz.size();
220 ////MJ Alternative thickness determination
222 // // Edges on layer.
223 // const Map<label>& zoneMeshPointMap = fz().meshPointMap();
227 // // Edges with only one point on zone
228 // const polyMesh& mesh = topoChanger().mesh();
232 // const cell& cFaces = mesh.cells()[mc[faceI]];
233 // const edgeList cellEdges(cFaces.edges(mesh.faces()));
235 // forAll(cellEdges, i)
237 // const edge& e = cellEdges[i];
239 // if (zoneMeshPointMap.found(e[0]))
241 // if (!zoneMeshPointMap.found(e[1]))
243 // scalar curDelta = e.mag(mesh.points());
244 // avgDelta += curDelta;
246 // minDelta = min(minDelta, curDelta);
247 // maxDelta = max(maxDelta, curDelta);
252 // if (zoneMeshPointMap.found(e[1]))
254 // scalar curDelta = e.mag(mesh.points());
255 // avgDelta += curDelta;
257 // minDelta = min(minDelta, curDelta);
258 // maxDelta = max(maxDelta, curDelta);
264 // avgDelta /= nDelta;
269 Pout<< "bool layerAdditionRemoval::changeTopology() const "
270 << " for object " << name() << " : " << nl
271 << "Layer thickness: min: " << minDelta
272 << " max: " << maxDelta << " avg: " << avgDelta
273 << " old thickness: " << oldLayerThickness_ << nl
274 << "Removal threshold: " << minLayerThickness_
275 << " addition threshold: " << maxLayerThickness_ << endl;
278 bool topologicalChange = false;
280 // If the thickness is decreasing and crosses the min thickness,
282 if (oldLayerThickness_ < 0)
286 Pout<< "First step. No addition/removal" << endl;
289 // No topological changes allowed before first mesh motion
291 oldLayerThickness_ = avgDelta;
293 topologicalChange = false;
295 else if (avgDelta < oldLayerThickness_)
297 // Layers moving towards removal
298 if (minDelta < minLayerThickness_)
300 // Check layer pairing
301 if (setLayerPairing())
303 // A mesh layer detected. Check that collapse is valid
306 // At this point, info about moving the old mesh
307 // in a way to collapse the cells in the removed
308 // layer is available. Not sure what to do with
313 Pout<< "bool layerAdditionRemoval::changeTopology() "
314 << " const for object " << name() << " : "
315 << "Triggering layer removal" << endl;
318 triggerRemoval_ = topoChanger().mesh().time().timeIndex();
320 // Old thickness looses meaning.
321 // Set it up to indicate layer removal
322 oldLayerThickness_ = GREAT;
324 topologicalChange = true;
328 // No removal, clear addressing
335 oldLayerThickness_ = avgDelta;
340 // Layers moving towards addition
341 if (maxDelta > maxLayerThickness_)
345 Pout<< "bool layerAdditionRemoval::changeTopology() const "
346 << " for object " << name() << " : "
347 << "Triggering layer addition" << endl;
350 triggerAddition_ = topoChanger().mesh().time().timeIndex();
352 // Old thickness looses meaning.
353 // Set it up to indicate layer removal
354 oldLayerThickness_ = 0;
356 topologicalChange = true;
360 oldLayerThickness_ = avgDelta;
364 return topologicalChange;
368 void Foam::layerAdditionRemoval::setRefinement(polyTopoChange& ref) const
370 // Insert the layer addition/removal instructions
371 // into the topological change
373 if (triggerRemoval_ == topoChanger().mesh().time().timeIndex())
375 removeCellLayer(ref);
377 // Clear addressing. This also resets the addition/removal data
380 Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
381 << " for object " << name() << " : "
382 << "Clearing addressing after layer removal. " << endl;
385 triggerRemoval_ = -1;
389 if (triggerAddition_ == topoChanger().mesh().time().timeIndex())
393 // Clear addressing. This also resets the addition/removal data
396 Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
397 << " for object " << name() << " : "
398 << "Clearing addressing after layer addition. " << endl;
401 triggerAddition_ = -1;
407 void Foam::layerAdditionRemoval::updateMesh(const mapPolyMesh&)
411 Pout<< "layerAdditionRemoval::updateMesh(const mapPolyMesh&) "
412 << " for object " << name() << " : "
413 << "Clearing addressing on external request. ";
415 if (pointsPairingPtr_ || facesPairingPtr_)
417 Pout<< "Pointers set." << endl;
421 Pout<< "Pointers not set." << endl;
425 // Mesh has changed topologically. Update local topological data
426 faceZoneID_.update(topoChanger().mesh().faceZones());
432 void Foam::layerAdditionRemoval::setMinLayerThickness(const scalar t) const
437 || maxLayerThickness_ < t
442 "void layerAdditionRemoval::setMinLayerThickness("
443 "const scalar t) const"
444 ) << "Incorrect layer thickness definition."
445 << abort(FatalError);
448 minLayerThickness_ = t;
452 void Foam::layerAdditionRemoval::setMaxLayerThickness(const scalar t) const
456 t < minLayerThickness_
461 "void layerAdditionRemoval::setMaxLayerThickness("
462 "const scalar t) const"
463 ) << "Incorrect layer thickness definition."
464 << abort(FatalError);
467 maxLayerThickness_ = t;
471 void Foam::layerAdditionRemoval::write(Ostream& os) const
473 os << nl << type() << nl
476 << minLayerThickness_ << nl
477 << oldLayerThickness_ << nl
478 << maxLayerThickness_ << endl;
482 void Foam::layerAdditionRemoval::writeDict(Ostream& os) const
484 os << nl << name() << nl << token::BEGIN_BLOCK << nl
485 << " type " << type()
486 << token::END_STATEMENT << nl
487 << " faceZoneName " << faceZoneID_.name()
488 << token::END_STATEMENT << nl
489 << " minLayerThickness " << minLayerThickness_
490 << token::END_STATEMENT << nl
491 << " maxLayerThickness " << maxLayerThickness_
492 << token::END_STATEMENT << nl
493 << " oldLayerThickness " << oldLayerThickness_
494 << token::END_STATEMENT << nl
495 << " active " << active()
496 << token::END_STATEMENT << nl
497 << token::END_BLOCK << endl;
501 // ************************************************************************* //