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
37 bnd=d{pass=40,dif=1,rem=1}f{move=80,pass=-1,bal=0.005},
38 org=f{move=80,pass=-1,bal=0.005},width=3
40 low=h{pass=10}f{move=80,pass=-1,bal=0.0005},
49 bnd=d{pass=40,dif=1,rem=1}f{move=80,pass=-1,bal=0.005},
50 org=f{move=80,pass=-1,bal=0.005},
52 low=h{pass=10}f{move=80,pass=-1,bal=0.0005},
59 \*---------------------------------------------------------------------------*/
61 #include "scotchDecomp.H"
62 #include "addToRunTimeSelectionTable.H"
63 #include "floatScalar.H"
66 #include "cyclicPolyPatch.H"
71 #define OMPI_SKIP_MPICXX
78 // Hack: scotch generates floating point errors so need to switch of error
80 #if defined(linux) || defined(linuxAMD64) || defined(linuxIA64)
84 #if defined(LINUX) && defined(__GNUC__)
96 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
100 defineTypeNameAndDebug(scotchDecomp, 0);
102 addToRunTimeSelectionTable
110 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
112 void Foam::scotchDecomp::check(const int retVal, const char* str)
116 FatalErrorIn("scotchDecomp::decompose(..)")
117 << "Called to scotch routine " << str << " failed."
123 // Call Metis with options from dictionary.
124 Foam::label Foam::scotchDecomp::decompose
126 const List<int>& adjncy,
127 const List<int>& xadj,
129 List<int>& finalDecomp
136 SCOTCH_Strat stradat;
137 check(SCOTCH_stratInit(&stradat), "SCOTCH_stratInit");
139 if (decompositionDict_.found("scotchCoeffs"))
141 const dictionary& scotchCoeffs =
142 decompositionDict_.subDict("scotchCoeffs");
146 if (scotchCoeffs.readIfPresent("strategy", strategy))
150 Info<< "scotchDecomp : Using strategy " << strategy << endl;
152 SCOTCH_stratGraphMap(&stradat, strategy.c_str());
153 //fprintf(stdout, "S\tStrat=");
154 //SCOTCH_stratSave(&stradat, stdout);
155 //fprintf(stdout, "\n");
163 SCOTCH_Graph grafdat;
164 check(SCOTCH_graphInit(&grafdat), "SCOTCH_graphInit");
170 0, // baseval, c-style numbering
171 xadj.size()-1, // vertnbr, nCells
172 xadj.begin(), // verttab, start index per cell into adjncy
173 &xadj[1], // vendtab, end index ,,
174 NULL, // velotab, vertex weights
176 adjncy.size(), // edgenbr, number of arcs
177 adjncy.begin(), // edgetab
178 NULL // edlotab, edge weights
182 check(SCOTCH_graphCheck(&grafdat), "SCOTCH_graphCheck");
186 if (decompositionDict_.found("scotchCoeffs"))
188 const dictionary& scotchCoeffs =
189 decompositionDict_.subDict("scotchCoeffs");
191 if (scotchCoeffs.found("writeGraph"))
193 Switch writeGraph(scotchCoeffs.lookup("writeGraph"));
197 OFstream str(mesh_.time().path() / mesh_.name() + ".grf");
199 Info<< "Dumping Scotch graph file to " << str.name() << endl
200 << "Use this in combination with gpart." << endl;
203 str << version << nl;
205 str << xadj.size()-1 << ' ' << adjncy.size() << nl;
206 // Numbering starts from 0
209 label hasEdgeWeights = 0;
210 label hasVertexWeights = 0;
211 label numericflag = 10*hasEdgeWeights+hasVertexWeights;
212 str << baseval << ' ' << numericflag << nl;
213 for (label cellI = 0; cellI < xadj.size()-1; cellI++)
215 label start = xadj[cellI];
216 label end = xadj[cellI+1];
219 for (label i = start; i < end; i++)
221 str << ' ' << adjncy[i];
232 // (fully connected network topology since using switch)
235 check(SCOTCH_archInit(&archdat), "SCOTCH_archInit");
237 List<label> processorWeights;
238 if (decompositionDict_.found("scotchCoeffs"))
240 const dictionary& scotchCoeffs =
241 decompositionDict_.subDict("scotchCoeffs");
243 scotchCoeffs.readIfPresent("processorWeights", processorWeights);
245 if (processorWeights.size())
249 Info<< "scotchDecomp : Using procesor weights " << processorWeights
254 SCOTCH_archCmpltw(&archdat, nProcessors_, processorWeights.begin()),
262 SCOTCH_archCmplt(&archdat, nProcessors_),
268 //SCOTCH_Mapping mapdat;
269 //SCOTCH_graphMapInit(&grafdat, &mapdat, &archdat, NULL);
270 //SCOTCH_graphMapCompute(&grafdat, &mapdat, &stradat); /* Perform mapping */
271 //SCOTCH_graphMapExit(&grafdat, &mapdat);
274 // Hack:switch off fpu error trapping
276 int oldExcepts = fedisableexcept
284 finalDecomp.setSize(xadj.size()-1);
292 &stradat, // const SCOTCH_Strat *
293 finalDecomp.begin() // parttab
299 feenableexcept(oldExcepts);
304 //finalDecomp.setSize(xadj.size()-1);
310 // nProcessors_, // partnbr
311 // &stradat, // const SCOTCH_Strat *
312 // finalDecomp.begin() // parttab
314 // "SCOTCH_graphPart"
317 // Release storage for graph
318 SCOTCH_graphExit(&grafdat);
319 // Release storage for strategy
320 SCOTCH_stratExit(&stradat);
321 // Release storage for network topology
322 SCOTCH_archExit(&archdat);
328 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
330 Foam::scotchDecomp::scotchDecomp
332 const dictionary& decompositionDict,
336 decompositionMethod(decompositionDict),
341 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
343 Foam::labelList Foam::scotchDecomp::decompose(const pointField& points)
345 if (points.size() != mesh_.nCells())
347 FatalErrorIn("scotchDecomp::decompose(const pointField&)")
348 << "Can use this decomposition method only for the whole mesh"
350 << "and supply one coordinate (cellCentre) for every cell." << endl
351 << "The number of coordinates " << points.size() << endl
352 << "The number of cells in the mesh " << mesh_.nCells()
356 // Make Metis CSR (Compressed Storage Format) storage
357 // adjncy : contains neighbours (= edges in graph)
358 // xadj(celli) : start of information in adjncy for celli
360 List<int> xadj(mesh_.nCells()+1);
362 // Initialise the number of internal faces of the cells to twice the
363 // number of internal faces
364 label nInternalFaces = 2*mesh_.nInternalFaces();
366 // Check the boundary for coupled patches and add to the number of
368 const polyBoundaryMesh& pbm = mesh_.boundaryMesh();
372 if (isA<cyclicPolyPatch>(pbm[patchi]))
374 nInternalFaces += pbm[patchi].size();
378 // Create the adjncy array the size of the total number of internal and
380 List<int> adjncy(nInternalFaces);
386 for (label cellI = 0; cellI < mesh_.nCells(); cellI++)
388 xadj[cellI] = freeAdj;
390 const labelList& cFaces = mesh_.cells()[cellI];
394 label faceI = cFaces[i];
398 mesh_.isInternalFace(faceI)
399 || isA<cyclicPolyPatch>(pbm[pbm.whichPatch(faceI)])
406 xadj[mesh_.nCells()] = freeAdj;
412 labelList nFacesPerCell(mesh_.nCells(), 0);
415 for (label faceI = 0; faceI < mesh_.nInternalFaces(); faceI++)
417 label own = mesh_.faceOwner()[faceI];
418 label nei = mesh_.faceNeighbour()[faceI];
420 adjncy[xadj[own] + nFacesPerCell[own]++] = nei;
421 adjncy[xadj[nei] + nFacesPerCell[nei]++] = own;
424 // Coupled faces. Only cyclics done.
427 if (isA<cyclicPolyPatch>(pbm[patchi]))
429 const unallocLabelList& faceCells = pbm[patchi].faceCells();
431 label sizeby2 = faceCells.size()/2;
433 for (label facei=0; facei<sizeby2; facei++)
435 label own = faceCells[facei];
436 label nei = faceCells[facei + sizeby2];
438 adjncy[xadj[own] + nFacesPerCell[own]++] = nei;
439 adjncy[xadj[nei] + nFacesPerCell[nei]++] = own;
444 // Decompose using default weights
445 List<int> finalDecomp;
446 decompose(adjncy, xadj, finalDecomp);
448 // Copy back to labelList
449 labelList decomp(finalDecomp.size());
452 decomp[i] = finalDecomp[i];
458 // From cell-cell connections to Metis format (like CompactListList)
459 void Foam::scotchDecomp::calcMetisCSR
461 const labelListList& cellCells,
466 // Count number of internal faces
467 label nConnections = 0;
469 forAll(cellCells, coarseI)
471 nConnections += cellCells[coarseI].size();
474 // Create the adjncy array as twice the size of the total number of
476 adjncy.setSize(nConnections);
478 xadj.setSize(cellCells.size()+1);
485 forAll(cellCells, coarseI)
487 xadj[coarseI] = freeAdj;
489 const labelList& cCells = cellCells[coarseI];
493 adjncy[freeAdj++] = cCells[i];
496 xadj[cellCells.size()] = freeAdj;
500 Foam::labelList Foam::scotchDecomp::decompose
502 const labelList& agglom,
503 const pointField& agglomPoints
506 if (agglom.size() != mesh_.nCells())
510 "parMetisDecomp::decompose(const labelList&, const pointField&)"
511 ) << "Size of cell-to-coarse map " << agglom.size()
512 << " differs from number of cells in mesh " << mesh_.nCells()
516 // Make Metis CSR (Compressed Storage Format) storage
517 // adjncy : contains neighbours (= edges in graph)
518 // xadj(celli) : start of information in adjncy for celli
522 // Get cellCells on coarse mesh.
523 labelListList cellCells;
532 calcMetisCSR(cellCells, adjncy, xadj);
535 // Decompose using default weights
536 List<int> finalDecomp;
537 decompose(adjncy, xadj, finalDecomp);
540 // Rework back into decomposition for original mesh_
541 labelList fineDistribution(agglom.size());
543 forAll(fineDistribution, i)
545 fineDistribution[i] = finalDecomp[agglom[i]];
548 return fineDistribution;
552 Foam::labelList Foam::scotchDecomp::decompose
554 const labelListList& globalCellCells,
555 const pointField& cellCentres
558 if (cellCentres.size() != globalCellCells.size())
562 "scotchDecomp::decompose(const pointField&, const labelListList&)"
563 ) << "Inconsistent number of cells (" << globalCellCells.size()
564 << ") and number of cell centres (" << cellCentres.size()
565 << ")." << exit(FatalError);
569 // Make Metis CSR (Compressed Storage Format) storage
570 // adjncy : contains neighbours (= edges in graph)
571 // xadj(celli) : start of information in adjncy for celli
575 calcMetisCSR(globalCellCells, adjncy, xadj);
578 // Decompose using default weights
579 List<int> finalDecomp;
580 decompose(adjncy, xadj, finalDecomp);
582 // Copy back to labelList
583 labelList decomp(finalDecomp.size());
586 decomp[i] = finalDecomp[i];
592 // ************************************************************************* //