mirror of
https://github.com/OpenFOAM/OpenFOAM-6.git
synced 2025-12-08 06:57:46 +00:00
Add the OpenFOAM source tree
This commit is contained in:
491
applications/utilities/mesh/advanced/modifyMesh/cellSplitter.C
Normal file
491
applications/utilities/mesh/advanced/modifyMesh/cellSplitter.C
Normal file
@ -0,0 +1,491 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2012 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "cellSplitter.H"
|
||||
#include "polyMesh.H"
|
||||
#include "polyTopoChange.H"
|
||||
#include "polyAddCell.H"
|
||||
#include "polyAddFace.H"
|
||||
#include "polyAddPoint.H"
|
||||
#include "polyModifyFace.H"
|
||||
#include "mapPolyMesh.H"
|
||||
#include "meshTools.H"
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(cellSplitter, 0);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::cellSplitter::getFaceInfo
|
||||
(
|
||||
const label faceI,
|
||||
label& patchID,
|
||||
label& zoneID,
|
||||
label& zoneFlip
|
||||
) const
|
||||
{
|
||||
patchID = -1;
|
||||
|
||||
if (!mesh_.isInternalFace(faceI))
|
||||
{
|
||||
patchID = mesh_.boundaryMesh().whichPatch(faceI);
|
||||
}
|
||||
|
||||
zoneID = mesh_.faceZones().whichZone(faceI);
|
||||
|
||||
zoneFlip = false;
|
||||
|
||||
if (zoneID >= 0)
|
||||
{
|
||||
const faceZone& fZone = mesh_.faceZones()[zoneID];
|
||||
|
||||
zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Find the new owner of faceI (since the original cell has been split into
|
||||
// newCells
|
||||
Foam::label Foam::cellSplitter::newOwner
|
||||
(
|
||||
const label faceI,
|
||||
const Map<labelList>& cellToCells
|
||||
) const
|
||||
{
|
||||
label oldOwn = mesh_.faceOwner()[faceI];
|
||||
|
||||
Map<labelList>::const_iterator fnd = cellToCells.find(oldOwn);
|
||||
|
||||
if (fnd == cellToCells.end())
|
||||
{
|
||||
// Unsplit cell
|
||||
return oldOwn;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look up index of face in the cells' faces.
|
||||
|
||||
const labelList& newCells = fnd();
|
||||
|
||||
const cell& cFaces = mesh_.cells()[oldOwn];
|
||||
|
||||
return newCells[findIndex(cFaces, faceI)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::cellSplitter::newNeighbour
|
||||
(
|
||||
const label faceI,
|
||||
const Map<labelList>& cellToCells
|
||||
) const
|
||||
{
|
||||
label oldNbr = mesh_.faceNeighbour()[faceI];
|
||||
|
||||
Map<labelList>::const_iterator fnd = cellToCells.find(oldNbr);
|
||||
|
||||
if (fnd == cellToCells.end())
|
||||
{
|
||||
// Unsplit cell
|
||||
return oldNbr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Look up index of face in the cells' faces.
|
||||
|
||||
const labelList& newCells = fnd();
|
||||
|
||||
const cell& cFaces = mesh_.cells()[oldNbr];
|
||||
|
||||
return newCells[findIndex(cFaces, faceI)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
// Construct from components
|
||||
Foam::cellSplitter::cellSplitter(const polyMesh& mesh)
|
||||
:
|
||||
mesh_(mesh),
|
||||
addedPoints_()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::cellSplitter::~cellSplitter()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::cellSplitter::setRefinement
|
||||
(
|
||||
const Map<point>& cellToMidPoint,
|
||||
polyTopoChange& meshMod
|
||||
)
|
||||
{
|
||||
addedPoints_.clear();
|
||||
addedPoints_.resize(cellToMidPoint.size());
|
||||
|
||||
|
||||
//
|
||||
// Introduce cellToMidPoints.
|
||||
//
|
||||
|
||||
forAllConstIter(Map<point>, cellToMidPoint, iter)
|
||||
{
|
||||
label cellI = iter.key();
|
||||
|
||||
label anchorPoint = mesh_.cellPoints()[cellI][0];
|
||||
|
||||
label addedPointI =
|
||||
meshMod.setAction
|
||||
(
|
||||
polyAddPoint
|
||||
(
|
||||
iter(), // point
|
||||
anchorPoint, // master point
|
||||
-1, // zone for point
|
||||
true // supports a cell
|
||||
)
|
||||
);
|
||||
addedPoints_.insert(cellI, addedPointI);
|
||||
|
||||
//Pout<< "Added point " << addedPointI
|
||||
// << iter() << " in cell " << cellI << " with centre "
|
||||
// << mesh_.cellCentres()[cellI] << endl;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Add cells (first one is modified original cell)
|
||||
//
|
||||
|
||||
Map<labelList> cellToCells(cellToMidPoint.size());
|
||||
|
||||
forAllConstIter(Map<point>, cellToMidPoint, iter)
|
||||
{
|
||||
label cellI = iter.key();
|
||||
|
||||
const cell& cFaces = mesh_.cells()[cellI];
|
||||
|
||||
// Cells created for this cell.
|
||||
labelList newCells(cFaces.size());
|
||||
|
||||
// First pyramid is the original cell
|
||||
newCells[0] = cellI;
|
||||
|
||||
// Add other pyramids
|
||||
for (label i = 1; i < cFaces.size(); i++)
|
||||
{
|
||||
label addedCellI =
|
||||
meshMod.setAction
|
||||
(
|
||||
polyAddCell
|
||||
(
|
||||
-1, // master point
|
||||
-1, // master edge
|
||||
-1, // master face
|
||||
cellI, // master cell
|
||||
-1 // zone
|
||||
)
|
||||
);
|
||||
|
||||
newCells[i] = addedCellI;
|
||||
}
|
||||
|
||||
cellToCells.insert(cellI, newCells);
|
||||
|
||||
//Pout<< "Split cell " << cellI
|
||||
// << " with centre " << mesh_.cellCentres()[cellI] << nl
|
||||
// << " faces:" << cFaces << nl
|
||||
// << " into :" << newCells << endl;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Introduce internal faces. These go from edges of the cell to the mid
|
||||
// point.
|
||||
//
|
||||
|
||||
forAllConstIter(Map<point>, cellToMidPoint, iter)
|
||||
{
|
||||
label cellI = iter.key();
|
||||
|
||||
label midPointI = addedPoints_[cellI];
|
||||
|
||||
const cell& cFaces = mesh_.cells()[cellI];
|
||||
|
||||
const labelList& cEdges = mesh_.cellEdges()[cellI];
|
||||
|
||||
forAll(cEdges, i)
|
||||
{
|
||||
label edgeI = cEdges[i];
|
||||
const edge& e = mesh_.edges()[edgeI];
|
||||
|
||||
// Get the faces on the cell using the edge
|
||||
label face0, face1;
|
||||
meshTools::getEdgeFaces(mesh_, cellI, edgeI, face0, face1);
|
||||
|
||||
// Get the cells on both sides of the face by indexing into cFaces.
|
||||
// (since newly created cells are stored in cFaces order)
|
||||
const labelList& newCells = cellToCells[cellI];
|
||||
|
||||
label cell0 = newCells[findIndex(cFaces, face0)];
|
||||
label cell1 = newCells[findIndex(cFaces, face1)];
|
||||
|
||||
if (cell0 < cell1)
|
||||
{
|
||||
// Construct face to midpoint that is pointing away from
|
||||
// (pyramid split off from) cellI
|
||||
|
||||
const face& f0 = mesh_.faces()[face0];
|
||||
|
||||
label index = findIndex(f0, e[0]);
|
||||
|
||||
bool edgeInFaceOrder = (f0[f0.fcIndex(index)] == e[1]);
|
||||
|
||||
// Check if cellI is the face owner
|
||||
|
||||
face newF(3);
|
||||
if (edgeInFaceOrder == (mesh_.faceOwner()[face0] == cellI))
|
||||
{
|
||||
// edge used in face order.
|
||||
newF[0] = e[1];
|
||||
newF[1] = e[0];
|
||||
newF[2] = midPointI;
|
||||
}
|
||||
else
|
||||
{
|
||||
newF[0] = e[0];
|
||||
newF[1] = e[1];
|
||||
newF[2] = midPointI;
|
||||
}
|
||||
|
||||
// Now newF points away from cell0
|
||||
meshMod.setAction
|
||||
(
|
||||
polyAddFace
|
||||
(
|
||||
newF, // face
|
||||
cell0, // owner
|
||||
cell1, // neighbour
|
||||
-1, // master point
|
||||
-1, // master edge
|
||||
face0, // master face for addition
|
||||
false, // flux flip
|
||||
-1, // patch for face
|
||||
-1, // zone for face
|
||||
false // face zone flip
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Construct face to midpoint that is pointing away from
|
||||
// (pyramid split off from) cellI
|
||||
|
||||
const face& f1 = mesh_.faces()[face1];
|
||||
|
||||
label index = findIndex(f1, e[0]);
|
||||
|
||||
bool edgeInFaceOrder = (f1[f1.fcIndex(index)] == e[1]);
|
||||
|
||||
// Check if cellI is the face owner
|
||||
|
||||
face newF(3);
|
||||
if (edgeInFaceOrder == (mesh_.faceOwner()[face1] == cellI))
|
||||
{
|
||||
// edge used in face order.
|
||||
newF[0] = e[1];
|
||||
newF[1] = e[0];
|
||||
newF[2] = midPointI;
|
||||
}
|
||||
else
|
||||
{
|
||||
newF[0] = e[0];
|
||||
newF[1] = e[1];
|
||||
newF[2] = midPointI;
|
||||
}
|
||||
|
||||
// Now newF points away from cell1
|
||||
meshMod.setAction
|
||||
(
|
||||
polyAddFace
|
||||
(
|
||||
newF, // face
|
||||
cell1, // owner
|
||||
cell0, // neighbour
|
||||
-1, // master point
|
||||
-1, // master edge
|
||||
face0, // master face for addition
|
||||
false, // flux flip
|
||||
-1, // patch for face
|
||||
-1, // zone for face
|
||||
false // face zone flip
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Update all existing faces for split owner or neighbour.
|
||||
//
|
||||
|
||||
|
||||
// Mark off affected face.
|
||||
boolList faceUpToDate(mesh_.nFaces(), true);
|
||||
|
||||
forAllConstIter(Map<point>, cellToMidPoint, iter)
|
||||
{
|
||||
label cellI = iter.key();
|
||||
|
||||
const cell& cFaces = mesh_.cells()[cellI];
|
||||
|
||||
forAll(cFaces, i)
|
||||
{
|
||||
label faceI = cFaces[i];
|
||||
|
||||
faceUpToDate[faceI] = false;
|
||||
}
|
||||
}
|
||||
|
||||
forAll(faceUpToDate, faceI)
|
||||
{
|
||||
if (!faceUpToDate[faceI])
|
||||
{
|
||||
const face& f = mesh_.faces()[faceI];
|
||||
|
||||
if (mesh_.isInternalFace(faceI))
|
||||
{
|
||||
label newOwn = newOwner(faceI, cellToCells);
|
||||
label newNbr = newNeighbour(faceI, cellToCells);
|
||||
|
||||
if (newOwn < newNbr)
|
||||
{
|
||||
meshMod.setAction
|
||||
(
|
||||
polyModifyFace
|
||||
(
|
||||
f,
|
||||
faceI,
|
||||
newOwn, // owner
|
||||
newNbr, // neighbour
|
||||
false, // flux flip
|
||||
-1, // patch for face
|
||||
false, // remove from zone
|
||||
-1, // zone for face
|
||||
false // face zone flip
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
meshMod.setAction
|
||||
(
|
||||
polyModifyFace
|
||||
(
|
||||
f.reverseFace(),
|
||||
faceI,
|
||||
newNbr, // owner
|
||||
newOwn, // neighbour
|
||||
false, // flux flip
|
||||
-1, // patch for face
|
||||
false, // remove from zone
|
||||
-1, // zone for face
|
||||
false // face zone flip
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
label newOwn = newOwner(faceI, cellToCells);
|
||||
|
||||
label patchID, zoneID, zoneFlip;
|
||||
getFaceInfo(faceI, patchID, zoneID, zoneFlip);
|
||||
|
||||
meshMod.setAction
|
||||
(
|
||||
polyModifyFace
|
||||
(
|
||||
mesh_.faces()[faceI],
|
||||
faceI,
|
||||
newOwn, // owner
|
||||
-1, // neighbour
|
||||
false, // flux flip
|
||||
patchID, // patch for face
|
||||
false, // remove from zone
|
||||
zoneID, // zone for face
|
||||
zoneFlip // face zone flip
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
faceUpToDate[faceI] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::cellSplitter::updateMesh(const mapPolyMesh& morphMap)
|
||||
{
|
||||
// Create copy since we're deleting entries. Only if both cell and added
|
||||
// point get mapped do they get inserted.
|
||||
Map<label> newAddedPoints(addedPoints_.size());
|
||||
|
||||
forAllConstIter(Map<label>, addedPoints_, iter)
|
||||
{
|
||||
label oldCellI = iter.key();
|
||||
|
||||
label newCellI = morphMap.reverseCellMap()[oldCellI];
|
||||
|
||||
label oldPointI = iter();
|
||||
|
||||
label newPointI = morphMap.reversePointMap()[oldPointI];
|
||||
|
||||
if (newCellI >= 0 && newPointI >= 0)
|
||||
{
|
||||
newAddedPoints.insert(newCellI, newPointI);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy
|
||||
addedPoints_.transfer(newAddedPoints);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user