void Foam::decompositionMethod::calcCellCells
(
    const polyMesh& mesh,
    const labelList& agglom,
    const label nLocalCoarse,
    const bool parallel,
    CompactListList<label>& cellCells
)
{
    const labelList& faceOwner = mesh.faceOwner();
    const labelList& faceNeighbour = mesh.faceNeighbour();
    const polyBoundaryMesh& patches = mesh.boundaryMesh();


    // Create global cell numbers
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~

    globalIndex globalAgglom
    (
        nLocalCoarse,
        Pstream::msgType(),
        Pstream::worldComm,
        parallel
    );


    // Get agglomerate owner on other side of coupled faces
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    labelList globalNeighbour(mesh.nFaces()-mesh.nInternalFaces());

    forAll(patches, patchI)
    {
        const polyPatch& pp = patches[patchI];

        if (pp.coupled() && (parallel || !isA<processorPolyPatch>(pp)))
        {
            label faceI = pp.start();
            label bFaceI = pp.start() - mesh.nInternalFaces();

            forAll(pp, i)
            {
                globalNeighbour[bFaceI] = globalAgglom.toGlobal
                (
                    agglom[faceOwner[faceI]]
                );

                bFaceI++;
                faceI++;
            }
        }
Foam::Cloud<ParticleType>::Cloud
(
    const polyMesh& pMesh,
    const IDLList<ParticleType>& particles
)
:
    cloud(pMesh),
    IDLList<ParticleType>(particles),
    polyMesh_(pMesh),
    allFaces_(pMesh.faces()),
    points_(pMesh.points()),
    cellFaces_(pMesh.cells()),
    allFaceCentres_(pMesh.faceCentres()),
    owner_(pMesh.faceOwner()),
    neighbour_(pMesh.faceNeighbour()),
    meshInfo_(polyMesh_)
{}
Foam::Cloud<ParticleType>::Cloud
(
    const polyMesh& pMesh,
    const bool checkClass
)
:
    cloud(pMesh),
    polyMesh_(pMesh),
    allFaces_(pMesh.faces()),
    points_(pMesh.points()),
    cellFaces_(pMesh.cells()),
    allFaceCentres_(pMesh.faceCentres()),
    owner_(pMesh.faceOwner()),
    neighbour_(pMesh.faceNeighbour()),
    meshInfo_(polyMesh_)
{
    initCloud(checkClass);
}
Foam::label Foam::polyMeshTetDecomposition::findSharedBasePoint
(
    const polyMesh& mesh,
    label fI,
    const point& nCc,
    scalar tol,
    bool report
)
{
    const faceList& pFaces = mesh.faces();
    const pointField& pPts = mesh.points();
    const vectorField& pC = mesh.cellCentres();
    const labelList& pOwner = mesh.faceOwner();

    const face& f = pFaces[fI];

    label oCI = pOwner[fI];

    const point& oCc = pC[oCI];

    List<scalar> tetQualities(2, 0.0);

    forAll(f, faceBasePtI)
    {
        scalar thisBaseMinTetQuality = VGREAT;

        const point& tetBasePt = pPts[f[faceBasePtI]];

        for (label tetPtI = 1; tetPtI < f.size() - 1; tetPtI++)
        {
            label facePtI = (tetPtI + faceBasePtI) % f.size();
            label otherFacePtI = f.fcIndex(facePtI);

            {
                // owner cell tet
                label ptAI = f[facePtI];
                label ptBI = f[otherFacePtI];

                const point& pA = pPts[ptAI];
                const point& pB = pPts[ptBI];

                tetPointRef tet(oCc, tetBasePt, pA, pB);

                tetQualities[0] = tet.quality();
            }

            {
                // neighbour cell tet
                label ptAI = f[otherFacePtI];
                label ptBI = f[facePtI];

                const point& pA = pPts[ptAI];
                const point& pB = pPts[ptBI];

                tetPointRef tet(nCc, tetBasePt, pA, pB);

                tetQualities[1] = tet.quality();
            }

            if (min(tetQualities) < thisBaseMinTetQuality)
            {
                thisBaseMinTetQuality = min(tetQualities);
            }
        }

        if (thisBaseMinTetQuality > tol)
        {
            return faceBasePtI;
        }
    }
示例#5
0
Foam::vtkTopo::vtkTopo(const polyMesh& mesh)
:
    mesh_(mesh),
    vertLabels_(),
    cellTypes_(),
    addPointCellLabels_(),
    superCells_()
{
    const cellModel& tet = *(cellModeller::lookup("tet"));
    const cellModel& pyr = *(cellModeller::lookup("pyr"));
    const cellModel& prism = *(cellModeller::lookup("prism"));
    const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
    const cellModel& hex = *(cellModeller::lookup("hex"));

    const cellShapeList& cellShapes = mesh_.cellShapes();

    // Number of additional points needed by the decomposition of polyhedra
    label nAddPoints = 0;

    // Number of additional cells generated by the decomposition of polyhedra
    label nAddCells = 0;

    // face owner is needed to determine the face orientation
    const labelList& owner = mesh.faceOwner();

    // Scan for cells which need to be decomposed and count additional points
    // and cells
    if (decomposePoly)
    {
        forAll(cellShapes, cellI)
        {
            const cellModel& model = cellShapes[cellI].model();

            if
            (
                model != hex
                // && model != wedge    // See above.
             && model != prism
             && model != pyr
             && model != tet
             && model != tetWedge
            )
            {
                const cell& cFaces = mesh_.cells()[cellI];

                forAll(cFaces, cFaceI)
                {
                    const face& f = mesh_.faces()[cFaces[cFaceI]];

                    label nQuads = 0;
                    label nTris = 0;
                    f.nTrianglesQuads(mesh_.points(), nTris, nQuads);

                    nAddCells += nQuads + nTris;
                }

                nAddCells--;
                nAddPoints++;
            }
        }
    }


    // Set size of additional point addressing array
    // (from added point to original cell)
    addPointCellLabels_.setSize(nAddPoints);

    // Set size of additional cells mapping array
    // (from added cell to original cell)
    superCells_.setSize(nAddCells);

    // List of vertex labels in VTK ordering
    vertLabels_.setSize(cellShapes.size() + nAddCells);

    // Label of vtk type
    cellTypes_.setSize(cellShapes.size() + nAddCells);

    // Set counters for additional points and additional cells
    label addPointI = 0, addCellI = 0;

    forAll(cellShapes, cellI)
    {
        const cellShape& cellShape = cellShapes[cellI];
        const cellModel& cellModel = cellShape.model();

        labelList& vtkVerts = vertLabels_[cellI];

        if (cellModel == tet)
        {
            vtkVerts = cellShape;

            cellTypes_[cellI] = VTK_TETRA;
        }
        else if (cellModel == pyr)
        {
            vtkVerts = cellShape;

            cellTypes_[cellI] = VTK_PYRAMID;
        }
        else if (cellModel == prism)
        {
            // VTK has a different node order for VTK_WEDGE
            // their triangles point outwards!
            vtkVerts = cellShape;

            Foam::Swap(vtkVerts[1], vtkVerts[2]);
            Foam::Swap(vtkVerts[4], vtkVerts[5]);

            cellTypes_[cellI] = VTK_WEDGE;
        }
        else if (cellModel == tetWedge)
        {
            // Treat as squeezed prism
            vtkVerts.setSize(6);
            vtkVerts[0] = cellShape[0];
            vtkVerts[1] = cellShape[2];
            vtkVerts[2] = cellShape[1];
            vtkVerts[3] = cellShape[3];
            vtkVerts[4] = cellShape[4];
            vtkVerts[5] = cellShape[4];

            cellTypes_[cellI] = VTK_WEDGE;
        }
//        else if (cellModel == wedge)
//        {
//            // Treat as squeezed hex
//            vtkVerts.setSize(8);
//            vtkVerts[0] = cellShape[0];
//            vtkVerts[1] = cellShape[1];
//            vtkVerts[2] = cellShape[2];
//            vtkVerts[3] = cellShape[0];
//            vtkVerts[4] = cellShape[3];
//            vtkVerts[5] = cellShape[4];
//            vtkVerts[6] = cellShape[5];
//            vtkVerts[7] = cellShape[6];
//
//            cellTypes_[cellI] = VTK_HEXAHEDRON;
//        }
        else if (cellModel == hex)
        {
            vtkVerts = cellShape;

            cellTypes_[cellI] = VTK_HEXAHEDRON;
        }
        else if (decomposePoly)
        {
            // Polyhedral cell. Decompose into tets + pyramids.

            // Mapping from additional point to cell
            addPointCellLabels_[addPointI] = cellI;

            // The new vertex from the cell-centre
            const label newVertexLabel = mesh_.nPoints() + addPointI;

            // Whether to insert cell in place of original or not.
            bool substituteCell = true;

            const labelList& cFaces = mesh_.cells()[cellI];
            forAll(cFaces, cFaceI)
            {
                const face& f = mesh_.faces()[cFaces[cFaceI]];
                const bool isOwner = (owner[cFaces[cFaceI]] == cellI);

                // Number of triangles and quads in decomposition
                label nTris = 0;
                label nQuads = 0;
                f.nTrianglesQuads(mesh_.points(), nTris, nQuads);

                // Do actual decomposition into triFcs and quadFcs.
                faceList triFcs(nTris);
                faceList quadFcs(nQuads);
                label trii = 0;
                label quadi = 0;
                f.trianglesQuads(mesh_.points(), trii, quadi, triFcs, quadFcs);

                forAll(quadFcs, quadI)
                {
                    label thisCellI;

                    if (substituteCell)
                    {
                        thisCellI = cellI;
                        substituteCell = false;
                    }
                    else
                    {
                        thisCellI = mesh_.nCells() + addCellI;
                        superCells_[addCellI++] = cellI;
                    }

                    labelList& addVtkVerts = vertLabels_[thisCellI];

                    addVtkVerts.setSize(5);

                    const face& quad = quadFcs[quadI];

                    // Ensure we have the correct orientation for the
                    // base of the primitive cell shape.
                    // If the cell is face owner, the orientation needs to be
                    // flipped.
                    // At the moment, VTK doesn't actually seem to care if
                    // negative cells are defined, but we'll do it anyhow
                    // (for safety).
                    if (isOwner)
                    {
                        addVtkVerts[0] = quad[3];
                        addVtkVerts[1] = quad[2];
                        addVtkVerts[2] = quad[1];
                        addVtkVerts[3] = quad[0];
                    }
                    else
                    {
                        addVtkVerts[0] = quad[0];
                        addVtkVerts[1] = quad[1];
                        addVtkVerts[2] = quad[2];
                        addVtkVerts[3] = quad[3];
                    }
                    addVtkVerts[4] = newVertexLabel;

                    cellTypes_[thisCellI] = VTK_PYRAMID;
                }

                forAll(triFcs, triI)
                {
                    label thisCellI;

                    if (substituteCell)
                    {
                        thisCellI = cellI;
                        substituteCell = false;
                    }
                    else
                    {
                        thisCellI = mesh_.nCells() + addCellI;
                        superCells_[addCellI++] = cellI;
                    }


                    labelList& addVtkVerts = vertLabels_[thisCellI];

                    const face& tri = triFcs[triI];

                    addVtkVerts.setSize(4);

                    // See note above about the orientation.
                    if (isOwner)
                    {
                        addVtkVerts[0] = tri[2];
                        addVtkVerts[1] = tri[1];
                        addVtkVerts[2] = tri[0];
                    }
                    else
                    {
                        addVtkVerts[0] = tri[0];
                        addVtkVerts[1] = tri[1];
                        addVtkVerts[2] = tri[2];
                    }
                    addVtkVerts[3] = newVertexLabel;

                    cellTypes_[thisCellI] = VTK_TETRA;
                }
            }

            addPointI++;
        }
示例#6
0
void Foam::cellPointWeight::findTriangle
(
    const polyMesh& mesh,
    const vector& position,
    const label facei
)
{
    if (debug)
    {
        Pout<< "\nbool Foam::cellPointWeight::findTriangle" << nl
            << "position = " << position << nl
            << "facei = " << facei << endl;
    }

    List<tetIndices> faceTets = polyMeshTetDecomposition::faceTetIndices
    (
        mesh,
        facei,
        mesh.faceOwner()[facei]
    );

    const scalar faceAreaSqr = magSqr(mesh.faceAreas()[facei]);

    forAll(faceTets, tetI)
    {
        const tetIndices& tetIs = faceTets[tetI];

        // Barycentric coordinates of the position
        barycentric2D triWeights;
        const scalar det =
            tetIs.faceTri(mesh).pointToBarycentric(position, triWeights);

        if (0.25*mag(det)/faceAreaSqr > tol)
        {
            const scalar& u = triWeights[0];
            const scalar& v = triWeights[1];

            if
            (
                (u + tol > 0)
             && (v + tol > 0)
             && (u + v < 1 + tol)
            )
            {
                // Weight[0] is for the cell centre.
                weights_[0] = 0;
                weights_[1] = triWeights[0];
                weights_[2] = triWeights[1];
                weights_[3] = triWeights[2];

                faceVertices_ = tetIs.faceTriIs(mesh);

                return;
            }
        }
    }

    // A suitable point in a triangle was not found, find the nearest.

    scalar minNearDist = vGreat;

    label nearestTetI = -1;

    forAll(faceTets, tetI)
    {
        const tetIndices& tetIs = faceTets[tetI];

        scalar nearDist = tetIs.faceTri(mesh).nearestPoint(position).distance();

        if (nearDist < minNearDist)
        {
            minNearDist = nearDist;

            nearestTetI = tetI;
        }
    }

    if (debug)
    {
        Pout<< "cellPointWeight::findTriangle" << nl
            << "    Triangle search failed; using closest tri to point "
            << position << nl
            << "    face: "
            << facei << nl
            << endl;
    }

    const tetIndices& tetIs = faceTets[nearestTetI];

    // Barycentric coordinates of the position, ignoring if the
    // determinant is suitable.  If not, the return from barycentric
    // to triWeights is safe.

    const barycentric2D triWeights =
        tetIs.faceTri(mesh).pointToBarycentric(position);

    // Weight[0] is for the cell centre.
    weights_[0] = 0;
    weights_[1] = triWeights[0];
    weights_[2] = triWeights[1];
    weights_[3] = triWeights[2];

    faceVertices_ = tetIs.faceTriIs(mesh);
}
void insertDuplicateMerge
(
    const polyMesh& mesh,
    const labelList& duplicates,
    polyTopoChange& meshMod
)
{
    const faceList& faces = mesh.faces();
    const labelList& faceOwner = mesh.faceOwner();
    const faceZoneMesh& faceZones = mesh.faceZones();

    forAll(duplicates, bFacei)
    {
        label otherFacei = duplicates[bFacei];

        if (otherFacei != -1 && otherFacei > bFacei)
        {
            // Two duplicate faces. Merge.

            label face0 = mesh.nInternalFaces() + bFacei;
            label face1 = mesh.nInternalFaces() + otherFacei;

            label own0 = faceOwner[face0];
            label own1 = faceOwner[face1];

            if (own0 < own1)
            {
                // Use face0 as the new internal face.
                label zoneID = faceZones.whichZone(face0);
                bool zoneFlip = false;

                if (zoneID >= 0)
                {
                    const faceZone& fZone = faceZones[zoneID];
                    zoneFlip = fZone.flipMap()[fZone.whichFace(face0)];
                }

                meshMod.setAction(polyRemoveFace(face1));
                meshMod.setAction
                (
                    polyModifyFace
                    (
                        faces[face0],           // modified face
                        face0,                  // label of face being modified
                        own0,                   // owner
                        own1,                   // neighbour
                        false,                  // face flip
                        -1,                     // patch for face
                        false,                  // remove from zone
                        zoneID,                 // zone for face
                        zoneFlip                // face flip in zone
                    )
                );
            }
            else
            {
                // Use face1 as the new internal face.
                label zoneID = faceZones.whichZone(face1);
                bool zoneFlip = false;

                if (zoneID >= 0)
                {
                    const faceZone& fZone = faceZones[zoneID];
                    zoneFlip = fZone.flipMap()[fZone.whichFace(face1)];
                }

                meshMod.setAction(polyRemoveFace(face0));
                meshMod.setAction
                (
                    polyModifyFace
                    (
                        faces[face1],           // modified face
                        face1,                  // label of face being modified
                        own1,                   // owner
                        own0,                   // neighbour
                        false,                  // face flip
                        -1,                     // patch for face
                        false,                  // remove from zone
                        zoneID,                 // zone for face
                        zoneFlip                // face flip in zone
                    )
                );
            }
        }
    }