ENH: renumberMesh: use renumberMethods library

This commit is contained in:
mattijs
2011-12-08 16:28:32 +00:00
parent f1911657d1
commit d5268bf30c
4 changed files with 433 additions and 101 deletions

View File

@ -2,6 +2,7 @@ EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/dynamicMesh/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/renumberMethods/lnInclude \
-I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude
EXE_LIBS = \ EXE_LIBS = \
@ -9,4 +10,5 @@ EXE_LIBS = \
-ldynamicMesh \ -ldynamicMesh \
-lfiniteVolume \ -lfiniteVolume \
-lgenericPatchFields \ -lgenericPatchFields \
-lrenumberMethods \
-ldecompositionMethods -ldecompositionMethods

View File

@ -37,16 +37,51 @@ Description
#include "ReadFields.H" #include "ReadFields.H"
#include "volFields.H" #include "volFields.H"
#include "surfaceFields.H" #include "surfaceFields.H"
#include "bandCompression.H"
#include "faceSet.H"
#include "SortableList.H" #include "SortableList.H"
#include "decompositionMethod.H" #include "decompositionMethod.H"
#include "fvMeshSubset.H" #include "renumberMethod.H"
#include "zeroGradientFvPatchFields.H" #include "zeroGradientFvPatchFields.H"
using namespace Foam; using namespace Foam;
// Create named field from labelList for postprocessing
tmp<volScalarField> createScalarField
(
const fvMesh& mesh,
const word& name,
const labelList& elems
)
{
tmp<volScalarField> tfld
(
new volScalarField
(
IOobject
(
name,
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE,
false
),
mesh,
dimensionedScalar("zero", dimless, 0),
zeroGradientFvPatchScalarField::typeName
)
);
volScalarField& fld = tfld();
forAll(fld, cellI)
{
fld[cellI] = elems[cellI];
}
return tfld;
}
// Calculate band of matrix // Calculate band of matrix
label getBand(const labelList& owner, const labelList& neighbour) label getBand(const labelList& owner, const labelList& neighbour)
{ {
@ -65,56 +100,111 @@ label getBand(const labelList& owner, const labelList& neighbour)
} }
// Return new to old cell numbering // Determine upper-triangular face order
labelList regionBandCompression labelList getFaceOrder
( (
const fvMesh& mesh, const primitiveMesh& mesh,
const labelList& cellToRegion const labelList& cellOrder // new to old cell
) )
{ {
Pout<< "Determining cell order:" << endl; labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
labelList cellOrder(cellToRegion.size()); labelList oldToNewFace(mesh.nFaces(), -1);
label nRegions = max(cellToRegion)+1; label newFaceI = 0;
labelListList regionToCells(invertOneToMany(nRegions, cellToRegion)); labelList nbr;
labelList order;
label cellI = 0; forAll(cellOrder, newCellI)
forAll(regionToCells, regionI)
{ {
Pout<< " region " << regionI << " starts at " << cellI << endl; label oldCellI = cellOrder[newCellI];
// Per region do a reordering. const cell& cFaces = mesh.cells()[oldCellI];
fvMeshSubset subsetter(mesh);
subsetter.setLargeCellSubset(cellToRegion, regionI);
const fvMesh& subMesh = subsetter.subMesh();
labelList subCellOrder(bandCompression(subMesh.cellCells()));
const labelList& cellMap = subsetter.cellMap(); // Neighbouring cells
nbr.setSize(cFaces.size());
forAll(subCellOrder, i) forAll(cFaces, i)
{ {
cellOrder[cellI++] = cellMap[subCellOrder[i]]; label faceI = cFaces[i];
if (mesh.isInternalFace(faceI))
{
// Internal face. Get cell on other side.
label nbrCellI = reverseCellOrder[mesh.faceNeighbour()[faceI]];
if (nbrCellI == newCellI)
{
nbrCellI = reverseCellOrder[mesh.faceOwner()[faceI]];
}
if (newCellI < nbrCellI)
{
// CellI is master
nbr[i] = nbrCellI;
}
else
{
// nbrCell is master. Let it handle this face.
nbr[i] = -1;
}
}
else
{
// External face. Do later.
nbr[i] = -1;
}
}
order.setSize(nbr.size());
sortedOrder(nbr, order);
forAll(order, i)
{
label index = order[i];
if (nbr[index] != -1)
{
oldToNewFace[cFaces[index]] = newFaceI++;
}
} }
} }
Pout<< endl;
return cellOrder; // Leave patch faces intact.
for (label faceI = newFaceI; faceI < mesh.nFaces(); faceI++)
{
oldToNewFace[faceI] = faceI;
}
// Check done all faces.
forAll(oldToNewFace, faceI)
{
if (oldToNewFace[faceI] == -1)
{
FatalErrorIn
(
"getFaceOrder"
"(const primitiveMesh&, const labelList&, const labelList&)"
) << "Did not determine new position"
<< " for face " << faceI
<< abort(FatalError);
}
}
return invert(mesh.nFaces(), oldToNewFace);
} }
// Determine face order such that inside region faces are sorted // Determine face order such that inside region faces are sorted
// upper-triangular but inbetween region faces are handled like boundary faces. // upper-triangular but inbetween region faces are handled like boundary faces.
labelList regionFaceOrder labelList getRegionFaceOrder
( (
const primitiveMesh& mesh, const primitiveMesh& mesh,
const labelList& cellOrder, // new to old cell const labelList& cellOrder, // new to old cell
const labelList& cellToRegion // old cell to region const labelList& cellToRegion // old cell to region
) )
{ {
Pout<< "Determining face order:" << endl; //Pout<< "Determining face order:" << endl;
labelList reverseCellOrder(invert(cellOrder.size(), cellOrder)); labelList reverseCellOrder(invert(cellOrder.size(), cellOrder));
@ -131,8 +221,8 @@ labelList regionFaceOrder
if (cellToRegion[oldCellI] != prevRegion) if (cellToRegion[oldCellI] != prevRegion)
{ {
prevRegion = cellToRegion[oldCellI]; prevRegion = cellToRegion[oldCellI];
Pout<< " region " << prevRegion << " internal faces start at " //Pout<< " region " << prevRegion << " internal faces start at "
<< newFaceI << endl; // << newFaceI << endl;
} }
const cell& cFaces = mesh.cells()[oldCellI]; const cell& cFaces = mesh.cells()[oldCellI];
@ -219,9 +309,9 @@ labelList regionFaceOrder
if (prevKey != key) if (prevKey != key)
{ {
Pout<< " faces inbetween region " << key/nRegions //Pout<< " faces inbetween region " << key/nRegions
<< " and " << key%nRegions // << " and " << key%nRegions
<< " start at " << newFaceI << endl; // << " start at " << newFaceI << endl;
prevKey = key; prevKey = key;
} }
@ -243,14 +333,14 @@ labelList regionFaceOrder
{ {
FatalErrorIn FatalErrorIn
( (
"polyDualMesh::getFaceOrder" "getRegionFaceOrder"
"(const labelList&, const labelList&, const label) const" "(const primitveMesh&, const labelList&, const labelList&)"
) << "Did not determine new position" ) << "Did not determine new position"
<< " for face " << faceI << " for face " << faceI
<< abort(FatalError); << abort(FatalError);
} }
} }
Pout<< endl; //Pout<< endl;
return invert(mesh.nFaces(), oldToNewFace); return invert(mesh.nFaces(), oldToNewFace);
} }
@ -365,10 +455,11 @@ autoPtr<mapPolyMesh> reorderMesh
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
argList::addBoolOption argList::addOption
( (
"blockOrder", "blockSize",
"order cells into regions (using decomposition)" "block size",
"order cells into blocks (using decomposition) before ordering"
); );
argList::addBoolOption argList::addBoolOption
( (
@ -400,12 +491,23 @@ int main(int argc, char *argv[])
# include "createNamedMesh.H" # include "createNamedMesh.H"
const word oldInstance = mesh.pointsInstance(); const word oldInstance = mesh.pointsInstance();
const bool blockOrder = args.optionFound("blockOrder"); label blockSize = 0;
if (blockOrder) args.optionReadIfPresent("blockSize", blockSize, 0);
if (blockSize > 0)
{ {
Info<< "Ordering cells into regions (using decomposition);" Info<< "Ordering cells into regions of size " << blockSize
<< " (using decomposition);"
<< " ordering faces into region-internal and region-external." << nl << " ordering faces into region-internal and region-external." << nl
<< endl; << endl;
if (blockSize < 0 || blockSize >= mesh.nCells())
{
FatalErrorIn(args.executable())
<< "Block size " << blockSize << " should be positive integer"
<< " and less than the number of cells in the mesh."
<< exit(FatalError);
}
} }
const bool orderPoints = args.optionFound("orderPoints"); const bool orderPoints = args.optionFound("orderPoints");
@ -432,6 +534,24 @@ int main(int argc, char *argv[])
<< returnReduce(band, maxOp<label>()) << nl << endl; << returnReduce(band, maxOp<label>()) << nl << endl;
// Construct renumberMethod
IOdictionary renumberDict
(
IOobject
(
"renumberMeshDict",
runTime.system(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
autoPtr<renumberMethod> renumberPtr = renumberMethod::New(renumberDict);
Info<< "Selecting renumberMethod " << renumberPtr().type() << endl;
// Read parallel reconstruct maps // Read parallel reconstruct maps
labelIOList cellProcAddressing labelIOList cellProcAddressing
( (
@ -522,13 +642,19 @@ int main(int argc, char *argv[])
ReadFields(mesh, objects, stFlds); ReadFields(mesh, objects, stFlds);
autoPtr<mapPolyMesh> map; // From renumbering:
// - from new cell/face back to original cell/face
labelList cellOrder;
labelList faceOrder;
if (blockOrder) if (blockSize > 0)
{ {
// Renumbering in two phases. Should be done in one so mapping of // Renumbering in two phases. Should be done in one so mapping of
// fields is done correctly! // fields is done correctly!
label nBlocks = mesh.nCells() / blockSize;
Info<< "nBlocks = " << nBlocks << endl;
// Read decomposePar dictionary // Read decomposePar dictionary
IOdictionary decomposeDict IOdictionary decomposeDict
( (
@ -541,6 +667,8 @@ int main(int argc, char *argv[])
IOobject::NO_WRITE IOobject::NO_WRITE
) )
); );
decomposeDict.set("numberOfSubdomains", nBlocks);
autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
( (
decomposeDict decomposeDict
@ -556,80 +684,99 @@ int main(int argc, char *argv[])
); );
// For debugging: write out region // For debugging: write out region
createScalarField
(
mesh,
"cellDist",
cellToRegion
)().write();
Info<< nl << "Written decomposition as volScalarField to "
<< "cellDist for use in postprocessing."
<< nl << endl;
// Find point per region
pointField regionPoints(nBlocks, vector::zero);
forAll(cellToRegion, cellI)
{ {
volScalarField cellDist regionPoints[cellToRegion[cellI]] = mesh.cellCentres()[cellI];
(
IOobject
(
"cellDist",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
mesh,
dimensionedScalar("cellDist", dimless, 0),
zeroGradientFvPatchScalarField::typeName
);
forAll(cellToRegion, cellI)
{
cellDist[cellI] = cellToRegion[cellI];
}
cellDist.write();
Info<< nl << "Written decomposition as volScalarField to "
<< cellDist.name() << " for use in postprocessing."
<< nl << endl;
} }
// Use block based renumbering. // Use block based renumbering.
//labelList cellOrder(bandCompression(mesh.cellCells())); // Detemines old to new cell ordering
labelList cellOrder(regionBandCompression(mesh, cellToRegion)); labelList reverseCellOrder = renumberPtr().renumber
// Determine new to old face order with new cell numbering
labelList faceOrder
( (
regionFaceOrder mesh,
( cellToRegion,
mesh, regionPoints
cellOrder,
cellToRegion
)
); );
if (!overwrite) cellOrder = invert(mesh.nCells(), reverseCellOrder);
{
runTime++;
}
// Change the mesh. // Determine new to old face order with new cell numbering
map = reorderMesh(mesh, cellOrder, faceOrder); faceOrder = getRegionFaceOrder
(
mesh,
cellOrder,
cellToRegion
);
} }
else else
{ {
// Use built-in renumbering. // Detemines old to new cell ordering
labelList reverseCellOrder = renumberPtr().renumber
polyTopoChange meshMod(mesh);
if (!overwrite)
{
runTime++;
}
// Change the mesh.
map = meshMod.changeMesh
( (
mesh, mesh,
false, // inflate mesh.cellCentres()
true, // parallel sync );
true, // cell ordering
orderPoints // point ordering cellOrder = invert(mesh.nCells(), reverseCellOrder);
// Determine new to old face order with new cell numbering
faceOrder = getFaceOrder
(
mesh,
cellOrder // new to old cell
); );
} }
if (!overwrite)
{
runTime++;
}
// Change the mesh.
autoPtr<mapPolyMesh> map = reorderMesh(mesh, cellOrder, faceOrder);
if (orderPoints)
{
polyTopoChange meshMod(mesh);
autoPtr<mapPolyMesh> pointOrderMap = meshMod.changeMesh
(
mesh,
false, //inflate
true, //syncParallel
false, //orderCells
orderPoints //orderPoints
);
// Combine point reordering into map.
const_cast<labelList&>(map().pointMap()) = UIndirectList<label>
(
map().pointMap(),
pointOrderMap().pointMap()
)();
inplaceRenumber
(
pointOrderMap().reversePointMap(),
const_cast<labelList&>(map().reversePointMap())
);
}
// Update fields // Update fields
mesh.updateMesh(map); mesh.updateMesh(map);
@ -767,6 +914,24 @@ int main(int argc, char *argv[])
if (writeMaps) if (writeMaps)
{ {
// For debugging: write out region
createScalarField
(
mesh,
"origCellID",
map().cellMap()
)().write();
createScalarField
(
mesh,
"cellID",
identity(mesh.nCells())
)().write();
Info<< nl << "Written current cellID and origCellID as volScalarField"
<< " for use in postprocessing."
<< nl << endl;
labelIOList labelIOList
( (
IOobject IOobject

View File

@ -0,0 +1,51 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: dev |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
note "mesh renumbering dictionary";
object renumberMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
method CuthillMcKee;
//method manual;
//method random;
//method spring;
CuthillMcKeeCoeffs
{
// Reverse CuthillMcKee (RCM) or plain
reverse true;
}
manualCoeffs
{
// In system directory: old to new labelIOList
dataFile "cellMap";
}
springCoeffs
{
// Maximum jump of cell indices. Is fraction of number of cells
maxCo 0.1;
// Limit the amount of movement; the fraction maxCo gets decreased
// with every iteration
freezeFraction 0.9;
// Maximum number of iterations
maxIter 1000;
}
// ************************************************************************* //

View File

@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 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 "CuthillMcKeeRenumber.H"
#include "addToRunTimeSelectionTable.H"
#include "bandCompression.H"
#include "decompositionMethod.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(CuthillMcKeeRenumber, 0);
addToRunTimeSelectionTable
(
renumberMethod,
CuthillMcKeeRenumber,
dictionary
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::CuthillMcKeeRenumber::CuthillMcKeeRenumber(const dictionary& renumberDict)
:
renumberMethod(renumberDict),
reverse_
(
renumberDict.found(typeName + "Coeffs")
? Switch(renumberDict.subDict(typeName + "Coeffs").lookup("reverse"))
: Switch(true)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::labelList Foam::CuthillMcKeeRenumber::renumber
(
const polyMesh& mesh,
const pointField& points
)
{
CompactListList<label> cellCells;
decompositionMethod::calcCellCells
(
mesh,
identity(mesh.nCells()),
mesh.nCells(),
false, // local only
cellCells
);
labelList orderedToOld = bandCompression(cellCells());
if (reverse_)
{
Pout<< "** REverseing.." << endl;
for (label i = 0; i < orderedToOld.size()/2; i++)
{
Swap(orderedToOld[i], orderedToOld[orderedToOld.size()-i-1]);
}
}
return invert(orderedToOld.size(), orderedToOld);
}
Foam::labelList Foam::CuthillMcKeeRenumber::renumber
(
const labelListList& cellCells,
const pointField& points
)
{
labelList orderedToOld = bandCompression(cellCells);
if (reverse_)
{
Pout<< "** REverseing.." << endl;
for (label i = 0; i < orderedToOld.size()/2; i++)
{
Swap(orderedToOld[i], orderedToOld[orderedToOld.size()-i-1]);
}
}
return invert(orderedToOld.size(), orderedToOld);
}
// ************************************************************************* //