/*---------------------------------------------------------------------------*\
========= |
\\ / 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