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

Description
    Wrapper class for interfacial models for which multiple instances of the
    model are used for different configurations of the interface; e.g.,
    bubbles, droplets, segregated flow, displaced by another phase, ... The
    values generated by these multiple models are then "blended" to create a
    single effective coefficient or source.

SourceFiles
    BlendedInterfacialModel.C

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

#ifndef BlendedInterfacialModel_H
#define BlendedInterfacialModel_H

#include "blendingMethod.H"
#include "HashPtrTable.H"
#include "hashedWordList.H"
#include "dispersedDisplacedPhaseInterface.H"
#include "segregatedDisplacedPhaseInterface.H"
#include "TypeSet.H"

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

namespace Foam
{

/*---------------------------------------------------------------------------*\
                   Class BlendedInterfacialModel Declaration
\*---------------------------------------------------------------------------*/

template<class ModelType>
class BlendedInterfacialModel
:
    public regIOobject
{
    // Private Data

        //- The interface
        const phaseInterface interface_;

        //- Blending method
        autoPtr<blendingMethod> blending_;

        //- Model for general configurations
        autoPtr<ModelType> modelGeneral_;

        //- Model for phase 1 dispersed in phase 2
        autoPtr<ModelType> model1DispersedIn2_;

        //- Model for phase 2 dispersed in phase 1
        autoPtr<ModelType> model2DispersedIn1_;

        //- Model for phase 1 segregated with phase 2
        autoPtr<ModelType> model1SegregatedWith2_;

        //- Models for general configurations displaced by a third phase
        PtrList<ModelType> modelsGeneralDisplaced_;

        //- Models for phase 1 dispersed in phase 2 displaced by a third phase
        PtrList<ModelType> models1DispersedIn2Displaced_;

        //- Models for phase 2 dispersed in phase 1 displaced by a third phase
        PtrList<ModelType> models2DispersedIn1Displaced_;

        //- Models for phase 1 segregated with phase 2 displaced by a third
        //  phase
        PtrList<ModelType> models1SegregatedWith2Displaced_;

        //- Time index of last check
        mutable label checkTimeIndex_;


    // Private Member Functions

        //- Check compatibility of the available models and the blending method
        void check() const;

        //- Calculate the blending coefficients
        template<class GeoMesh>
        void calculateBlendingCoeffs
        (
            const UPtrList<const volScalarField>& alphas,
            tmp<GeometricField<scalar, GeoMesh>>& fG,
            tmp<GeometricField<scalar, GeoMesh>>& f1D2,
            tmp<GeometricField<scalar, GeoMesh>>& f2D1,
            tmp<GeometricField<scalar, GeoMesh>>& fS,
            PtrList<GeometricField<scalar, GeoMesh>>& fGD,
            PtrList<GeometricField<scalar, GeoMesh>>& f1D2D,
            PtrList<GeometricField<scalar, GeoMesh>>& f2D1D,
            PtrList<GeometricField<scalar, GeoMesh>>& fSD
        ) const;

        //- Write out a set or surface that visualises the various models'
        //  utilisation of the blending space
        void postProcessBlendingCoefficients(const word& format) const;


protected:

    // Protected Member Functions

        //- Return a blended field
        template<class Type, class GeoMesh, class ... Args>
        tmp<GeometricField<Type, GeoMesh>> evaluate
        (
            tmp<GeometricField<Type, GeoMesh>>
            (ModelType::*method)(Args ...) const,
            const word& name,
            const dimensionSet& dims,
            Args ... args
        ) const;

        //- Return a table of blended fields
        template<class Type, class GeoMesh, class ... Args>
        HashPtrTable<GeometricField<Type, GeoMesh>> evaluate
        (
            HashPtrTable<GeometricField<Type, GeoMesh>>
            (ModelType::*method)(Args ...) const,
            const word& name,
            const dimensionSet& dims,
            Args ... args
        ) const;

        //- Return a bool combined (or) from all models
        template<class ... Args>
        bool evaluate
        (
            bool (ModelType::*method)(Args ...) const,
            Args ... args
        ) const;

        //- Return a hashed word list combined from all models
        template<class ... Args>
        hashedWordList evaluate
        (
            const hashedWordList& (ModelType::*method)(Args ...) const,
            Args ... args
        ) const;


public:

    //- Public Type Definitions

        //- The underlying model type
        typedef ModelType modelType;

        //- Required phase interface types
        typedef TypeSet<> requiredPhaseInterfaces;

        //- Allowed phase interface types
        typedef TypeSet
        <
            dispersedPhaseInterface,
            segregatedPhaseInterface,
            displacedPhaseInterface
        > allowedPhaseInterfaces;


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


    // Constructors

        //- Construct from a dictionary, an interface and a blending dictionary
        template<class ... Args>
        BlendedInterfacialModel
        (
            const dictionary& dict,
            const phaseInterface& interface,
            const dictionary& blendingDict,
            const Args& ... args
        );

        //- Disallow default bitwise copy construction
        BlendedInterfacialModel
        (
            const BlendedInterfacialModel<ModelType>&
        ) = delete;


    //- Destructor
    ~BlendedInterfacialModel();


    // Member Functions

        //- Access the interface
        const phaseInterface& interface() const;

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


    // Member Operators

        //- Disallow default bitwise assignment
        void operator=(const BlendedInterfacialModel<ModelType>&) = delete;
};


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

#define defineBlendedInterfacialModelTypeNameAndDebug(ModelType, DebugSwitch)  \
                                                                               \
    defineTemplateTypeNameAndDebugWithName                                     \
    (                                                                          \
        BlendedInterfacialModel<ModelType>,                                    \
        (                                                                      \
            word(BlendedInterfacialModel<ModelType>::typeName_()) + "<"        \
          + ModelType::typeName + ">"                                          \
        ).c_str(),                                                             \
        DebugSwitch                                                            \
    );


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

} // End namespace Foam

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

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

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

#endif

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