FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

layerAdditionRemoval.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Description
00025     Cell layer addition/removal mesh modifier
00026 
00027 \*---------------------------------------------------------------------------*/
00028 
00029 #include "layerAdditionRemoval.H"
00030 #include <dynamicMesh/polyTopoChanger.H>
00031 #include <OpenFOAM/polyMesh.H>
00032 #include <OpenFOAM/Time.H>
00033 #include <OpenFOAM/primitiveMesh.H>
00034 #include <dynamicMesh/polyTopoChange.H>
00035 #include <OpenFOAM/addToRunTimeSelectionTable.H>
00036 
00037 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00038 
00039 namespace Foam
00040 {
00041     defineTypeNameAndDebug(layerAdditionRemoval, 0);
00042     addToRunTimeSelectionTable
00043     (
00044         polyMeshModifier,
00045         layerAdditionRemoval,
00046         dictionary
00047     );
00048 }
00049 
00050 
00051 const Foam::scalar Foam::layerAdditionRemoval::addDelta_ = 0.3;
00052 const Foam::scalar Foam::layerAdditionRemoval::removeDelta_ = 0.1;
00053 
00054 
00055 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00056 
00057 void Foam::layerAdditionRemoval::checkDefinition()
00058 {
00059     if (!faceZoneID_.active())
00060     {
00061         FatalErrorIn
00062         (
00063             "void Foam::layerAdditionRemoval::checkDefinition()"
00064         )   << "Master face zone named " << faceZoneID_.name()
00065             << " cannot be found."
00066             << abort(FatalError);
00067     }
00068 
00069     if
00070     (
00071         minLayerThickness_ < VSMALL
00072      || maxLayerThickness_ < minLayerThickness_
00073     )
00074     {
00075         FatalErrorIn
00076         (
00077             "void Foam::layerAdditionRemoval::checkDefinition()"
00078         )   << "Incorrect layer thickness definition."
00079             << abort(FatalError);
00080     }
00081 
00082     if (topoChanger().mesh().faceZones()[faceZoneID_.index()].empty())
00083     {
00084         FatalErrorIn
00085         (
00086             "void Foam::layerAdditionRemoval::checkDefinition()"
00087         )   << "Face extrusion zone contains no faces. "
00088             << " Please check your mesh definition."
00089             << abort(FatalError);
00090     }
00091 
00092     if (debug)
00093     {
00094         Pout<< "Cell layer addition/removal object " << name() << " :" << nl
00095             << "    faceZoneID: " << faceZoneID_ << endl;
00096     }
00097 }
00098 
00099 Foam::scalar Foam::layerAdditionRemoval::readOldThickness
00100 (
00101     const dictionary& dict
00102 )
00103 {
00104     return dict.lookupOrDefault("oldLayerThickness", -1.0);
00105 }
00106 
00107 
00108 void Foam::layerAdditionRemoval::clearAddressing() const
00109 {
00110     // Layer removal data
00111     deleteDemandDrivenData(pointsPairingPtr_);
00112     deleteDemandDrivenData(facesPairingPtr_);
00113 }
00114 
00115 
00116 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00117 
00118 // Construct from components
00119 Foam::layerAdditionRemoval::layerAdditionRemoval
00120 (
00121     const word& name,
00122     const label index,
00123     const polyTopoChanger& mme,
00124     const word& zoneName,
00125     const scalar minThickness,
00126     const scalar maxThickness
00127 )
00128 :
00129     polyMeshModifier(name, index, mme, true),
00130     faceZoneID_(zoneName, mme.mesh().faceZones()),
00131     minLayerThickness_(minThickness),
00132     maxLayerThickness_(maxThickness),
00133     oldLayerThickness_(-1.0),
00134     pointsPairingPtr_(NULL),
00135     facesPairingPtr_(NULL),
00136     triggerRemoval_(-1),
00137     triggerAddition_(-1)
00138 {
00139     checkDefinition();
00140 }
00141 
00142 
00143 // Construct from dictionary
00144 Foam::layerAdditionRemoval::layerAdditionRemoval
00145 (
00146     const word& name,
00147     const dictionary& dict,
00148     const label index,
00149     const polyTopoChanger& mme
00150 )
00151 :
00152     polyMeshModifier(name, index, mme, Switch(dict.lookup("active"))),
00153     faceZoneID_(dict.lookup("faceZoneName"), mme.mesh().faceZones()),
00154     minLayerThickness_(readScalar(dict.lookup("minLayerThickness"))),
00155     maxLayerThickness_(readScalar(dict.lookup("maxLayerThickness"))),
00156     oldLayerThickness_(readOldThickness(dict)),
00157     pointsPairingPtr_(NULL),
00158     facesPairingPtr_(NULL),
00159     triggerRemoval_(-1),
00160     triggerAddition_(-1)
00161 {
00162     checkDefinition();
00163 }
00164 
00165 
00166 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00167 
00168 Foam::layerAdditionRemoval::~layerAdditionRemoval()
00169 {
00170     clearAddressing();
00171 }
00172 
00173 
00174 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00175 
00176 bool Foam::layerAdditionRemoval::changeTopology() const
00177 {
00178     // Protect from multiple calculation in the same time-step
00179     if (triggerRemoval_ > -1 || triggerAddition_ > -1)
00180     {
00181         return true;
00182     }
00183 
00184     // Go through all the cells in the master layer and calculate
00185     // approximate layer thickness as the ratio of the cell volume and
00186     // face area in the face zone.
00187     // Layer addition:
00188     //     When the max thickness exceeds the threshold, trigger refinement.
00189     // Layer removal:
00190     //     When the min thickness falls below the threshold, trigger removal.
00191 
00192     const faceZone& fz = topoChanger().mesh().faceZones()[faceZoneID_.index()];
00193     const labelList& mc = fz.masterCells();
00194 
00195     const scalarField& V = topoChanger().mesh().cellVolumes();
00196     const vectorField& S = topoChanger().mesh().faceAreas();
00197 
00198     if (min(V) < -VSMALL)
00199     {
00200         FatalErrorIn("bool layerAdditionRemoval::changeTopology() const")
00201             << "negative cell volume. Error in mesh motion before "
00202             << "topological change.\n V: " << V
00203             << abort(FatalError);
00204     }
00205 
00206     scalar avgDelta = 0;
00207     scalar minDelta = GREAT;
00208     scalar maxDelta = 0;
00209 
00210     forAll (fz, faceI)
00211     {
00212         scalar curDelta = V[mc[faceI]]/mag(S[fz[faceI]]);
00213         avgDelta += curDelta;
00214         minDelta = min(minDelta, curDelta);
00215         maxDelta = max(maxDelta, curDelta);
00216     }
00217 
00218     avgDelta /= fz.size();
00219 
00221     //{
00222     //    // Edges on layer.
00223     //    const Map<label>& zoneMeshPointMap = fz().meshPointMap();
00224     //
00225     //    label nDelta = 0;
00226     //
00227     //    // Edges with only one point on zone
00228     //    const polyMesh& mesh = topoChanger().mesh();
00229     //
00230     //    forAll(mc, faceI)
00231     //    {
00232     //        const cell& cFaces = mesh.cells()[mc[faceI]];
00233     //        const edgeList cellEdges(cFaces.edges(mesh.faces()));
00234     //
00235     //        forAll(cellEdges, i)
00236     //        {
00237     //            const edge& e = cellEdges[i];
00238     //
00239     //            if (zoneMeshPointMap.found(e[0]))
00240     //            {
00241     //                if (!zoneMeshPointMap.found(e[1]))
00242     //                {
00243     //                    scalar curDelta = e.mag(mesh.points());
00244     //                    avgDelta += curDelta;
00245     //                    nDelta++;
00246     //                    minDelta = min(minDelta, curDelta);
00247     //                    maxDelta = max(maxDelta, curDelta);
00248     //                }
00249     //            }
00250     //            else
00251     //            {
00252     //                if (zoneMeshPointMap.found(e[1]))
00253     //                {
00254     //                    scalar curDelta = e.mag(mesh.points());
00255     //                    avgDelta += curDelta;
00256     //                    nDelta++;
00257     //                    minDelta = min(minDelta, curDelta);
00258     //                    maxDelta = max(maxDelta, curDelta);
00259     //                }
00260     //            }
00261     //        }
00262     //    }
00263     //
00264     //    avgDelta /= nDelta;
00265     //}
00266 
00267     if (debug)
00268     {
00269         Pout<< "bool layerAdditionRemoval::changeTopology() const "
00270             << " for object " << name() << " : " << nl
00271             << "Layer thickness: min: " << minDelta
00272             << " max: " << maxDelta << " avg: " << avgDelta
00273             << " old thickness: " << oldLayerThickness_ << nl
00274             << "Removal threshold: " << minLayerThickness_
00275             << " addition threshold: " << maxLayerThickness_ << endl;
00276     }
00277 
00278     bool topologicalChange = false;
00279 
00280     // If the thickness is decreasing and crosses the min thickness,
00281     // trigger removal
00282     if (oldLayerThickness_ < 0)
00283     {
00284         if (debug)
00285         {
00286             Pout << "First step. No addition/removal" << endl;
00287         }
00288 
00289         // No topological changes allowed before first mesh motion
00290         //
00291         oldLayerThickness_ = avgDelta;
00292 
00293         topologicalChange = false;
00294     }
00295     else if (avgDelta < oldLayerThickness_)
00296     {
00297         // Layers moving towards removal
00298         if (minDelta < minLayerThickness_)
00299         {
00300             // Check layer pairing
00301             if (setLayerPairing())
00302             {
00303                 // A mesh layer detected.  Check that collapse is valid
00304                 if (validCollapse())
00305                 {
00306                     // At this point, info about moving the old mesh
00307                     // in a way to collapse the cells in the removed
00308                     // layer is available.  Not sure what to do with
00309                     // it.
00310 
00311                     if (debug)
00312                     {
00313                         Pout<< "bool layerAdditionRemoval::changeTopology() "
00314                             << " const for object " << name() << " : "
00315                             << "Triggering layer removal" << endl;
00316                     }
00317 
00318                     triggerRemoval_ = topoChanger().mesh().time().timeIndex();
00319 
00320                     // Old thickness looses meaning.
00321                     // Set it up to indicate layer removal
00322                     oldLayerThickness_ = GREAT;
00323 
00324                     topologicalChange = true;
00325                 }
00326                 else
00327                 {
00328                     // No removal, clear addressing
00329                     clearAddressing();
00330                 }
00331             }
00332         }
00333         else
00334         {
00335             oldLayerThickness_ = avgDelta;
00336         }
00337     }
00338     else
00339     {
00340         // Layers moving towards addition
00341         if (maxDelta > maxLayerThickness_)
00342         {
00343             if (debug)
00344             {
00345                 Pout<< "bool layerAdditionRemoval::changeTopology() const "
00346                     << " for object " << name() << " : "
00347                     << "Triggering layer addition" << endl;
00348             }
00349 
00350             triggerAddition_ = topoChanger().mesh().time().timeIndex();
00351 
00352             // Old thickness looses meaning.
00353             // Set it up to indicate layer removal
00354             oldLayerThickness_ = 0;
00355 
00356             topologicalChange = true;
00357         }
00358         else
00359         {
00360             oldLayerThickness_ = avgDelta;
00361         }
00362     }
00363 
00364     return topologicalChange;
00365 }
00366 
00367 
00368 void Foam::layerAdditionRemoval::setRefinement(polyTopoChange& ref) const
00369 {
00370     // Insert the layer addition/removal instructions
00371     // into the topological change
00372 
00373     if (triggerRemoval_ == topoChanger().mesh().time().timeIndex())
00374     {
00375         removeCellLayer(ref);
00376 
00377         // Clear addressing.  This also resets the addition/removal data
00378         if (debug)
00379         {
00380             Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
00381                 << " for object " << name() << " : "
00382                 << "Clearing addressing after layer removal. " << endl;
00383         }
00384 
00385         triggerRemoval_ = -1;
00386         clearAddressing();
00387     }
00388 
00389     if (triggerAddition_ == topoChanger().mesh().time().timeIndex())
00390     {
00391         addCellLayer(ref);
00392 
00393         // Clear addressing.  This also resets the addition/removal data
00394         if (debug)
00395         {
00396             Pout<< "layerAdditionRemoval::setRefinement(polyTopoChange& ref) "
00397                 << " for object " << name() << " : "
00398                 << "Clearing addressing after layer addition. " << endl;
00399         }
00400 
00401         triggerAddition_ = -1;
00402         clearAddressing();
00403     }
00404 }
00405 
00406 
00407 void Foam::layerAdditionRemoval::updateMesh(const mapPolyMesh&)
00408 {
00409     if (debug)
00410     {
00411         Pout<< "layerAdditionRemoval::updateMesh(const mapPolyMesh&) "
00412             << " for object " << name() << " : "
00413             << "Clearing addressing on external request. ";
00414 
00415         if (pointsPairingPtr_ || facesPairingPtr_)
00416         {
00417             Pout << "Pointers set." << endl;
00418         }
00419         else
00420         {
00421             Pout << "Pointers not set." << endl;
00422         }
00423     }
00424 
00425     // Mesh has changed topologically.  Update local topological data
00426     faceZoneID_.update(topoChanger().mesh().faceZones());
00427 
00428     clearAddressing();
00429 }
00430 
00431 
00432 void Foam::layerAdditionRemoval::setMinLayerThickness(const scalar t) const
00433 {
00434     if
00435     (
00436         t < VSMALL
00437      || maxLayerThickness_ < t
00438     )
00439     {
00440         FatalErrorIn
00441         (
00442             "void layerAdditionRemoval::setMinLayerThickness("
00443             "const scalar t) const"
00444         )   << "Incorrect layer thickness definition."
00445             << abort(FatalError);
00446     }
00447 
00448     minLayerThickness_ = t;
00449 }
00450 
00451 
00452 void Foam::layerAdditionRemoval::setMaxLayerThickness(const scalar t) const
00453 {
00454     if
00455     (
00456         t < minLayerThickness_
00457     )
00458     {
00459         FatalErrorIn
00460         (
00461             "void layerAdditionRemoval::setMaxLayerThickness("
00462             "const scalar t) const"
00463         )   << "Incorrect layer thickness definition."
00464             << abort(FatalError);
00465     }
00466 
00467     maxLayerThickness_ = t;
00468 }
00469 
00470 
00471 void Foam::layerAdditionRemoval::write(Ostream& os) const
00472 {
00473     os  << nl << type() << nl
00474         << name()<< nl
00475         << faceZoneID_ << nl
00476         << minLayerThickness_ << nl
00477         << oldLayerThickness_ << nl
00478         << maxLayerThickness_ << endl;
00479 }
00480 
00481 
00482 void Foam::layerAdditionRemoval::writeDict(Ostream& os) const
00483 {
00484     os  << nl << name() << nl << token::BEGIN_BLOCK << nl
00485         << "    type " << type()
00486         << token::END_STATEMENT << nl
00487         << "    faceZoneName " << faceZoneID_.name()
00488         << token::END_STATEMENT << nl
00489         << "    minLayerThickness " << minLayerThickness_
00490         << token::END_STATEMENT << nl
00491         << "    maxLayerThickness " << maxLayerThickness_
00492         << token::END_STATEMENT << nl
00493         << "    oldLayerThickness " << oldLayerThickness_
00494         << token::END_STATEMENT << nl
00495         << "    active " << active()
00496         << token::END_STATEMENT << nl
00497         << token::END_BLOCK << endl;
00498 }
00499 
00500 
00501 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines