1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
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 return dict.lookupOrDefault("oldLayerThickness", -1.0);
109 void Foam::layerAdditionRemoval::clearAddressing() const
111 // Layer removal data
112 deleteDemandDrivenData(pointsPairingPtr_);
113 deleteDemandDrivenData(facesPairingPtr_);
117 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
119 // Construct from components
120 Foam::layerAdditionRemoval::layerAdditionRemoval
124 const polyTopoChanger& mme,
125 const word& zoneName,
126 const scalar minThickness,
127 const scalar maxThickness
130 polyMeshModifier(name, index, mme, true),
131 faceZoneID_(zoneName, mme.mesh().faceZones()),
132 minLayerThickness_(minThickness),
133 maxLayerThickness_(maxThickness),
134 oldLayerThickness_(-1.0),
135 pointsPairingPtr_(NULL),
136 facesPairingPtr_(NULL),
144 // Construct from dictionary
145 Foam::layerAdditionRemoval::layerAdditionRemoval
148 const dictionary& dict,
150 const polyTopoChanger& mme
153 polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
154 faceZoneID_(dict.lookup("faceZoneName"), mme.mesh().faceZones()),
155 minLayerThickness_(readScalar(dict.lookup("minLayerThickness"))),
156 maxLayerThickness_(readScalar(dict.lookup("maxLayerThickness"))),
157 oldLayerThickness_(readOldThickness(dict)),
158 pointsPairingPtr_(NULL),
159 facesPairingPtr_(NULL),
167 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
169 Foam::layerAdditionRemoval::~layerAdditionRemoval()
175 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
177 bool Foam::layerAdditionRemoval::changeTopology() const
179 // Protect from multiple calculation in the same time-step
180 if (triggerRemoval_ > -1 || triggerAddition_ > -1)
185 // Go through all the cells in the master layer and calculate
186 // approximate layer thickness as the ratio of the cell volume and
187 // face area in the face zone.
189 // When the max thickness exceeds the threshold, trigger refinement.
191 // When the min thickness falls below the threshold, trigger removal.
193 const faceZone& fz = topoChanger().mesh().faceZones()[faceZoneID_.index()];
194 const labelList& mc = fz.masterCells();
196 const scalarField& V = topoChanger().mesh().cellVolumes();
197 const vectorField& S = topoChanger().mesh().faceAreas();
199 if (min(V) < -VSMALL)
201 FatalErrorIn("bool layerAdditionRemoval::changeTopology() const")
202 << "negative cell volume. Error in mesh motion before "
203 << "topological change.\n V: " << V
204 << abort(FatalError);
208 scalar minDelta = GREAT;
213 scalar curDelta = V[mc[faceI]]/mag(S[fz[faceI]]);
214 avgDelta += curDelta;
215 minDelta = min(minDelta, curDelta);
216 maxDelta = max(maxDelta, curDelta);
219 avgDelta /= fz.size();
221 ////MJ Alternative thickness determination
223 // // Edges on layer.
224 // const Map<label>& zoneMeshPointMap = fz().meshPointMap();
228 // // Edges with only one point on zone
229 // const polyMesh& mesh = topoChanger().mesh();
233 // const cell& cFaces = mesh.cells()[mc[faceI]];
234 // const edgeList cellEdges(cFaces.edges(mesh.faces()));
236 // forAll(cellEdges, i)
238 // const edge& e = cellEdges[i];
240 // if (zoneMeshPointMap.found(e[0]))
242 // if (!zoneMeshPointMap.found(e[1]))
244 // scalar curDelta = e.mag(mesh.points());
245 // avgDelta += curDelta;
247 // minDelta = min(minDelta, curDelta);
248 // maxDelta = max(maxDelta, curDelta);
253 // if (zoneMeshPointMap.found(e[1]))
255 // scalar curDelta = e.mag(mesh.points());
256 // avgDelta += curDelta;
258 // minDelta = min(minDelta, curDelta);
259 // maxDelta = max(maxDelta, curDelta);
265 // avgDelta /= nDelta;
270 Pout<< "bool layerAdditionRemoval::changeTopology() const "
271 << " for object " << name() << " : " << nl
272 << "Layer thickness: min: " << minDelta
273 << " max: " << maxDelta << " avg: " << avgDelta
274 << " old thickness: " << oldLayerThickness_ << nl
275 << "Removal threshold: " << minLayerThickness_
276 << " addition threshold: " << maxLayerThickness_ << endl;
279 bool topologicalChange = false;
281 // If the thickness is decreasing and crosses the min thickness,
283 if (oldLayerThickness_ < 0)
287 Pout << "First step. No addition/removal" << endl;
290 // No topological changes allowed before first mesh motion
292 oldLayerThickness_ = avgDelta;
294 topologicalChange = false;
296 else if (avgDelta < oldLayerThickness_)
298 // Layers moving towards removal
299 if (minDelta < minLayerThickness_)
301 // Check layer pairing
302 if (setLayerPairing())
304 // A mesh layer detected. Check that collapse is valid
307 // At this point, info about moving the old mesh
308 // in a way to collapse the cells in the removed
309 // layer is available. Not sure what to do with
314 Pout<< "bool layerAdditionRemoval::changeTopology() "
315 << " const for object " << name() << " : "
316 << "Triggering layer removal" << endl;
319 triggerRemoval_ = topoChanger().mesh().time().timeIndex();
321 // Old thickness looses meaning.
322 // Set it up to indicate layer removal
323 oldLayerThickness_ = GREAT;
325 topologicalChange = true;
329 // No removal, clear addressing
336 oldLayerThickness_ = avgDelta;
341 // Layers moving towards addition
342 if (maxDelta > maxLayerThickness_)
346 Pout<< "bool layerAdditionRemoval::changeTopology() const "
347 << " for object " << name() << " : "
348 << "Triggering layer addition" << endl;
351 triggerAddition_ = topoChanger().mesh().time().timeIndex();
353 // Old thickness looses meaning.
354 // Set it up to indicate layer removal
355 oldLayerThickness_ = 0;
357 topologicalChange = true;
361 oldLayerThickness_ = avgDelta;
365 return topologicalChange;
369 void Foam::layerAdditionRemoval::setRefinement(polyTopoChange& ref) const
371 // Insert the layer addition/removal instructions
372 // into the topological change
374 if (triggerRemoval_ == topoChanger().mesh().time().timeIndex())
376 removeCellLayer(ref);
378 // Clear addressing. This also resets the addition/removal data
381 Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
382 << " for object " << name() << " : "
383 << "Clearing addressing after layer removal. " << endl;
386 triggerRemoval_ = -1;
390 if (triggerAddition_ == topoChanger().mesh().time().timeIndex())
394 // Clear addressing. This also resets the addition/removal data
397 Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
398 << " for object " << name() << " : "
399 << "Clearing addressing after layer addition. " << endl;
402 triggerAddition_ = -1;
408 void Foam::layerAdditionRemoval::updateMesh(const mapPolyMesh&)
412 Pout<< "layerAdditionRemoval::updateMesh(const mapPolyMesh&) "
413 << " for object " << name() << " : "
414 << "Clearing addressing on external request. ";
416 if (pointsPairingPtr_ || facesPairingPtr_)
418 Pout << "Pointers set." << endl;
422 Pout << "Pointers not set." << endl;
426 // Mesh has changed topologically. Update local topological data
427 faceZoneID_.update(topoChanger().mesh().faceZones());
433 void Foam::layerAdditionRemoval::setMinLayerThickness(const scalar t) const
438 || maxLayerThickness_ < t
443 "void layerAdditionRemoval::setMinLayerThickness("
444 "const scalar t) const"
445 ) << "Incorrect layer thickness definition."
446 << abort(FatalError);
449 minLayerThickness_ = t;
453 void Foam::layerAdditionRemoval::setMaxLayerThickness(const scalar t) const
457 t < minLayerThickness_
462 "void layerAdditionRemoval::setMaxLayerThickness("
463 "const scalar t) const"
464 ) << "Incorrect layer thickness definition."
465 << abort(FatalError);
468 maxLayerThickness_ = t;
472 void Foam::layerAdditionRemoval::write(Ostream& os) const
474 os << nl << type() << nl
477 << minLayerThickness_ << nl
478 << oldLayerThickness_ << nl
479 << maxLayerThickness_ << endl;
483 void Foam::layerAdditionRemoval::writeDict(Ostream& os) const
485 os << nl << name() << nl << token::BEGIN_BLOCK << nl
486 << " type " << type()
487 << token::END_STATEMENT << nl
488 << " faceZoneName " << faceZoneID_.name()
489 << token::END_STATEMENT << nl
490 << " minLayerThickness " << minLayerThickness_
491 << token::END_STATEMENT << nl
492 << " maxLayerThickness " << maxLayerThickness_
493 << token::END_STATEMENT << nl
494 << " oldLayerThickness " << oldLayerThickness_
495 << token::END_STATEMENT << nl
496 << " active " << active()
497 << token::END_STATEMENT << nl
498 << token::END_BLOCK << endl;
502 // ************************************************************************* //