diff --git a/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C b/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C index 00efb6f237f570c4665fd46c25eebf8c40889de3..284110b2c58ea598e2dc6c62ca05fc39cd4295dd 100644 --- a/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C +++ b/applications/utilities/parallelProcessing/reconstructParMesh/reconstructParMesh.C @@ -39,7 +39,8 @@ Description \*---------------------------------------------------------------------------*/ #include "argList.H" -#include "Time.H" +#include "timeSelector.H" + #include "IOobjectList.H" #include "labelIOList.H" #include "processorPolyPatch.H" @@ -278,6 +279,151 @@ autoPtr<mapPolyMesh> mergeSharedPoints } +boundBox procBounds +( + const argList& args, + const PtrList<Time>& databases, + const word& regionDir +) +{ + boundBox bb = boundBox::invertedBox; + + forAll(databases, procI) + { + fileName pointsInstance + ( + databases[procI].findInstance + ( + regionDir/polyMesh::meshSubDir, + "points" + ) + ); + + if (pointsInstance != databases[procI].timeName()) + { + FatalErrorIn(args.executable()) + << "Your time was specified as " << databases[procI].timeName() + << " but there is no polyMesh/points in that time." << endl + << "(there is a points file in " << pointsInstance + << ")" << endl + << "Please rerun with the correct time specified" + << " (through the -constant, -time or -latestTime " + << "(at your option)." + << endl << exit(FatalError); + } + + Info<< "Reading points from " + << databases[procI].caseName() + << " for time = " << databases[procI].timeName() + << nl << endl; + + pointIOField points + ( + IOobject + ( + "points", + databases[procI].findInstance + ( + regionDir/polyMesh::meshSubDir, + "points" + ), + regionDir/polyMesh::meshSubDir, + databases[procI], + IOobject::MUST_READ, + IOobject::NO_WRITE, + false + ) + ); + + boundBox domainBb(points, false); + + bb.min() = min(bb.min(), domainBb.min()); + bb.max() = max(bb.max(), domainBb.max()); + } + + return bb; +} + + +void writeCellDistance +( + Time& runTime, + const fvMesh& masterMesh, + const labelListList& cellProcAddressing + +) +{ + // Write the decomposition as labelList for use with 'manual' + // decomposition method. + labelIOList cellDecomposition + ( + IOobject + ( + "cellDecomposition", + masterMesh.facesInstance(), + masterMesh, + IOobject::NO_READ, + IOobject::NO_WRITE, + false + ), + masterMesh.nCells() + ); + + forAll(cellProcAddressing, procI) + { + const labelList& pCells = cellProcAddressing[procI]; + UIndirectList<label>(cellDecomposition, pCells) = procI; + } + + cellDecomposition.write(); + + Info<< nl << "Wrote decomposition to " + << cellDecomposition.objectPath() + << " for use in manual decomposition." << endl; + + + // Write as volScalarField for postprocessing. Change time to 0 + // if was 'constant' + { + const scalar oldTime = runTime.value(); + const label oldIndex = runTime.timeIndex(); + if (runTime.timeName() == runTime.constant() && oldIndex == 0) + { + runTime.setTime(0, oldIndex+1); + } + + volScalarField cellDist + ( + IOobject + ( + "cellDist", + runTime.timeName(), + masterMesh, + IOobject::NO_READ, + IOobject::AUTO_WRITE + ), + masterMesh, + dimensionedScalar("cellDist", dimless, 0), + zeroGradientFvPatchScalarField::typeName + ); + + forAll(cellDecomposition, cellI) + { + cellDist[cellI] = cellDecomposition[cellI]; + } + + cellDist.write(); + + Info<< nl << "Wrote decomposition as volScalarField to " + << cellDist.name() << " for use in postprocessing." + << endl; + + // Restore time + runTime.setTime(oldTime, oldIndex); + } +} + + int main(int argc, char *argv[]) { argList::addNote @@ -390,7 +536,7 @@ int main(int argc, char *argv[]) Info<< "Found " << nProcs << " processor directories" << nl << endl; - // Read all databases. + // Read all time databases PtrList<Time> databases(nProcs); forAll(databases, procI) @@ -409,447 +555,339 @@ int main(int argc, char *argv[]) args.caseName()/fileName(word("processor") + name(procI)) ) ); + } - Time& procTime = databases[procI]; - - instantList Times = procTime.times(); - // set startTime and endTime depending on -time and -latestTime options -# include "checkTimeOptions.H" + // use the times list from the master processor + // and select a subset based on the command-line options + instantList Times = timeSelector::select + ( + databases[0].times(), + args + ); - procTime.setTime(Times[startTime], startTime); + // set startTime and endTime depending on -time and -latestTime options + #include "checkTimeOptions.H" - if (procI > 0 && databases[procI-1].value() != procTime.value()) - { - FatalErrorIn(args.executable()) - << "Time not equal on processors." << nl - << "Processor:" << procI-1 - << " time:" << databases[procI-1].value() << nl - << "Processor:" << procI - << " time:" << procTime.value() - << exit(FatalError); - } + if (Times.empty()) + { + FatalErrorIn(args.executable()) + << "No times selected" + << exit(FatalError); } - // Set master time - Info<< "Setting master time to " << databases[0].timeName() << nl << endl; - runTime.setTime(databases[0]); - - // Read point on individual processors to determine merge tolerance - // (otherwise single cell domains might give problems) - - boundBox bb = boundBox::invertedBox; - - for (label procI = 0; procI < nProcs; procI++) + // Loop over all times + forAll(Times, timeI) { - fileName pointsInstance - ( - databases[procI].findInstance - ( - regionDir/polyMesh::meshSubDir, - "points" - ) - ); + // Set time for global database + runTime.setTime(Times[timeI], timeI); - if (pointsInstance != databases[procI].timeName()) + Info<< "Time = " << runTime.timeName() << endl << endl; + + // Set time for all databases + forAll(databases, procI) { - FatalErrorIn(args.executable()) - << "Your time was specified as " << databases[procI].timeName() - << " but there is no polyMesh/points in that time." << endl - << "(there is a points file in " << pointsInstance - << ")" << endl - << "Please rerun with the correct time specified" - << " (through the -constant, -time or -latestTime " - << "(at your option)." - << endl << exit(FatalError); + databases[procI].setTime(Times[timeI], timeI); } - Info<< "Reading points from " - << databases[procI].caseName() - << " for time = " << databases[procI].timeName() - << nl << endl; + // Read point on individual processors to determine merge tolerance + // (otherwise single cell domains might give problems) - pointIOField points - ( - IOobject - ( - "points", - databases[procI].findInstance - ( - regionDir/polyMesh::meshSubDir, - "points" - ), - regionDir/polyMesh::meshSubDir, - databases[procI], - IOobject::MUST_READ, - IOobject::NO_WRITE, - false - ) - ); - - boundBox domainBb(points, false); - - bb.min() = min(bb.min(), domainBb.min()); - bb.max() = max(bb.max(), domainBb.max()); - } - const scalar mergeDist = mergeTol * bb.mag(); - - Info<< "Overall mesh bounding box : " << bb << nl - << "Relative tolerance : " << mergeTol << nl - << "Absolute matching distance : " << mergeDist << nl - << endl; + const boundBox bb = procBounds(args, databases, regionDir); + const scalar mergeDist = mergeTol*bb.mag(); + Info<< "Overall mesh bounding box : " << bb << nl + << "Relative tolerance : " << mergeTol << nl + << "Absolute matching distance : " << mergeDist << nl + << endl; - // Addressing from processor to reconstructed case - labelListList cellProcAddressing(nProcs); - labelListList faceProcAddressing(nProcs); - labelListList pointProcAddressing(nProcs); - labelListList boundaryProcAddressing(nProcs); - // Internal faces on the final reconstructed mesh - label masterInternalFaces; - // Owner addressing on the final reconstructed mesh - labelList masterOwner; + // Addressing from processor to reconstructed case + labelListList cellProcAddressing(nProcs); + labelListList faceProcAddressing(nProcs); + labelListList pointProcAddressing(nProcs); + labelListList boundaryProcAddressing(nProcs); - { - // Construct empty mesh. - Info<< "Constructing empty mesh to add to." << nl << endl; - fvMesh masterMesh - ( - IOobject - ( - regionName, - runTime.timeName(), - runTime, - IOobject::NO_READ - ), - xferCopy(pointField()), - xferCopy(faceList()), - xferCopy(cellList()) - ); + // Internal faces on the final reconstructed mesh + label masterInternalFaces; + // Owner addressing on the final reconstructed mesh + labelList masterOwner; - for (label procI = 0; procI < nProcs; procI++) { - Info<< "Reading mesh to add from " - << databases[procI].caseName() - << " for time = " << databases[procI].timeName() - << nl << endl; - - fvMesh meshToAdd + // Construct empty mesh. + Info<< "Constructing empty mesh to add to." << nl << endl; + fvMesh masterMesh ( IOobject ( regionName, - databases[procI].timeName(), - databases[procI] - ) - ); - - // Initialize its addressing - cellProcAddressing[procI] = identity(meshToAdd.nCells()); - faceProcAddressing[procI] = identity(meshToAdd.nFaces()); - pointProcAddressing[procI] = identity(meshToAdd.nPoints()); - boundaryProcAddressing[procI] = - identity(meshToAdd.boundaryMesh().size()); - - - // Find geometrically shared points/faces. - autoPtr<faceCoupleInfo> couples = determineCoupledFaces - ( - fullMatch, - procI, - masterMesh, - meshToAdd, - mergeDist - ); - - - // Add elements to mesh - Info<< "Adding to master mesh" << nl << endl; - - autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add - ( - masterMesh, - meshToAdd, - couples + runTime.timeName(), + runTime, + IOobject::NO_READ + ), + xferCopy(pointField()), + xferCopy(faceList()), + xferCopy(cellList()) ); - // Update all addressing so xxProcAddressing points to correct item - // in masterMesh. - - // Processors that were already in masterMesh - for (label mergedI = 0; mergedI < procI; mergedI++) + for (label procI = 0; procI < nProcs; procI++) { - renumber(map().oldCellMap(), cellProcAddressing[mergedI]); - renumber(map().oldFaceMap(), faceProcAddressing[mergedI]); - renumber(map().oldPointMap(), pointProcAddressing[mergedI]); - // Note: boundary is special since can contain -1. - renumber(map().oldPatchMap(), boundaryProcAddressing[mergedI]); - } - - // Added processor - renumber(map().addedCellMap(), cellProcAddressing[procI]); - renumber(map().addedFaceMap(), faceProcAddressing[procI]); - renumber(map().addedPointMap(), pointProcAddressing[procI]); - renumber(map().addedPatchMap(), boundaryProcAddressing[procI]); - - Info<< endl; - } - - // See if any points on the mastermesh have become connected - // because of connections through processor meshes. - mergeSharedPoints(mergeDist, masterMesh, pointProcAddressing); + Info<< "Reading mesh to add from " + << databases[procI].caseName() + << " for time = " << databases[procI].timeName() + << nl << endl; - // Save some properties on the reconstructed mesh - masterInternalFaces = masterMesh.nInternalFaces(); - masterOwner = masterMesh.faceOwner(); + fvMesh meshToAdd + ( + IOobject + ( + regionName, + databases[procI].timeName(), + databases[procI] + ) + ); + // Initialize its addressing + cellProcAddressing[procI] = identity(meshToAdd.nCells()); + faceProcAddressing[procI] = identity(meshToAdd.nFaces()); + pointProcAddressing[procI] = identity(meshToAdd.nPoints()); + boundaryProcAddressing[procI] = + identity(meshToAdd.boundaryMesh().size()); - Info<< "\nWriting merged mesh to " - << runTime.path()/runTime.timeName() - << nl << endl; - if (!masterMesh.write()) - { - FatalErrorIn(args.executable()) - << "Failed writing polyMesh." - << exit(FatalError); - } + // Find geometrically shared points/faces. + autoPtr<faceCoupleInfo> couples = determineCoupledFaces + ( + fullMatch, + procI, + masterMesh, + meshToAdd, + mergeDist + ); + // Add elements to mesh + Info<< "Adding to master mesh" << nl << endl; - if (writeCellDist) - { - // Write the decomposition as labelList for use with 'manual' - // decomposition method. - labelIOList cellDecomposition - ( - IOobject + autoPtr<mapAddedPolyMesh> map = fvMeshAdder::add ( - "cellDecomposition", - masterMesh.facesInstance(), masterMesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false - ), - masterMesh.nCells() - ); + meshToAdd, + couples + ); - forAll(cellProcAddressing, procI) - { - const labelList& pCells = cellProcAddressing[procI]; - UIndirectList<label>(cellDecomposition, pCells) = procI; - } + // Update all addressing so xxProcAddressing points to correct + // item in masterMesh. - cellDecomposition.write(); + // Processors that were already in masterMesh + for (label mergedI = 0; mergedI < procI; mergedI++) + { + renumber(map().oldCellMap(), cellProcAddressing[mergedI]); + renumber(map().oldFaceMap(), faceProcAddressing[mergedI]); + renumber(map().oldPointMap(), pointProcAddressing[mergedI]); + // Note: boundary is special since can contain -1. + renumber + ( + map().oldPatchMap(), + boundaryProcAddressing[mergedI] + ); + } - Info<< nl << "Wrote decomposition to " - << cellDecomposition.objectPath() - << " for use in manual decomposition." << endl; + // Added processor + renumber(map().addedCellMap(), cellProcAddressing[procI]); + renumber(map().addedFaceMap(), faceProcAddressing[procI]); + renumber(map().addedPointMap(), pointProcAddressing[procI]); + renumber(map().addedPatchMap(), boundaryProcAddressing[procI]); + Info<< endl; + } - // Write as volScalarField for postprocessing. Change time to 0 - // if was 'constant' - { - const scalar oldTime = runTime.value(); - const label oldIndex = runTime.timeIndex(); - if (runTime.timeName() == runTime.constant() && oldIndex == 0) - { - runTime.setTime(0, oldIndex+1); - } + // See if any points on the mastermesh have become connected + // because of connections through processor meshes. + mergeSharedPoints(mergeDist, masterMesh, pointProcAddressing); - volScalarField cellDist - ( - IOobject - ( - "cellDist", - runTime.timeName(), - masterMesh, - IOobject::NO_READ, - IOobject::AUTO_WRITE - ), - masterMesh, - dimensionedScalar("cellDist", dimless, 0), - zeroGradientFvPatchScalarField::typeName - ); + // Save some properties on the reconstructed mesh + masterInternalFaces = masterMesh.nInternalFaces(); + masterOwner = masterMesh.faceOwner(); - forAll(cellDecomposition, cellI) - { - cellDist[cellI] = cellDecomposition[cellI]; - } - cellDist.write(); + Info<< "\nWriting merged mesh to " + << runTime.path()/runTime.timeName() + << nl << endl; - Info<< nl << "Wrote decomposition as volScalarField to " - << cellDist.name() << " for use in postprocessing." - << endl; + if (!masterMesh.write()) + { + FatalErrorIn(args.executable()) + << "Failed writing polyMesh." + << exit(FatalError); + } - // Restore time - runTime.setTime(oldTime, oldIndex); + if (writeCellDist) + { + writeCellDistance(runTime, masterMesh, cellProcAddressing); } } - } - // Write the addressing + // Write the addressing - Info<< "Reconstructing the addressing from the processor meshes" - << " to the newly reconstructed mesh" << nl << endl; + Info<< "Reconstructing the addressing from the processor meshes" + << " to the newly reconstructed mesh" << nl << endl; - forAll(databases, procI) - { - Info<< "Reading processor " << procI << " mesh from " - << databases[procI].caseName() << endl; + forAll(databases, procI) + { + Info<< "Reading processor " << procI << " mesh from " + << databases[procI].caseName() << endl; - polyMesh procMesh - ( - IOobject + polyMesh procMesh ( - regionName, - databases[procI].timeName(), - databases[procI] - ) - ); + IOobject + ( + regionName, + databases[procI].timeName(), + databases[procI] + ) + ); - // From processor point to reconstructed mesh point + // From processor point to reconstructed mesh point - Info<< "Writing pointProcAddressing to " - << databases[procI].caseName() - /procMesh.facesInstance() - /polyMesh::meshSubDir - << endl; + Info<< "Writing pointProcAddressing to " + << databases[procI].caseName() + /procMesh.facesInstance() + /polyMesh::meshSubDir + << endl; - labelIOList - ( - IOobject + labelIOList ( - "pointProcAddressing", - procMesh.facesInstance(), - polyMesh::meshSubDir, - procMesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false // do not register - ), - pointProcAddressing[procI] - ).write(); + IOobject + ( + "pointProcAddressing", + procMesh.facesInstance(), + polyMesh::meshSubDir, + procMesh, + IOobject::NO_READ, + IOobject::NO_WRITE, + false // do not register + ), + pointProcAddressing[procI] + ).write(); - // From processor face to reconstructed mesh face + // From processor face to reconstructed mesh face - Info<< "Writing faceProcAddressing to " - << databases[procI].caseName() - /procMesh.facesInstance() - /polyMesh::meshSubDir - << endl; + Info<< "Writing faceProcAddressing to " + << databases[procI].caseName() + /procMesh.facesInstance() + /polyMesh::meshSubDir + << endl; - labelIOList faceProcAddr - ( - IOobject + labelIOList faceProcAddr ( - "faceProcAddressing", - procMesh.facesInstance(), - polyMesh::meshSubDir, - procMesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false // do not register - ), - faceProcAddressing[procI] - ); - - // Now add turning index to faceProcAddressing. - // See reconstrurPar for meaning of turning index. - forAll(faceProcAddr, procFaceI) - { - label masterFaceI = faceProcAddr[procFaceI]; + IOobject + ( + "faceProcAddressing", + procMesh.facesInstance(), + polyMesh::meshSubDir, + procMesh, + IOobject::NO_READ, + IOobject::NO_WRITE, + false // do not register + ), + faceProcAddressing[procI] + ); - if - ( - !procMesh.isInternalFace(procFaceI) - && masterFaceI < masterInternalFaces - ) + // Now add turning index to faceProcAddressing. + // See reconstrurPar for meaning of turning index. + forAll(faceProcAddr, procFaceI) { - // proc face is now external but used to be internal face. - // Check if we have owner or neighbour. - - label procOwn = procMesh.faceOwner()[procFaceI]; - label masterOwn = masterOwner[masterFaceI]; + label masterFaceI = faceProcAddr[procFaceI]; - if (cellProcAddressing[procI][procOwn] == masterOwn) + if + ( + !procMesh.isInternalFace(procFaceI) + && masterFaceI < masterInternalFaces + ) { - // No turning. Offset by 1. - faceProcAddr[procFaceI]++; + // proc face is now external but used to be internal face. + // Check if we have owner or neighbour. + + label procOwn = procMesh.faceOwner()[procFaceI]; + label masterOwn = masterOwner[masterFaceI]; + + if (cellProcAddressing[procI][procOwn] == masterOwn) + { + // No turning. Offset by 1. + faceProcAddr[procFaceI]++; + } + else + { + // Turned face. + faceProcAddr[procFaceI] = + -1 - faceProcAddr[procFaceI]; + } } else { - // Turned face. - faceProcAddr[procFaceI] = - -1 - faceProcAddr[procFaceI]; + // No turning. Offset by 1. + faceProcAddr[procFaceI]++; } } - else - { - // No turning. Offset by 1. - faceProcAddr[procFaceI]++; - } - } - faceProcAddr.write(); + faceProcAddr.write(); - // From processor cell to reconstructed mesh cell + // From processor cell to reconstructed mesh cell - Info<< "Writing cellProcAddressing to " - << databases[procI].caseName() - /procMesh.facesInstance() - /polyMesh::meshSubDir - << endl; + Info<< "Writing cellProcAddressing to " + << databases[procI].caseName() + /procMesh.facesInstance() + /polyMesh::meshSubDir + << endl; - labelIOList - ( - IOobject + labelIOList ( - "cellProcAddressing", - procMesh.facesInstance(), - polyMesh::meshSubDir, - procMesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false // do not register - ), - cellProcAddressing[procI] - ).write(); + IOobject + ( + "cellProcAddressing", + procMesh.facesInstance(), + polyMesh::meshSubDir, + procMesh, + IOobject::NO_READ, + IOobject::NO_WRITE, + false // do not register + ), + cellProcAddressing[procI] + ).write(); - // From processor patch to reconstructed mesh patch + // From processor patch to reconstructed mesh patch - Info<< "Writing boundaryProcAddressing to " - << databases[procI].caseName() - /procMesh.facesInstance() - /polyMesh::meshSubDir - << endl; + Info<< "Writing boundaryProcAddressing to " + << databases[procI].caseName() + /procMesh.facesInstance() + /polyMesh::meshSubDir + << endl; - labelIOList - ( - IOobject + labelIOList ( - "boundaryProcAddressing", - procMesh.facesInstance(), - polyMesh::meshSubDir, - procMesh, - IOobject::NO_READ, - IOobject::NO_WRITE, - false // do not register - ), - boundaryProcAddressing[procI] - ).write(); + IOobject + ( + "boundaryProcAddressing", + procMesh.facesInstance(), + polyMesh::meshSubDir, + procMesh, + IOobject::NO_READ, + IOobject::NO_WRITE, + false // do not register + ), + boundaryProcAddressing[procI] + ).write(); - Info<< endl; + Info<< endl; + } }