1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
28 Private member of domainDecomposition.
29 Decomposes the mesh into bits
31 \*---------------------------------------------------------------------------*/
33 #include "domainDecomposition.H"
34 #include "IOstreams.H"
35 #include "SLPtrList.H"
38 #include "primitiveMesh.H"
39 #include "cyclicPolyPatch.H"
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 void domainDecomposition::decomposeMesh(const bool filterEmptyPatches)
45 // Decide which cell goes to which processor
48 // Distribute the cells according to the given processor label
50 // calculate the addressing information for the original mesh
51 Info<< "\nCalculating original mesh data" << endl;
53 // set references to the original mesh
54 const polyBoundaryMesh& patches = boundaryMesh();
56 // Access all faces to grab the zones
57 const faceList& fcs = allFaces();
58 const labelList& owner = faceOwner();
59 const labelList& neighbour = faceNeighbour();
61 // loop through the list of processor labels for the cell and add the
62 // cell shape to the list of cells for the appropriate processor
64 Info<< "\nDistributing cells to processors" << endl;
68 List<SLList<label> > procCellList(nProcs_);
70 forAll (cellToProc_, celli)
72 if (cellToProc_[celli] >= nProcs_)
74 FatalErrorIn("domainDecomposition::decomposeMesh()")
75 << "Impossible processor label " << cellToProc_[celli]
76 << "for cell " << celli
81 procCellList[cellToProc_[celli]].append(celli);
85 // Convert linked lists into normal lists
86 forAll (procCellList, procI)
88 procCellAddressing_[procI] = procCellList[procI];
92 Info << "\nDistributing faces to processors" << endl;
94 // Loop through internal faces and decide which processor they belong to
95 // First visit all internal faces. If cells at both sides belong to the
96 // same processor, the face is an internal face. If they are different,
97 // it belongs to both processors.
101 List<SLList<label> > procFaceList(nProcs_);
103 forAll (neighbour, facei)
105 if (cellToProc_[owner[facei]] == cellToProc_[neighbour[facei]])
107 // Face internal to processor
108 procFaceList[cellToProc_[owner[facei]]].append(facei);
112 // Record number of internal faces on each processor
113 forAll (procFaceList, procI)
115 nInternalProcFaces_[procI] = procFaceList[procI].size();
118 // Detect inter-processor boundaries
120 // Neighbour processor for each subdomain
121 List<SLList<label> > interProcBoundaries(nProcs_);
123 // Face labels belonging to each inter-processor boundary
124 List<SLList<SLList<label> > > interProcBFaces(nProcs_);
126 List<SLList<label> > procPatchIndex(nProcs_);
128 forAll (neighbour, facei)
130 if (cellToProc_[owner[facei]] != cellToProc_[neighbour[facei]])
132 // inter - processor patch face found. Go through the list of
133 // inside boundaries for the owner processor and try to find
134 // this inter-processor patch.
136 label ownerProc = cellToProc_[owner[facei]];
137 label neighbourProc = cellToProc_[neighbour[facei]];
139 SLList<label>::iterator curInterProcBdrsOwnIter =
140 interProcBoundaries[ownerProc].begin();
142 SLList<SLList<label> >::iterator curInterProcBFacesOwnIter =
143 interProcBFaces[ownerProc].begin();
145 bool interProcBouFound = false;
147 // WARNING: Synchronous SLList iterators
152 curInterProcBdrsOwnIter
153 != interProcBoundaries[ownerProc].end()
154 && curInterProcBFacesOwnIter
155 != interProcBFaces[ownerProc].end();
156 ++curInterProcBdrsOwnIter, ++curInterProcBFacesOwnIter
159 if (curInterProcBdrsOwnIter() == neighbourProc)
161 // the inter - processor boundary exists. Add the face
162 interProcBouFound = true;
164 curInterProcBFacesOwnIter().append(facei);
166 SLList<label>::iterator curInterProcBdrsNeiIter =
167 interProcBoundaries[neighbourProc].begin();
169 SLList<SLList<label> >::iterator
170 curInterProcBFacesNeiIter =
171 interProcBFaces[neighbourProc].begin();
173 bool neighbourFound = false;
175 // WARNING: Synchronous SLList iterators
180 curInterProcBdrsNeiIter !=
181 interProcBoundaries[neighbourProc].end()
182 && curInterProcBFacesNeiIter !=
183 interProcBFaces[neighbourProc].end();
184 ++curInterProcBdrsNeiIter,
185 ++curInterProcBFacesNeiIter
188 if (curInterProcBdrsNeiIter() == ownerProc)
190 // boundary found. Add the face
191 neighbourFound = true;
193 curInterProcBFacesNeiIter().append(facei);
196 if (neighbourFound) break;
199 if (interProcBouFound && !neighbourFound)
203 "domainDecomposition::decomposeMesh()"
204 ) << "Inconsistency in inter - "
205 << "processor boundary lists for processors "
206 << ownerProc << " and " << neighbourProc
207 << abort(FatalError);
211 if (interProcBouFound) break;
214 if (!interProcBouFound)
216 // inter - processor boundaries do not exist and need to
219 // set the new addressing information
222 interProcBoundaries[ownerProc].append(neighbourProc);
223 interProcBFaces[ownerProc].append(SLList<label>(facei));
226 interProcBoundaries[neighbourProc].append(ownerProc);
227 interProcBFaces[neighbourProc].append
235 // Loop through patches. For cyclic boundaries detect inter-processor
236 // faces; for all other, add faces to the face list and remember start
237 // and size of all patches.
239 // for all processors, set the size of start index and patch size
240 // lists to the number of patches in the mesh
241 forAll (procPatchSize_, procI)
243 procPatchSize_[procI].setSize(patches.size());
244 procPatchStartIndex_[procI].setSize(patches.size());
247 forAll (patches, patchi)
249 // Reset size and start index for all processors
250 forAll (procPatchSize_, procI)
252 procPatchSize_[procI][patchi] = 0;
253 procPatchStartIndex_[procI][patchi] =
254 procFaceList[procI].size();
257 const label patchStart = patches[patchi].start();
259 if (!isA<cyclicPolyPatch>(patches[patchi]))
261 // Normal patch. Add faces to processor where the cell
262 // next to the face lives
264 const unallocLabelList& patchFaceCells =
265 patches[patchi].faceCells();
267 forAll (patchFaceCells, facei)
269 const label curProc = cellToProc_[patchFaceCells[facei]];
272 procFaceList[curProc].append(patchStart + facei);
274 // increment the number of faces for this patch
275 procPatchSize_[curProc][patchi]++;
280 // Cyclic patch special treatment
282 const polyPatch& cPatch = patches[patchi];
284 const label cycOffset = cPatch.size()/2;
286 // Set reference to faceCells for both patches
287 const labelList::subList firstFaceCells
293 const labelList::subList secondFaceCells
300 forAll (firstFaceCells, facei)
304 cellToProc_[firstFaceCells[facei]]
305 != cellToProc_[secondFaceCells[facei]]
308 // This face becomes an inter-processor boundary face
309 // inter - processor patch face found. Go through
310 // the list of inside boundaries for the owner
311 // processor and try to find this inter-processor
314 cyclicParallel_ = true;
316 label ownerProc = cellToProc_[firstFaceCells[facei]];
317 label neighbourProc =
318 cellToProc_[secondFaceCells[facei]];
320 SLList<label>::iterator curInterProcBdrsOwnIter =
321 interProcBoundaries[ownerProc].begin();
323 SLList<SLList<label> >::iterator
324 curInterProcBFacesOwnIter =
325 interProcBFaces[ownerProc].begin();
327 bool interProcBouFound = false;
329 // WARNING: Synchronous SLList iterators
334 curInterProcBdrsOwnIter !=
335 interProcBoundaries[ownerProc].end()
336 && curInterProcBFacesOwnIter !=
337 interProcBFaces[ownerProc].end();
338 ++curInterProcBdrsOwnIter,
339 ++curInterProcBFacesOwnIter
342 if (curInterProcBdrsOwnIter() == neighbourProc)
344 // the inter - processor boundary exists.
346 interProcBouFound = true;
348 curInterProcBFacesOwnIter().append
349 (patchStart + facei);
351 SLList<label>::iterator curInterProcBdrsNeiIter
352 = interProcBoundaries[neighbourProc].begin();
354 SLList<SLList<label> >::iterator
355 curInterProcBFacesNeiIter =
356 interProcBFaces[neighbourProc].begin();
358 bool neighbourFound = false;
360 // WARNING: Synchronous SLList iterators
365 curInterProcBdrsNeiIter
366 != interProcBoundaries[neighbourProc].end()
367 && curInterProcBFacesNeiIter
368 != interProcBFaces[neighbourProc].end();
369 ++curInterProcBdrsNeiIter,
370 ++curInterProcBFacesNeiIter
373 if (curInterProcBdrsNeiIter() == ownerProc)
375 // boundary found. Add the face
376 neighbourFound = true;
378 curInterProcBFacesNeiIter()
387 if (neighbourFound) break;
390 if (interProcBouFound && !neighbourFound)
394 "domainDecomposition::decomposeMesh()"
395 ) << "Inconsistency in inter-processor "
396 << "boundary lists for processors "
397 << ownerProc << " and "
399 << " in cyclic boundary matching"
400 << abort(FatalError);
404 if (interProcBouFound) break;
407 if (!interProcBouFound)
409 // inter - processor boundaries do not exist
410 // and need to be created
412 // set the new addressing information
415 interProcBoundaries[ownerProc]
416 .append(neighbourProc);
417 interProcBFaces[ownerProc]
418 .append(SLList<label>(patchStart + facei));
421 interProcBoundaries[neighbourProc]
423 interProcBFaces[neighbourProc]
437 // This cyclic face remains on the processor
438 label ownerProc = cellToProc_[firstFaceCells[facei]];
441 procFaceList[ownerProc].append(patchStart + facei);
443 // increment the number of faces for this patch
444 procPatchSize_[ownerProc][patchi]++;
446 // Note: I cannot add the other side of the cyclic
447 // boundary here because this would violate the order.
448 // They will be added in a separate loop below
453 // Ordering in cyclic boundaries is important.
454 // Add the other half of cyclic faces for cyclic boundaries
455 // that remain on the processor
456 forAll (secondFaceCells, facei)
460 cellToProc_[firstFaceCells[facei]]
461 == cellToProc_[secondFaceCells[facei]]
464 // This cyclic face remains on the processor
465 label ownerProc = cellToProc_[firstFaceCells[facei]];
467 // add the second face
468 procFaceList[ownerProc].append
469 (patchStart + cycOffset + facei);
471 // increment the number of faces for this patch
472 procPatchSize_[ownerProc][patchi]++;
478 // Face zone treatment. HJ, 27/Mar/2009
479 // Face zones identified as global will be present on all CPUs
480 List<SLList<label> > procZoneFaceList(nProcs_);
482 if (decompositionDict_.found("globalFaceZones"))
484 wordList fzNames(decompositionDict_.lookup("globalFaceZones"));
486 const faceZoneMesh& fz = faceZones();
488 forAll (fzNames, nameI)
490 const label zoneID = fz.findZoneID(fzNames[nameI]);
494 FatalErrorIn("domainDecomposition::decomposeMesh()")
495 << "Unknown global face zone " << fzNames[nameI]
496 << nl << "Valid face zones are" << fz.names()
500 Info<< "Preserving global face zone " << fzNames[nameI]
503 const faceZone& curFz = fz[zoneID];
505 // Go through all the faces in the zone. If the owner of the
506 // face equals to current processor, it has already been added;
507 // otherwise, add the face to all processor face lists
508 forAll (curFz, faceI)
510 const label curFaceID = curFz[faceI];
512 if (curFaceID < owner.size())
514 // This is an active mesh face, and it already belongs
515 // to one CPU. Find out which and add it to the others
517 const label curProc = cellToProc_[owner[curFaceID]];
519 forAll (procZoneFaceList, procI)
521 if (procI != curProc)
523 procZoneFaceList[procI].append(curFaceID);
529 // This is a stand-alone face, add it to all processors
530 forAll (procFaceList, procI)
532 procZoneFaceList[procI].append(curFaceID);
540 // Convert linked lists into normal lists
541 // Add inter-processor boundaries and remember start indices
543 forAll (procFaceList, procI)
545 // Get internal and regular boundary processor faces
546 const SLList<label>& curProcFaces = procFaceList[procI];
548 // Get reference to processor face addressing
549 labelList& curProcFaceAddressing = procFaceAddressing_[procI];
551 labelList& curProcNeighbourProcessors =
552 procNeighbourProcessors_[procI];
554 labelList& curProcProcessorPatchSize =
555 procProcessorPatchSize_[procI];
557 labelList& curProcProcessorPatchStartIndex =
558 procProcessorPatchStartIndex_[procI];
560 // calculate the size
561 label nFacesOnProcessor = curProcFaces.size();
565 SLList<SLList<label> >::const_iterator curInterProcBFacesIter =
566 interProcBFaces[procI].begin();
567 curInterProcBFacesIter != interProcBFaces[procI].end();
568 ++curInterProcBFacesIter
571 nFacesOnProcessor += curInterProcBFacesIter().size();
574 // Add stand-alone global zone faces
575 nFacesOnProcessor += procZoneFaceList[procI].size();
577 curProcFaceAddressing.setSize(nFacesOnProcessor);
579 // Fill in the list. Calculate turning index.
580 // Turning index will be -1 only for some faces on processor
581 // boundaries, i.e. the ones where the current processor ID
582 // is in the cell which is a face neighbour.
583 // Turning index is stored as the sign of the face addressing list
587 // Add internal and boundary faces
588 // Remember to increment the index by one such that the
589 // turning index works properly. HJ, 5/Dec/2001
592 SLList<label>::const_iterator curProcFacesIter =
593 curProcFaces.begin();
594 curProcFacesIter != curProcFaces.end();
598 curProcFaceAddressing[nFaces] = curProcFacesIter() + 1;
602 // Add inter-processor boundary faces. At the beginning of each
603 // patch, grab the patch start index and size
605 curProcNeighbourProcessors.setSize
607 interProcBoundaries[procI].size()
610 curProcProcessorPatchSize.setSize
612 interProcBoundaries[procI].size()
615 curProcProcessorPatchStartIndex.setSize
617 interProcBoundaries[procI].size()
620 label nProcPatches = 0;
622 SLList<label>::iterator curInterProcBdrsIter =
623 interProcBoundaries[procI].begin();
625 SLList<SLList<label> >::iterator curInterProcBFacesIter =
626 interProcBFaces[procI].begin();
631 curInterProcBdrsIter != interProcBoundaries[procI].end()
632 && curInterProcBFacesIter != interProcBFaces[procI].end();
633 ++curInterProcBdrsIter, ++curInterProcBFacesIter
636 curProcNeighbourProcessors[nProcPatches] =
637 curInterProcBdrsIter();
639 // Get start index for processor patch
640 curProcProcessorPatchStartIndex[nProcPatches] = nFaces;
643 curProcProcessorPatchSize[nProcPatches];
647 // Add faces for this processor boundary
651 SLList<label>::iterator curFacesIter =
652 curInterProcBFacesIter().begin();
653 curFacesIter != curInterProcBFacesIter().end();
659 // Remember to increment the index by one such that the
660 // turning index works properly. HJ, 5/Dec/2001
661 if (cellToProc_[owner[curFacesIter()]] == procI)
663 curProcFaceAddressing[nFaces] = curFacesIter() + 1;
668 curProcFaceAddressing[nFaces] = -(curFacesIter() + 1);
671 // increment the size
680 // Record number of live faces
681 nLiveProcFaces_[procI] = nFaces;
683 // Add stand-alone face zone faces
684 const SLList<label>& curProcZoneFaces = procZoneFaceList[procI];
688 SLList<label>::const_iterator curProcZoneFacesIter =
689 curProcZoneFaces.begin();
690 curProcZoneFacesIter != curProcZoneFaces.end();
691 ++curProcZoneFacesIter
694 curProcFaceAddressing[nFaces] = curProcZoneFacesIter() + 1;
697 } // End for all processors
698 } // End of memory management
700 Info << "\nCalculating processor boundary addressing" << endl;
701 // For every patch of processor boundary, find the index of the original
702 // patch. Mis-alignment is caused by the fact that patches with zero size
703 // are omitted. For processor patches, set index to -1.
704 // At the same time, filter the procPatchSize_ and procPatchStartIndex_
705 // lists to exclude zero-size patches
706 forAll (procPatchSize_, procI)
708 // Make a local copy of old lists
709 const labelList oldPatchSizes = procPatchSize_[procI];
711 const labelList oldPatchStarts = procPatchStartIndex_[procI];
713 labelList& curPatchSizes = procPatchSize_[procI];
715 labelList& curPatchStarts = procPatchStartIndex_[procI];
717 const labelList& curProcessorPatchSizes =
718 procProcessorPatchSize_[procI];
720 labelList& curBoundaryAddressing = procBoundaryAddressing_[procI];
722 curBoundaryAddressing.setSize
725 + curProcessorPatchSizes.size()
730 forAll (oldPatchSizes, patchi)
732 if (!filterEmptyPatches || oldPatchSizes[patchi] > 0)
734 curBoundaryAddressing[nPatches] = patchi;
736 curPatchSizes[nPatches] = oldPatchSizes[patchi];
738 curPatchStarts[nPatches] = oldPatchStarts[patchi];
744 // reset to the size of live patches
745 curPatchSizes.setSize(nPatches);
746 curPatchStarts.setSize(nPatches);
748 forAll (curProcessorPatchSizes, procPatchI)
750 curBoundaryAddressing[nPatches] = -1;
755 curBoundaryAddressing.setSize(nPatches);
758 Info << "\nDistributing points to processors" << endl;
759 // For every processor, loop through the list of faces for the processor.
760 // For every face, loop through the list of points and mark the point as
761 // used for the processor. Collect the list of used points for the
764 // Record number of live points on each processor
765 labelList nLivePoints(nProcs_, 0);
767 forAll (procPointAddressing_, procI)
769 // Dimension list to all points in the mesh. HJ, 27/Mar/2009
770 boolList pointLabels(allPoints().size(), false);
772 // Get reference to list of used faces
773 const labelList& procFaceLabels = procFaceAddressing_[procI];
775 // Collect the used points
776 labelList& procPointLabels = procPointAddressing_[procI];
778 procPointLabels.setSize(pointLabels.size());
780 // Two-pass algorithm:
781 // First loop through live faces and record them in the points list
782 // Second, visit all inactive zone faces and record the points
784 label nUsedPoints = 0;
786 // First pass: live faces
788 for (label faceI = 0; faceI < nLiveProcFaces_[procI]; faceI++)
790 // Because of the turning index, some labels may be negative
791 const labelList& facePoints = fcs[mag(procFaceLabels[faceI]) - 1];
793 forAll (facePoints, pointI)
795 // Mark the point as used
796 pointLabels[facePoints[pointI]] = true;
800 forAll (pointLabels, pointI)
802 if (pointLabels[pointI])
804 procPointLabels[nUsedPoints] = pointI;
810 // Record number of live points
811 nLivePoints[procI] = nUsedPoints;
813 // Second pass: zone faces
815 // Reset point usage list
816 boolList pointLabelsSecondPass(allPoints().size(), false);
820 label faceI = nLiveProcFaces_[procI];
821 faceI < procFaceLabels.size();
825 // Because of the turning index, some labels may be negative
826 const labelList& facePoints = fcs[mag(procFaceLabels[faceI]) - 1];
828 forAll (facePoints, pointI)
830 // Mark the point as used
831 if (!pointLabels[facePoints[pointI]])
833 pointLabelsSecondPass[facePoints[pointI]] = true;
838 forAll (pointLabelsSecondPass, pointI)
840 if (pointLabelsSecondPass[pointI])
842 procPointLabels[nUsedPoints] = pointI;
848 // Reset the size of used points
849 procPointLabels.setSize(nUsedPoints);
852 // Gather data about globally shared points
856 // Dimension list to all points in the mesh. HJ, 27/Mar/2009
857 labelList pointsUsage(allPoints().size(), 0);
859 // Globally shared points are the ones used by more than 2 processors
860 // Size the list approximately and gather the points
861 labelHashSet gSharedPoints
863 min(100, nPoints()/1000)
866 // Loop through all the processors and mark up points used by
867 // processor boundaries. When a point is used twice, it is a
868 // globally shared point
870 for (label procI = 0; procI < nProcs_; procI++)
872 // Get list of face labels
873 const labelList& curFaceLabels = procFaceAddressing_[procI];
875 // Get start of processor faces
876 const labelList& curProcessorPatchStarts =
877 procProcessorPatchStartIndex_[procI];
879 const labelList& curProcessorPatchSizes =
880 procProcessorPatchSize_[procI];
882 // Reset the lookup list
885 forAll (curProcessorPatchStarts, patchi)
887 const label curStart = curProcessorPatchStarts[patchi];
888 const label curEnd = curStart + curProcessorPatchSizes[patchi];
892 label faceI = curStart;
897 // Mark the original face as used
898 // Remember to decrement the index by one (turning index)
900 const label curF = mag(curFaceLabels[faceI]) - 1;
902 const face& f = fcs[curF];
906 if (pointsUsage[f[pointI]] == 0)
908 // Point not previously used
909 pointsUsage[f[pointI]] = patchi + 1;
911 else if (pointsUsage[f[pointI]] != patchi + 1)
913 // Point used by some other patch = global point!
914 gSharedPoints.insert(f[pointI]);
921 // Grab the result from the hash list
922 globallySharedPoints_ = gSharedPoints.toc();
923 sort(globallySharedPoints_);