1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "domainDecomposition.H"
29 #include "dictionary.H"
30 #include "labelIOList.H"
31 #include "processorPolyPatch.H"
33 #include "OSspecific.H"
35 #include "globalMeshData.H"
36 #include "DynamicList.H"
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 void domainDecomposition::mark
42 const labelList& zoneElems,
44 labelList& elementToZone
49 label pointi = zoneElems[i];
51 if (elementToZone[pointi] == -1)
54 elementToZone[pointi] = zoneI;
56 else if (elementToZone[pointi] >= 0)
59 elementToZone[pointi] = -2;
65 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
68 domainDecomposition::domainDecomposition(const IOobject& io)
82 nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
84 cellToProc_(nCells()),
85 procPointAddressing_(nProcs_),
86 procFaceAddressing_(nProcs_),
87 procCellAddressing_(nProcs_),
88 procBoundaryAddressing_(nProcs_),
89 procPatchSize_(nProcs_),
90 procPatchStartIndex_(nProcs_),
91 procNeighbourProcessors_(nProcs_),
92 procProcessorPatchSize_(nProcs_),
93 procProcessorPatchStartIndex_(nProcs_),
94 globallySharedPoints_(0),
95 cyclicParallel_(false)
97 if (decompositionDict_.found("distributed"))
99 Switch distributed(decompositionDict_.lookup("distributed"));
100 distributed_ = distributed;
105 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
107 domainDecomposition::~domainDecomposition()
111 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
113 bool domainDecomposition::writeDecomposition()
115 Info<< "\nConstructing processor meshes" << endl;
117 // Make a lookup map for globally shared points
118 Map<label> sharedPointLookup(2*globallySharedPoints_.size());
120 forAll (globallySharedPoints_, pointi)
122 sharedPointLookup.insert(globallySharedPoints_[pointi], pointi);
126 // Mark point/faces/cells that are in zones.
128 // -2 : in multiple zones
129 // >= 0 : in single given zone
130 // This will give direct lookup of elements that are in a single zone
131 // and we'll only have to revert back to searching through all zones
132 // for the duplicate elements
135 labelList pointToZone(points().size(), -1);
137 forAll(pointZones(), zoneI)
139 mark(pointZones()[zoneI], zoneI, pointToZone);
143 labelList faceToZone(faces().size(), -1);
145 forAll(faceZones(), zoneI)
147 mark(faceZones()[zoneI], zoneI, faceToZone);
151 labelList cellToZone(nCells(), -1);
153 forAll(cellZones(), zoneI)
155 mark(cellZones()[zoneI], zoneI, cellToZone);
159 label totProcFaces = 0;
160 label maxProcPatches = 0;
161 label maxProcFaces = 0;
164 // Write out the meshes
165 for (label procI = 0; procI < nProcs_; procI++)
167 // Create processor points
168 const labelList& curPointLabels = procPointAddressing_[procI];
170 const pointField& meshPoints = points();
172 labelList pointLookup(nPoints(), -1);
174 pointField procPoints(curPointLabels.size());
176 forAll (curPointLabels, pointi)
178 procPoints[pointi] = meshPoints[curPointLabels[pointi]];
180 pointLookup[curPointLabels[pointi]] = pointi;
183 // Create processor faces
184 const labelList& curFaceLabels = procFaceAddressing_[procI];
186 const faceList& meshFaces = faces();
188 labelList faceLookup(nFaces(), -1);
190 faceList procFaces(curFaceLabels.size());
192 forAll (curFaceLabels, facei)
194 // Mark the original face as used
195 // Remember to decrement the index by one (turning index)
197 label curF = mag(curFaceLabels[facei]) - 1;
199 faceLookup[curF] = facei;
201 // get the original face
202 labelList origFaceLabels;
204 if (curFaceLabels[facei] >= 0)
207 origFaceLabels = meshFaces[curF];
211 origFaceLabels = meshFaces[curF].reverseFace();
214 // translate face labels into local point list
215 face& procFaceLabels = procFaces[facei];
217 procFaceLabels.setSize(origFaceLabels.size());
219 forAll (origFaceLabels, pointi)
221 procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]];
225 // Create processor cells
226 const labelList& curCellLabels = procCellAddressing_[procI];
228 const cellList& meshCells = cells();
230 cellList procCells(curCellLabels.size());
232 forAll (curCellLabels, celli)
234 const labelList& origCellLabels = meshCells[curCellLabels[celli]];
236 cell& curCell = procCells[celli];
238 curCell.setSize(origCellLabels.size());
240 forAll (origCellLabels, cellFaceI)
242 curCell[cellFaceI] = faceLookup[origCellLabels[cellFaceI]];
246 // Create processor mesh without a boundary
248 fileName processorCasePath
250 time().caseName()/fileName(word("processor") + Foam::name(procI))
253 // make the processor directory
254 mkDir(time().rootPath()/processorCasePath);
259 Time::controlDictName,
271 this->polyMesh::name(), // region name of undecomposed mesh
275 xferMove(procPoints),
280 // Create processor boundary patches
281 const labelList& curBoundaryAddressing = procBoundaryAddressing_[procI];
283 const labelList& curPatchSizes = procPatchSize_[procI];
285 const labelList& curPatchStarts = procPatchStartIndex_[procI];
287 const labelList& curNeighbourProcessors =
288 procNeighbourProcessors_[procI];
290 const labelList& curProcessorPatchSizes =
291 procProcessorPatchSize_[procI];
293 const labelList& curProcessorPatchStarts =
294 procProcessorPatchStartIndex_[procI];
296 const polyPatchList& meshPatches = boundaryMesh();
298 List<polyPatch*> procPatches
301 + curProcessorPatchSizes.size(),
302 reinterpret_cast<polyPatch*>(0)
307 forAll (curPatchSizes, patchi)
309 procPatches[nPatches] =
310 meshPatches[curBoundaryAddressing[patchi]].clone
312 procMesh.boundaryMesh(),
314 curPatchSizes[patchi],
315 curPatchStarts[patchi]
321 forAll (curProcessorPatchSizes, procPatchI)
323 procPatches[nPatches] =
324 new processorPolyPatch
326 word("procBoundary") + Foam::name(procI)
328 + Foam::name(curNeighbourProcessors[procPatchI]),
329 curProcessorPatchSizes[procPatchI],
330 curProcessorPatchStarts[procPatchI],
332 procMesh.boundaryMesh(),
334 curNeighbourProcessors[procPatchI]
340 // Add boundary patches
341 procMesh.addPatches(procPatches);
343 // Create and add zones
347 const pointZoneMesh& pz = pointZones();
349 // Go through all the zoned points and find out if they
350 // belong to a zone. If so, add it to the zone as
352 List<DynamicList<label> > zonePoints(pz.size());
355 forAll(zonePoints, zoneI)
357 zonePoints[zoneI].setCapacity(pz[zoneI].size() / nProcs_);
360 // Use the pointToZone map to find out the single zone (if any),
361 // use slow search only for shared points.
362 forAll (curPointLabels, pointi)
364 label curPoint = curPointLabels[pointi];
366 label zoneI = pointToZone[curPoint];
371 zonePoints[zoneI].append(pointi);
373 else if (zoneI == -2)
375 // Multiple zones. Lookup.
378 label index = pz[zoneI].whichPoint(curPoint);
382 zonePoints[zoneI].append(pointi);
388 procMesh.pointZones().clearAddressing();
389 procMesh.pointZones().setSize(zonePoints.size());
390 forAll(zonePoints, zoneI)
392 procMesh.pointZones().set
397 procMesh.pointZones(),
399 zonePoints[zoneI].shrink()
406 // Force writing on all processors
407 procMesh.pointZones().writeOpt() = IOobject::AUTO_WRITE;
413 const faceZoneMesh& fz = faceZones();
415 // Go through all the zoned face and find out if they
416 // belong to a zone. If so, add it to the zone as
418 List<DynamicList<label> > zoneFaces(fz.size());
419 List<DynamicList<bool> > zoneFaceFlips(fz.size());
422 forAll(zoneFaces, zoneI)
424 label procSize = fz[zoneI].size() / nProcs_;
426 zoneFaces[zoneI].setCapacity(procSize);
427 zoneFaceFlips[zoneI].setCapacity(procSize);
430 // Go through all the zoned faces and find out if they
431 // belong to a zone. If so, add it to the zone as
433 forAll (curFaceLabels, facei)
435 // Remember to decrement the index by one (turning index)
437 label curF = mag(curFaceLabels[facei]) - 1;
439 label zoneI = faceToZone[curF];
443 // Single zone. Add the face
444 zoneFaces[zoneI].append(facei);
446 label index = fz[zoneI].whichFace(curF);
448 bool flip = fz[zoneI].flipMap()[index];
450 if (curFaceLabels[facei] < 0)
455 zoneFaceFlips[zoneI].append(flip);
457 else if (zoneI == -2)
459 // Multiple zones. Lookup.
462 label index = fz[zoneI].whichFace(curF);
466 zoneFaces[zoneI].append(facei);
468 bool flip = fz[zoneI].flipMap()[index];
470 if (curFaceLabels[facei] < 0)
475 zoneFaceFlips[zoneI].append(flip);
481 procMesh.faceZones().clearAddressing();
482 procMesh.faceZones().setSize(zoneFaces.size());
483 forAll(zoneFaces, zoneI)
485 procMesh.faceZones().set
490 zoneFaces[zoneI].shrink(), // addressing
491 zoneFaceFlips[zoneI].shrink(), // flipmap
500 // Force writing on all processors
501 procMesh.faceZones().writeOpt() = IOobject::AUTO_WRITE;
507 const cellZoneMesh& cz = cellZones();
509 // Go through all the zoned cells and find out if they
510 // belong to a zone. If so, add it to the zone as
512 List<DynamicList<label> > zoneCells(cz.size());
515 forAll(zoneCells, zoneI)
517 zoneCells[zoneI].setCapacity(cz[zoneI].size() / nProcs_);
520 forAll (curCellLabels, celli)
522 label curCellI = curCellLabels[celli];
524 label zoneI = cellToZone[curCellI];
529 zoneCells[zoneI].append(celli);
531 else if (zoneI == -2)
533 // Multiple zones. Lookup.
536 label index = cz[zoneI].whichCell(curCellI);
540 zoneCells[zoneI].append(celli);
546 procMesh.cellZones().clearAddressing();
547 procMesh.cellZones().setSize(zoneCells.size());
548 forAll(zoneCells, zoneI)
550 procMesh.cellZones().set
555 zoneCells[zoneI].shrink(),
564 // Force writing on all processors
565 procMesh.cellZones().writeOpt() = IOobject::AUTO_WRITE;
569 // Set the precision of the points data to 10
570 IOstream::defaultPrecision(10);
575 << "Processor " << procI << nl
576 << " Number of cells = " << procMesh.nCells()
579 label nBoundaryFaces = 0;
580 label nProcPatches = 0;
581 label nProcFaces = 0;
583 forAll (procMesh.boundaryMesh(), patchi)
587 procMesh.boundaryMesh()[patchi].type()
588 == processorPolyPatch::typeName
591 const processorPolyPatch& ppp =
592 refCast<const processorPolyPatch>
594 procMesh.boundaryMesh()[patchi]
597 Info<< " Number of faces shared with processor "
598 << ppp.neighbProcNo() << " = " << ppp.size() << endl;
601 nProcFaces += ppp.size();
605 nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
609 Info<< " Number of processor patches = " << nProcPatches << nl
610 << " Number of processor faces = " << nProcFaces << nl
611 << " Number of boundary faces = " << nBoundaryFaces << endl;
613 totProcFaces += nProcFaces;
614 maxProcPatches = max(maxProcPatches, nProcPatches);
615 maxProcFaces = max(maxProcFaces, nProcFaces);
617 // create and write the addressing information
618 labelIOList pointProcAddressing
622 "pointProcAddressing",
623 procMesh.facesInstance(),
629 procPointAddressing_[procI]
631 pointProcAddressing.write();
633 labelIOList faceProcAddressing
637 "faceProcAddressing",
638 procMesh.facesInstance(),
644 procFaceAddressing_[procI]
646 faceProcAddressing.write();
648 labelIOList cellProcAddressing
652 "cellProcAddressing",
653 procMesh.facesInstance(),
659 procCellAddressing_[procI]
661 cellProcAddressing.write();
663 labelIOList boundaryProcAddressing
667 "boundaryProcAddressing",
668 procMesh.facesInstance(),
674 procBoundaryAddressing_[procI]
676 boundaryProcAddressing.write();
680 << "Number of processor faces = " << totProcFaces/2 << nl
681 << "Max number of processor patches = " << maxProcPatches << nl
682 << "Max number of faces between processors = " << maxProcFaces
689 // ************************************************************************* //