/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd. \\/ 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 . \*---------------------------------------------------------------------------*/ #include "domainDecomposition.H" #include "Time.H" #include "dictionary.H" #include "labelIOList.H" #include "processorPolyPatch.H" #include "processorCyclicPolyPatch.H" #include "fvMesh.H" #include "OSspecific.H" #include "Map.H" #include "globalMeshData.H" #include "DynamicList.H" #include "fvFieldDecomposer.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::domainDecomposition::mark ( const labelList& zoneElems, const label zoneI, labelList& elementToZone ) { forAll(zoneElems, i) { label pointi = zoneElems[i]; if (elementToZone[pointi] == -1) { // First occurrence elementToZone[pointi] = zoneI; } else if (elementToZone[pointi] >= 0) { // Multiple zones elementToZone[pointi] = -2; } } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // from components Foam::domainDecomposition::domainDecomposition(const IOobject& io) : fvMesh(io), facesInstancePointsPtr_ ( pointsInstance() != facesInstance() ? new pointIOField ( IOobject ( "points", facesInstance(), polyMesh::meshSubDir, *this, IOobject::MUST_READ, IOobject::NO_WRITE, false ) ) : NULL ), decompositionDict_ ( IOobject ( "decomposeParDict", time().system(), *this, IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE ) ), nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))), distributed_(false), cellToProc_(nCells()), procPointAddressing_(nProcs_), procFaceAddressing_(nProcs_), procCellAddressing_(nProcs_), procPatchSize_(nProcs_), procPatchStartIndex_(nProcs_), procNeighbourProcessors_(nProcs_), procProcessorPatchSize_(nProcs_), procProcessorPatchStartIndex_(nProcs_), procProcessorPatchSubPatchIDs_(nProcs_), procProcessorPatchSubPatchStarts_(nProcs_) { decompositionDict_.readIfPresent("distributed", distributed_); } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::domainDecomposition::~domainDecomposition() {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // bool Foam::domainDecomposition::writeDecomposition() { Info<< "\nConstructing processor meshes" << endl; // Mark point/faces/cells that are in zones. // -1 : not in zone // -2 : in multiple zones // >= 0 : in single given zone // This will give direct lookup of elements that are in a single zone // and we'll only have to revert back to searching through all zones // for the duplicate elements // Point zones labelList pointToZone(points().size(), -1); forAll(pointZones(), zoneI) { mark(pointZones()[zoneI], zoneI, pointToZone); } // Face zones labelList faceToZone(faces().size(), -1); forAll(faceZones(), zoneI) { mark(faceZones()[zoneI], zoneI, faceToZone); } // Cell zones labelList cellToZone(nCells(), -1); forAll(cellZones(), zoneI) { mark(cellZones()[zoneI], zoneI, cellToZone); } label totProcFaces = 0; label maxProcPatches = 0; label maxProcFaces = 0; // Write out the meshes for (label procI = 0; procI < nProcs_; procI++) { // Create processor points const labelList& curPointLabels = procPointAddressing_[procI]; const pointField& meshPoints = points(); labelList pointLookup(nPoints(), -1); pointField procPoints(curPointLabels.size()); forAll(curPointLabels, pointi) { procPoints[pointi] = meshPoints[curPointLabels[pointi]]; pointLookup[curPointLabels[pointi]] = pointi; } // Create processor faces const labelList& curFaceLabels = procFaceAddressing_[procI]; const faceList& meshFaces = faces(); labelList faceLookup(nFaces(), -1); faceList procFaces(curFaceLabels.size()); forAll(curFaceLabels, facei) { // Mark the original face as used // Remember to decrement the index by one (turning index) // label curF = mag(curFaceLabels[facei]) - 1; faceLookup[curF] = facei; // get the original face labelList origFaceLabels; if (curFaceLabels[facei] >= 0) { // face not turned origFaceLabels = meshFaces[curF]; } else { origFaceLabels = meshFaces[curF].reverseFace(); } // translate face labels into local point list face& procFaceLabels = procFaces[facei]; procFaceLabels.setSize(origFaceLabels.size()); forAll(origFaceLabels, pointi) { procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]]; } } // Create processor cells const labelList& curCellLabels = procCellAddressing_[procI]; const cellList& meshCells = cells(); cellList procCells(curCellLabels.size()); forAll(curCellLabels, celli) { const labelList& origCellLabels = meshCells[curCellLabels[celli]]; cell& curCell = procCells[celli]; curCell.setSize(origCellLabels.size()); forAll(origCellLabels, cellFaceI) { curCell[cellFaceI] = faceLookup[origCellLabels[cellFaceI]]; } } // Create processor mesh without a boundary fileName processorCasePath ( time().caseName()/fileName(word("processor") + Foam::name(procI)) ); // make the processor directory mkDir(time().rootPath()/processorCasePath); // create a database Time processorDb ( Time::controlDictName, time().rootPath(), processorCasePath, "system", "constant" ); processorDb.setTime(time()); // create the mesh. Two situations: // - points and faces come from the same time ('instance'). The mesh // will get constructed in the same instance. // - points come from a different time (moving mesh cases). // It will read the points belonging to the faces instance and // construct the procMesh with it which then gets handled as above. // (so with 'old' geometry). // Only at writing time will it additionally write the current // points. autoPtr procMeshPtr; if (facesInstancePointsPtr_.valid()) { // Construct mesh from facesInstance. pointField facesInstancePoints ( facesInstancePointsPtr_(), curPointLabels ); procMeshPtr.reset ( new polyMesh ( IOobject ( this->polyMesh::name(), // region of undecomposed mesh facesInstance(), processorDb ), xferMove(facesInstancePoints), xferMove(procFaces), xferMove(procCells) ) ); } else { procMeshPtr.reset ( new polyMesh ( IOobject ( this->polyMesh::name(), // region of undecomposed mesh facesInstance(), processorDb ), xferMove(procPoints), xferMove(procFaces), xferMove(procCells) ) ); } polyMesh& procMesh = procMeshPtr(); // Create processor boundary patches const labelList& curPatchSizes = procPatchSize_[procI]; const labelList& curPatchStarts = procPatchStartIndex_[procI]; const labelList& curNeighbourProcessors = procNeighbourProcessors_[procI]; const labelList& curProcessorPatchSizes = procProcessorPatchSize_[procI]; const labelList& curProcessorPatchStarts = procProcessorPatchStartIndex_[procI]; const labelListList& curSubPatchIDs = procProcessorPatchSubPatchIDs_[procI]; const labelListList& curSubStarts = procProcessorPatchSubPatchStarts_[procI]; const polyPatchList& meshPatches = boundaryMesh(); // Count the number of inter-proc patches label nInterProcPatches = 0; forAll(curSubPatchIDs, procPatchI) { //Info<< "For processor " << procI // << " have to destination processor " // << curNeighbourProcessors[procPatchI] << endl; // //forAll(curSubPatchIDs[procPatchI], i) //{ // Info<< " from patch:" << curSubPatchIDs[procPatchI][i] // << " starting at:" << curSubStarts[procPatchI][i] // << endl; //} nInterProcPatches += curSubPatchIDs[procPatchI].size(); } //Info<< "For processor " << procI // << " have " << nInterProcPatches // << " patches to neighbouring processors" << endl; List procPatches ( curPatchSizes.size() + nInterProcPatches, //curProcessorPatchSizes.size(), reinterpret_cast(0) ); label nPatches = 0; forAll(curPatchSizes, patchi) { // Get the face labels consistent with the field mapping // (reuse the patch field mappers) const polyPatch& meshPatch = meshPatches[patchi]; fvFieldDecomposer::patchFieldDecomposer patchMapper ( SubList