/*---------------------------------------------------------------------------*\
  ==  == ====== ====   ====    |
                    \\     ||  | 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

    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::clusterTrackingModel

Description
    Model for tracking fluid particles of a given size. The particles can be
    over-resolved, partially resolved or fully resolved. The class can be used
    to prepare the conversion of large unresolved fluid particles to resolved
    fluid particles.

    The clustering is based on an enhanced k-means clustering algorithm. It
    considers the following field:

    \f[
        r_o = r_{g,c} + I_o \, r_{g,d}
    \f]

    The over-resolution indicator \f$I_o\f$ is equal to one in cells which are
    much smaller than the diameter of the disperse phase, \f$d\f$. It can be
    controlled via `cellsPerDiameterThreshold` defining the necessary condition
    to take a disperse phase locally into account. The number of particles
    can be deduced from the field \f$r_o\f$ because \f$d\f$ is given.

    Each cluster is defined by a centre position and a radius, both constantly
    updated during the simulation. Each cluster encloses approximately the
    material required to build the target particle. The enclosed volume is
    computed from \f$r_o\f$. The target volume is computed based on the given
    diameter \f$d\f$, assuming a sphere in 3D or a cylinder in 2D.

    Part of the algorithm is the centre-proximity field \f$P\f$, which is
    related to the distance of a given cell to the closest cluster centre. This
    field has its maximum value (one) at each cluster centre, decreases with
    the distance from this closest cluster centre and finally approaches zero
    at the edge of each cluster. The field is zero in regions where no cluster
    exists. It can be used in other models to realise the transport of material
    towards or away from the cluster centres.

    Clusters containing fully resolved particles are excluded from the process.
    They are identified by comparing the enclosed continuous volume to the
    target particle volume. If the difference is below the limit
    `particleVolumeTol*(cluster-averaged cell volume)`, the cluster is excluded.
    This formulation ensures a higher accuracy in regions with high spatial
    resolution. If a fully resolved particle is detected, the corresponding
    region of the field \f$P\f$ is set to zero assuming that it is not required
    within these clusters.

    The over-resolution indicator \f$I_o\f$ and the centre-proximity field
    \f$P\f$ are made globally available for further usage.

Usage
    Example entry in phaseProperties dictionary:
    \verbatim
    clusterTracking
    {
        airD_airC
        {
            compressedPhase     airD;
            emergingPhase       airC;
            proximityFieldName  potential.air;
        }
    }
    \endverbatim

    \table
        Property                  | Description          | Required | Default
        compressedPhase           | Disperse phase       | yes      | none
        emergingPhase             | Continuous phase     | yes      | none
        cellsPerDiameterThreshold | Resolution criterion | no       | 8
        proximityFieldName        | Name of proximity field | yes   | none
        maxIter                   | Max iterations       | no       | 100
        particleVolumeTol         | Particle volume tol. | no       | 10
    \endtable

See also
    Foam::moveAlphaByPotentialModel
    Foam::phaseTransferModels::accumulationToContinuous

SourceFiles
    clusterTrackingModel.C

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

#ifndef clusterTrackingModel_H
#define clusterTrackingModel_H

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

#include "volFields.H"
#include "dictionary.H"
#include "dispersedPhaseInterface.H"
#include "runTimeSelectionTables.H"

namespace Foam
{

class phaseSystem;
class phaseModel;

/*---------------------------------------------------------------------------*\
               Class clusterTrackingModel Declaration
\*---------------------------------------------------------------------------*/

class clusterTrackingModel
:
    public regIOobject
{
protected:

    // Protected Data

        //- Reference to the mesh
        const fvMesh& mesh_;

        //- Two dimensional domain
        bool twoDimensional_;

        //- Thickness of 2D domain
        scalar thickness_;

        //- Compressed disperse phase
        const phaseModel& compressedPhase_;

        //- Emerging continuous phase
        const phaseModel& emergingPhase_;

        //- Threshold value to determine transitionRegion
        scalar cellsPerDiameterThreshold_;

        //- Maximum number of iterations
        label maxIter_;

        //- Particle volume tolerance
        label particleVolumeTol_;

        //- Largest relevant diameter
        scalar diameter_;

        //- Number of clusters
        label nClusters_;

        //- Number of valid clusters
        label nActiveClusters_;

        //- Cluster centre positions
        Map<vector> clusterCentre_;

        //- Cluster radius
        Map<scalar> clusterRadius_;

        //-Initial radius of each cluster
        scalar initialRadius_;

        //- Proximity field name
        word centreProximityFieldName_;

        //- Proximity to cluster cell centres
        volScalarField centreProximity_;

        //- Cluster colour
        volScalarField colour_;

        //- Over-resolution indicator
        volScalarField overResolutionIndicator_;


public:

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


    // Declare runtime construction

        declareRunTimeSelectionTable
        (
            autoPtr,
            clusterTrackingModel,
            dictionary,
            (
                const dictionary& dict,
                const phaseInterface& interface,
                const bool registerObject
            ),
            (dict, interface, registerObject)
        );

    // Constructors

        //- Construct from a dictionary and an interface
        clusterTrackingModel
        (
            const dictionary& dict,
            const phaseInterface& interface,
            const bool registerObject
        );


    //- Destructor
    virtual ~clusterTrackingModel();


    // Selectors

        static autoPtr<clusterTrackingModel> New
        (
            const dictionary& dict,
            const phaseInterface& interface,
            const bool outer=true,
            const bool registerObject=true
        );


    // Member Functions

        //- Return interface key
        phaseInterfaceKey key() const;

        //- Return representative diameter of disperse phase
        scalar diameter() const;

        //- Return disperse phase
        const phaseModel& compressedPhase() const;

        //- Update number, position and size of clusters
        label updateClusters();

        //- Report existence of active clusters
        bool isActive();

        //- Discard all clusters
        void discard();

        //- Dummy write for regIOobject
        bool writeData(Ostream& os) const;
};


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

} // End namespace Foam

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

#endif

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