1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2010 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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "domainDecomposition.H"
27 #include "dictionary.H"
28 #include "labelIOList.H"
29 #include "processorPolyPatch.H"
31 #include "OSspecific.H"
33 #include "globalMeshData.H"
34 #include "DynamicList.H"
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
38 void domainDecomposition::mark
40 const labelList& zoneElems,
42 labelList& elementToZone
47 label pointi = zoneElems[i];
49 if (elementToZone[pointi] == -1)
52 elementToZone[pointi] = zoneI;
54 else if (elementToZone[pointi] >= 0)
57 elementToZone[pointi] = -2;
63 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
66 domainDecomposition::domainDecomposition(const IOobject& io)
80 nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
82 cellToProc_(nCells()),
83 procPointAddressing_(nProcs_),
84 procFaceAddressing_(nProcs_),
85 procCellAddressing_(nProcs_),
86 procBoundaryAddressing_(nProcs_),
87 procPatchSize_(nProcs_),
88 procPatchStartIndex_(nProcs_),
89 procNeighbourProcessors_(nProcs_),
90 procProcessorPatchSize_(nProcs_),
91 procProcessorPatchStartIndex_(nProcs_),
92 globallySharedPoints_(0),
93 cyclicParallel_(false)
95 if (decompositionDict_.found("distributed"))
97 Switch distributed(decompositionDict_.lookup("distributed"));
98 distributed_ = distributed;
103 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
105 domainDecomposition::~domainDecomposition()
109 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
111 bool domainDecomposition::writeDecomposition()
113 Info<< "\nConstructing processor meshes" << endl;
115 // Make a lookup map for globally shared points
116 Map<label> sharedPointLookup(2*globallySharedPoints_.size());
118 forAll (globallySharedPoints_, pointi)
120 sharedPointLookup.insert(globallySharedPoints_[pointi], pointi);
124 // Mark point/faces/cells that are in zones.
126 // -2 : in multiple zones
127 // >= 0 : in single given zone
128 // This will give direct lookup of elements that are in a single zone
129 // and we'll only have to revert back to searching through all zones
130 // for the duplicate elements
133 labelList pointToZone(points().size(), -1);
135 forAll(pointZones(), zoneI)
137 mark(pointZones()[zoneI], zoneI, pointToZone);
141 labelList faceToZone(faces().size(), -1);
143 forAll(faceZones(), zoneI)
145 mark(faceZones()[zoneI], zoneI, faceToZone);
149 labelList cellToZone(nCells(), -1);
151 forAll(cellZones(), zoneI)
153 mark(cellZones()[zoneI], zoneI, cellToZone);
157 label totProcFaces = 0;
158 label maxProcPatches = 0;
159 label maxProcFaces = 0;
162 // Write out the meshes
163 for (label procI = 0; procI < nProcs_; procI++)
165 // Create processor points
166 const labelList& curPointLabels = procPointAddressing_[procI];
168 const pointField& meshPoints = points();
170 labelList pointLookup(nPoints(), -1);
172 pointField procPoints(curPointLabels.size());
174 forAll (curPointLabels, pointi)
176 procPoints[pointi] = meshPoints[curPointLabels[pointi]];
178 pointLookup[curPointLabels[pointi]] = pointi;
181 // Create processor faces
182 const labelList& curFaceLabels = procFaceAddressing_[procI];
184 const faceList& meshFaces = faces();
186 labelList faceLookup(nFaces(), -1);
188 faceList procFaces(curFaceLabels.size());
190 forAll (curFaceLabels, facei)
192 // Mark the original face as used
193 // Remember to decrement the index by one (turning index)
195 label curF = mag(curFaceLabels[facei]) - 1;
197 faceLookup[curF] = facei;
199 // get the original face
200 labelList origFaceLabels;
202 if (curFaceLabels[facei] >= 0)
205 origFaceLabels = meshFaces[curF];
209 origFaceLabels = meshFaces[curF].reverseFace();
212 // translate face labels into local point list
213 face& procFaceLabels = procFaces[facei];
215 procFaceLabels.setSize(origFaceLabels.size());
217 forAll (origFaceLabels, pointi)
219 procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]];
223 // Create processor cells
224 const labelList& curCellLabels = procCellAddressing_[procI];
226 const cellList& meshCells = cells();
228 cellList procCells(curCellLabels.size());
230 forAll (curCellLabels, celli)
232 const labelList& origCellLabels = meshCells[curCellLabels[celli]];
234 cell& curCell = procCells[celli];
236 curCell.setSize(origCellLabels.size());
238 forAll (origCellLabels, cellFaceI)
240 curCell[cellFaceI] = faceLookup[origCellLabels[cellFaceI]];
244 // Create processor mesh without a boundary
246 fileName processorCasePath
248 time().caseName()/fileName(word("processor") + Foam::name(procI))
251 // make the processor directory
252 mkDir(time().rootPath()/processorCasePath);
257 Time::controlDictName,
269 this->polyMesh::name(), // region name of undecomposed mesh
273 xferMove(procPoints),
278 // Create processor boundary patches
279 const labelList& curBoundaryAddressing = procBoundaryAddressing_[procI];
281 const labelList& curPatchSizes = procPatchSize_[procI];
283 const labelList& curPatchStarts = procPatchStartIndex_[procI];
285 const labelList& curNeighbourProcessors =
286 procNeighbourProcessors_[procI];
288 const labelList& curProcessorPatchSizes =
289 procProcessorPatchSize_[procI];
291 const labelList& curProcessorPatchStarts =
292 procProcessorPatchStartIndex_[procI];
294 const polyPatchList& meshPatches = boundaryMesh();
296 List<polyPatch*> procPatches
299 + curProcessorPatchSizes.size(),
300 reinterpret_cast<polyPatch*>(0)
305 forAll (curPatchSizes, patchi)
307 procPatches[nPatches] =
308 meshPatches[curBoundaryAddressing[patchi]].clone
310 procMesh.boundaryMesh(),
312 curPatchSizes[patchi],
313 curPatchStarts[patchi]
319 forAll (curProcessorPatchSizes, procPatchI)
321 procPatches[nPatches] =
322 new processorPolyPatch
324 word("procBoundary") + Foam::name(procI)
326 + Foam::name(curNeighbourProcessors[procPatchI]),
327 curProcessorPatchSizes[procPatchI],
328 curProcessorPatchStarts[procPatchI],
330 procMesh.boundaryMesh(),
332 curNeighbourProcessors[procPatchI]
338 // Add boundary patches
339 procMesh.addPatches(procPatches);
341 // Create and add zones
345 const pointZoneMesh& pz = pointZones();
347 // Go through all the zoned points and find out if they
348 // belong to a zone. If so, add it to the zone as
350 List<DynamicList<label> > zonePoints(pz.size());
353 forAll(zonePoints, zoneI)
355 zonePoints[zoneI].setCapacity(pz[zoneI].size() / nProcs_);
358 // Use the pointToZone map to find out the single zone (if any),
359 // use slow search only for shared points.
360 forAll (curPointLabels, pointi)
362 label curPoint = curPointLabels[pointi];
364 label zoneI = pointToZone[curPoint];
369 zonePoints[zoneI].append(pointi);
371 else if (zoneI == -2)
373 // Multiple zones. Lookup.
376 label index = pz[zoneI].whichPoint(curPoint);
380 zonePoints[zoneI].append(pointi);
386 procMesh.pointZones().clearAddressing();
387 procMesh.pointZones().setSize(zonePoints.size());
388 forAll(zonePoints, zoneI)
390 procMesh.pointZones().set
395 procMesh.pointZones(),
397 zonePoints[zoneI].shrink()
404 // Force writing on all processors
405 procMesh.pointZones().writeOpt() = IOobject::AUTO_WRITE;
411 const faceZoneMesh& fz = faceZones();
413 // Go through all the zoned face and find out if they
414 // belong to a zone. If so, add it to the zone as
416 List<DynamicList<label> > zoneFaces(fz.size());
417 List<DynamicList<bool> > zoneFaceFlips(fz.size());
420 forAll(zoneFaces, zoneI)
422 label procSize = fz[zoneI].size() / nProcs_;
424 zoneFaces[zoneI].setCapacity(procSize);
425 zoneFaceFlips[zoneI].setCapacity(procSize);
428 // Go through all the zoned faces and find out if they
429 // belong to a zone. If so, add it to the zone as
431 forAll (curFaceLabels, facei)
433 // Remember to decrement the index by one (turning index)
435 label curF = mag(curFaceLabels[facei]) - 1;
437 label zoneI = faceToZone[curF];
441 // Single zone. Add the face
442 zoneFaces[zoneI].append(facei);
444 label index = fz[zoneI].whichFace(curF);
446 bool flip = fz[zoneI].flipMap()[index];
448 if (curFaceLabels[facei] < 0)
453 zoneFaceFlips[zoneI].append(flip);
455 else if (zoneI == -2)
457 // Multiple zones. Lookup.
460 label index = fz[zoneI].whichFace(curF);
464 zoneFaces[zoneI].append(facei);
466 bool flip = fz[zoneI].flipMap()[index];
468 if (curFaceLabels[facei] < 0)
473 zoneFaceFlips[zoneI].append(flip);
479 procMesh.faceZones().clearAddressing();
480 procMesh.faceZones().setSize(zoneFaces.size());
481 forAll(zoneFaces, zoneI)
483 procMesh.faceZones().set
488 zoneFaces[zoneI].shrink(), // addressing
489 zoneFaceFlips[zoneI].shrink(), // flipmap
498 // Force writing on all processors
499 procMesh.faceZones().writeOpt() = IOobject::AUTO_WRITE;
505 const cellZoneMesh& cz = cellZones();
507 // Go through all the zoned cells and find out if they
508 // belong to a zone. If so, add it to the zone as
510 List<DynamicList<label> > zoneCells(cz.size());
513 forAll(zoneCells, zoneI)
515 zoneCells[zoneI].setCapacity(cz[zoneI].size() / nProcs_);
518 forAll (curCellLabels, celli)
520 label curCellI = curCellLabels[celli];
522 label zoneI = cellToZone[curCellI];
527 zoneCells[zoneI].append(celli);
529 else if (zoneI == -2)
531 // Multiple zones. Lookup.
534 label index = cz[zoneI].whichCell(curCellI);
538 zoneCells[zoneI].append(celli);
544 procMesh.cellZones().clearAddressing();
545 procMesh.cellZones().setSize(zoneCells.size());
546 forAll(zoneCells, zoneI)
548 procMesh.cellZones().set
553 zoneCells[zoneI].shrink(),
562 // Force writing on all processors
563 procMesh.cellZones().writeOpt() = IOobject::AUTO_WRITE;
567 // Set the precision of the points data to 10
568 IOstream::defaultPrecision(10);
573 << "Processor " << procI << nl
574 << " Number of cells = " << procMesh.nCells()
577 label nBoundaryFaces = 0;
578 label nProcPatches = 0;
579 label nProcFaces = 0;
581 forAll (procMesh.boundaryMesh(), patchi)
585 procMesh.boundaryMesh()[patchi].type()
586 == processorPolyPatch::typeName
589 const processorPolyPatch& ppp =
590 refCast<const processorPolyPatch>
592 procMesh.boundaryMesh()[patchi]
595 Info<< " Number of faces shared with processor "
596 << ppp.neighbProcNo() << " = " << ppp.size() << endl;
599 nProcFaces += ppp.size();
603 nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
607 Info<< " Number of processor patches = " << nProcPatches << nl
608 << " Number of processor faces = " << nProcFaces << nl
609 << " Number of boundary faces = " << nBoundaryFaces << endl;
611 totProcFaces += nProcFaces;
612 maxProcPatches = max(maxProcPatches, nProcPatches);
613 maxProcFaces = max(maxProcFaces, nProcFaces);
615 // create and write the addressing information
616 labelIOList pointProcAddressing
620 "pointProcAddressing",
621 procMesh.facesInstance(),
627 procPointAddressing_[procI]
629 pointProcAddressing.write();
631 labelIOList faceProcAddressing
635 "faceProcAddressing",
636 procMesh.facesInstance(),
642 procFaceAddressing_[procI]
644 faceProcAddressing.write();
646 labelIOList cellProcAddressing
650 "cellProcAddressing",
651 procMesh.facesInstance(),
657 procCellAddressing_[procI]
659 cellProcAddressing.write();
661 labelIOList boundaryProcAddressing
665 "boundaryProcAddressing",
666 procMesh.facesInstance(),
672 procBoundaryAddressing_[procI]
674 boundaryProcAddressing.write();
678 << "Number of processor faces = " << totProcFaces/2 << nl
679 << "Max number of processor patches = " << maxProcPatches << nl
680 << "Max number of faces between processors = " << maxProcFaces
687 // ************************************************************************* //