/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\/ 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 3 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, see . \*---------------------------------------------------------------------------*/ #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 "unitConversion.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 { forAllConstIter(Map, liveSplitCells_, 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) { FatalErrorInFunction << "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(degToRad(30.0)) ) {} // * * * * * * * * * * * * * * * * 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