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

Description
    Writes out the size distribution determined by a population balance model,
    either for the entire domain or a cell zone. Requires solver post-
    processing.

    The following function object specification for example returns the volume-
    based number density function:

    Example of function object specification:
    \verbatim
    numberDensity
    {
        type                populationBalanceSizeDistribution;
        libs                ("libaddonMultiphaseEulerFunctionObjects.so");
        writeControl        writeTime;
        populationBalance   bubbles;
        functionType        numberDensity;
        coordinateType      volume;
        setFormat           raw;
    }
    \endverbatim

Usage
    \table
        Property          | Description                    | Required  | Default
        populationBalance | population balance name        | yes       |
        functionType      | function type                  | yes       |
        coordinateType    | particle property              | yes       |
        allCoordinates    | write all coordinate values    | no        | false
        normalise         | divide by total concentration  | no        | false
        logTransform      | class width based on log of coordinate\\
                                                           | no        | false
        weightType        | weighting in case of field-dependent particle\\
                            properties                     | no\\
                                                           | numberConcentration
        cellZone          | cellZone                       | yes       |
        name              | name of cellZone if required   | no        |
        setFormat         | output format                  | yes       |
    \endtable

See also
    Foam::populationBalanceModel
    Foam::functionObjects::fvMeshFunctionObject
    Foam::fvCellZone
    Foam::functionObject

SourceFiles
    populationBalanceSizeDistribution.C

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

#ifndef populationBalanceSizeDistribution_H
#define populationBalanceSizeDistribution_H

#include "fvMeshFunctionObject.H"
#include "fvCellZone.H"
#include "populationBalanceModel.H"
#include "writeFile.H"
#include "setWriter.H"

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

namespace Foam
{
namespace functionObjects
{

/*---------------------------------------------------------------------------*\
             Class populationBalanceSizeDistribution Declaration
\*---------------------------------------------------------------------------*/

class populationBalanceSizeDistribution
:
    public fvMeshFunctionObject
{
public:

    // Public Data Types

        //- Function type enumeration
        enum functionType
        {
            numberConcentration,
            numberDensity,
            volumeConcentration,
            volumeDensity,
            areaConcentration,
            areaDensity
        };

        //- Function type names
        static const NamedEnum<functionType, 6> functionTypeNames_;

        //- Coordinate type enumeration
        enum coordinateType
        {
            volume,
            area,
            diameter,
            projectedAreaDiameter
        };

        //- Coordinate type names
        static const NamedEnum<coordinateType, 4> coordinateTypeNames_;

        //- Enumeration for the weight types
        enum class weightType
        {
            numberConcentration,
            volumeConcentration,
            areaConcentration,
            cellVolume
        };

        //- Names of the weight types
        static const NamedEnum<weightType, 4> weightTypeNames_;


private:

    // Private Data

        //- Write file
        writeFile file_;

        //- Reference to mesh
        const fvMesh& mesh_;

        //- cellZone
        fvCellZone zone_;

        //- Name of the population balance
        const word popBalName_;

        //- Function type
        functionType functionType_;

        //- Coordinate type
        coordinateType coordinateType_;

        //- Add values for all coordinate types to output
        Switch allCoordinates_;

        //- Normalise result through division by sum
        Switch normalise_;

        //- Log transform
        Switch logTransform_;

        //- Weight types, relevant if particle properties are field dependent
        weightType weightType_;

        //- Set formatter
        autoPtr<setWriter> formatterPtr_;


    // Private Member Functions

        //- Function type symbolic name for shorter file header
        word functionTypeSymbolicName();

        //- Coordinate type symbolic name for shorter file header
        word coordinateTypeSymbolicName(const coordinateType& cType);

        //- Filter a field according to cellIds
        tmp<scalarField> filterField(const scalarField& field) const;

        //- Field averaged coordinate value
        scalar averageCoordinateValue
        (
            const populationBalanceModel&,
            const label i,
            const coordinateType&
        );

        //- Weighted average
        scalar weightedAverage
        (
            const populationBalanceModel&,
            const label i,
            const scalarField& field
        );


public:

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


    // Constructors

        //- Construct from Time and dictionary
        populationBalanceSizeDistribution
        (
            const word& name,
            const Time& runTime,
            const dictionary& dict
        );

        //- Disallow default bitwise copy construction
        populationBalanceSizeDistribution
        (
            const populationBalanceSizeDistribution&
        ) = delete;


    //- Destructor
    virtual ~populationBalanceSizeDistribution();


    // Member Functions

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

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

        //- Execute, currently does nothing
        virtual bool execute();

        //- Calculate and write the size distribution
        virtual bool write();


        // Mesh changes

            //- Update for mesh motion
            virtual void movePoints(const polyMesh&);

            //- Update topology using the given map
            virtual void topoChange(const polyTopoChangeMap&);

            //- Update from another mesh using the given map
            virtual void mapMesh(const polyMeshMap&);

            //- Redistribute or update using the given distribution map
            virtual void distribute(const polyDistributionMap&);


    // Member Operators

        //- Disallow default bitwise assignment
        void operator=(const populationBalanceSizeDistribution&) = delete;
};


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

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

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

#endif

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