diff --git a/applications/utilities/mesh/manipulation/renumberMesh/Make/options b/applications/utilities/mesh/manipulation/renumberMesh/Make/options index b5e293282a48fcc11891c2222ad3a6b75ee23d2f..2981cf30bea351bd387501cbaa5c65443ae6b769 100644 --- a/applications/utilities/mesh/manipulation/renumberMesh/Make/options +++ b/applications/utilities/mesh/manipulation/renumberMesh/Make/options @@ -2,6 +2,7 @@ EXE_INC = \ -I$(LIB_SRC)/meshTools/lnInclude \ -I$(LIB_SRC)/dynamicMesh/lnInclude \ -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/renumberMethods/lnInclude \ -I$(LIB_SRC)/parallel/decompose/decompositionMethods/lnInclude EXE_LIBS = \ @@ -9,4 +10,5 @@ EXE_LIBS = \ -ldynamicMesh \ -lfiniteVolume \ -lgenericPatchFields \ + -lrenumberMethods \ -ldecompositionMethods diff --git a/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C b/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C index 8d9b0c91ebab1b0c35cb032be821c1c711c7292a..4bb6512a35fbaa331ec7753811f43c2330981143 100644 --- a/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C +++ b/applications/utilities/mesh/manipulation/renumberMesh/renumberMesh.C @@ -37,16 +37,51 @@ Description #include "ReadFields.H" #include "volFields.H" #include "surfaceFields.H" -#include "bandCompression.H" -#include "faceSet.H" #include "SortableList.H" #include "decompositionMethod.H" -#include "fvMeshSubset.H" +#include "renumberMethod.H" #include "zeroGradientFvPatchFields.H" 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 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 -labelList regionBandCompression +// Determine upper-triangular face order +labelList getFaceOrder ( - const fvMesh& mesh, - const labelList& cellToRegion + const primitiveMesh& mesh, + const labelList& cellOrder // new to old cell ) { - Pout<< "Determining cell order:" << endl; - - labelList cellOrder(cellToRegion.size()); + labelList reverseCellOrder(invert(cellOrder.size(), cellOrder)); - label nRegions = max(cellToRegion)+1; + labelList oldToNewFace(mesh.nFaces(), -1); - labelListList regionToCells(invertOneToMany(nRegions, cellToRegion)); + label newFaceI = 0; - label cellI = 0; + labelList nbr; + labelList order; - forAll(regionToCells, regionI) + forAll(cellOrder, newCellI) { - Pout<< " region " << regionI << " starts at " << cellI << endl; + label oldCellI = cellOrder[newCellI]; - // Per region do a reordering. - fvMeshSubset subsetter(mesh); - subsetter.setLargeCellSubset(cellToRegion, regionI); - const fvMesh& subMesh = subsetter.subMesh(); - labelList subCellOrder(bandCompression(subMesh.cellCells())); + const cell& cFaces = mesh.cells()[oldCellI]; - const labelList& cellMap = subsetter.cellMap(); + // Neighbouring cells + nbr.setSize(cFaces.size()); - forAll(subCellOrder, i) + forAll(cFaces, 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++; + } + } + } + + // 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) { - cellOrder[cellI++] = cellMap[subCellOrder[i]]; + FatalErrorIn + ( + "getFaceOrder" + "(const primitiveMesh&, const labelList&, const labelList&)" + ) << "Did not determine new position" + << " for face " << faceI + << abort(FatalError); } } - Pout<< endl; - return cellOrder; + return invert(mesh.nFaces(), oldToNewFace); } // Determine face order such that inside region faces are sorted // upper-triangular but inbetween region faces are handled like boundary faces. -labelList regionFaceOrder +labelList getRegionFaceOrder ( const primitiveMesh& mesh, const labelList& cellOrder, // new to old cell const labelList& cellToRegion // old cell to region ) { - Pout<< "Determining face order:" << endl; + //Pout<< "Determining face order:" << endl; labelList reverseCellOrder(invert(cellOrder.size(), cellOrder)); @@ -131,8 +221,8 @@ labelList regionFaceOrder if (cellToRegion[oldCellI] != prevRegion) { prevRegion = cellToRegion[oldCellI]; - Pout<< " region " << prevRegion << " internal faces start at " - << newFaceI << endl; + //Pout<< " region " << prevRegion << " internal faces start at " + // << newFaceI << endl; } const cell& cFaces = mesh.cells()[oldCellI]; @@ -219,9 +309,9 @@ labelList regionFaceOrder if (prevKey != key) { - Pout<< " faces inbetween region " << key/nRegions - << " and " << key%nRegions - << " start at " << newFaceI << endl; + //Pout<< " faces inbetween region " << key/nRegions + // << " and " << key%nRegions + // << " start at " << newFaceI << endl; prevKey = key; } @@ -243,14 +333,14 @@ labelList regionFaceOrder { FatalErrorIn ( - "polyDualMesh::getFaceOrder" - "(const labelList&, const labelList&, const label) const" + "getRegionFaceOrder" + "(const primitveMesh&, const labelList&, const labelList&)" ) << "Did not determine new position" << " for face " << faceI << abort(FatalError); } } - Pout<< endl; + //Pout<< endl; return invert(mesh.nFaces(), oldToNewFace); } @@ -365,10 +455,11 @@ autoPtr<mapPolyMesh> reorderMesh int main(int argc, char *argv[]) { - argList::addBoolOption + argList::addOption ( - "blockOrder", - "order cells into regions (using decomposition)" + "blockSize", + "block size", + "order cells into blocks (using decomposition) before ordering" ); argList::addBoolOption ( @@ -400,12 +491,23 @@ int main(int argc, char *argv[]) # include "createNamedMesh.H" const word oldInstance = mesh.pointsInstance(); - const bool blockOrder = args.optionFound("blockOrder"); - if (blockOrder) + label blockSize = 0; + 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 << 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"); @@ -432,6 +534,24 @@ int main(int argc, char *argv[]) << 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 labelIOList cellProcAddressing ( @@ -522,13 +642,19 @@ int main(int argc, char *argv[]) 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 // fields is done correctly! + label nBlocks = mesh.nCells() / blockSize; + Info<< "nBlocks = " << nBlocks << endl; + // Read decomposePar dictionary IOdictionary decomposeDict ( @@ -541,6 +667,8 @@ int main(int argc, char *argv[]) IOobject::NO_WRITE ) ); + decomposeDict.set("numberOfSubdomains", nBlocks); + autoPtr<decompositionMethod> decomposePtr = decompositionMethod::New ( decomposeDict @@ -556,80 +684,99 @@ int main(int argc, char *argv[]) ); // For debugging: write out region - { - volScalarField cellDist - ( - IOobject - ( - "cellDist", - runTime.timeName(), - mesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false - ), - mesh, - dimensionedScalar("cellDist", dimless, 0), - zeroGradientFvPatchScalarField::typeName - ); + createScalarField + ( + mesh, + "cellDist", + cellToRegion + )().write(); - forAll(cellToRegion, cellI) - { - cellDist[cellI] = cellToRegion[cellI]; - } + Info<< nl << "Written decomposition as volScalarField to " + << "cellDist for use in postprocessing." + << nl << endl; - cellDist.write(); - Info<< nl << "Written decomposition as volScalarField to " - << cellDist.name() << " for use in postprocessing." - << nl << endl; + // Find point per region + pointField regionPoints(nBlocks, vector::zero); + forAll(cellToRegion, cellI) + { + regionPoints[cellToRegion[cellI]] = mesh.cellCentres()[cellI]; } // Use block based renumbering. - //labelList cellOrder(bandCompression(mesh.cellCells())); - labelList cellOrder(regionBandCompression(mesh, cellToRegion)); + // Detemines old to new cell ordering + labelList reverseCellOrder = renumberPtr().renumber + ( + mesh, + cellToRegion, + regionPoints + ); + + cellOrder = invert(mesh.nCells(), reverseCellOrder); // Determine new to old face order with new cell numbering - labelList faceOrder + faceOrder = getRegionFaceOrder ( - regionFaceOrder - ( - mesh, - cellOrder, - cellToRegion - ) + mesh, + cellOrder, + cellToRegion + ); + } + else + { + // Detemines old to new cell ordering + labelList reverseCellOrder = renumberPtr().renumber + ( + mesh, + mesh.cellCentres() ); - if (!overwrite) - { - runTime++; - } + cellOrder = invert(mesh.nCells(), reverseCellOrder); - // Change the mesh. - map = reorderMesh(mesh, cellOrder, faceOrder); + // Determine new to old face order with new cell numbering + faceOrder = getFaceOrder + ( + mesh, + cellOrder // new to old cell + ); } - else + + + if (!overwrite) { - // Use built-in renumbering. + runTime++; + } - polyTopoChange meshMod(mesh); - if (!overwrite) - { - runTime++; - } + // Change the mesh. + autoPtr<mapPolyMesh> map = reorderMesh(mesh, cellOrder, faceOrder); - // Change the mesh. - map = meshMod.changeMesh + + if (orderPoints) + { + polyTopoChange meshMod(mesh); + autoPtr<mapPolyMesh> pointOrderMap = meshMod.changeMesh ( mesh, - false, // inflate - true, // parallel sync - true, // cell ordering - orderPoints // point ordering + 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 mesh.updateMesh(map); @@ -767,6 +914,24 @@ int main(int argc, char *argv[]) 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 ( IOobject diff --git a/applications/utilities/mesh/manipulation/renumberMesh/renumberMeshDict b/applications/utilities/mesh/manipulation/renumberMesh/renumberMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..7cd0fb8c5168a8d5eb3c7bcf3b958b2e24173c56 --- /dev/null +++ b/applications/utilities/mesh/manipulation/renumberMesh/renumberMeshDict @@ -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; +} + + +// ************************************************************************* // diff --git a/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.C b/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.C new file mode 100644 index 0000000000000000000000000000000000000000..29e9e19683217128fb3888e319fe7cb3b1892f65 --- /dev/null +++ b/src/renumberMethods/CuthillMcKeeRenumber/CuthillMcKeeRenumber.C @@ -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); +} + + +// ************************************************************************* //