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

refinementLevel.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 Application
00025     refinementLevel
00026 
00027 Description
00028     Tries to figure out what the refinement level is on refined cartesian
00029     meshes. Run BEFORE snapping.
00030 
00031     Writes
00032     - volScalarField 'refinementLevel' with current refinement level.
00033     - cellSet 'refCells' which are the cells that need to be refined to satisfy
00034       2:1 refinement.
00035 
00036     Works by dividing cells into volume bins.
00037 
00038 Usage
00039 
00040     - refinementLevel [OPTIONS]
00041 
00042     @param -readLevel \n
00043     Read reference refinementLevel file.
00044 
00045     @param -case <dir>\n
00046     Case directory.
00047 
00048     @param -parallel \n
00049     Run in parallel.
00050 
00051     @param -help \n
00052     Display help message.
00053 
00054     @param -doc \n
00055     Display Doxygen API documentation page for this application.
00056 
00057     @param -srcDoc \n
00058     Display Doxygen source documentation page for this application.
00059 
00060 \*---------------------------------------------------------------------------*/
00061 
00062 #include <OpenFOAM/argList.H>
00063 #include <OpenFOAM/Time.H>
00064 #include <OpenFOAM/polyMesh.H>
00065 #include <meshTools/cellSet.H>
00066 #include <OpenFOAM/SortableList.H>
00067 #include <OpenFOAM/labelIOList.H>
00068 #include <finiteVolume/fvMesh.H>
00069 #include <finiteVolume/volFields.H>
00070 
00071 using namespace Foam;
00072 
00073 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00074 
00075 // Return true if any cells had to be split to keep a difference between
00076 // neighbouring refinement levels < limitDiff. Puts cells into refCells and
00077 // update refLevel to account for refinement.
00078 bool limitRefinementLevel
00079 (
00080     const primitiveMesh& mesh,
00081     labelList& refLevel,
00082     cellSet& refCells
00083 )
00084 {
00085     const labelListList& cellCells = mesh.cellCells();
00086 
00087     label oldNCells = refCells.size();
00088 
00089     forAll(cellCells, cellI)
00090     {
00091         const labelList& cCells = cellCells[cellI];
00092 
00093         forAll(cCells, i)
00094         {
00095             if (refLevel[cCells[i]] > (refLevel[cellI]+1))
00096             {
00097                 // Found neighbour with >=2 difference in refLevel.
00098                 refCells.insert(cellI);
00099                 refLevel[cellI]++;
00100                 break;
00101             }
00102         }
00103     }
00104 
00105     if (refCells.size() > oldNCells)
00106     {
00107         Info<< "Added an additional " << refCells.size() - oldNCells
00108             << " cells to satisfy 1:2 refinement level"
00109             << endl;
00110 
00111         return true;
00112     }
00113     else
00114     {
00115         return false;
00116     }
00117 }
00118 
00119 
00120 // Main program:
00121 
00122 int main(int argc, char *argv[])
00123 {
00124     argList::validOptions.insert("readLevel", "");
00125 
00126 #   include <OpenFOAM/setRootCase.H>
00127 #   include <OpenFOAM/createTime.H>
00128 #   include <OpenFOAM/createPolyMesh.H>
00129 
00130     Info<< "Dividing cells into bins depending on cell volume.\nThis will"
00131         << " correspond to refinement levels for a mesh with only 2x2x2"
00132         << " refinement\n"
00133         << "The upper range for every bin is always 1.1 times the lower range"
00134         << " to allow for some truncation error."
00135         << nl << endl;
00136 
00137     bool readLevel = args.optionFound("readLevel");
00138 
00139     const scalarField& vols = mesh.cellVolumes();
00140 
00141     SortableList<scalar> sortedVols(vols);
00142 
00143     // All cell labels, sorted per bin.
00144     // Use autoPtr to help GCC compilers (< 4.3) which suffer from core
00145     // language defect 391, i.e. require a copy-ctor to be present when passing
00146     // a temporary as an rvalue.
00147     DynamicList<autoPtr<DynamicList<label> > > bins;
00148 
00149     // Lower/upper limits
00150     DynamicList<scalar> lowerLimits;
00151     DynamicList<scalar> upperLimits;
00152 
00153     // Create bin0. Have upperlimit as factor times lowerlimit.
00154     bins.append(autoPtr<DynamicList<label> >(new DynamicList<label>()));
00155     lowerLimits.append(sortedVols[0]);
00156     upperLimits.append(1.1*lowerLimits[lowerLimits.size()-1]);
00157 
00158     forAll(sortedVols, i)
00159     {
00160         if (sortedVols[i] > upperLimits[upperLimits.size()-1])
00161         {
00162             // New value outside of current bin
00163 
00164             // Shrink old bin.
00165             DynamicList<label>& bin = bins[bins.size()-1]();
00166 
00167             bin.shrink();
00168 
00169             Info<< "Collected " << bin.size() << " elements in bin "
00170                 << lowerLimits[lowerLimits.size()-1] << " .. "
00171                 << upperLimits[upperLimits.size()-1] << endl;
00172 
00173             // Create new bin.
00174             bins.append(autoPtr<DynamicList<label> >(new DynamicList<label>()));
00175             lowerLimits.append(sortedVols[i]);
00176             upperLimits.append(1.1*lowerLimits[lowerLimits.size()-1]);
00177 
00178             Info<< "Creating new bin " << lowerLimits[lowerLimits.size()-1]
00179                 << " .. " << upperLimits[upperLimits.size()-1]
00180                 << endl;
00181         }
00182 
00183         // Append to current bin.
00184         DynamicList<label>& bin = bins[bins.size()-1]();
00185 
00186         bin.append(sortedVols.indices()[i]);
00187     }
00188     Info<< endl;
00189 
00190     bins[bins.size()-1]->shrink();
00191     bins.shrink();
00192     lowerLimits.shrink();
00193     upperLimits.shrink();
00194 
00195 
00196     //
00197     // Write to cellSets.
00198     //
00199 
00200     Info<< "Volume bins:" << nl;
00201     forAll(bins, binI)
00202     {
00203         const DynamicList<label>& bin = bins[binI]();
00204 
00205         cellSet cells(mesh, "vol" + name(binI), bin.size());
00206 
00207         forAll(bin, i)
00208         {
00209             cells.insert(bin[i]);
00210         }
00211 
00212         Info<< "    " << lowerLimits[binI] << " .. " << upperLimits[binI]
00213             << "  : writing " << bin.size() << " cells to cellSet "
00214             << cells.name() << endl;
00215 
00216         cells.write();
00217     }
00218 
00219 
00220 
00221     //
00222     // Convert bins into refinement level.
00223     //
00224 
00225 
00226     // Construct fvMesh to be able to construct volScalarField
00227 
00228     fvMesh fMesh
00229     (
00230         IOobject
00231         (
00232             fvMesh::defaultRegion,
00233             runTime.timeName(),
00234             runTime
00235         ),
00236         xferCopy(mesh.points()),   // could we safely re-use the data?
00237         xferCopy(mesh.faces()),
00238         xferCopy(mesh.cells())
00239     );
00240 
00241     // Add the boundary patches
00242     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00243 
00244     List<polyPatch*> p(patches.size());
00245 
00246     forAll (p, patchI)
00247     {
00248         p[patchI] = patches[patchI].clone(fMesh.boundaryMesh()).ptr();
00249     }
00250 
00251     fMesh.addFvPatches(p);
00252 
00253 
00254     // Refinement level
00255     IOobject refHeader
00256     (
00257         "refinementLevel",
00258         runTime.timeName(),
00259         polyMesh::defaultRegion,
00260         runTime
00261     );
00262 
00263     if (!readLevel && refHeader.headerOk())
00264     {
00265         WarningIn(args.executable())
00266             << "Detected " << refHeader.name() << " file in "
00267             << polyMesh::defaultRegion <<  " directory. Please remove to"
00268             << " recreate it or use the -readLevel option to use it"
00269             << endl;
00270         return 1;
00271     }
00272 
00273 
00274     labelIOList refLevel
00275     (
00276         IOobject
00277         (
00278             "refinementLevel",
00279             runTime.timeName(),
00280             mesh,
00281             IOobject::NO_READ,
00282             IOobject::AUTO_WRITE
00283         ),
00284         labelList(mesh.nCells(), 0)
00285     );
00286 
00287     if (readLevel)
00288     {
00289         refLevel = labelIOList(refHeader);
00290     }
00291 
00292     // Construct volScalarField with same info for post processing
00293     volScalarField postRefLevel
00294     (
00295         IOobject
00296         (
00297             "refinementLevel",
00298             runTime.timeName(),
00299             mesh,
00300             IOobject::NO_READ,
00301             IOobject::NO_WRITE
00302         ),
00303         fMesh,
00304         dimensionedScalar("zero", dimless/dimTime, 0)
00305     );
00306 
00307     // Set cell values
00308     forAll(bins, binI)
00309     {
00310         const DynamicList<label>& bin = bins[binI]();
00311 
00312         forAll(bin, i)
00313         {
00314             refLevel[bin[i]] = bins.size() - binI - 1;
00315             postRefLevel[bin[i]] = refLevel[bin[i]];
00316         }
00317     }
00318 
00319 
00320     // For volScalarField: set boundary values to same as cell.
00321     // Note: could also put
00322     // zeroGradient b.c. on postRefLevel and do evaluate.
00323     forAll(postRefLevel.boundaryField(), patchI)
00324     {
00325         const polyPatch& pp = patches[patchI];
00326 
00327         fvPatchScalarField& bField = postRefLevel.boundaryField()[patchI];
00328 
00329         Info<< "Setting field for patch "<< endl;
00330 
00331         forAll(bField, faceI)
00332         {
00333             label own = mesh.faceOwner()[pp.start() + faceI];
00334 
00335             bField[faceI] = postRefLevel[own];
00336         }
00337     }
00338 
00339     Info<< "Determined current refinement level and writing to "
00340         << postRefLevel.name() << " (as volScalarField; for post processing)"
00341         << nl
00342         << polyMesh::defaultRegion/refLevel.name()
00343         << " (as labelIOList; for meshing)" << nl
00344         << endl;
00345 
00346     refLevel.write();
00347     postRefLevel.write();
00348 
00349 
00350     // Find out cells to refine to keep to 2:1 refinement level restriction
00351 
00352     // Cells to refine
00353     cellSet refCells(mesh, "refCells", 100);
00354 
00355     while
00356     (
00357         limitRefinementLevel
00358         (
00359             mesh,
00360             refLevel,       // current refinement level
00361             refCells        // cells to refine
00362         )
00363     )
00364     {}
00365 
00366     if (refCells.size())
00367     {
00368         Info<< "Collected " << refCells.size() << " cells that need to be"
00369             << " refined to get closer to overall 2:1 refinement level limit"
00370             << nl
00371             << "Written cells to be refined to cellSet " << refCells.name()
00372             << nl << endl;
00373 
00374         refCells.write();
00375 
00376         Info<< "After refinement this tool can be run again to see if the 2:1"
00377             << " limit is observed all over the mesh" << nl << endl;
00378     }
00379     else
00380     {
00381         Info<< "All cells in the mesh observe the 2:1 refinement level limit"
00382             << nl << endl;
00383     }
00384 
00385     Info << nl << "End" << endl;
00386 
00387     return 0;
00388 }
00389 
00390 
00391 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines