ENH: renumberMesh: get block ordering working

- added boundaryFirst renumbering method
- renumbering in parallel
- make api methods const
This commit is contained in:
mattijs
2011-12-21 15:13:04 +00:00
parent c037d24848
commit 704b33fa79
16 changed files with 473 additions and 82 deletions

View File

@ -11,4 +11,4 @@ EXE_LIBS = \
-lfiniteVolume \
-lgenericPatchFields \
-lrenumberMethods \
-ldecompositionMethods
-ldecompositionMethods -L$(FOAM_LIBBIN)/dummy -lmetisDecomp -lscotchDecomp

View File

@ -29,7 +29,7 @@ Description
renumbering all fields from all the time directories.
By default uses bandCompression (CuthillMcKee) but will
read system/renumberMeshDict if present and use the method from there.
read system/renumberMeshDict if -dict option is present
\*---------------------------------------------------------------------------*/
@ -45,6 +45,7 @@ Description
#include "renumberMethod.H"
#include "zeroGradientFvPatchFields.H"
#include "CuthillMcKeeRenumber.H"
#include "fvMeshSubset.H"
using namespace Foam;
@ -455,6 +456,69 @@ autoPtr<mapPolyMesh> reorderMesh
}
// Return new to old cell numbering
labelList regionRenumber
(
const renumberMethod& method,
const fvMesh& mesh,
const labelList& cellToRegion
)
{
Info<< "Determining cell order:" << endl;
labelList cellOrder(cellToRegion.size());
label nRegions = max(cellToRegion)+1;
labelListList regionToCells(invertOneToMany(nRegions, cellToRegion));
label cellI = 0;
forAll(regionToCells, regionI)
{
Info<< " region " << regionI << " starts at " << cellI << endl;
// Make sure no parallel comms
bool oldParRun = UPstream::parRun();
UPstream::parRun() = false;
// Per region do a reordering.
fvMeshSubset subsetter(mesh);
subsetter.setLargeCellSubset(cellToRegion, regionI);
const fvMesh& subMesh = subsetter.subMesh();
labelList subReverseCellOrder = method.renumber
(
subMesh,
subMesh.cellCentres()
);
labelList subCellOrder
(
invert
(
subMesh.nCells(),
subReverseCellOrder
)
);
// Restore state
UPstream::parRun() = oldParRun;
const labelList& cellMap = subsetter.cellMap();
forAll(subCellOrder, i)
{
cellOrder[cellI++] = cellMap[subCellOrder[i]];
}
}
Info<< endl;
return cellOrder;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
@ -505,23 +569,28 @@ int main(int argc, char *argv[])
label blockSize = 0;
// Construct renumberMethod
autoPtr<IOdictionary> renumberDictPtr;
autoPtr<renumberMethod> renumberPtr;
if (readDict)
{
Info<< "Renumber according to renumberMeshDict." << nl << endl;
IOdictionary renumberDict
renumberDictPtr.reset
(
IOobject
new IOdictionary
(
"renumberMeshDict",
runTime.system(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
IOobject
(
"renumberMeshDict",
runTime.system(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
)
);
const IOdictionary renumberDict = renumberDictPtr();
renumberPtr = renumberMethod::New(renumberDict);
@ -683,22 +752,15 @@ int main(int argc, char *argv[])
// fields is done correctly!
label nBlocks = mesh.nCells() / blockSize;
Info<< "nBlocks = " << nBlocks << endl;
Info<< "nBlocks = " << nBlocks << endl;
// Read decomposePar dictionary
IOdictionary decomposeDict
(
IOobject
(
"decomposeParDict",
runTime.system(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
// Read decompositionMethod dictionary
dictionary decomposeDict(renumberDictPtr().subDict("blockCoeffs"));
decomposeDict.set("numberOfSubdomains", nBlocks);
bool oldParRun = UPstream::parRun();
UPstream::parRun() = false;
autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New
(
decomposeDict
@ -713,6 +775,9 @@ int main(int argc, char *argv[])
)
);
// Restore state
UPstream::parRun() = oldParRun;
// For debugging: write out region
createScalarField
(
@ -726,23 +791,7 @@ int main(int argc, char *argv[])
<< nl << endl;
// Find point per region
pointField regionPoints(nBlocks, vector::zero);
forAll(cellToRegion, cellI)
{
regionPoints[cellToRegion[cellI]] = mesh.cellCentres()[cellI];
}
// Use block based renumbering.
// Detemines old to new cell ordering
labelList reverseCellOrder = renumberPtr().renumber
(
mesh,
cellToRegion,
regionPoints
);
cellOrder = invert(mesh.nCells(), reverseCellOrder);
cellOrder = regionRenumber(renumberPtr(), mesh, cellToRegion);
// Determine new to old face order with new cell numbering
faceOrder = getRegionFaceOrder

View File

@ -22,10 +22,14 @@ writeMaps true;
// e.g. nonBlockingGaussSeidel.
sortCoupledFaceCells false;
// Optional entry: renumber on a block-by-block basis. This can be used on
// large cases to keep the blocks fitting in cache with all the the cache
// missed bunched at the end.
//blockSize 0;
// Optional entry: renumber on a block-by-block basis. It uses a
// blockCoeffs dictionary to construct a decompositionMethod to do
// a block subdivision) and then applies the renumberMethod to each
// block in turn. This can be used in large cases to keep the blocks
// fitting in cache with all the the cache misses bunched at the end.
// This number is the approximate size of the blocks - this gets converted
// to a number of blocks that is the input to the decomposition method.
//blockSize 1000;
// Optional entry: sort points into internal and boundary points
//orderPoints false;
@ -37,11 +41,11 @@ method CuthillMcKee;
//method random;
//method spring;
CuthillMcKeeCoeffs
{
// Reverse CuthillMcKee (RCM) or plain
reverse true;
}
//CuthillMcKeeCoeffs
//{
// // Reverse CuthillMcKee (RCM) or plain
// reverse true;
//}
manualCoeffs
@ -65,4 +69,17 @@ springCoeffs
}
blockCoeffs
{
method scotch;
//method hierarchical;
//hierarchicalCoeffs
//{
// n (1 2 1);
// delta 0.001;
// order xyz;
//}
}
// ************************************************************************* //

View File

@ -63,7 +63,7 @@ Foam::labelList Foam::CuthillMcKeeRenumber::renumber
(
const polyMesh& mesh,
const pointField& points
)
) const
{
CompactListList<label> cellCells;
decompositionMethod::calcCellCells
@ -79,10 +79,7 @@ Foam::labelList Foam::CuthillMcKeeRenumber::renumber
if (reverse_)
{
for (label i = 0; i < orderedToOld.size()/2; i++)
{
Swap(orderedToOld[i], orderedToOld[orderedToOld.size()-i-1]);
}
reverse(orderedToOld);
}
return invert(orderedToOld.size(), orderedToOld);
@ -93,16 +90,13 @@ Foam::labelList Foam::CuthillMcKeeRenumber::renumber
(
const labelListList& cellCells,
const pointField& points
)
) const
{
labelList orderedToOld = bandCompression(cellCells);
if (reverse_)
{
for (label i = 0; i < orderedToOld.size()/2; i++)
{
Swap(orderedToOld[i], orderedToOld[orderedToOld.size()-i-1]);
}
reverse(orderedToOld);
}
return invert(orderedToOld.size(), orderedToOld);

View File

@ -82,7 +82,7 @@ public:
//- Return for every coordinate the wanted processor number.
// We need a polyMesh (to be able to load the file)
virtual labelList renumber(const pointField&)
virtual labelList renumber(const pointField&) const
{
notImplemented("CuthillMcKeeRenumber::renumber(const pointField&)");
return labelList(0);
@ -94,7 +94,7 @@ public:
(
const polyMesh& mesh,
const pointField& cc
);
) const;
//- Return for every cell the new cell label.
// The connectivity is equal to mesh.cellCells() except
@ -103,7 +103,7 @@ public:
(
const labelListList& cellCells,
const pointField& cc
);
) const;
};

View File

@ -3,5 +3,6 @@ manualRenumber/manualRenumber.C
CuthillMcKeeRenumber/CuthillMcKeeRenumber.C
randomRenumber/randomRenumber.C
springRenumber/springRenumber.C
boundaryFirstRenumber/boundaryFirstRenumber.C
LIB = $(FOAM_LIBBIN)/librenumberMethods

View File

@ -0,0 +1,201 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "boundaryFirstRenumber.H"
#include "addToRunTimeSelectionTable.H"
#include "bandCompression.H"
#include "decompositionMethod.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(boundaryFirstRenumber, 0);
addToRunTimeSelectionTable
(
renumberMethod,
boundaryFirstRenumber,
dictionary
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::boundaryFirstRenumber::boundaryFirstRenumber
(
const dictionary& renumberDict
)
:
renumberMethod(renumberDict),
reverse_
(
renumberDict.found(typeName + "Coeffs")
? Switch(renumberDict.subDict(typeName + "Coeffs").lookup("reverse"))
: Switch(true)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::labelList Foam::boundaryFirstRenumber::renumber
(
const polyMesh& mesh,
const pointField& points
) const
{
const labelList& own = mesh.faceOwner();
const labelList& nei = mesh.faceNeighbour();
// Distance to boundary. Minimum of neighbours.
labelList distance(mesh.nCells(), -1);
// New order
labelList newOrder(mesh.nCells());
label cellInOrder = 0;
// Starting faces for walk. These are the zero distance faces.
DynamicList<label> frontFaces(mesh.nFaces()-mesh.nInternalFaces());
const polyBoundaryMesh& patches = mesh.boundaryMesh();
forAll(patches, patchI)
{
const polyPatch& pp = patches[patchI];
//- Note: cannot check for empty since these are introduced by
// fvMeshSubset. Also most loops don't care about patch type.
//if (!isA<emptyPolyPatch>(pp))
{
forAll(pp, i)
{
frontFaces.append(pp.start()+i);
}
}
}
// Loop over all frontFaces
label currentDistance = 0;
while (frontFaces.size() > 0)
{
DynamicList<label> frontCells(frontFaces.size());
// Set all of frontFaces' neighbours to current distance
forAll(frontFaces, i)
{
label faceI = frontFaces[i];
if (mesh.isInternalFace(faceI))
{
label ownCellI = own[faceI];
if (distance[ownCellI] == -1)
{
distance[ownCellI] = currentDistance;
frontCells.append(ownCellI);
}
label neiCellI = nei[faceI];
if (distance[neiCellI] == -1)
{
distance[neiCellI] = currentDistance;
frontCells.append(neiCellI);
}
}
else
{
label ownCellI = own[faceI];
if (distance[ownCellI] == -1)
{
distance[ownCellI] = currentDistance;
frontCells.append(ownCellI);
}
}
}
//Pout<< "For distance:" << currentDistance
// << " from " << frontFaces.size() << " faces to "
// << frontCells.size() << " cells." << endl;
// TBD. Determine order within current shell (frontCells). For now
// just add them.
forAll(frontCells, i)
{
newOrder[cellInOrder] = frontCells[i];
cellInOrder++;
}
// From cells to faces
frontFaces.clear();
forAll(frontCells, i)
{
label cellI = frontCells[i];
const cell& cFaces = mesh.cells()[cellI];
forAll(cFaces, i)
{
label faceI = cFaces[i];
if (mesh.isInternalFace(faceI))
{
label nbrCellI =
(
mesh.faceOwner()[faceI] == cellI
? mesh.faceNeighbour()[faceI]
: mesh.faceOwner()[faceI]
);
if (distance[nbrCellI] == -1)
{
frontFaces.append(faceI);
}
}
}
}
currentDistance++;
}
// Return furthest away cell first
if (reverse_)
{
reverse(newOrder);
}
//forAll(newOrder, i)
//{
// label cellI = newOrder[i];
//
// Pout<< "cell:" << cellI << endl;
// Pout<< " at distance:" << distance[cellI]
// << endl;
//}
return invert(newOrder.size(), newOrder);
}
// ************************************************************************* //

View File

@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::boundaryFirstRenumber
Description
Cuthill-McKee renumbering
SourceFiles
boundaryFirstRenumber.C
\*---------------------------------------------------------------------------*/
#ifndef boundaryFirstRenumber_H
#define boundaryFirstRenumber_H
#include "renumberMethod.H"
#include "Switch.H"
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class boundaryFirstRenumber Declaration
\*---------------------------------------------------------------------------*/
class boundaryFirstRenumber
:
public renumberMethod
{
// Private data
const Switch reverse_;
// Private Member Functions
//- Disallow default bitwise copy construct and assignment
void operator=(const boundaryFirstRenumber&);
boundaryFirstRenumber(const boundaryFirstRenumber&);
public:
//- Runtime type information
TypeName("boundaryFirst");
// Constructors
//- Construct given the renumber dictionary
boundaryFirstRenumber(const dictionary& renumberDict);
//- Destructor
virtual ~boundaryFirstRenumber()
{}
// Member Functions
//- Return for every coordinate the wanted processor number.
// We need a polyMesh (to be able to load the file)
virtual labelList renumber(const pointField&) const
{
notImplemented
(
"boundaryFirstRenumber::renumber(const pointField&)"
);
return labelList(0);
}
//- Return for every coordinate the wanted processor number. Use the
// mesh connectivity (if needed)
virtual labelList renumber
(
const polyMesh& mesh,
const pointField& cc
) const;
//- Return for every cell the new cell label.
// The connectivity is equal to mesh.cellCells() except
// - the connections are across coupled patches
virtual labelList renumber
(
const labelListList& cellCells,
const pointField& cc
) const
{
notImplemented
(
"boundaryFirstRenumber::renumber"
"(const labelListList&, const pointField&)"
);
return labelList(0);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -61,7 +61,7 @@ Foam::labelList Foam::manualRenumber::renumber
(
const polyMesh& mesh,
const pointField& points
)
) const
{
labelIOList oldToNew
(

View File

@ -81,7 +81,7 @@ public:
//- Return for every coordinate the wanted processor number.
// We need a polyMesh (to be able to load the file)
virtual labelList renumber(const pointField&)
virtual labelList renumber(const pointField&) const
{
notImplemented("manualRenumber::renumber(const pointField&)");
return labelList(0);
@ -93,7 +93,7 @@ public:
(
const polyMesh& mesh,
const pointField& cc
);
) const;
//- Return for every cell the new cell label.
// The connectivity is equal to mesh.cellCells() except
@ -102,7 +102,7 @@ public:
(
const labelListList& cellCells,
const pointField& cc
)
) const
{
notImplemented
(

View File

@ -55,7 +55,7 @@ Foam::randomRenumber::randomRenumber(const dictionary& renumberDict)
Foam::labelList Foam::randomRenumber::renumber
(
const pointField& points
)
) const
{
Random rndGen(0);
@ -77,7 +77,7 @@ Foam::labelList Foam::randomRenumber::renumber
(
const polyMesh& mesh,
const pointField& points
)
) const
{
return renumber(points);
}
@ -87,7 +87,7 @@ Foam::labelList Foam::randomRenumber::renumber
(
const labelListList& cellCells,
const pointField& points
)
) const
{
return renumber(points);
}

View File

@ -76,7 +76,7 @@ public:
//- Return for every coordinate the wanted processor number.
// We need a polyMesh (to be able to load the file)
virtual labelList renumber(const pointField&);
virtual labelList renumber(const pointField&) const;
//- Return for every coordinate the wanted processor number. Use the
// mesh connectivity (if needed)
@ -84,7 +84,7 @@ public:
(
const polyMesh& mesh,
const pointField& cc
);
) const;
//- Return for every cell the new cell label.
// The connectivity is equal to mesh.cellCells() except
@ -93,7 +93,7 @@ public:
(
const labelListList& cellCells,
const pointField& cc
);
) const;
};

View File

@ -72,7 +72,7 @@ Foam::labelList Foam::renumberMethod::renumber
(
const polyMesh& mesh,
const pointField& points
)
) const
{
CompactListList<label> cellCells;
decompositionMethod::calcCellCells
@ -94,7 +94,7 @@ Foam::labelList Foam::renumberMethod::renumber
const polyMesh& mesh,
const labelList& fineToCoarse,
const pointField& coarsePoints
)
) const
{
CompactListList<label> coarseCellCells;
decompositionMethod::calcCellCells

View File

@ -111,7 +111,7 @@ public:
//- Return for every cell the new cell label.
// This is only defined for geometric renumberMethods.
virtual labelList renumber(const pointField&)
virtual labelList renumber(const pointField&) const
{
notImplemented
(
@ -122,7 +122,7 @@ public:
//- Return for every cell the new cell label. Use the
// mesh connectivity (if needed)
virtual labelList renumber(const polyMesh&, const pointField&);
virtual labelList renumber(const polyMesh&, const pointField&) const;
//- Return for every cell the new cell label. Gets
// passed agglomeration map (from fine to coarse cells) and coarse
@ -136,7 +136,7 @@ public:
const polyMesh& mesh,
const labelList& cellToRegion,
const pointField& regionPoints
);
) const;
//- Return for every cell the new cell label.
// The connectivity is equal to mesh.cellCells() except
@ -145,7 +145,7 @@ public:
(
const labelListList& cellCells,
const pointField& cc
) = 0;
) const = 0;
};

View File

@ -60,7 +60,7 @@ Foam::labelList Foam::springRenumber::renumber
(
const polyMesh& mesh,
const pointField& points
)
) const
{
CompactListList<label> cellCells;
decompositionMethod::calcCellCells
@ -80,7 +80,7 @@ Foam::labelList Foam::springRenumber::renumber
(
const labelListList& cellCells,
const pointField& points
)
) const
{
// Look at cell index as a 1D position parameter.
// Move cells to the average 'position' of their neighbour.

View File

@ -96,7 +96,7 @@ public:
// Member Functions
//- Return for every coordinate the wanted processor number.
virtual labelList renumber(const pointField&)
virtual labelList renumber(const pointField&) const
{
notImplemented("springRenumber::renumber(const pointField&)");
return labelList(0);
@ -108,7 +108,7 @@ public:
(
const polyMesh& mesh,
const pointField& cc
);
) const;
//- Return for every cell the new cell label.
// The connectivity is equal to mesh.cellCells() except
@ -117,7 +117,7 @@ public:
(
const labelListList& cellCells,
const pointField& cc
);
) const;
};