Skip to content
Snippets Groups Projects
mappedPatchBase.H 20.1 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/>.
    
    Class
        Foam::mappedPatchBase
    
    Description
        Determines a mapping between patch face centres and mesh cell or face
        centres and processors they're on.
    
        If constructed from dictionary:
    
            // Optional world to sample (default is all)
            //sampleWorld solidSim;
    
            // Optional explicit coupling (requires functionObject to synchronise
            // databases. Default is close coupling (bc to bc)
            //sampleDatabase true;
    
    
            // Region to sample (default is region0)
            sampleRegion region0;
    
            // What to sample:
    
            // - nearestCell         : sample cell containing point
    
            // - nearestOnlyCell     : nearest sample cell (even if not containing
            //                         point)
    
            // - nearestPatchFace    : nearest face on selected patch
            // - nearestPatchFaceAMI : nearest face on selected patch
                                       - patches need not conform
                                       - uses AMI interpolation
            // - nearestFace         : nearest boundary face on any patch
    
            // - nearestPatchPoint   : nearest patch point (for coupled points
            //                         this might be any of the points so you have
            //                         to guarantee the point data is synchronised
            //                         beforehand)
    
            // If sampleMode is nearestPatchFace : patch to find faces of
    
            // If sampleMode is nearestPatchFace : specify patchgroup to find
            // samplePatch and sampleRegion (if not provided)
            coupleGroup baffleGroup;
    
    
            // How to supply offset (w.r.t. my patch face centres):
            // - uniform : single offset vector
            // - nonuniform : per-face offset vector
            // - normal : using supplied distance and face normal
            offsetMode uniform;
    
            // According to offsetMode (see above) supply one of
            // offset, offsets or distance
            offset  (1 0 0);
    
        \endverbatim
    
        Note: if offsetMode is \c normal it uses outwards pointing normals. So
    
        supply a negative distance if sampling inside the domain.
    
    Note
        Storage is not optimal. It temporary collects all (patch)face centres
        on all processors to keep the addressing calculation simple.
    
    SourceFiles
        mappedPatchBase.C
    
    \*---------------------------------------------------------------------------*/
    
    #ifndef mappedPatchBase_H
    #define mappedPatchBase_H
    
    #include "pointField.H"
    #include "Tuple2.H"
    #include "pointIndexHit.H"
    #include "AMIPatchToPatchInterpolation.H"
    
    #include "coupleGroupIdentifier.H"
    
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    namespace Foam
    {
    
    class polyPatch;
    class polyMesh;
    class mapDistribute;
    
    /*---------------------------------------------------------------------------*\
    
                           Class mappedPatchBase Declaration
    
    \*---------------------------------------------------------------------------*/
    
    class mappedPatchBase
    {
    public:
    
        // Type enumerations
    
            //- Mesh items to sample
            enum sampleMode
            {
    
                NEARESTCELL,         //!< nearest cell containing sample
                NEARESTPATCHFACE,    //!< nearest face on selected patch
                NEARESTPATCHFACEAMI, //!< nearest patch face + AMI interpolation
                NEARESTPATCHPOINT,   //!< nearest point on selected patch
                NEARESTFACE,         //!< nearest face
                NEARESTONLYCELL      //!< nearest cell (even if not containing cell)
    
            };
    
            //- How to project face centres
            enum offsetMode
            {
    
                UNIFORM,            //!< single offset vector
                NONUNIFORM,         //!< per-face offset vector
                NORMAL              //!< use face normal + distance
    
            static const Enum<sampleMode> sampleModeNames_;
    
            static const Enum<offsetMode> offsetModeNames_;
    
    
        //- Helper class for finding nearest
    
        //  Nearest:
    
        //  - point+local index
        //  - sqr(distance)
        //  - processor
    
        typedef Tuple2<pointIndexHit, Tuple2<scalar, label>> nearInfo;
    
    
        class nearestEqOp
        {
        public:
    
            void operator()(nearInfo& x, const nearInfo& y) const
            {
                if (y.first().hit())
                {
                    if (!x.first().hit())
                    {
                        x = y;
                    }
                    else if (y.second().first() < x.second().first())
                    {
                        x = y;
                    }
                }
            }
        };
    
    
        class maxProcEqOp
        {
        public:
    
            void operator()(nearInfo& x, const nearInfo& y) const
            {
                if (y.first().hit())
                {
                    if (!x.first().hit())
                    {
                        x = y;
                    }
                    else if (y.second().second() > x.second().second())
                    {
                        x = y;
                    }
                }
            }
        };
    
    
        //- nearest + world
        //  Used to only look at entries from same world
        typedef Tuple2<nearInfo, label> nearInfoWorld;
    
        class nearestWorldEqOp
        {
        public:
    
            void operator()(nearInfoWorld& x, const nearInfoWorld& y) const
            {
                // Is there a hit and is it sampling the same world
                const nearInfo& xi = x.first();
                const nearInfo& yi = y.first();
                if (yi.first().hit())
                {
                    if (x.second() == y.second())
                    {
                        if (!xi.first().hit())
                        {
                            x = y;
                        }
                        else if (yi.second().first() < xi.second().first())
                        {
                            x = y;
                        }
                    }
                }
            }
        };
    
    
    
    
            //- Patch to sample
            const polyPatch& patch_;
    
    
            //- World to sample
            mutable word sampleWorld_;
    
    
            mutable word sampleRegion_;
    
    
            //- What to sample
            const sampleMode mode_;
    
    
            //- Patch (if in sampleMode NEARESTPATCH*)
    
            mutable word samplePatch_;
    
            //- PatchGroup (if in sampleMode NEARESTPATCH*)
            const coupleGroupIdentifier coupleGroup_;
    
            //- Empty or location of database
            const autoPtr<fileName> sampleDatabasePtr_;
    
    
            //- How to obtain samples
            offsetMode offsetMode_;
    
            //- Offset vector (uniform)
            vector offset_;
    
            //- Offset vector (nonuniform)
            vectorField offsets_;
    
            //- Offset distance (normal)
            scalar distance_;
    
    
            //- Communicator
    
            mutable bool sameRegion_;
    
    
    
            // Derived information
    
                //- Communication schedule:
    
                //
                //    - Cells/faces to sample per processor
                //    - Patch faces to receive per processor
                //    - schedule
    
                mutable autoPtr<mapDistribute> mapPtr_;
    
    
    
            // AMI interpolator (only for NEARESTPATCHFACEAMI)
    
                //- Flag to indicate that slave patch should be reversed for AMI
                const bool AMIReverse_;
    
    
                //- Pointer to AMI interpolator
                mutable autoPtr<AMIPatchToPatchInterpolation> AMIPtr_;
    
    
                //- Pointer to projection surface employed by AMI interpolator
                mutable autoPtr<searchableSurface> surfPtr_;
    
                //- Dictionary storing projection surface description
                dictionary surfDict_;
    
    
    
        // Protected Member Functions
    
            //- Add a world-world connection
            bool addWorldConnection();
    
            //- Get the communicator for the world-world connection
            label getWorldCommunicator() const;
    
    
            //- Lookup mesh
            const polyMesh& lookupMesh(const word& region) const;
    
            //- Lookup patch
            const polyPatch& lookupPatch
            (
                const word& sampleRegion,
                const word& samplePatch
            ) const;
    
    
    
            //- Get the points from face-centre-decomposition face centres
    
            //- and project them onto the face-diagonal-decomposition triangles.
    
            tmp<pointField> facePoints(const polyPatch&) const;
    
    
    Mark OLESEN's avatar
    Mark OLESEN committed
            //- Collect single list of samples and originating processor+face +
    
                const label mySampleWorld,  // My wanted sampling world
    
                const pointField& facePoints,
    
                pointField& samples,        // Per sample: coordinate
                labelList& patchFaceWorlds, // Per sample: wanted world
                labelList& patchFaceProcs,  // Per sample: originating proc
                labelList& patchFaces,      // Per sample: originating face
    
            //- Find (local) cells/faces containing samples
            void findLocalSamples
            (
                const sampleMode mode,
                const label sampleWorld,        // my world as index
                const word& sampleRegion,
                const word& samplePatch,
                const pointField& samplePoints,
    
                List<nearInfoWorld>& nearest
            ) const;
    
            //- Find (global) cells/faces containing samples
    
                const sampleMode mode,      // search mode
    
                const label myWorldIndex,   // my world (in index form)
    
    
                const labelList& wantedWorlds,
                const labelList& origProcs, // per sample the originating proc
    
    
                labelList& sampleProcs,     // processor containing sample
                labelList& sampleIndices,   // local index of cell/face
                pointField& sampleLocations // actual representative location
            ) const;
    
    
            //- Get the sample points given the face points
            tmp<pointField> samplePoints(const pointField&) const;
    
    
            //- Calculate mapping
            void calcMapping() const;
    
            //- Calculate AMI interpolator
            void calcAMI() const;
    
    
    
                //- Read optional database name from dictionary
                static autoPtr<fileName> readDatabase(const dictionary& dict);
    
                //- Lookup (sub)objectRegistry by following names of sub registries.
                //- Creates non-existing intermediate ones.
                static const objectRegistry& subRegistry
                (
                    const objectRegistry& obr,
                    const wordList& names,
                    const label index
                );
    
                //- Attempt to detect an IOField<Type> and write to dictionary
                template<class Type>
                static bool writeIOField
                (
                    const regIOobject& obj,
                    dictionary& dict
                );
    
                //- Attempt to read an IOField<Type> and store on objectRegistry
                template<class Type>
                static bool constructIOField
                (
                    const word& name,
                    token& tok,
                    Istream& is,
                    objectRegistry& obr
                );
    
    
    public:
    
        //- Runtime type information
        TypeName("mappedPatchBase");
    
    
        // Constructors
    
            //- Construct from patch
    
            explicit mappedPatchBase(const polyPatch&);
    
    
            //- Construct with offsetMode=non-uniform
            mappedPatchBase
            (
                const polyPatch& pp,
                const word& sampleRegion,
                const sampleMode sampleMode,
                const word& samplePatch,
                const vectorField& offsets
            );
    
            //- Construct from offsetMode=uniform
            mappedPatchBase
            (
                const polyPatch& pp,
                const word& sampleRegion,
                const sampleMode sampleMode,
                const word& samplePatch,
    
            );
    
            //- Construct from offsetMode=normal and distance
            mappedPatchBase
            (
                const polyPatch& pp,
                const word& sampleRegion,
                const sampleMode sampleMode,
                const word& samplePatch,
    
            );
    
            //- Construct from dictionary
            mappedPatchBase(const polyPatch&, const dictionary&);
    
    
            //- Construct from dictionary and (collocated) sample mode
            //  (only for nearestPatchFace, nearestPatchFaceAMI, nearestPatchPoint)
            //  Assumes zero offset.
            mappedPatchBase(const polyPatch&, const sampleMode, const dictionary&);
    
    
            //- Construct as copy, resetting patch
            mappedPatchBase(const polyPatch&, const mappedPatchBase&);
    
            //- Construct as copy, resetting patch, map original data
            mappedPatchBase
            (
                const polyPatch&,
                const mappedPatchBase&,
                const labelUList& mapAddressing
            );
    
    
        //- Destructor
        virtual ~mappedPatchBase();
    
    
    
            //- Change to normal offset with given distance
            void setOffset(const scalar normalDist);
    
            //- Change to uniform offset with value
            void setOffset(const vector& uniformOffset);
    
            //- Change to non-uniform offsets
            void setOffset(const vectorField& offsets);
    
    
    
    andy's avatar
    andy committed
            // Access
    
    andy's avatar
    andy committed
                //- What to sample
    
                inline sampleMode mode() const noexcept;
    
                //- World to sample
    
                inline const word& sampleWorld() const noexcept;
    
    andy's avatar
    andy committed
                //- Region to sample
                inline const word& sampleRegion() const;
    
    andy's avatar
    andy committed
                //- Patch (only if NEARESTPATCHFACE)
                inline const word& samplePatch() const;
    
                //- PatchGroup (only if NEARESTPATCHFACE)
                inline const word& coupleGroup() const;
    
    
                //- Return size of mapped mesh/patch/boundary
                inline label sampleSize() const;
    
    
    andy's avatar
    andy committed
                //- Offset vector (from patch faces to destination mesh objects)
    
                inline const vector& offset() const noexcept;
    
                //- Offset vectors (from patch faces to destination mesh objects)
                inline const vectorField& offsets() const noexcept;
    
                //- Get the communicator (worldComm or world-to-world)
                inline label getCommunicator() const;
    
                //- Identical to getCommunicator()
    
                inline label comm() const;
    
    
                //- Is sample world the local world?
    
                inline bool sameWorld() const;
    
    
                //- Is my world ordered before the sampleWorld?
                inline bool masterWorld() const;
    
    
    andy's avatar
    andy committed
                //- Cached sampleRegion != mesh.name()
    
                inline bool sameRegion() const noexcept;
    
    andy's avatar
    andy committed
                //- Return reference to the parallel distribution map
                inline const mapDistribute& map() const;
    
    andy's avatar
    andy committed
                //- Return reference to the AMI interpolator
                inline const AMIPatchToPatchInterpolation& AMI
                (
                    const bool forceUpdate = false
                ) const;
    
                //- Is it owner
                inline bool owner() const;
    
    
    andy's avatar
    andy committed
                //- Return a pointer to the AMI projection surface
                const autoPtr<Foam::searchableSurface>& surfPtr() const;
    
    andy's avatar
    andy committed
                //- Get the region mesh
                const polyMesh& sampleMesh() const;
    
    andy's avatar
    andy committed
                //- Get the patch on the region
                const polyPatch& samplePolyPatch() const;
    
    andy's avatar
    andy committed
    
    
    andy's avatar
    andy committed
                //- Get the sample points
                tmp<pointField> samplePoints() const;
    
                //- Get a point on the face given a face decomposition method:
                //  face-centre-tet : face centre. Returns index of face.
                //  face-planes     : face centre. Returns index of face.
                //  face-diagonal   : intersection of ray from cellcentre to
                //                    facecentre with any of the triangles.
                //                    Returns index (0..size-2) of triangle.
                static pointIndexHit facePoint
                (
                    const polyMesh&,
    
            // For database storage
    
                inline const fileName& sampleDatabasePath() const
                {
                    return *sampleDatabasePtr_;
                }
    
                inline bool sampleDatabase() const
                {
    
                    return bool(sampleDatabasePtr_);
    
                }
    
                //- Helper: return path to store data to be sent to processor i
                static fileName sendPath(const fileName& root, const label proci);
    
                virtual fileName sendPath(const label proci) const;
    
                //- Helper: return path to store data to be received from
                //- processor i
                static fileName receivePath
                (
                    const fileName& root,
                    const label proci
                );
    
                virtual fileName receivePath(const label proci) const;
    
                //- Lookup (sub)objectRegistry from '/' separated path (relative to
                //- objectRegistry). Creates non-existing intermediate ones.
                static const objectRegistry& subRegistry
                (
                    const objectRegistry& obr,
                    const fileName& path
                );
    
                //- Store an IOField on the objectRegistry relative to obr
                template<class Type>
                static void storeField
                (
                    objectRegistry& obr,
                    const word& fieldName,
                    const Field<Type>& values
                );
    
                //- Convert objectRegistry contents into dictionary
                static void writeDict
                (
                    const objectRegistry& obr,
                    dictionary& dict
                );
    
                //- (recursively) construct and register IOFields from dictionary
                static void readDict(const dictionary& d, objectRegistry& obr);
    
    
    andy's avatar
    andy committed
            // Distribute
    
    andy's avatar
    andy committed
                //- Wrapper around map/interpolate data distribution
                template<class Type>
                void distribute(List<Type>& lst) const;
    
    andy's avatar
    andy committed
                //- Wrapper around map/interpolate data distribution with operation
    
                template<class Type, class CombineOp>
                void distribute(List<Type>& lst, const CombineOp& cop) const;
    
    andy's avatar
    andy committed
                //- Wrapper around map/interpolate data distribution
                template<class Type>
                void reverseDistribute(List<Type>& lst) const;
    
    andy's avatar
    andy committed
                //- Wrapper around map/interpolate data distribution with operation
    
                template<class Type, class CombineOp>
                void reverseDistribute(List<Type>& lst, const CombineOp& cop) const;
    
    andy's avatar
    andy committed
            // I/O
    
    andy's avatar
    andy committed
                //- Write as a dictionary
    
                virtual void write(Ostream& os) const;
    
    };
    
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    } // End namespace Foam
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    
    andy's avatar
    andy committed
    #include "mappedPatchBaseI.H"
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    #ifdef NoRepository
        #include "mappedPatchBaseTemplates.C"
    #endif
    
    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    
    
    #endif
    
    // ************************************************************************* //