00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
00052 elementToZone[pointi] = zoneI;
00053 }
00054 else if (elementToZone[pointi] >= 0)
00055 {
00056
00057 elementToZone[pointi] = -2;
00058 }
00059 }
00060 }
00061
00062
00063
00064
00065
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
00104
00105 domainDecomposition::~domainDecomposition()
00106 {}
00107
00108
00109
00110
00111 bool domainDecomposition::writeDecomposition()
00112 {
00113 Info<< "\nConstructing processor meshes" << endl;
00114
00115
00116 Map<label> sharedPointLookup(2*globallySharedPoints_.size());
00117
00118 forAll (globallySharedPoints_, pointi)
00119 {
00120 sharedPointLookup.insert(globallySharedPoints_[pointi], pointi);
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 labelList pointToZone(points().size(), -1);
00134
00135 forAll(pointZones(), zoneI)
00136 {
00137 mark(pointZones()[zoneI], zoneI, pointToZone);
00138 }
00139
00140
00141 labelList faceToZone(faces().size(), -1);
00142
00143 forAll(faceZones(), zoneI)
00144 {
00145 mark(faceZones()[zoneI], zoneI, faceToZone);
00146 }
00147
00148
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
00163 for (label procI = 0; procI < nProcs_; procI++)
00164 {
00165
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
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
00193
00194
00195 label curF = mag(curFaceLabels[facei]) - 1;
00196
00197 faceLookup[curF] = facei;
00198
00199
00200 labelList origFaceLabels;
00201
00202 if (curFaceLabels[facei] >= 0)
00203 {
00204
00205 origFaceLabels = meshFaces[curF];
00206 }
00207 else
00208 {
00209 origFaceLabels = meshFaces[curF].reverseFace();
00210 }
00211
00212
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
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
00245
00246 fileName processorCasePath
00247 (
00248 time().caseName()/fileName(word("processor") + Foam::name(procI))
00249 );
00250
00251
00252 mkDir(time().rootPath()/processorCasePath);
00253
00254
00255 Time processorDb
00256 (
00257 Time::controlDictName,
00258 time().rootPath(),
00259 processorCasePath,
00260 "system",
00261 "constant"
00262 );
00263
00264
00265 polyMesh procMesh
00266 (
00267 IOobject
00268 (
00269 this->polyMesh::name(),
00270 pointsInstance(),
00271 processorDb
00272 ),
00273 xferMove(procPoints),
00274 xferMove(procFaces),
00275 xferMove(procCells)
00276 );
00277
00278
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
00339 procMesh.addPatches(procPatches);
00340
00341
00342
00343
00344 {
00345 const pointZoneMesh& pz = pointZones();
00346
00347
00348
00349
00350 List<DynamicList<label> > zonePoints(pz.size());
00351
00352
00353 forAll(zonePoints, zoneI)
00354 {
00355 zonePoints[zoneI].setCapacity(pz[zoneI].size() / nProcs_);
00356 }
00357
00358
00359
00360 forAll (curPointLabels, pointi)
00361 {
00362 label curPoint = curPointLabels[pointi];
00363
00364 label zoneI = pointToZone[curPoint];
00365
00366 if (zoneI >= 0)
00367 {
00368
00369 zonePoints[zoneI].append(pointi);
00370 }
00371 else if (zoneI == -2)
00372 {
00373
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
00405 procMesh.pointZones().writeOpt() = IOobject::AUTO_WRITE;
00406 }
00407 }
00408
00409
00410 {
00411 const faceZoneMesh& fz = faceZones();
00412
00413
00414
00415
00416 List<DynamicList<label> > zoneFaces(fz.size());
00417 List<DynamicList<bool> > zoneFaceFlips(fz.size());
00418
00419
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
00429
00430
00431 forAll (curFaceLabels, facei)
00432 {
00433
00434
00435 label curF = mag(curFaceLabels[facei]) - 1;
00436
00437 label zoneI = faceToZone[curF];
00438
00439 if (zoneI >= 0)
00440 {
00441
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
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(),
00489 zoneFaceFlips[zoneI].shrink(),
00490 zoneI,
00491 procMesh.faceZones()
00492 )
00493 );
00494 }
00495
00496 if (fz.size())
00497 {
00498
00499 procMesh.faceZones().writeOpt() = IOobject::AUTO_WRITE;
00500 }
00501 }
00502
00503
00504 {
00505 const cellZoneMesh& cz = cellZones();
00506
00507
00508
00509
00510 List<DynamicList<label> > zoneCells(cz.size());
00511
00512
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
00527 zoneCells[zoneI].append(celli);
00528 }
00529 else if (zoneI == -2)
00530 {
00531
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
00563 procMesh.cellZones().writeOpt() = IOobject::AUTO_WRITE;
00564 }
00565 }
00566
00567
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
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