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

multiDirRefinement.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 \*---------------------------------------------------------------------------*/
00025 
00026 #include "multiDirRefinement.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <dynamicMesh/polyTopoChanger.H>
00029 #include <OpenFOAM/Time.H>
00030 #include <dynamicMesh/undoableMeshCutter.H>
00031 #include <dynamicMesh/hexCellLooper.H>
00032 #include <dynamicMesh/geomCellLooper.H>
00033 #include <meshTools/topoSet.H>
00034 #include <dynamicMesh/directions.H>
00035 #include <dynamicMesh/hexRef8.H>
00036 #include <OpenFOAM/mapPolyMesh.H>
00037 #include <dynamicMesh/polyTopoChange.H>
00038 #include <OpenFOAM/ListOps.H>
00039 #include <OpenFOAM/cellModeller.H>
00040 
00041 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00042 
00043 namespace Foam
00044 {
00045     defineTypeNameAndDebug(multiDirRefinement, 0);
00046 }
00047 
00048 
00049 // * * * * * * * * * * * * * Private Statc Functions * * * * * * * * * * * * //
00050 
00051 // Update refCells pattern for split cells. Note refCells is current
00052 // list of cells to refine (these should all have been refined)
00053 void Foam::multiDirRefinement::addCells
00054 (
00055     const Map<label>& splitMap,
00056     List<refineCell>& refCells
00057 )
00058 {
00059     label newRefI = refCells.size();
00060 
00061     label oldSize = refCells.size();
00062 
00063     refCells.setSize(newRefI + splitMap.size());
00064 
00065     for (label refI = 0; refI < oldSize; refI++)
00066     {
00067         const refineCell& refCell = refCells[refI];
00068 
00069         Map<label>::const_iterator iter = splitMap.find(refCell.cellNo());
00070 
00071         if (iter == splitMap.end())
00072         {
00073             FatalErrorIn
00074             (
00075                 "multiDirRefinement::addCells(const Map<label>&"
00076                 ", List<refineCell>&)"
00077             )   << "Problem : cannot find added cell for cell "
00078                 << refCell.cellNo() << abort(FatalError);
00079         }
00080 
00081         refCells[newRefI++] = refineCell(iter(), refCell.direction());
00082     }
00083 }
00084 
00085 
00086 // Update vectorField for all the new cells. Takes over value of
00087 // original cell.
00088 void Foam::multiDirRefinement::update
00089 (
00090     const Map<label>& splitMap,
00091     vectorField& field
00092 )
00093 {
00094     field.setSize(field.size() + splitMap.size());
00095 
00096     for
00097     (
00098         Map<label>::const_iterator iter = splitMap.begin();
00099         iter != splitMap.end();
00100         ++iter
00101     )
00102     {
00103         field[iter()] = field[iter.key()];
00104     }
00105 }
00106 
00107 
00108 // Add added cells to labelList
00109 void Foam::multiDirRefinement::addCells
00110 (
00111     const Map<label>& splitMap,
00112     labelList& labels
00113 )
00114 {
00115     label newCellI = labels.size();
00116 
00117     labels.setSize(labels.size() + splitMap.size());
00118 
00119     for
00120     (
00121         Map<label>::const_iterator iter = splitMap.begin();
00122         iter != splitMap.end();
00123         ++iter
00124     )
00125     {
00126         labels[newCellI++] = iter();
00127     }
00128 }
00129 
00130 
00131 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00132 
00133 void Foam::multiDirRefinement::addCells
00134 (
00135     const primitiveMesh& mesh,
00136     const Map<label>& splitMap
00137 )
00138 {
00139     // Construct inverse addressing: from new to original cell.
00140     labelList origCell(mesh.nCells(), -1);
00141 
00142     forAll(addedCells_, cellI)
00143     {
00144         const labelList& added = addedCells_[cellI];
00145 
00146         forAll(added, i)
00147         {
00148             label slave = added[i];
00149 
00150             if (origCell[slave] == -1)
00151             {
00152                 origCell[slave] = cellI;
00153             }
00154             else if (origCell[slave] != cellI)
00155             {
00156                 FatalErrorIn
00157                 (
00158                     "multiDirRefinement::addCells(const primitiveMesh&"
00159                     ", const Map<label>&"
00160                 )   << "Added cell " << slave << " has two different masters:"
00161                     << origCell[slave] << " , " << cellI
00162                     << abort(FatalError);
00163             }
00164         }
00165     }
00166 
00167 
00168     for
00169     (
00170         Map<label>::const_iterator iter = splitMap.begin();
00171         iter != splitMap.end();
00172         ++iter
00173     )
00174     {
00175         label masterI = iter.key();
00176         label newCellI = iter();
00177 
00178         while (origCell[masterI] != -1 && origCell[masterI] != masterI)
00179         {
00180             masterI = origCell[masterI];
00181         }
00182 
00183         if (masterI >= addedCells_.size())
00184         {
00185             FatalErrorIn
00186             (
00187                 "multiDirRefinement::addCells(const primitiveMesh&"
00188                 ", const Map<label>&"
00189             )   << "Map of added cells contains master cell " << masterI
00190                 << " which is not a valid cell number" << endl
00191                 << "This means that the mesh is not consistent with the"
00192                 << " done refinement" << endl
00193                 << "newCell:" << newCellI << abort(FatalError);
00194         }
00195 
00196         labelList& added = addedCells_[masterI];
00197 
00198         if (added.empty())
00199         {
00200             added.setSize(2);
00201             added[0] = masterI;
00202             added[1] = newCellI;
00203         }
00204         else if (findIndex(added, newCellI) == -1)
00205         {
00206             label sz = added.size();
00207             added.setSize(sz + 1);
00208             added[sz] = newCellI;
00209         }
00210     }
00211 }
00212 
00213 
00214 Foam::labelList Foam::multiDirRefinement::splitOffHex(const primitiveMesh& mesh)
00215 {
00216     const cellModel& hex = *(cellModeller::lookup("hex"));
00217 
00218     const cellShapeList& cellShapes = mesh.cellShapes();
00219 
00220     // Split cellLabels_ into two lists.
00221 
00222     labelList nonHexLabels(cellLabels_.size());
00223     label nonHexI = 0;
00224 
00225     labelList hexLabels(cellLabels_.size());
00226     label hexI = 0;
00227 
00228     forAll(cellLabels_, i)
00229     {
00230         label cellI = cellLabels_[i];
00231 
00232         if (cellShapes[cellI].model() == hex)
00233         {
00234             hexLabels[hexI++] = cellI;
00235         }
00236         else
00237         {
00238             nonHexLabels[nonHexI++] = cellI;
00239         }
00240     }
00241 
00242     nonHexLabels.setSize(nonHexI);
00243 
00244     cellLabels_.transfer(nonHexLabels);
00245 
00246     hexLabels.setSize(hexI);
00247 
00248     return hexLabels;
00249 }
00250 
00251 
00252 void Foam::multiDirRefinement::refineHex8
00253 (
00254     polyMesh& mesh,
00255     const labelList& hexCells,
00256     const bool writeMesh
00257 )
00258 {
00259     if (debug)
00260     {
00261         Pout<< "multiDirRefinement : Refining hexes " << hexCells.size()
00262             << endl;
00263     }
00264 
00265     hexRef8 hexRefiner
00266     (
00267         mesh,
00268         labelList(mesh.nCells(), 0),    // cellLevel
00269         labelList(mesh.nPoints(), 0),   // pointLevel
00270         refinementHistory
00271         (
00272             IOobject
00273             (
00274                 "refinementHistory",
00275                 mesh.facesInstance(),
00276                 polyMesh::meshSubDir,
00277                 mesh,
00278                 IOobject::NO_READ,
00279                 IOobject::NO_WRITE,
00280                 false
00281             ),
00282             List<refinementHistory::splitCell8>(0),
00283             labelList(0)
00284         )                                   // refinement history
00285     );
00286 
00287     polyTopoChange meshMod(mesh);
00288 
00289     labelList consistentCells
00290     (
00291         hexRefiner.consistentRefinement
00292         (
00293             hexCells,
00294             true                  // buffer layer
00295         )
00296     );
00297 
00298     // Check that consistentRefinement hasn't added cells
00299     {
00300         // Create count 1 for original cells
00301         Map<label> hexCellSet(2*hexCells.size());
00302         forAll(hexCells, i)
00303         {
00304             hexCellSet.insert(hexCells[i], 1);
00305         }
00306 
00307         // Increment count 
00308         forAll(consistentCells, i)
00309         {
00310             label cellI = consistentCells[i];
00311 
00312             Map<label>::iterator iter = hexCellSet.find(cellI);
00313 
00314             if (iter == hexCellSet.end())
00315             {
00316                 FatalErrorIn
00317                 (
00318                     "multiDirRefinement::refineHex8"
00319                     "(polyMesh&, const labelList&, const bool)"
00320                 )   << "Resulting mesh would not satisfy 2:1 ratio"
00321                     << " when refining cell " << cellI << abort(FatalError);
00322             }
00323             else
00324             {
00325                 iter() = 2;
00326             }
00327         }
00328 
00329         // Check if all been visited (should always be since
00330         // consistentRefinement set up to extend set.
00331         forAllConstIter(Map<label>, hexCellSet, iter)
00332         {
00333             if (iter() != 2)
00334             {
00335                 FatalErrorIn
00336                 (
00337                     "multiDirRefinement::refineHex8"
00338                     "(polyMesh&, const labelList&, const bool)"
00339                 )   << "Resulting mesh would not satisfy 2:1 ratio"
00340                     << " when refining cell " << iter.key()
00341                     << abort(FatalError);
00342             }
00343         }
00344     }
00345 
00346 
00347     hexRefiner.setRefinement(consistentCells, meshMod);
00348 
00349     // Change mesh, no inflation
00350     autoPtr<mapPolyMesh> morphMapPtr = meshMod.changeMesh(mesh, false, true);
00351     const mapPolyMesh& morphMap = morphMapPtr();
00352 
00353     if (morphMap.hasMotionPoints())
00354     {
00355         mesh.movePoints(morphMap.preMotionPoints());
00356     }
00357 
00358     if (writeMesh)
00359     {
00360         mesh.write();
00361     }
00362 
00363     if (debug)
00364     {
00365         Pout<< "multiDirRefinement : updated mesh at time "
00366             << mesh.time().timeName() << endl;
00367     }
00368 
00369     hexRefiner.updateMesh(morphMap);
00370 
00371     // Collect all cells originating from same old cell (original + 7 extra)
00372 
00373     forAll(consistentCells, i)
00374     {
00375         addedCells_[consistentCells[i]].setSize(8);
00376     }
00377     labelList nAddedCells(addedCells_.size(), 0);
00378 
00379     const labelList& cellMap = morphMap.cellMap();
00380 
00381     forAll(cellMap, cellI)
00382     {
00383         label oldCellI = cellMap[cellI];
00384 
00385         if (addedCells_[oldCellI].size())
00386         {
00387             addedCells_[oldCellI][nAddedCells[oldCellI]++] = cellI;
00388         }
00389     }
00390 }
00391 
00392 
00393 void Foam::multiDirRefinement::refineAllDirs
00394 (
00395     polyMesh& mesh,
00396     List<vectorField>& cellDirections,
00397     const cellLooper& cellWalker,
00398     undoableMeshCutter& cutter,
00399     const bool writeMesh
00400 )
00401 {
00402     // Iterator
00403     refinementIterator refiner(mesh, cutter, cellWalker, writeMesh);
00404 
00405     forAll(cellDirections, dirI)
00406     {
00407         if (debug)
00408         {
00409             Pout<< "multiDirRefinement : Refining " << cellLabels_.size()
00410                 << " cells in direction " << dirI << endl
00411                 << endl;
00412         }
00413 
00414         const vectorField& dirField = cellDirections[dirI];
00415 
00416         // Combine cell to be cut with direction to cut in.
00417         // If dirField is only one element use this for all cells.
00418 
00419         List<refineCell> refCells(cellLabels_.size());
00420 
00421         if (dirField.size() == 1)
00422         {
00423             // Uniform directions.
00424             if (debug)
00425             {
00426                 Pout<< "multiDirRefinement : Uniform refinement:"
00427                     << dirField[0] << endl;
00428             }
00429 
00430             forAll(refCells, refI)
00431             {
00432                 label cellI = cellLabels_[refI];
00433 
00434                 refCells[refI] = refineCell(cellI, dirField[0]);
00435             }
00436         }
00437         else
00438         {
00439             // Non uniform directions.
00440             forAll(refCells, refI)
00441             {
00442                 label cellI = cellLabels_[refI];
00443 
00444                 refCells[refI] = refineCell(cellI, dirField[cellI]);
00445             }
00446         }
00447 
00448         // Do refine mesh (multiple iterations). Remember added cells.
00449         Map<label> splitMap = refiner.setRefinement(refCells);
00450 
00451         // Update overall map of added cells
00452         addCells(mesh, splitMap);
00453 
00454         // Add added cells to list of cells to refine in next iteration
00455         addCells(splitMap, cellLabels_);
00456 
00457         // Update refinement direction for added cells.
00458         if (dirField.size() != 1)
00459         {
00460             forAll(cellDirections, i)
00461             {
00462                 update(splitMap, cellDirections[i]);
00463             }
00464         }
00465 
00466         if (debug)
00467         {
00468             Pout<< "multiDirRefinement : Done refining direction " << dirI
00469                 << " resulting in " << cellLabels_.size() << " cells" << nl
00470                 << endl;
00471         }
00472     }
00473 }
00474 
00475 
00476 void Foam::multiDirRefinement::refineFromDict
00477 (
00478     polyMesh& mesh,
00479     List<vectorField>& cellDirections,
00480     const dictionary& dict,
00481     const bool writeMesh
00482 )
00483 {
00484     // How to walk cell circumference.
00485     Switch pureGeomCut(dict.lookup("geometricCut"));
00486 
00487     autoPtr<cellLooper> cellWalker(NULL);
00488     if (pureGeomCut)
00489     {
00490         cellWalker.reset(new geomCellLooper(mesh));
00491     }
00492     else
00493     {
00494         cellWalker.reset(new hexCellLooper(mesh));
00495     }
00496 
00497     // Construct undoable refinement topology modifier. 
00498     //Note: undoability switched off.
00499     // Might want to reconsider if needs to be possible. But then can always
00500     // use other constructor.
00501     undoableMeshCutter cutter(mesh, false);
00502 
00503     refineAllDirs(mesh, cellDirections, cellWalker(), cutter, writeMesh);
00504 }
00505 
00506 
00507 
00508 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00509 
00510 // Construct from dictionary
00511 Foam::multiDirRefinement::multiDirRefinement
00512 (
00513     polyMesh& mesh,
00514     const labelList& cellLabels,        // list of cells to refine
00515     const dictionary& dict
00516 )
00517 :
00518     cellLabels_(cellLabels),
00519     addedCells_(mesh.nCells())
00520 {
00521     Switch useHex(dict.lookup("useHexTopology"));
00522 
00523     Switch writeMesh(dict.lookup("writeMesh"));
00524 
00525     wordList dirNames(dict.lookup("directions"));
00526 
00527     if (useHex && dirNames.size() == 3)
00528     {
00529         // Filter out hexes from cellLabels_
00530         labelList hexCells(splitOffHex(mesh));
00531 
00532         refineHex8(mesh, hexCells, writeMesh);
00533     }
00534 
00535     label nRemainingCells = cellLabels_.size();
00536 
00537     reduce(nRemainingCells, sumOp<label>());
00538 
00539     if (nRemainingCells > 0)
00540     {
00541         // Any cells to refine using meshCutter
00542 
00543         // Determine directions for every cell. Can either be uniform
00544         // (size = 1) or non-uniform (one vector per cell)
00545         directions cellDirections(mesh, dict);
00546 
00547         refineFromDict(mesh, cellDirections, dict, writeMesh);
00548     }
00549 }
00550 
00551 
00552 // Construct from directionary and directions to refine.
00553 Foam::multiDirRefinement::multiDirRefinement
00554 (
00555     polyMesh& mesh,
00556     const labelList& cellLabels,        // list of cells to refine
00557     const List<vectorField>& cellDirs,  // Explicitly provided directions
00558     const dictionary& dict
00559 )
00560 :
00561     cellLabels_(cellLabels),
00562     addedCells_(mesh.nCells())
00563 {
00564     Switch useHex(dict.lookup("useHexTopology"));
00565 
00566     Switch writeMesh(dict.lookup("writeMesh"));
00567 
00568     wordList dirNames(dict.lookup("directions"));
00569 
00570     if (useHex && dirNames.size() == 3)
00571     {
00572         // Filter out hexes from cellLabels_
00573         labelList hexCells(splitOffHex(mesh));
00574 
00575         refineHex8(mesh, hexCells, writeMesh);
00576     }
00577 
00578     label nRemainingCells = cellLabels_.size();
00579 
00580     reduce(nRemainingCells, sumOp<label>());
00581 
00582     if (nRemainingCells > 0)
00583     {
00584         // Any cells to refine using meshCutter
00585 
00586         // Working copy of cells to refine
00587         List<vectorField> cellDirections(cellDirs);
00588 
00589         refineFromDict(mesh, cellDirections, dict, writeMesh);
00590     }
00591 }
00592 
00593 
00594 // Construct from components. Implies meshCutter since directions provided.
00595 Foam::multiDirRefinement::multiDirRefinement
00596 (
00597     polyMesh& mesh,
00598     undoableMeshCutter& cutter,     // actual mesh modifier
00599     const cellLooper& cellWalker,   // how to cut a single cell with
00600                                     // a plane
00601     const labelList& cellLabels,    // list of cells to refine
00602     const List<vectorField>& cellDirs,
00603     const bool writeMesh            // write intermediate meshes
00604 )
00605 :
00606     cellLabels_(cellLabels),
00607     addedCells_(mesh.nCells())
00608 {
00609     // Working copy of cells to refine
00610     List<vectorField> cellDirections(cellDirs);
00611 
00612     refineAllDirs(mesh, cellDirections, cellWalker, cutter, writeMesh);
00613 }
00614 
00615 
00616 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines