Foam::labelList Foam::metisDecomp::decompose ( const polyMesh& mesh, const pointField& points, const scalarField& pointWeights ) { if (points.size() != mesh.nCells()) { FatalErrorIn ( "metisDecomp::decompose(const pointField&,const scalarField&)" ) << "Can use this decomposition method only for the whole mesh" << endl << "and supply one coordinate (cellCentre) for every cell." << endl << "The number of coordinates " << points.size() << endl << "The number of cells in the mesh " << mesh.nCells() << exit(FatalError); } CompactListList<label> cellCells; calcCellCells(mesh, identity(mesh.nCells()), mesh.nCells(), cellCells); // Decompose using default weights labelList decomp; decompose(cellCells.m(), cellCells.offsets(), pointWeights, decomp); return decomp; }
Foam::labelList Foam::CuthillMcKeeRenumber::renumber ( const polyMesh& mesh, const pointField& points ) const { CompactListList<label> cellCells; decompositionMethod::calcCellCells ( mesh, identity(mesh.nCells()), mesh.nCells(), false, // local only cellCells ); labelList orderedToOld = bandCompression(cellCells()); if (reverse_) { reverse(orderedToOld); } return orderedToOld; }
Foam::labelList Foam::structuredRenumber::renumber ( const polyMesh& mesh, const pointField& points ) const { if (points.size() != mesh.nCells()) { FatalErrorInFunction << "Number of points " << points.size() << " should equal the number of cells " << mesh.nCells() << exit(FatalError); } const polyBoundaryMesh& pbm = mesh.boundaryMesh(); const labelHashSet patchIDs(pbm.patchSet(patches_)); label nFaces = 0; forAllConstIter(labelHashSet, patchIDs, iter) { nFaces += pbm[iter.key()].size(); } // Extract a submesh. labelHashSet patchCells(2*nFaces); forAllConstIter(labelHashSet, patchIDs, iter) { const labelUList& fc = pbm[iter.key()].faceCells(); forAll(fc, i) { patchCells.insert(fc[i]); } }
void Foam::syncTools::swapBoundaryCellPositions ( const polyMesh& mesh, const UList<point>& cellData, List<point>& neighbourCellData ) { if (cellData.size() != mesh.nCells()) { FatalErrorInFunction << "Number of cell values " << cellData.size() << " is not equal to the number of cells in the mesh " << mesh.nCells() << abort(FatalError); } const polyBoundaryMesh& patches = mesh.boundaryMesh(); label nBnd = mesh.nFaces()-mesh.nInternalFaces(); neighbourCellData.setSize(nBnd); forAll(patches, patchI) { const polyPatch& pp = patches[patchI]; const labelUList& faceCells = pp.faceCells(); forAll(faceCells, i) { label bFaceI = pp.start()+i-mesh.nInternalFaces(); neighbourCellData[bFaceI] = cellData[faceCells[i]]; } }
void Foam::scotchDecomp::calcCSR ( const polyMesh& mesh, List<int>& adjncy, List<int>& xadj ) { // Make Metis CSR (Compressed Storage Format) storage // adjncy : contains neighbours (= edges in graph) // xadj(celli) : start of information in adjncy for celli xadj.setSize(mesh.nCells()+1); // Initialise the number of internal faces of the cells to twice the // number of internal faces label nInternalFaces = 2*mesh.nInternalFaces(); // Check the boundary for coupled patches and add to the number of // internal faces const polyBoundaryMesh& pbm = mesh.boundaryMesh(); forAll(pbm, patchi) { if (isA<cyclicPolyPatch>(pbm[patchi])) { nInternalFaces += pbm[patchi].size(); } } // Create the adjncy array the size of the total number of internal and // coupled faces adjncy.setSize(nInternalFaces); // Fill in xadj // ~~~~~~~~~~~~ label freeAdj = 0; for (label cellI = 0; cellI < mesh.nCells(); cellI++) { xadj[cellI] = freeAdj; const labelList& cFaces = mesh.cells()[cellI]; forAll(cFaces, i) { label faceI = cFaces[i]; if ( mesh.isInternalFace(faceI) || isA<cyclicPolyPatch>(pbm[pbm.whichPatch(faceI)]) ) { freeAdj++; } } }
Foam::labelList Foam::ptscotchDecomp::decompose ( const polyMesh& mesh, const pointField& points, const scalarField& pointWeights ) { if (points.size() != mesh.nCells()) { FatalErrorIn ( "ptscotchDecomp::decompose(const pointField&, const scalarField&)" ) << "Can use this decomposition method only for the whole mesh" << endl << "and supply one coordinate (cellCentre) for every cell." << endl << "The number of coordinates " << points.size() << endl << "The number of cells in the mesh " << mesh.nCells() << exit(FatalError); } // // For running sequential ... // if (Pstream::nProcs() <= 1) // { // return scotchDecomp(decompositionDict_, mesh_) // .decompose(points, pointWeights); // } // Make Metis CSR (Compressed Storage Format) storage // adjncy : contains neighbours (= edges in graph) // xadj(celli) : start of information in adjncy for celli CompactListList<label> cellCells; calcCellCells(mesh, identity(mesh.nCells()), mesh.nCells(), cellCells); // Decompose using default weights List<int> finalDecomp; decomposeZeroDomains ( mesh.time().path()/mesh.name(), cellCells.m(), cellCells.offsets(), pointWeights, finalDecomp ); // Copy back to labelList labelList decomp(finalDecomp.size()); forAll(decomp, i) { decomp[i] = finalDecomp[i]; } return decomp; }
Foam::labelList Foam::ptscotchDecomp::decompose ( const polyMesh& mesh, const labelList& agglom, const pointField& agglomPoints, const scalarField& pointWeights ) { if (agglom.size() != mesh.nCells()) { FatalErrorIn ( "ptscotchDecomp::decompose(const labelList&, const pointField&)" ) << "Size of cell-to-coarse map " << agglom.size() << " differs from number of cells in mesh " << mesh.nCells() << exit(FatalError); } // // For running sequential ... // if (Pstream::nProcs() <= 1) // { // return scotchDecomp(decompositionDict_, mesh) // .decompose(agglom, agglomPoints, pointWeights); // } // Make Metis CSR (Compressed Storage Format) storage // adjncy : contains neighbours (= edges in graph) // xadj(celli) : start of information in adjncy for celli CompactListList<label> cellCells; calcCellCells(mesh, agglom, agglomPoints.size(), cellCells); // Decompose using weights List<int> finalDecomp; decomposeZeroDomains ( mesh.time().path()/mesh.name(), cellCells.m(), cellCells.offsets(), pointWeights, finalDecomp ); // Rework back into decomposition for original mesh labelList fineDistribution(agglom.size()); forAll(fineDistribution, i) { fineDistribution[i] = finalDecomp[agglom[i]]; } return fineDistribution; }
//- (optionally destructively) construct from components Foam::mapDistributePolyMesh::mapDistributePolyMesh ( const polyMesh& mesh, const label nOldPoints, const label nOldFaces, const label nOldCells, labelList& oldPatchStarts, labelList& oldPatchNMeshPoints, labelListList& subPointMap, labelListList& subFaceMap, labelListList& subCellMap, labelListList& subPatchMap, labelListList& constructPointMap, labelListList& constructFaceMap, labelListList& constructCellMap, labelListList& constructPatchMap, const bool reUse // clone or reuse ) : mesh_(mesh), nOldPoints_(nOldPoints), nOldFaces_(nOldFaces), nOldCells_(nOldCells), oldPatchSizes_(oldPatchStarts.size()), oldPatchStarts_(oldPatchStarts, reUse), oldPatchNMeshPoints_(oldPatchNMeshPoints, reUse), pointMap_(mesh.nPoints(), subPointMap, constructPointMap, reUse), faceMap_(mesh.nFaces(), subFaceMap, constructFaceMap, reUse), cellMap_(mesh.nCells(), subCellMap, constructCellMap, reUse), patchMap_(mesh.boundaryMesh().size(), subPatchMap, constructPatchMap, reUse) { calcPatchSizes(); }
Foam::label Foam::meshToMeshNew::calcDistribution ( const polyMesh& src, const polyMesh& tgt ) const { label procI = 0; if (Pstream::parRun()) { List<label> cellsPresentOnProc(Pstream::nProcs(), 0); if ((src.nCells() > 0) || (tgt.nCells() > 0)) { cellsPresentOnProc[Pstream::myProcNo()] = 1; } else { cellsPresentOnProc[Pstream::myProcNo()] = 0; } Pstream::gatherList(cellsPresentOnProc); Pstream::scatterList(cellsPresentOnProc); label nHaveCells = sum(cellsPresentOnProc); if (nHaveCells > 1) { procI = -1; if (debug) { Info<< "meshToMeshNew::calcDistribution: " << "Meshes split across multiple processors" << endl; } } else if (nHaveCells == 1) { procI = findIndex(cellsPresentOnProc, 1); if (debug) { Info<< "meshToMeshNew::calcDistribution: " << "Meshes local to processor" << procI << endl; } } } return procI; }
// Construct from mesh. No morphing data: the mesh has not changed // HJ, 27/Nov/2009 Foam::mapPolyMesh::mapPolyMesh(const polyMesh& mesh) : mesh_(mesh), morphing_(false), nOldPoints_(mesh.nPoints()), nOldFaces_(mesh.nFaces()), nOldCells_(mesh.nCells()) {}
Foam::labelList Foam::refinementParameters::findCells(const polyMesh& mesh) const { // Force calculation of tet-diag decomposition (for use in findCell) (void)mesh.tetBasePtIs(); // Global calculation engine globalIndex globalCells(mesh.nCells()); // Cell label per point labelList cellLabels(keepPoints_.size()); forAll(keepPoints_, i) { const point& keepPoint = keepPoints_[i]; label localCellI = mesh.findCell(keepPoint); label globalCellI = -1; if (localCellI != -1) { globalCellI = globalCells.toGlobal(localCellI); } reduce(globalCellI, maxOp<label>()); if (globalCellI == -1) { FatalErrorInFunction << "Point " << keepPoint << " is not inside the mesh or on a face or edge." << nl << "Bounding box of the mesh:" << mesh.bounds() << exit(FatalError); } label procI = globalCells.whichProcID(globalCellI); label procCellI = globalCells.toLocal(procI, globalCellI); Info<< "Found point " << keepPoint << " in cell " << procCellI << " on processor " << procI << endl; if (globalCells.isLocal(globalCellI)) { cellLabels[i] = localCellI; } else { cellLabels[i] = -1; } } return cellLabels; }
void Foam::meshToMeshNew::writeConnectivity ( const polyMesh& src, const polyMesh& tgt, const labelListList& srcToTargetAddr ) const { Pout<< "Source size = " << src.nCells() << endl; Pout<< "Target size = " << tgt.nCells() << endl; word fName("addressing_" + src.name() + "_to_" + tgt.name()); if (Pstream::parRun()) { fName = fName + "_proc" + Foam::name(Pstream::myProcNo()); } OFstream os(src.time().path()/fName + ".obj"); label vertI = 0; forAll(srcToTargetAddr, i) { const labelList& tgtAddress = srcToTargetAddr[i]; forAll(tgtAddress, j) { label tgtI = tgtAddress[j]; const vector& c0 = src.cellCentres()[i]; const cell& c = tgt.cells()[tgtI]; const pointField pts(c.points(tgt.faces(), tgt.points())); forAll(pts, j) { const point& p = pts[j]; os << "v " << p.x() << ' ' << p.y() << ' ' << p.z() << nl; vertI++; os << "v " << c0.x() << ' ' << c0.y() << ' ' << c0.z() << nl; vertI++; os << "l " << vertI - 1 << ' ' << vertI << nl; } } }
Foam::labelList Foam::metisDecomp::decompose ( const polyMesh& mesh, const labelList& agglom, const pointField& agglomPoints, const scalarField& agglomWeights ) { if (agglom.size() != mesh.nCells()) { FatalErrorIn ( "metisDecomp::decompose" "(const labelList&, const pointField&, const scalarField&)" ) << "Size of cell-to-coarse map " << agglom.size() << " differs from number of cells in mesh " << mesh.nCells() << exit(FatalError); } // Make Metis CSR (Compressed Storage Format) storage // adjncy : contains neighbours (= edges in graph) // xadj(celli) : start of information in adjncy for celli CompactListList<label> cellCells; calcCellCells(mesh, agglom, agglomPoints.size(), cellCells); // Decompose using default weights labelList finalDecomp; decompose(cellCells.m(), cellCells.offsets(), agglomWeights, finalDecomp); // Rework back into decomposition for original mesh labelList fineDistribution(agglom.size()); forAll(fineDistribution, i) { fineDistribution[i] = finalDecomp[agglom[i]]; } return finalDecomp; }
cellSet::cellSet ( const polyMesh& mesh, const word& name, readOption r, writeOption w ) : topoSet(mesh, typeName, name, r, w) { // Make sure set within valid range check(mesh.nCells()); }
// Construct from mesh reference Foam::polyTopoChange::polyTopoChange(const polyMesh& mesh) : mesh_(mesh), addedPoints_(minListSize), modifiedPoints_(minListSize), removedPoints_ ( Foam::max(mesh.allPoints().size()/pointFraction, minListSize) ), addedFaces_(minListSize), modifiedFaces_(minListSize), removedFaces_(Foam::max(mesh.allFaces().size()/faceFraction, minListSize)), addedCells_(minListSize), removedCells_(Foam::max(mesh.nCells()/cellFraction, minListSize)) {}
Foam::labelList Foam::refinementParameters::findCells(const polyMesh& mesh) const { // Global calculation engine globalIndex globalCells(mesh.nCells()); // Cell label per point labelList cellLabels(keepPoints_.size()); forAll(keepPoints_, i) { const point& keepPoint = keepPoints_[i]; label localCellI = mesh.findCell(keepPoint); label globalCellI = -1; if (localCellI != -1) { Pout<< "Found point " << keepPoint << " in cell " << localCellI << " on processor " << Pstream::myProcNo() << endl; globalCellI = globalCells.toGlobal(localCellI); } reduce(globalCellI, maxOp<label>()); if (globalCellI == -1) { FatalErrorIn ( "refinementParameters::findCells(const polyMesh&) const" ) << "Point " << keepPoint << " is not inside the mesh or on a face or edge." << nl << "Bounding box of the mesh:" << mesh.bounds() << exit(FatalError); } if (globalCells.isLocal(globalCellI)) { cellLabels[i] = localCellI; } else { cellLabels[i] = -1; } } return cellLabels; }
Foam::MeshWave<Type>::MeshWave ( const polyMesh& mesh, const labelList& changedFaces, const List<Type>& changedFacesInfo, const label maxIter ) : allFaceInfo_(mesh.nFaces()), allCellInfo_(mesh.nCells()), calc_ ( mesh, changedFaces, changedFacesInfo, allFaceInfo_, allCellInfo_, maxIter ) {}
//- Construct from components Foam::mapDistributePolyMesh::mapDistributePolyMesh ( const polyMesh& mesh, // mesh before changes const label nOldPoints, const label nOldFaces, const label nOldCells, const labelList& oldPatchStarts, const labelList& oldPatchNMeshPoints, // how to subset pieces of mesh to send across const labelListList& subPointMap, const labelListList& subFaceMap, const labelListList& subCellMap, const labelListList& subPatchMap, // how to reconstruct received mesh const labelListList& constructPointMap, const labelListList& constructFaceMap, const labelListList& constructCellMap, const labelListList& constructPatchMap ) : mesh_(mesh), nOldPoints_(nOldPoints), nOldFaces_(nOldFaces), nOldCells_(nOldCells), oldPatchSizes_(oldPatchStarts.size()), oldPatchStarts_(oldPatchStarts), oldPatchNMeshPoints_(oldPatchNMeshPoints), pointMap_(mesh.nPoints(), subPointMap, constructPointMap), faceMap_(mesh.nFaces(), subFaceMap, constructFaceMap), cellMap_(mesh.nCells(), subCellMap, constructCellMap), patchMap_(mesh.boundaryMesh().size(), subPatchMap, constructPatchMap) { calcPatchSizes(); }
label cellSet::maxSize(const polyMesh& mesh) const { return mesh.nCells(); }
void Foam::printMeshStats(const polyMesh& mesh, const bool allTopology) { Info<< "Mesh stats" << nl << " points: " << returnReduce(mesh.points().size(), sumOp<label>()) << nl; label nInternalPoints = returnReduce ( mesh.nInternalPoints(), sumOp<label>() ); if (nInternalPoints != -Pstream::nProcs()) { Info<< " internal points: " << nInternalPoints << nl; if (returnReduce(mesh.nInternalPoints(), minOp<label>()) == -1) { WarningIn("Foam::printMeshStats(const polyMesh&, const bool)") << "Some processors have their points sorted into internal" << " and external and some do not." << endl << "This can cause problems later on." << endl; } } if (allTopology && nInternalPoints != -Pstream::nProcs()) { label nEdges = returnReduce(mesh.nEdges(), sumOp<label>()); label nInternalEdges = returnReduce ( mesh.nInternalEdges(), sumOp<label>() ); label nInternal1Edges = returnReduce ( mesh.nInternal1Edges(), sumOp<label>() ); label nInternal0Edges = returnReduce ( mesh.nInternal0Edges(), sumOp<label>() ); Info<< " edges: " << nEdges << nl << " internal edges: " << nInternalEdges << nl << " internal edges using one boundary point: " << nInternal1Edges-nInternal0Edges << nl << " internal edges using two boundary points: " << nInternalEdges-nInternal1Edges << nl; } label nFaces = returnReduce(mesh.faces().size(), sumOp<label>()); label nIntFaces = returnReduce(mesh.faceNeighbour().size(), sumOp<label>()); label nCells = returnReduce(mesh.cells().size(), sumOp<label>()); Info<< " faces: " << nFaces << nl << " internal faces: " << nIntFaces << nl << " cells: " << nCells << nl << " faces per cell: " << scalar(nFaces + nIntFaces)/max(1, nCells) << nl << " boundary patches: " << mesh.boundaryMesh().size() << nl << " point zones: " << mesh.pointZones().size() << nl << " face zones: " << mesh.faceZones().size() << nl << " cell zones: " << mesh.cellZones().size() << nl << endl; // Construct shape recognizers hexMatcher hex; prismMatcher prism; wedgeMatcher wedge; pyrMatcher pyr; tetWedgeMatcher tetWedge; tetMatcher tet; // Counters for different cell types label nHex = 0; label nWedge = 0; label nPrism = 0; label nPyr = 0; label nTet = 0; label nTetWedge = 0; label nUnknown = 0; Map<label> polyhedralFaces; for (label cellI = 0; cellI < mesh.nCells(); cellI++) { if (hex.isA(mesh, cellI)) { nHex++; } else if (tet.isA(mesh, cellI)) { nTet++; } else if (pyr.isA(mesh, cellI)) { nPyr++; } else if (prism.isA(mesh, cellI)) { nPrism++; } else if (wedge.isA(mesh, cellI)) { nWedge++; } else if (tetWedge.isA(mesh, cellI)) { nTetWedge++; } else { nUnknown++; polyhedralFaces(mesh.cells()[cellI].size())++; } } reduce(nHex,sumOp<label>()); reduce(nPrism,sumOp<label>()); reduce(nWedge,sumOp<label>()); reduce(nPyr,sumOp<label>()); reduce(nTetWedge,sumOp<label>()); reduce(nTet,sumOp<label>()); reduce(nUnknown,sumOp<label>()); Info<< "Overall number of cells of each type:" << nl << " hexahedra: " << nHex << nl << " prisms: " << nPrism << nl << " wedges: " << nWedge << nl << " pyramids: " << nPyr << nl << " tet wedges: " << nTetWedge << nl << " tetrahedra: " << nTet << nl << " polyhedra: " << nUnknown << endl; if (nUnknown > 0) { Pstream::mapCombineGather(polyhedralFaces, plusEqOp<label>()); Info<< " Breakdown of polyhedra by number of faces:" << nl << " faces" << " number of cells" << endl; const labelList sortedKeys = polyhedralFaces.sortedToc(); forAll(sortedKeys, keyI) { const label nFaces = sortedKeys[keyI]; Info<< setf(std::ios::right) << setw(13) << nFaces << " " << polyhedralFaces[nFaces] << nl; } }
Foam::autoPtr<Foam::mapDistribute> Foam::meshToMeshNew::calcProcMap ( const polyMesh& src, const polyMesh& tgt ) const { // get decomposition of cells on src mesh List<boundBox> procBb(Pstream::nProcs()); if (src.nCells() > 0) { // bounding box for my mesh - do not parallel reduce procBb[Pstream::myProcNo()] = boundBox(src.points(), false); // slightly increase size of bounding boxes to allow for cases where // bounding boxes are perfectly alligned procBb[Pstream::myProcNo()].inflate(0.01); } else { procBb[Pstream::myProcNo()] = boundBox(); } Pstream::gatherList(procBb); Pstream::scatterList(procBb); if (debug) { Info<< "Determining extent of src mesh per processor:" << nl << "\tproc\tbb" << endl; forAll(procBb, procI) { Info<< '\t' << procI << '\t' << procBb[procI] << endl; } } // determine which cells of tgt mesh overlaps src mesh per proc const cellList& cells = tgt.cells(); const faceList& faces = tgt.faces(); const pointField& points = tgt.points(); labelListList sendMap; { // per processor indices into all segments to send List<DynamicList<label> > dynSendMap(Pstream::nProcs()); label iniSize = floor(tgt.nCells()/Pstream::nProcs()); forAll(dynSendMap, procI) { dynSendMap[procI].setCapacity(iniSize); } // work array - whether src processor bb overlaps the tgt cell bounds boolList procBbOverlaps(Pstream::nProcs()); forAll(cells, cellI) { const cell& c = cells[cellI]; // determine bounding box of tgt cell boundBox cellBb(point::max, point::min); forAll(c, faceI) { const face& f = faces[c[faceI]]; forAll(f, fp) { cellBb.min() = min(cellBb.min(), points[f[fp]]); cellBb.max() = max(cellBb.max(), points[f[fp]]); } } // find the overlapping tgt cells on each src processor (void)calcOverlappingProcs(procBb, cellBb, procBbOverlaps); forAll(procBbOverlaps, procI) { if (procBbOverlaps[procI]) { dynSendMap[procI].append(cellI); } } }