Skip to content
Snippets Groups Projects
isoSurfaceCellTemplates.C 13.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*---------------------------------------------------------------------------*\
      =========                 |
      \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
       \\    /   O peration     |
    
    OpenFOAM bot's avatar
    OpenFOAM bot committed
        \\  /    A nd           | www.openfoam.com
    
    -------------------------------------------------------------------------------
    
    OpenFOAM bot's avatar
    OpenFOAM bot committed
        Copyright (C) 2011-2016 OpenFOAM Foundation
    
        Copyright (C) 2020-2021 OpenCFD Ltd.
    
    -------------------------------------------------------------------------------
    License
        This file is part of OpenFOAM.
    
    
        OpenFOAM is free software: you can redistribute it and/or modify it
        under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
    
        OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
        FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        for more details.
    
        You should have received a copy of the GNU General Public License
    
        along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
    
    
    \*---------------------------------------------------------------------------*/
    
    #include "isoSurfaceCell.H"
    
    #include "isoSurfacePoint.H"
    
    #include "polyMesh.H"
    #include "tetMatcher.H"
    
    // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
    
    template<class Type>
    Type Foam::isoSurfaceCell::generatePoint
    (
        const DynamicList<Type>& snappedPoints,
    
        const scalar s0,
        const Type& p0,
        const label p0Index,
    
        const scalar s1,
        const Type& p1,
        const label p1Index
    ) const
    {
    
        const scalar d = s1-s0;
    
            const scalar s = (iso_-s0)/d;
    
    
            if (s >= 0.5 && s <= 1 && p1Index != -1)
            {
                return snappedPoints[p1Index];
            }
            else if (s >= 0.0 && s <= 0.5 && p0Index != -1)
            {
                return snappedPoints[p0Index];
            }
            else
            {
                return s*p1 + (1.0-s)*p0;
            }
        }
        else
        {
    
            constexpr scalar s = 0.4999;
    
    
            return s*p1 + (1.0-s)*p0;
        }
    }
    
    
    template<class Type>
    void Foam::isoSurfaceCell::generateTriPoints
    (
        const DynamicList<Type>& snapped,
    
        const scalar s0,
        const Type& p0,
        const label p0Index,
    
        const scalar s1,
        const Type& p1,
        const label p1Index,
    
        const scalar s2,
        const Type& p2,
        const label p2Index,
    
        const scalar s3,
        const Type& p3,
        const label p3Index,
    
    
        DynamicList<Type>& pts
    
    ) const
    {
        int triIndex = 0;
        if (s0 < iso_)
        {
            triIndex |= 1;
        }
        if (s1 < iso_)
        {
            triIndex |= 2;
        }
        if (s2 < iso_)
        {
            triIndex |= 4;
        }
        if (s3 < iso_)
        {
            triIndex |= 8;
        }
    
    
        // Form the vertices of the triangles for each case
    
        switch (triIndex)
        {
            case 0x00:
            case 0x0F:
            break;
    
            case 0x01:
    
                pts.append(generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index));
                pts.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index));
                pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index));
    
                if (triIndex == 0x0E)
    
                    // Flip normals
    
                    const label sz = pts.size();
    
                    std::swap(pts[sz-2], pts[sz-1]);
    
                pts.append(generatePoint(snapped,s1,p1,p1Index,s0,p0,p0Index));
                pts.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index));
                pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index));
    
    
                if (triIndex == 0x0D)
    
                    // Flip normals
    
                    const label sz = pts.size();
    
                    std::swap(pts[sz-2], pts[sz-1]);
    
                Type p0p2 = generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index);
                Type p1p3 = generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index);
    
                pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index));
    
                pts.append(p1p3);
                pts.append(p0p2);
    
                pts.append(p1p3);
                pts.append
                (
                    generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index)
                );
                pts.append(p0p2);
    
                if (triIndex == 0x0C)
    
                    // Flip normals
    
                    const label sz = pts.size();
    
                    std::swap(pts[sz-5], pts[sz-4]);
                    std::swap(pts[sz-2], pts[sz-1]);
    
                pts.append(generatePoint(snapped,s2,p2,p2Index,s0,p0,p0Index));
                pts.append(generatePoint(snapped,s2,p2,p2Index,s1,p1,p1Index));
                pts.append(generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index));
    
    
                if (triIndex == 0x0B)
    
                    // Flip normals
    
                    const label sz = pts.size();
    
                    std::swap(pts[sz-2], pts[sz-1]);
    
                Type p0p1 = generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index);
                Type p2p3 = generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index);
    
    
                pts.append(p0p1);
                pts.append(p2p3);
    
                pts.append(generatePoint(snapped,s0,p0,p0Index,s3,p3,p3Index));
    
    
                pts.append(p0p1);
    
                pts.append(generatePoint(snapped,s1,p1,p1Index,s2,p2,p2Index));
    
                pts.append(p2p3);
    
                if (triIndex == 0x0A)
    
                    // Flip normals
    
                    const label sz = pts.size();
    
                    std::swap(pts[sz-5], pts[sz-4]);
                    std::swap(pts[sz-2], pts[sz-1]);
    
                Type p0p1 = generatePoint(snapped,s0,p0,p0Index,s1,p1,p1Index);
                Type p2p3 = generatePoint(snapped,s2,p2,p2Index,s3,p3,p3Index);
    
    
                pts.append(p0p1);
    
                pts.append(generatePoint(snapped,s1,p1,p1Index,s3,p3,p3Index));
    
                pts.append(p2p3);
    
                pts.append(p0p1);
                pts.append(p2p3);
    
                pts.append(generatePoint(snapped,s0,p0,p0Index,s2,p2,p2Index));
    
    
                if (triIndex == 0x09)
    
                    // Flip normals
    
                    const label sz = pts.size();
    
                    std::swap(pts[sz-5], pts[sz-4]);
                    std::swap(pts[sz-2], pts[sz-1]);
    
                pts.append(generatePoint(snapped,s3,p3,p3Index,s0,p0,p0Index));
                pts.append(generatePoint(snapped,s3,p3,p3Index,s2,p2,p2Index));
                pts.append(generatePoint(snapped,s3,p3,p3Index,s1,p1,p1Index));
    
                if (triIndex == 0x07)
    
                    // Flip normals
    
                    const label sz = pts.size();
    
                    std::swap(pts[sz-2], pts[sz-1]);
    
            break;
        }
    }
    
    
    template<class Type>
    void Foam::isoSurfaceCell::generateTriPoints
    (
        const scalarField& cVals,
        const scalarField& pVals,
    
        const Field<Type>& cCoords,
        const Field<Type>& pCoords,
    
        const DynamicList<Type>& snappedPoints,
        const labelList& snappedCc,
        const labelList& snappedPoint,
    
        DynamicList<Type>& triPoints,
        DynamicList<label>& triMeshCells
    ) const
    {
    
        label countNotFoundTets = 0;
    
        forAll(mesh_.cells(), celli)
    
            if ((cellCutType_[celli] & cutType::ANYCUT) != 0)
    
            {
                label oldNPoints = triPoints.size();
    
    
                const cell& cFaces = mesh_.cells()[celli];
    
                if (tetMatcher::test(mesh_, celli))
    
                {
                    // For tets don't do cell-centre decomposition, just use the
                    // tet points and values
    
                    const face& f0 = mesh_.faces()[cFaces[0]];
    
                    // Get the other point
                    const face& f1 = mesh_.faces()[cFaces[1]];
                    label oppositeI = -1;
                    forAll(f1, fp)
                    {
                        oppositeI = f1[fp];
    
    
                    // Start off from positive volume tet to make sure we
                    // generate outwards pointing tets
    
                    if (mesh_.faceOwner()[cFaces[0]] == celli)
    
                    {
                        generateTriPoints
                        (
                            snappedPoints,
    
                            pVals[f0[1]],
                            pCoords[f0[1]],
                            snappedPoint[f0[1]],
    
                            pVals[f0[0]],
                            pCoords[f0[0]],
                            snappedPoint[f0[0]],
    
                            pVals[f0[2]],
                            pCoords[f0[2]],
                            snappedPoint[f0[2]],
    
                            pVals[oppositeI],
                            pCoords[oppositeI],
                            snappedPoint[oppositeI],
    
                            triPoints
                        );
                    }
                    else
                    {
                        generateTriPoints
                        (
                            snappedPoints,
    
                            pVals[f0[0]],
                            pCoords[f0[0]],
                            snappedPoint[f0[0]],
    
                            pVals[f0[1]],
                            pCoords[f0[1]],
                            snappedPoint[f0[1]],
    
                            pVals[f0[2]],
                            pCoords[f0[2]],
                            snappedPoint[f0[2]],
    
                            pVals[oppositeI],
                            pCoords[oppositeI],
                            snappedPoint[oppositeI],
    
                            triPoints
                        );
                    }
    
                        label facei = cFaces[cFacei];
    
                        const face& f = mesh_.faces()[facei];
    
                        label fp0 = mesh_.tetBasePtIs()[facei];
    
    
                        // Skip undefined tets
                        if (fp0 < 0)
                        {
                            fp0 = 0;
                            countNotFoundTets++;
                        }
    
                        label fp = f.fcIndex(fp0);
                        for (label i = 2; i < f.size(); i++)
                        {
                            label nextFp = f.fcIndex(fp);
                            triFace tri(f[fp0], f[fp], f[nextFp]);
    
                            // Start off from positive volume tet to make sure we
                            // generate outwards pointing tets
    
                            if (mesh_.faceOwner()[facei] == celli)
    
                            {
                                generateTriPoints
                                (
                                    snappedPoints,
    
                                    pVals[tri[1]],
                                    pCoords[tri[1]],
                                    snappedPoint[tri[1]],
    
                                    pVals[tri[0]],
                                    pCoords[tri[0]],
                                    snappedPoint[tri[0]],
    
                                    pVals[tri[2]],
                                    pCoords[tri[2]],
                                    snappedPoint[tri[2]],
    
    
                                    cVals[celli],
                                    cCoords[celli],
                                    snappedCc[celli],
    
    
                                    triPoints
                                );
                            }
                            else
                            {
                                generateTriPoints
                                (
                                    snappedPoints,
    
                                    pVals[tri[0]],
                                    pCoords[tri[0]],
                                    snappedPoint[tri[0]],
    
                                    pVals[tri[1]],
                                    pCoords[tri[1]],
                                    snappedPoint[tri[1]],
    
                                    pVals[tri[2]],
                                    pCoords[tri[2]],
                                    snappedPoint[tri[2]],
    
    
                                    cVals[celli],
                                    cCoords[celli],
                                    snappedCc[celli],
    
                        }
                    }
                }
    
    
                // Every three triPoints is a cell
                label nCells = (triPoints.size()-oldNPoints)/3;
                for (label i = 0; i < nCells; i++)
                {
    
                    triMeshCells.append(celli);
    
        if (countNotFoundTets > 0)
        {
    
                << "Could not find " << countNotFoundTets
                << " tet base points, which may lead to inverted triangles."
                << endl;
        }
    
    
    template<class Type>
    
    Foam::isoSurfaceCell::interpolateTemplate
    
    (
        const Field<Type>& cCoords,
        const Field<Type>& pCoords
    ) const
    {
    
        DynamicList<Type> triPoints(3*nCutCells_);
    
        DynamicList<label> triMeshCells(nCutCells_);
    
        // Dummy snap data
        DynamicList<Type> snappedPoints;
        labelList snappedCc(mesh_.nCells(), -1);
        labelList snappedPoint(mesh_.nPoints(), -1);
    
    
        generateTriPoints
        (
            cVals_,
            pVals_,
    
            cCoords,
            pCoords,
    
            snappedPoints,
            snappedCc,
            snappedPoint,
    
            triPoints,
            triMeshCells
        );
    
    
        return isoSurfacePoint::interpolate
    
            triPointMergeMap_,
            interpolatedPoints_,
            interpolatedOldPoints_,
            interpolationWeights_,
            triPoints
        );
    
    // ************************************************************************* //