1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
40 domainDecomposition::domainDecomposition(const IOobject& io)
54 nProcs_(readInt(decompositionDict_.lookup("numberOfSubdomains"))),
56 cellToProc_(nCells()),
57 procPointAddressing_(nProcs_),
58 procFaceAddressing_(nProcs_),
59 nInternalProcFaces_(nProcs_),
60 nLiveProcFaces_(nProcs_),
61 procCellAddressing_(nProcs_),
62 procBoundaryAddressing_(nProcs_),
63 procPatchSize_(nProcs_),
64 procPatchStartIndex_(nProcs_),
65 procNeighbourProcessors_(nProcs_),
66 procProcessorPatchSize_(nProcs_),
67 procProcessorPatchStartIndex_(nProcs_),
68 globallySharedPoints_(0),
69 cyclicParallel_(false)
71 if (decompositionDict_.found("distributed"))
73 distributed_ = Switch(decompositionDict_.lookup("distributed"));
78 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
80 domainDecomposition::~domainDecomposition()
84 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
86 bool domainDecomposition::writeDecomposition()
88 Info<< "\nConstructing processor meshes" << endl;
90 // Make a lookup map for globally shared points
91 Map<label> sharedPointLookup(2*globallySharedPoints_.size());
93 forAll (globallySharedPoints_, pointi)
95 sharedPointLookup.insert(globallySharedPoints_[pointi], pointi);
99 // Mark point/faces/cells that are in zones. Bad coding - removed
102 label totProcFaces = 0;
103 label maxProcPatches = 0;
104 label maxProcFaces = 0;
107 // Write out the meshes
108 for (label procI = 0; procI < nProcs_; procI++)
110 // Create processor points
111 const labelList& curPointLabels = procPointAddressing_[procI];
113 // Access list of all points in the mesh. HJ, 27/Mar/2009
114 const pointField& meshPoints = allPoints();
116 labelList pointLookup(meshPoints.size(), -1);
118 pointField procPoints(curPointLabels.size());
120 forAll (curPointLabels, pointi)
122 procPoints[pointi] = meshPoints[curPointLabels[pointi]];
124 pointLookup[curPointLabels[pointi]] = pointi;
127 // Create processor faces
128 const labelList& curFaceLabels = procFaceAddressing_[procI];
130 // Access list of all faces in the mesh. HJ, 27/Mar/2009
131 const faceList& meshFaces = allFaces();
133 labelList faceLookup(meshFaces.size(), -1);
135 faceList procFaces(curFaceLabels.size());
137 forAll (curFaceLabels, facei)
139 // Mark the original face as used
140 // Remember to decrement the index by one (turning index)
142 label curF = mag(curFaceLabels[facei]) - 1;
144 faceLookup[curF] = facei;
146 // get the original face
147 labelList origFaceLabels;
149 if (curFaceLabels[facei] >= 0)
152 origFaceLabels = meshFaces[curF];
156 origFaceLabels = meshFaces[curF].reverseFace();
159 // translate face labels into local point list
160 face& procFaceLabels = procFaces[facei];
162 procFaceLabels.setSize(origFaceLabels.size());
164 forAll (origFaceLabels, pointi)
166 procFaceLabels[pointi] = pointLookup[origFaceLabels[pointi]];
170 // Create cell lookup
171 labelList cellLookup(nCells(), -1);
172 const labelList& curCellLabels = procCellAddressing_[procI];
174 forAll (curCellLabels, cellI)
176 cellLookup[curCellLabels[cellI]] = cellI;
179 // Get complete owner-neighour addressing in the mesh
180 const labelList& own = faceOwner();
181 const labelList& nei = faceNeighbour();
183 // Calculate owner and neighbour list
184 // Owner list is sized to number of live faces
185 // Neighbour list is sized to number of internal faces
187 labelList procOwner(nLiveProcFaces_[procI]);
189 // Note: loop over owner, not all faces: sizes are different
190 forAll (procOwner, faceI)
192 // Remember to decrement the index by one (turning index)
194 label curF = mag(curFaceLabels[faceI]) - 1;
196 if (curFaceLabels[faceI] >= 0)
198 procOwner[faceI] = cellLookup[own[curF]];
202 procOwner[faceI] = cellLookup[nei[curF]];
206 labelList procNeighbour(nInternalProcFaces_[procI]);
208 // Note: loop over neighbour, not all faces: sizes are different
209 forAll (procNeighbour, faceI)
211 // Remember to decrement the index by one (turning index)
213 label curF = mag(curFaceLabels[faceI]) - 1;
215 if (curFaceLabels[faceI] >= 0)
217 procNeighbour[faceI] = cellLookup[nei[curF]];
221 procNeighbour[faceI] = cellLookup[own[curF]];
225 // Create processor cells. No longer needed: using owner and neighbour
227 // const cellList& meshCells = cells();
229 // cellList procCells(curCellLabels.size());
231 // forAll (curCellLabels, cellI)
233 // const labelList& origCellLabels = meshCells[curCellLabels[cellI]];
235 // cell& curCell = procCells[cellI];
237 // curCell.setSize(origCellLabels.size());
239 // forAll (origCellLabels, cellFaceI)
241 // curCell[cellFaceI] = faceLookup[origCellLabels[cellFaceI]];
245 // Create processor mesh without a boundary
247 fileName processorCasePath
249 time().caseName()/fileName(word("processor") + Foam::name(procI))
252 // make the processor directory
253 mkDir(time().rootPath()/processorCasePath);
258 Time::controlDictName,
271 this->polyMesh::name(), // region name of undecomposed mesh
275 xferMove(procPoints),
278 xferMove(procNeighbour),
279 false // Do not sync par
280 // xferMove(procCells) // Old-fashioned mesh creation using cells.
281 // Deprecated: using face owner/neighbour
285 // Create processor boundary patches
286 const labelList& curBoundaryAddressing = procBoundaryAddressing_[procI];
288 const labelList& curPatchSizes = procPatchSize_[procI];
290 const labelList& curPatchStarts = procPatchStartIndex_[procI];
292 const labelList& curNeighbourProcessors =
293 procNeighbourProcessors_[procI];
295 const labelList& curProcessorPatchSizes =
296 procProcessorPatchSize_[procI];
298 const labelList& curProcessorPatchStarts =
299 procProcessorPatchStartIndex_[procI];
301 const polyPatchList& meshPatches = boundaryMesh();
303 List<polyPatch*> procPatches
306 + curProcessorPatchSizes.size(),
307 reinterpret_cast<polyPatch*>(0)
312 forAll (curPatchSizes, patchi)
314 procPatches[nPatches] =
315 meshPatches[curBoundaryAddressing[patchi]].clone
317 procMesh.boundaryMesh(),
319 curPatchSizes[patchi],
320 curPatchStarts[patchi]
326 forAll (curProcessorPatchSizes, procPatchI)
328 procPatches[nPatches] =
329 new processorPolyPatch
331 word("procBoundary") + Foam::name(procI)
333 + Foam::name(curNeighbourProcessors[procPatchI]),
334 curProcessorPatchSizes[procPatchI],
335 curProcessorPatchStarts[procPatchI],
337 procMesh.boundaryMesh(),
339 curNeighbourProcessors[procPatchI]
345 // Add boundary patches
346 procMesh.addPatches(procPatches);
348 // Create and add zones
351 // This coding was all wrong, as each point/face/cell may only
352 // belong to a single zone.
353 // Additionally, ordering of points/faces/cells in the processor mesh
354 // needs to match the ordering in global mesh zones. Full rewrite.
357 // Create zones if needed
360 pointZones().size() > 0
361 || faceZones().size() > 0
362 || cellZones().size() > 0
366 List<pointZone*> procPz(pointZones().size());
369 const pointZoneMesh& pz = pointZones();
371 // Go through all the zoned points and find out if they
372 // belong to a processor. If so, add it to the zone as
376 const labelList& zonePoints = pz[zoneI];
378 labelList procZonePoints(zonePoints.size());
379 label nZonePoints = 0;
381 forAll (zonePoints, pointI)
383 const label localIndex =
384 pointLookup[zonePoints[pointI]];
388 // Point live on processor: add to zone
389 procZonePoints[nZonePoints] = localIndex;
395 procZonePoints.setSize(nZonePoints);
397 procPz[zoneI] = new pointZone
402 procMesh.pointZones()
409 List<faceZone*> procFz(faceZones().size());
412 const faceZoneMesh& fz = faceZones();
416 const labelList& zoneFaces = fz[zoneI];
417 const boolList& flipMap = fz[zoneI].flipMap();
419 // Go through all the zoned faces and find out if they
420 // belong to a processor. If so, add it to the zone as
423 labelList procZoneFaces(zoneFaces.size());
424 boolList procZoneFaceFlips(zoneFaces.size());
425 label nZoneFaces = 0;
427 forAll (zoneFaces, faceI)
429 const label localIndex = faceLookup[zoneFaces[faceI]];
433 // Face is present on the processor
435 // Add the face to the zone
436 procZoneFaces[nZoneFaces] = localIndex;
439 bool flip = flipMap[faceI];
441 if (curFaceLabels[localIndex] < 0)
446 procZoneFaceFlips[nZoneFaces] = flip;
452 procZoneFaces.setSize(nZoneFaces);
453 procZoneFaceFlips.setSize(nZoneFaces);
455 procFz[zoneI] = new faceZone
467 List<cellZone*> procCz(cellZones().size());
470 const cellZoneMesh& cz = cellZones();
472 // Go through all the zoned cells and find out if they
473 // belong to a processor. If so, add it to the zone as
478 const labelList& zoneCells = cz[zoneI];
480 labelList procZoneCells(zoneCells.size());
481 label nZoneCells = 0;
483 forAll (zoneCells, cellI)
485 const label localIndex = cellLookup[zoneCells[cellI]];
489 procZoneCells[nZoneCells] = localIndex;
495 procZoneCells.setSize(nZoneCells);
497 procCz[zoneI] = new cellZone
508 procMesh.addZones(procPz, procFz, procCz);
511 // Set the precision of the points data to 10
512 IOstream::defaultPrecision(10);
517 << "Processor " << procI << nl
518 << " Number of cells = " << procMesh.nCells()
521 label nBoundaryFaces = 0;
522 label nProcPatches = 0;
523 label nProcFaces = 0;
525 forAll (procMesh.boundaryMesh(), patchi)
529 procMesh.boundaryMesh()[patchi].type()
530 == processorPolyPatch::typeName
533 const processorPolyPatch& ppp =
534 refCast<const processorPolyPatch>
536 procMesh.boundaryMesh()[patchi]
539 Info<< " Number of faces shared with processor "
540 << ppp.neighbProcNo() << " = " << ppp.size() << endl;
543 nProcFaces += ppp.size();
547 nBoundaryFaces += procMesh.boundaryMesh()[patchi].size();
551 Info<< " Number of processor patches = " << nProcPatches << nl
552 << " Number of processor faces = " << nProcFaces << nl
553 << " Number of boundary faces = " << nBoundaryFaces << endl;
555 totProcFaces += nProcFaces;
556 maxProcPatches = max(maxProcPatches, nProcPatches);
557 maxProcFaces = max(maxProcFaces, nProcFaces);
559 // create and write the addressing information
560 labelIOList pointProcAddressing
564 "pointProcAddressing",
565 procMesh.facesInstance(),
571 procPointAddressing_[procI]
573 pointProcAddressing.write();
575 labelIOList faceProcAddressing
579 "faceProcAddressing",
580 procMesh.facesInstance(),
586 procFaceAddressing_[procI]
588 faceProcAddressing.write();
590 labelIOList cellProcAddressing
594 "cellProcAddressing",
595 procMesh.facesInstance(),
601 procCellAddressing_[procI]
603 cellProcAddressing.write();
605 labelIOList boundaryProcAddressing
609 "boundaryProcAddressing",
610 procMesh.facesInstance(),
616 procBoundaryAddressing_[procI]
618 boundaryProcAddressing.write();
622 << "Number of processor faces = " << totProcFaces/2 << nl
623 << "Max number of processor patches = " << maxProcPatches << nl
624 << "Max number of faces between processors = " << maxProcFaces
631 // ************************************************************************* //