FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

domainDecomposition.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*---------------------------------------------------------------------------*/
00025 
00026 #include "domainDecomposition.H"
00027 #include <OpenFOAM/dictionary.H>
00028 #include <OpenFOAM/labelIOList.H>
00029 #include <OpenFOAM/processorPolyPatch.H>
00030 #include <finiteVolume/fvMesh.H>
00031 #include <OpenFOAM/OSspecific.H>
00032 #include <OpenFOAM/Map.H>
00033 #include <OpenFOAM/globalMeshData.H>
00034 #include <OpenFOAM/DynamicList.H>
00035 
00036 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00037 
00038 void domainDecomposition::mark
00039 (
00040     const labelList& zoneElems,
00041     const label zoneI,
00042     labelList& elementToZone
00043 )
00044 {
00045     forAll(zoneElems, i)
00046     {
00047         label pointi = zoneElems[i];
00048 
00049         if (elementToZone[pointi] == -1)
00050         {
00051             // First occurrence
00052             elementToZone[pointi] = zoneI;
00053         }
00054         else if (elementToZone[pointi] >= 0)
00055         {
00056             // Multiple zones
00057             elementToZone[pointi] = -2;
00058         }
00059     }
00060 }
00061 
00062 
00063 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00064 
00065 // from components
00066 domainDecomposition::domainDecomposition(const IOobject& io)
00067 :
00068     fvMesh(io),
00069     decompositionDict_
00070     (
00071         IOobject
00072         (
00073             "decomposeParDict",
00074             time().system(),
00075             *this,
00076             IOobject::MUST_READ,
00077             IOobject::NO_WRITE
00078         )
00079     ),
00080     nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
00081     distributed_(false),
00082     cellToProc_(nCells()),
00083     procPointAddressing_(nProcs_),
00084     procFaceAddressing_(nProcs_),
00085     procCellAddressing_(nProcs_),
00086     procBoundaryAddressing_(nProcs_),
00087     procPatchSize_(nProcs_),
00088     procPatchStartIndex_(nProcs_),
00089     procNeighbourProcessors_(nProcs_),
00090     procProcessorPatchSize_(nProcs_),
00091     procProcessorPatchStartIndex_(nProcs_),
00092     globallySharedPoints_(0),
00093     cyclicParallel_(false)
00094 {
00095     if (decompositionDict_.found("distributed"))
00096     {
00097         Switch distributed(decompositionDict_.lookup("distributed"));
00098         distributed_ = distributed;
00099     }
00100 }
00101 
00102 
00103 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
00104 
00105 domainDecomposition::~domainDecomposition()
00106 {}
00107 
00108 
00109 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00110 
00111 bool domainDecomposition::writeDecomposition()
00112 {
00113     Info<< "\nConstructing processor meshes" << endl;
00114 
00115     // Make a lookup map for globally shared points
00116     Map<label> sharedPointLookup(2*globallySharedPoints_.size());
00117 
00118     forAll (globallySharedPoints_, pointi)
00119     {
00120         sharedPointLookup.insert(globallySharedPoints_[pointi], pointi);
00121     }
00122 
00123 
00124     // Mark point/faces/cells that are in zones.
00125     // -1   : not in zone
00126     // -2   : in multiple zones
00127     // >= 0 : in single given zone
00128     // This will give direct lookup of elements that are in a single zone
00129     // and we'll only have to revert back to searching through all zones
00130     // for the duplicate elements
00131 
00132     // Point zones
00133     labelList pointToZone(points().size(), -1);
00134 
00135     forAll(pointZones(), zoneI)
00136     {
00137         mark(pointZones()[zoneI], zoneI, pointToZone);
00138     }
00139 
00140     // Face zones
00141     labelList faceToZone(faces().size(), -1);
00142 
00143     forAll(faceZones(), zoneI)
00144     {
00145         mark(faceZones()[zoneI], zoneI, faceToZone);
00146     }
00147 
00148     // Cell zones
00149     labelList cellToZone(nCells(), -1);
00150 
00151     forAll(cellZones(), zoneI)
00152     {
00153         mark(cellZones()[zoneI], zoneI, cellToZone);
00154     }
00155 
00156 
00157     label totProcFaces = 0;
00158     label maxProcPatches = 0;
00159     label maxProcFaces = 0;
00160 
00161 
00162     // Write out the meshes
00163     for (label procI = 0; procI < nProcs_; procI++)
00164     {
00165         // Create processor points
00166         const labelList& curPointLabels = procPointAddressing_[procI];
00167 
00168         const pointField& meshPoints = points();
00169 
00170         labelList pointLookup(nPoints(), -1);
00171 
00172         pointField procPoints(curPointLabels.size());
00173 
00174         forAll (curPointLabels, pointi)
00175         {
00176             procPoints[pointi] = meshPoints[curPointLabels[pointi]];
00177 
00178             pointLookup[curPointLabels[pointi]] = pointi;
00179         }
00180 
00181         // Create processor faces
00182         const labelList& curFaceLabels = procFaceAddressing_[procI];
00183 
00184         const faceList& meshFaces = faces();
00185 
00186         labelList faceLookup(nFaces(), -1);
00187 
00188         faceList procFaces(curFaceLabels.size());
00189 
00190         forAll (curFaceLabels, facei)
00191         {
00192             // Mark the original face as used
00193             // Remember to decrement the index by one (turning index)
00194             //
00195             label curF = mag(curFaceLabels[facei]) - 1;
00196 
00197             faceLookup[curF] = facei;
00198 
00199             // get the original face
00200             labelList origFaceLabels;
00201 
00202             if (curFaceLabels[facei] >= 0)
00203             {
00204                 // face not turned
00205                 origFaceLabels = meshFaces[curF];
00206             }
00207             else
00208             {
00209                 origFaceLabels = meshFaces[curF].reverseFace();
00210             }
00211 
00212             // translate face labels into local point list
00213             face& procFaceLabels = procFaces[facei];
00214 
00215             procFaceLabels.setSize(origFaceLabels.size());
00216 
00217             forAll (origFaceLabels, pointi)
00218             {
00219                 procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]];
00220             }
00221         }
00222 
00223         // Create processor cells
00224         const labelList& curCellLabels = procCellAddressing_[procI];
00225 
00226         const cellList& meshCells = cells();
00227 
00228         cellList procCells(curCellLabels.size());
00229 
00230         forAll (curCellLabels, celli)
00231         {
00232             const labelList& origCellLabels = meshCells[curCellLabels[celli]];
00233 
00234             cell& curCell = procCells[celli];
00235 
00236             curCell.setSize(origCellLabels.size());
00237 
00238             forAll (origCellLabels, cellFaceI)
00239             {
00240                 curCell[cellFaceI] = faceLookup[origCellLabels[cellFaceI]];
00241             }
00242         }
00243 
00244         // Create processor mesh without a boundary
00245 
00246         fileName processorCasePath
00247         (
00248             time().caseName()/fileName(word("processor") + Foam::name(procI))
00249         );
00250 
00251         // make the processor directory
00252         mkDir(time().rootPath()/processorCasePath);
00253 
00254         // create a database
00255         Time processorDb
00256         (
00257             Time::controlDictName,
00258             time().rootPath(),
00259             processorCasePath,
00260             "system",
00261             "constant"
00262         );
00263 
00264         // create the mesh
00265         polyMesh procMesh
00266         (
00267             IOobject
00268             (
00269                 this->polyMesh::name(),  // region name of undecomposed mesh
00270                 pointsInstance(),
00271                 processorDb
00272             ),
00273             xferMove(procPoints),
00274             xferMove(procFaces),
00275             xferMove(procCells)
00276         );
00277 
00278         // Create processor boundary patches
00279         const labelList& curBoundaryAddressing = procBoundaryAddressing_[procI];
00280 
00281         const labelList& curPatchSizes = procPatchSize_[procI];
00282 
00283         const labelList& curPatchStarts = procPatchStartIndex_[procI];
00284 
00285         const labelList& curNeighbourProcessors =
00286             procNeighbourProcessors_[procI];
00287 
00288         const labelList& curProcessorPatchSizes =
00289             procProcessorPatchSize_[procI];
00290 
00291         const labelList& curProcessorPatchStarts =
00292             procProcessorPatchStartIndex_[procI];
00293 
00294         const polyPatchList& meshPatches = boundaryMesh();
00295 
00296         List<polyPatch*> procPatches
00297         (
00298             curPatchSizes.size()
00299           + curProcessorPatchSizes.size(),
00300             reinterpret_cast<polyPatch*>(0)
00301         );
00302 
00303         label nPatches = 0;
00304 
00305         forAll (curPatchSizes, patchi)
00306         {
00307             procPatches[nPatches] =
00308                 meshPatches[curBoundaryAddressing[patchi]].clone
00309                 (
00310                     procMesh.boundaryMesh(),
00311                     nPatches,
00312                     curPatchSizes[patchi],
00313                     curPatchStarts[patchi]
00314                 ).ptr();
00315 
00316             nPatches++;
00317         }
00318 
00319         forAll (curProcessorPatchSizes, procPatchI)
00320         {
00321             procPatches[nPatches] =
00322                 new processorPolyPatch
00323                 (
00324                     word("procBoundary") + Foam::name(procI)
00325                   + word("to")
00326                   + Foam::name(curNeighbourProcessors[procPatchI]),
00327                     curProcessorPatchSizes[procPatchI],
00328                     curProcessorPatchStarts[procPatchI],
00329                     nPatches,
00330                     procMesh.boundaryMesh(),
00331                     procI,
00332                     curNeighbourProcessors[procPatchI]
00333             );
00334 
00335             nPatches++;
00336         }
00337 
00338         // Add boundary patches
00339         procMesh.addPatches(procPatches);
00340 
00341         // Create and add zones
00342 
00343         // Point zones
00344         {
00345             const pointZoneMesh& pz = pointZones();
00346 
00347             // Go through all the zoned points and find out if they
00348             // belong to a zone.  If so, add it to the zone as
00349             // necessary
00350             List<DynamicList<label> > zonePoints(pz.size());
00351 
00352             // Estimate size
00353             forAll(zonePoints, zoneI)
00354             {
00355                 zonePoints[zoneI].setCapacity(pz[zoneI].size() / nProcs_);
00356             }
00357 
00358             // Use the pointToZone map to find out the single zone (if any),
00359             // use slow search only for shared points.
00360             forAll (curPointLabels, pointi)
00361             {
00362                 label curPoint = curPointLabels[pointi];
00363 
00364                 label zoneI = pointToZone[curPoint];
00365 
00366                 if (zoneI >= 0)
00367                 {
00368                     // Single zone.
00369                     zonePoints[zoneI].append(pointi);
00370                 }
00371                 else if (zoneI == -2)
00372                 {
00373                     // Multiple zones. Lookup.
00374                     forAll(pz, zoneI)
00375                     {
00376                         label index = pz[zoneI].whichPoint(curPoint);
00377 
00378                         if (index != -1)
00379                         {
00380                             zonePoints[zoneI].append(pointi);
00381                         }
00382                     }
00383                 }
00384             }
00385 
00386             procMesh.pointZones().clearAddressing();
00387             procMesh.pointZones().setSize(zonePoints.size());
00388             forAll(zonePoints, zoneI)
00389             {
00390                 procMesh.pointZones().set
00391                 (
00392                     zoneI,
00393                     pz[zoneI].clone
00394                     (
00395                         procMesh.pointZones(),
00396                         zoneI,
00397                         zonePoints[zoneI].shrink()
00398                     )
00399                 );
00400             }
00401 
00402             if (pz.size())
00403             {
00404                 // Force writing on all processors
00405                 procMesh.pointZones().writeOpt() = IOobject::AUTO_WRITE;
00406             }
00407         }
00408 
00409         // Face zones
00410         {
00411             const faceZoneMesh& fz = faceZones();
00412 
00413             // Go through all the zoned face and find out if they
00414             // belong to a zone.  If so, add it to the zone as
00415             // necessary
00416             List<DynamicList<label> > zoneFaces(fz.size());
00417             List<DynamicList<bool> > zoneFaceFlips(fz.size());
00418 
00419             // Estimate size
00420             forAll(zoneFaces, zoneI)
00421             {
00422                 label procSize = fz[zoneI].size() / nProcs_;
00423 
00424                 zoneFaces[zoneI].setCapacity(procSize);
00425                 zoneFaceFlips[zoneI].setCapacity(procSize);
00426             }
00427 
00428             // Go through all the zoned faces and find out if they
00429             // belong to a zone.  If so, add it to the zone as
00430             // necessary
00431             forAll (curFaceLabels, facei)
00432             {
00433                 // Remember to decrement the index by one (turning index)
00434                 //
00435                 label curF = mag(curFaceLabels[facei]) - 1;
00436 
00437                 label zoneI = faceToZone[curF];
00438 
00439                 if (zoneI >= 0)
00440                 {
00441                     // Single zone. Add the face
00442                     zoneFaces[zoneI].append(facei);
00443 
00444                     label index = fz[zoneI].whichFace(curF);
00445 
00446                     bool flip = fz[zoneI].flipMap()[index];
00447 
00448                     if (curFaceLabels[facei] < 0)
00449                     {
00450                         flip = !flip;
00451                     }
00452 
00453                     zoneFaceFlips[zoneI].append(flip);
00454                 }
00455                 else if (zoneI == -2)
00456                 {
00457                     // Multiple zones. Lookup.
00458                     forAll(fz, zoneI)
00459                     {
00460                         label index = fz[zoneI].whichFace(curF);
00461 
00462                         if (index != -1)
00463                         {
00464                             zoneFaces[zoneI].append(facei);
00465 
00466                             bool flip = fz[zoneI].flipMap()[index];
00467 
00468                             if (curFaceLabels[facei] < 0)
00469                             {
00470                                 flip = !flip;
00471                             }
00472 
00473                             zoneFaceFlips[zoneI].append(flip);
00474                         }
00475                     }
00476                 }
00477             }
00478 
00479             procMesh.faceZones().clearAddressing();
00480             procMesh.faceZones().setSize(zoneFaces.size());
00481             forAll(zoneFaces, zoneI)
00482             {
00483                 procMesh.faceZones().set
00484                 (
00485                     zoneI,
00486                     fz[zoneI].clone
00487                     (
00488                         zoneFaces[zoneI].shrink(),          // addressing
00489                         zoneFaceFlips[zoneI].shrink(),      // flipmap
00490                         zoneI,
00491                         procMesh.faceZones()
00492                     )
00493                 );
00494             }
00495 
00496             if (fz.size())
00497             {
00498                 // Force writing on all processors
00499                 procMesh.faceZones().writeOpt() = IOobject::AUTO_WRITE;
00500             }
00501         }
00502 
00503         // Cell zones
00504         {
00505             const cellZoneMesh& cz = cellZones();
00506 
00507             // Go through all the zoned cells and find out if they
00508             // belong to a zone.  If so, add it to the zone as
00509             // necessary
00510             List<DynamicList<label> > zoneCells(cz.size());
00511 
00512             // Estimate size
00513             forAll(zoneCells, zoneI)
00514             {
00515                 zoneCells[zoneI].setCapacity(cz[zoneI].size() / nProcs_);
00516             }
00517 
00518             forAll (curCellLabels, celli)
00519             {
00520                 label curCellI = curCellLabels[celli];
00521 
00522                 label zoneI = cellToZone[curCellI];
00523 
00524                 if (zoneI >= 0)
00525                 {
00526                     // Single zone.
00527                     zoneCells[zoneI].append(celli);
00528                 }
00529                 else if (zoneI == -2)
00530                 {
00531                     // Multiple zones. Lookup.
00532                     forAll(cz, zoneI)
00533                     {
00534                         label index = cz[zoneI].whichCell(curCellI);
00535 
00536                         if (index != -1)
00537                         {
00538                             zoneCells[zoneI].append(celli);
00539                         }
00540                     }
00541                 }
00542             }
00543 
00544             procMesh.cellZones().clearAddressing();
00545             procMesh.cellZones().setSize(zoneCells.size());
00546             forAll(zoneCells, zoneI)
00547             {
00548                 procMesh.cellZones().set
00549                 (
00550                     zoneI,
00551                     cz[zoneI].clone
00552                     (
00553                         zoneCells[zoneI].shrink(),
00554                         zoneI,
00555                         procMesh.cellZones()
00556                     )
00557                 );
00558             }
00559 
00560             if (cz.size())
00561             {
00562                 // Force writing on all processors
00563                 procMesh.cellZones().writeOpt() = IOobject::AUTO_WRITE;
00564             }
00565         }
00566 
00567         // Set the precision of the points data to 10
00568         IOstream::defaultPrecision(10);
00569 
00570         procMesh.write();
00571 
00572         Info<< endl
00573             << "Processor " << procI << nl
00574             << "    Number of cells = " << procMesh.nCells()
00575             << endl;
00576 
00577         label nBoundaryFaces = 0;
00578         label nProcPatches = 0;
00579         label nProcFaces = 0;
00580 
00581         forAll (procMesh.boundaryMesh(), patchi)
00582         {
00583             if
00584             (
00585                 procMesh.boundaryMesh()[patchi].type()
00586              == processorPolyPatch::typeName
00587             )
00588             {
00589                 const processorPolyPatch& ppp =
00590                 refCast<const processorPolyPatch>
00591                 (
00592                     procMesh.boundaryMesh()[patchi]
00593                 );
00594 
00595                 Info<< "    Number of faces shared with processor "
00596                     << ppp.neighbProcNo() << " = " << ppp.size() << endl;
00597 
00598                 nProcPatches++;
00599                 nProcFaces += ppp.size();
00600             }
00601             else
00602             {
00603                 nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
00604             }
00605         }
00606 
00607         Info<< "    Number of processor patches = " << nProcPatches << nl
00608             << "    Number of processor faces = " << nProcFaces << nl
00609             << "    Number of boundary faces = " << nBoundaryFaces << endl;
00610 
00611         totProcFaces += nProcFaces;
00612         maxProcPatches = max(maxProcPatches, nProcPatches);
00613         maxProcFaces = max(maxProcFaces, nProcFaces);
00614 
00615         // create and write the addressing information
00616         labelIOList pointProcAddressing
00617         (
00618             IOobject
00619             (
00620                 "pointProcAddressing",
00621                 procMesh.facesInstance(),
00622                 procMesh.meshSubDir,
00623                 procMesh,
00624                 IOobject::NO_READ,
00625                 IOobject::NO_WRITE
00626             ),
00627             procPointAddressing_[procI]
00628         );
00629         pointProcAddressing.write();
00630 
00631         labelIOList faceProcAddressing
00632         (
00633             IOobject
00634             (
00635                 "faceProcAddressing",
00636                 procMesh.facesInstance(),
00637                 procMesh.meshSubDir,
00638                 procMesh,
00639                 IOobject::NO_READ,
00640                 IOobject::NO_WRITE
00641             ),
00642             procFaceAddressing_[procI]
00643         );
00644         faceProcAddressing.write();
00645 
00646         labelIOList cellProcAddressing
00647         (
00648             IOobject
00649             (
00650                 "cellProcAddressing",
00651                 procMesh.facesInstance(),
00652                 procMesh.meshSubDir,
00653                 procMesh,
00654                 IOobject::NO_READ,
00655                 IOobject::NO_WRITE
00656             ),
00657             procCellAddressing_[procI]
00658         );
00659         cellProcAddressing.write();
00660 
00661         labelIOList boundaryProcAddressing
00662         (
00663             IOobject
00664             (
00665                 "boundaryProcAddressing",
00666                 procMesh.facesInstance(),
00667                 procMesh.meshSubDir,
00668                 procMesh,
00669                 IOobject::NO_READ,
00670                 IOobject::NO_WRITE
00671             ),
00672             procBoundaryAddressing_[procI]
00673         );
00674         boundaryProcAddressing.write();
00675     }
00676 
00677     Info<< nl
00678         << "Number of processor faces = " << totProcFaces/2 << nl
00679         << "Max number of processor patches = " << maxProcPatches << nl
00680         << "Max number of faces between processors = " << maxProcFaces
00681         << endl;
00682 
00683     return true;
00684 }
00685 
00686 
00687 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines