void Foam::primitiveMesh::makeCellCentresAndVols ( const vectorField& fCtrs, const vectorField& fAreas, vectorField& cellCtrs, scalarField& cellVols ) const { // Clear the fields for accumulation cellCtrs = vector::zero; cellVols = 0.0; const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); // first estimate the approximate cell centre as the average of // face centres vectorField cEst(nCells(), vector::zero); labelField nCellFaces(nCells(), 0); forAll(own, facei) { cEst[own[facei]] += fCtrs[facei]; nCellFaces[own[facei]] += 1; }
void Foam::primitiveMesh::calcCellCells() const { // Loop through faceCells and mark up neighbours if (debug) { Pout<< "primitiveMesh::calcCellCells() : calculating cellCells" << endl; if (debug == -1) { // For checking calls:abort so we can quickly hunt down // origin of call FatalErrorIn("primitiveMesh::calcCellCells()") << abort(FatalError); } } // It is an error to attempt to recalculate cellCells // if the pointer is already set if (ccPtr_) { FatalErrorIn("primitiveMesh::calcCellCells() const") << "cellCells already calculated" << abort(FatalError); } else { // 1. Count number of internal faces per cell labelList ncc(nCells(), 0); const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); forAll (nei, faceI) { ncc[own[faceI]]++; ncc[nei[faceI]]++; } // Create the storage ccPtr_ = new labelListList(ncc.size()); labelListList& cellCellAddr = *ccPtr_; // 2. Size and fill cellFaceAddr forAll (cellCellAddr, cellI) { cellCellAddr[cellI].setSize(ncc[cellI]); }
void Foam::domainDecomposition::decomposeMesh() { // Decide which cell goes to which processor distributeCells(); // Distribute the cells according to the given processor label // calculate the addressing information for the original mesh Info<< "\nCalculating original mesh data" << endl; // set references to the original mesh const polyBoundaryMesh& patches = boundaryMesh(); const faceList& fcs = faces(); const labelList& owner = faceOwner(); const labelList& neighbour = faceNeighbour(); // loop through the list of processor labels for the cell and add the // cell shape to the list of cells for the appropriate processor Info<< "\nDistributing cells to processors" << endl; // Cells per processor procCellAddressing_ = invertOneToMany(nProcs_, cellToProc_); Info<< "\nDistributing faces to processors" << endl; // Loop through all internal faces and decide which processor they belong to // First visit all internal faces. If cells at both sides belong to the // same processor, the face is an internal face. If they are different, // it belongs to both processors. procFaceAddressing_.setSize(nProcs_); // Internal faces forAll(neighbour, facei) { if (cellToProc_[owner[facei]] == cellToProc_[neighbour[facei]]) { // Face internal to processor. Notice no turning index. procFaceAddressing_[cellToProc_[owner[facei]]].append(facei+1); } } // for all processors, set the size of start index and patch size // lists to the number of patches in the mesh forAll(procPatchSize_, procI) { procPatchSize_[procI].setSize(patches.size()); procPatchStartIndex_[procI].setSize(patches.size()); }
void primitiveMesh::makeCellCentresAndVols ( const vectorField& fCtrs, const vectorField& fAreas, vectorField& cellCtrs, scalarField& cellVols ) const { // Clear the fields for accumulation cellCtrs = vector::zero; cellVols = 0.0; const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); // next calculate exact cell volume and centre scalarField r1(nCells(), -1); scalarField r2(nCells(), -1); forAll (faces(), faceI) { if (!isRadialFace(fCtrs[faceI], fAreas[faceI])) { cellVols[own[faceI]] += fCtrs[faceI] & fAreas[faceI]; cellCtrs[own[faceI]] += fCtrs[faceI]; if (r1[own[faceI]] < 0) { r1 = mag(fCtrs[faceI]); } else { r2[own[faceI]] = mag(fCtrs[faceI]); } if (faceI < nInternalFaces()) { cellVols[nei[faceI]] += fCtrs[faceI] & fAreas[faceI]; cellCtrs[nei[faceI]] += fCtrs[faceI]; r2[nei[faceI]] = mag(fCtrs[faceI]); } } } cellVols *= 1./3.; cellCtrs *= 0.5*(r1+r2)/mag(cellCtrs); }
void dynamicRefineFvMesh::calculateProtectedCells ( PackedBoolList& unrefineableCell ) const { if (protectedCell_.empty()) { unrefineableCell.clear(); return; } const labelList& cellLevel = meshCutter_.cellLevel(); unrefineableCell = protectedCell_; // Get neighbouring cell level labelList neiLevel(nFaces()-nInternalFaces()); for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++) { neiLevel[faceI-nInternalFaces()] = cellLevel[faceOwner()[faceI]]; } syncTools::swapBoundaryFaceList(*this, neiLevel, false); while (true) { // Pick up faces on border of protected cells boolList seedFace(nFaces(), false); forAll(faceNeighbour(), faceI) { label own = faceOwner()[faceI]; bool ownProtected = (unrefineableCell.get(own) == 1); label nei = faceNeighbour()[faceI]; bool neiProtected = (unrefineableCell.get(nei) == 1); if (ownProtected && (cellLevel[nei] > cellLevel[own])) { seedFace[faceI] = true; } else if (neiProtected && (cellLevel[own] > cellLevel[nei])) { seedFace[faceI] = true; } } for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++) { label own = faceOwner()[faceI]; bool ownProtected = (unrefineableCell.get(own) == 1); if ( ownProtected && (neiLevel[faceI-nInternalFaces()] > cellLevel[own]) ) { seedFace[faceI] = true; } } syncTools::syncFaceList(*this, seedFace, orEqOp<bool>(), false); // Extend unrefineableCell bool hasExtended = false; for (label faceI = 0; faceI < nInternalFaces(); faceI++) { if (seedFace[faceI]) { label own = faceOwner()[faceI]; if (unrefineableCell.get(own) == 0) { unrefineableCell.set(own, 1); hasExtended = true; } label nei = faceNeighbour()[faceI]; if (unrefineableCell.get(nei) == 0) { unrefineableCell.set(nei, 1); hasExtended = true; } } } for (label faceI = nInternalFaces(); faceI < nFaces(); faceI++) { if (seedFace[faceI]) { label own = faceOwner()[faceI]; if (unrefineableCell.get(own) == 0) { unrefineableCell.set(own, 1); hasExtended = true; } } } if (!returnReduce(hasExtended, orOp<bool>())) { break; } }
const Foam::labelList& Foam::primitiveMesh::edgeCells ( const label edgeI, DynamicList<label>& storage ) const { if (hasEdgeCells()) { return edgeCells()[edgeI]; } else { const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); // Construct edgeFaces DynamicList<label> eFacesStorage; const labelList& eFaces = edgeFaces(edgeI, eFacesStorage); storage.clear(); // Do quadratic insertion. forAll(eFaces, i) { label faceI = eFaces[i]; { label ownCellI = own[faceI]; // Check if not already in storage forAll(storage, j) { if (storage[j] == ownCellI) { ownCellI = -1; break; } } if (ownCellI != -1) { storage.append(ownCellI); } } if (isInternalFace(faceI)) { label neiCellI = nei[faceI]; forAll(storage, j) { if (storage[j] == neiCellI) { neiCellI = -1; break; } } if (neiCellI != -1) { storage.append(neiCellI); } } } return storage; }
bool Foam::polyMesh::checkFaceOrthogonality ( const vectorField& fAreas, const vectorField& cellCtrs, const bool report, const bool detailedReport, labelHashSet* setPtr ) const { if (debug) { Info<< "bool polyMesh::checkFaceOrthogonality(" << "const bool, labelHashSet*) const: " << "checking mesh non-orthogonality" << endl; } const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); // Calculate orthogonality for all internal and coupled boundary faces // (1 for uncoupled boundary faces) tmp<scalarField> tortho = polyMeshTools::faceOrthogonality ( *this, fAreas, cellCtrs ); const scalarField& ortho = tortho(); // Severe nonorthogonality threshold const scalar severeNonorthogonalityThreshold = ::cos(degToRad(primitiveMesh::nonOrthThreshold_)); scalar minDDotS = GREAT; scalar sumDDotS = 0.0; label nSummed = 0; label severeNonOrth = 0; label errorNonOrth = 0; // Statistics only for internal and masters of coupled faces PackedBoolList isMasterFace(syncTools::getInternalOrMasterFaces(*this)); forAll(ortho, faceI) { if (ortho[faceI] < severeNonorthogonalityThreshold) { if (ortho[faceI] > SMALL) { if (setPtr) { setPtr->insert(faceI); } severeNonOrth++; } else { // Error : non-ortho too large if (setPtr) { setPtr->insert(faceI); } if (detailedReport && errorNonOrth == 0) { // Non-orthogonality greater than 90 deg WarningIn ( "polyMesh::checkFaceOrthogonality" "(const pointField&, const bool) const" ) << "Severe non-orthogonality for face " << faceI << " between cells " << own[faceI] << " and " << nei[faceI] << ": Angle = " << radToDeg(::acos(min(1.0, max(-1.0, ortho[faceI])))) << " deg." << endl; } errorNonOrth++; } } if (isMasterFace[faceI]) { minDDotS = min(minDDotS, ortho[faceI]); sumDDotS += ortho[faceI]; nSummed++; } } reduce(minDDotS, minOp<scalar>()); reduce(sumDDotS, sumOp<scalar>()); reduce(nSummed, sumOp<label>()); reduce(severeNonOrth, sumOp<label>()); reduce(errorNonOrth, sumOp<label>()); if (debug || report) { if (nSummed > 0) { if (debug || report) { Info<< " Mesh non-orthogonality Max: " << radToDeg(::acos(min(1.0, max(-1.0, minDDotS)))) << " average: " << radToDeg(::acos(min(1.0, max(-1.0, sumDDotS/nSummed)))) << endl; } } if (severeNonOrth > 0) { Info<< " *Number of severely non-orthogonal (> " << primitiveMesh::nonOrthThreshold_ << " degrees) faces: " << severeNonOrth << "." << endl; } } if (errorNonOrth > 0) { if (debug || report) { Info<< " ***Number of non-orthogonality errors: " << errorNonOrth << "." << endl; } return true; } else { if (debug || report) { Info<< " Non-orthogonality check OK." << endl; } return false; } }
bool Foam::polyMesh::checkFaceSkewness ( const pointField& points, const vectorField& fCtrs, const vectorField& fAreas, const vectorField& cellCtrs, const bool report, const bool detailedReport, labelHashSet* setPtr ) const { if (debug) { Info<< "bool polyMesh::checkFaceSkewnesss(" << "const bool, labelHashSet*) const: " << "checking face skewness" << endl; } const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); // Warn if the skew correction vector is more than skewWarning times // larger than the face area vector tmp<scalarField> tskew = polyMeshTools::faceSkewness ( *this, points, fCtrs, fAreas, cellCtrs ); const scalarField& skew = tskew(); scalar maxSkew = max(skew); label nWarnSkew = 0; // Statistics only for all faces except slave coupled faces PackedBoolList isMasterFace(syncTools::getMasterFaces(*this)); forAll(skew, faceI) { // Check if the skewness vector is greater than the PN vector. // This does not cause trouble but is a good indication of a poor mesh. if (skew[faceI] > skewThreshold_) { if (setPtr) { setPtr->insert(faceI); } if (detailedReport && nWarnSkew == 0) { // Non-orthogonality greater than 90 deg if (isInternalFace(faceI)) { WarningIn ( "polyMesh::checkFaceSkewnesss" "(const pointField&, const bool) const" ) << "Severe skewness " << skew[faceI] << " for face " << faceI << " between cells " << own[faceI] << " and " << nei[faceI]; } else { WarningIn ( "polyMesh::checkFaceSkewnesss" "(const pointField&, const bool) const" ) << "Severe skewness " << skew[faceI] << " for boundary face " << faceI << " on cell " << own[faceI]; } } if (isMasterFace[faceI]) { nWarnSkew++; } } } reduce(maxSkew, maxOp<scalar>()); reduce(nWarnSkew, sumOp<label>()); if (nWarnSkew > 0) { if (debug || report) { Info<< " ***Max skewness = " << maxSkew << ", " << nWarnSkew << " highly skew faces detected" " which may impair the quality of the results" << endl; } return true; } else { if (debug || report) { Info<< " Max skewness = " << maxSkew << " OK." << endl; } return false; } }
void Foam::primitiveMesh::calcCellEdges() const { // Loop through all faces and mark up cells with edges of the face. // Check for duplicates if (debug) { Pout<< "primitiveMesh::calcCellEdges() : " << "calculating cellEdges" << endl; if (debug == -1) { // For checking calls:abort so we can quickly hunt down // origin of call FatalErrorIn("primitiveMesh::calcCellEdges()") << abort(FatalError); } } // It is an error to attempt to recalculate cellEdges // if the pointer is already set if (cePtr_) { FatalErrorIn("primitiveMesh::calcCellEdges() const") << "cellEdges already calculated" << abort(FatalError); } else { // Set up temporary storage List<DynamicList<label, edgesPerCell_> > ce(nCells()); // Get reference to faceCells and faceEdges const labelList& own = faceOwner(); const labelList& nei = faceNeighbour(); const labelListList& fe = faceEdges(); // loop through the list again and add edges; checking for duplicates forAll(own, faceI) { DynamicList<label, edgesPerCell_>& curCellEdges = ce[own[faceI]]; const labelList& curEdges = fe[faceI]; forAll(curEdges, edgeI) { if (findIndex(curCellEdges, curEdges[edgeI]) == -1) { // Add the edge curCellEdges.append(curEdges[edgeI]); } } } forAll(nei, faceI) { DynamicList<label, edgesPerCell_>& curCellEdges = ce[nei[faceI]]; const labelList& curEdges = fe[faceI]; forAll(curEdges, edgeI) { if (findIndex(curCellEdges, curEdges[edgeI]) == -1) { // add the edge curCellEdges.append(curEdges[edgeI]); } } }