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;
    }
Exemple #2
0
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;
    }
Exemple #7
0
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;
    }
}
Exemple #8
0
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]);
                }
            }
        }