/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA \*---------------------------------------------------------------------------*/ #include "undoableMeshCutter.H" #include "polyMesh.H" #include "polyTopoChange.H" #include "DynamicList.H" #include "meshCutter.H" #include "cellCuts.H" #include "splitCell.H" #include "mapPolyMesh.H" #include "mathConstants.H" #include "meshTools.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // namespace Foam { defineTypeNameAndDebug(undoableMeshCutter, 0); } // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // For debugging void Foam::undoableMeshCutter::printCellRefTree ( Ostream& os, const word& indent, const splitCell* splitCellPtr ) const { if (splitCellPtr) { os << indent << splitCellPtr->cellLabel() << endl; word subIndent = indent + "--"; printCellRefTree(os, subIndent, splitCellPtr->master()); printCellRefTree(os, subIndent, splitCellPtr->slave()); } } // For debugging void Foam::undoableMeshCutter::printRefTree(Ostream& os) const { for ( Map::const_iterator iter = liveSplitCells_.begin(); iter != liveSplitCells_.end(); ++iter ) { const splitCell* splitPtr = iter(); // Walk to top (master path only) while (splitPtr->parent()) { if (!splitPtr->isMaster()) { splitPtr = NULL; break; } else { splitPtr = splitPtr->parent(); } } // If we have reached top along master path start printing. if (splitPtr) { // Print from top down printCellRefTree(os, word(""), splitPtr); } } } // Update all (cell) labels on splitCell structure. // Do in two passes to prevent allocation if nothing changed. void Foam::undoableMeshCutter::updateLabels ( const labelList& map, Map& liveSplitCells ) { // Pass1 : check if changed bool changed = false; forAllConstIter(Map,liveSplitCells, iter) { const splitCell* splitPtr = iter(); if (!splitPtr) { FatalErrorIn ( "undoableMeshCutter::updateLabels" "(const labelList&, Map&)" ) << "Problem: null pointer on liveSplitCells list" << abort(FatalError); } label cellI = splitPtr->cellLabel(); if (cellI != map[cellI]) { changed = true; break; } } // Pass2: relabel if (changed) { // Build new liveSplitCells // since new labels (= keys in Map) might clash with existing ones. Map newLiveSplitCells(2*liveSplitCells.size()); forAllIter(Map, liveSplitCells, iter) { splitCell* splitPtr = iter(); label cellI = splitPtr->cellLabel(); label newCellI = map[cellI]; if (debug && (cellI != newCellI)) { Pout<< "undoableMeshCutter::updateLabels :" << " Updating live (split)cell from " << cellI << " to " << newCellI << endl; } if (newCellI >= 0) { // Update splitCell. Can do inplace since only one cellI will // refer to this structure. splitPtr->cellLabel() = newCellI; // Update liveSplitCells newLiveSplitCells.insert(newCellI, splitPtr); } } liveSplitCells = newLiveSplitCells; } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // Construct from components Foam::undoableMeshCutter::undoableMeshCutter ( const polyMesh& mesh, const bool undoable ) : meshCutter(mesh), undoable_(undoable), liveSplitCells_(mesh.nCells()/100 + 100), faceRemover_ ( mesh, Foam::cos(30.0/180.0*constant::math::pi) ) {} // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::undoableMeshCutter::~undoableMeshCutter() { // Clean split cell tree. forAllIter(Map, liveSplitCells_, iter) { splitCell* splitPtr = iter(); while (splitPtr) { splitCell* parentPtr = splitPtr->parent(); // Sever ties with parent. Also of other side of refinement since // we are handling rest of tree so other side will not have to. if (parentPtr) { splitCell* otherSidePtr = splitPtr->getOther(); otherSidePtr->parent() = NULL; splitPtr->parent() = NULL; } // Delete splitCell (updates pointer on parent to itself) delete splitPtr; splitPtr = parentPtr; } } } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // void Foam::undoableMeshCutter::setRefinement ( const cellCuts& cuts, polyTopoChange& meshMod ) { // Insert commands to actually cut cells meshCutter::setRefinement(cuts, meshMod); if (undoable_) { // Use cells cut in this iteration to update splitCell tree. forAllConstIter(Map