/*---------------------------------------------------------------------------*\
  ==  == ====== ====   ====    |
                    \\     ||  | Multiphase Code Repository by HZDR
  ======   //   ||  || ===//   | Website: https://doi.org/10.14278/rodare.767
  ||  ||  //    ||  // || \\   | License: GPL-3.0-or-later
  ==  == ====== ====   ==  ==  |
-------------------------------------------------------------------------------
License
    This file is part of the Multiphase Code Repository by HZDR.

    Copyright (C) 2025 by Helmholtz-Zentrum Dresden-Rossendorf e.V. (HZDR),
    Website: https://hzdr.de

    Copyright (C) 2025 by Technische Universitaet Darmstadt,
    Website: https://www.tu-darmstadt.de

    Copyright (C) 2025 by Technische Universitaet Muenchen,
    Website: https://www.tum.de

    Multiphase Code Repository by HZDR is based on the free software for
    computational fluid dynamics (CFD) from the OpenFOAM Foundation.
    Copyright (C) 2025 by OpenFOAM Foundation, Website: https://openfoam.org

    If you are interested in which files are original OpenFOAM Foundation
    files, which OpenFOAM Foundation files were modified, and which files were
    newly created, see FILES.md.

    Multiphase Code Repository by HZDR 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.

    Multiphase Code Repository by HZDR 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 the Multiphase Code Repository by HZDR. If not, see
    <http://www.gnu.org/licenses/>.

Class
    Foam::functionObjects::trackPhaseStructures

Description
    This function object tracks multiple phase structures (disconnected regions)
    and calculate centre of gravity, velocity, volume, surface area and
    sphericity of each of them.

    Surface area is calculated via continuous interface reconstruction,
    according to Kunkelmann (2011).

    Structures are detected from alpha field of given name and with given
    threshold criterion. Structures, which are connected to a patch out of a
    given list, may be excluded from detection. This function object keeps track
    of structures at every execution (executionTime) and only if the physical
    distance a structure travelled since the last execution is below a given
    tolerance. Furthermore, structures may be excluded if they have a volume
    beyond given minimum or maximum value or if they are in touch with a
    boundary patch from a given list. The field of tracked indices may be
    written at write time. The velocity of structures is determined from a
    velocity field of a given name.

    The dimensionality of the case is determined automatically.

    Reference:
    \verbatim
        Kunkelmann, C. (2011).
        Numerical modeling and investigation of boiling phenomena.
        PhD Thesis, Technische Universit{\"a}t Darmstadt, 1-122.
    \endverbatim

    Example of function object specification:
    \verbatim
    bubbles
    {
        type                trackPhaseStructures;
        libs                ("libaddonFieldFunctionObjects.so");
        executeControl      runTime;
        executeInterval     1e-3;
        writeControl        runTime;
        writeInterval       0.1;
        log                 true;
        ...
        alpha               alpha.airC;
        U                   U.airC;
        excludePatches      (outlet inlet1 inlet2);
        threshold           0.8;
        tolerance           0.005;
        maxVolume           4e-6;
        minVolume           1e-6;
        writeIndexField     true;
        cutAtCyclicPatch    true;
    }
    \endverbatim

Usage
    \table
        Property       | Description                  | Required| Default value
        type           | type name: trackPhaseStructures | yes   |
        alpha          | name of alpha field             | no    | alpha
        U              | name of velocity field          | no    | U
        calcSphericity | turn on/off sphericity          | no    | true
        excludePatches | boundaries to exclude           | no    | none
        threshold      | value for detection             | no    | 0.5
        tolerance      | max distance to track           | no    | great
        maxVolume      | maximum volume                  | no    | great
        minVolume      | minimum volume                  | no    | 0
        writeIndexField| write out index field           | no    | false
        cutAtCyclicPatch| structures are split by cyclic patches | no | true
    \endtable

See also
    Foam::functionObjects::fvMeshFunctionObject
    Foam::functionObjects::logFiles

SourceFiles
    trackPhaseStructures.C

\*---------------------------------------------------------------------------*/

#ifndef functionObjects_trackPhaseStructures_H
#define functionObjects_trackPhaseStructures_H

#include "fvMeshFunctionObject.H"
#include "logFiles.H"
#include "setWriter.H"
#include "volFieldsFwd.H"
#include "coordinateSystem.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam
{

// Forward declaration of classes
class regionSplit;

namespace functionObjects
{

/*---------------------------------------------------------------------------*\
                    Class trackPhaseStructures Declaration
\*---------------------------------------------------------------------------*/

class trackPhaseStructures
:
    public fvMeshFunctionObject,
    public logFiles
{
    // Private Data

        //- Result file
        writeFile file_;

        //- Name of alpha field
        word alphaName_;

        //- Names of velocity field
        word UName_;

        //- Whether to calculate and write surface area and sphericity
        Switch calcSphericity_;

        //- Patches to walk from
        wordReList patchNames_;

        //- Clipping value
        scalar threshold_;

        //- Tolerance for distance a structure has moved over time
        scalar tolerance_;

        //- Maximum structure volume
        scalar maxVol_;

        //- Minimum structure volume
        scalar minVol_;

        //- Two dimensional domain
        bool twoDimensional_;

        //- For 2D cases: thickness of domain in 3rd direction
        scalar thickness_;

        //- Switch for calculating and writing global index as field
        bool writeIndexField_;

        //- Ignore cyclic patches and treat them as region boundary
        bool cutAtCyclicPatch_;

        //- Optional coordinate system
        autoPtr<coordinateSystem> coordSysPtr_;

        //- Indices of regions
        Map<label> allRegionIndex_;

        //- Centre of gravity of all regions
        Map<vector> allRegionCentreOfGravity_;

        //- Velocity of all regions
        Map<vector> allRegionVelocity_;

        //- Volume (2D: area) of all regions
        Map<scalar> allRegionVolume_;

        //- Surface area (2D: perimeter) of all regions
        Map<scalar> allRegionSurfaceArea_;

        //- Sphericity (2D: circularity) of all regions
        Map<scalar> allRegionSphericity_;

        //- Global index number for all tracked structures
        label index_;

        //- Regions as result from splitRegion
        labelList regions_;


    // Private Member Functions

        //- Combine fields from all processor domains into single field
        template<class Type>
        void combineFields(Field<Type>& field);

        //- Try to lookup object, read if not in obr
        template<class Type>
        const Type& lookupOrRead(autoPtr<Type>&, const word& name) const;

        //- Sum up field over all regions
        template<class Type>
        Map<Type> regionSum(const regionSplit&, const Field<Type>&) const;

        //- Mark all regions starting at patches
        Map<label> findPatchRegions(const regionSplit&) const;

        //- Determine blocked faces
        boolList getBlockedFaces(const volScalarField&) const;

        //- Interpolate cell centred values to node values by inverse distance
        tmp<scalarField> interpolateCellDataToPointData
        (
            const scalarField&
        ) const;

        //- Calculate surface area of iso-surface of given threshold
        scalarField surfaceArea(const scalarField&, const scalar);

        //- Update centre of gravity, velocity and volume for all regions
        void updateRegionProperties(const regionSplit&);

        //- Update global indices
        void updateTrackedIndices(const regionSplit&, const Map<vector>&);

        //- Output file header information
        virtual void writeFileHeader(const label i);

        //- Disallow default bitwise copy construct
        trackPhaseStructures(const trackPhaseStructures&);

        //- Disallow default bitwise assignment
        void operator=(const trackPhaseStructures&);


public:

    //- Runtime type information
    TypeName("trackPhaseStructures");


    // Constructors

        //- Construct for given objectRegistry and dictionary.
        //  Allow the possibility to load fields from files
        trackPhaseStructures
        (
            const word& name,
            const Time& runTime,
            const dictionary&
        );


    // Destructor

        virtual ~trackPhaseStructures();


    // Member Functions

        //- Read the trackPhaseStructures data
        virtual bool read(const dictionary&);

        //- Return the list of fields required
        virtual wordList fields() const
        {
            return wordList::null();
        }

        //- Detect structures and keep track
        virtual bool execute();

        //- Write out individual data of phase structures and write index field
        virtual bool write();
};


// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace functionObjects
} // End namespace Foam

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#ifdef NoRepository
    #include "trackPhaseStructuresTemplates.C"
#endif

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
