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

Description
    Class to represent an interface between phases. Derivations can further
    specify the configuration of that interface; e.g., representing dispersal,
    displacement or sidedness.

SourceFiles
    phaseInterface.C
    phaseInterfaceI.H

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

#ifndef phaseInterface_H
#define phaseInterface_H

#include "phaseModel.H"
#include "compressibleTwoPhases.H"
#include "runTimeSelectionTables.H"

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

namespace Foam
{

class phaseInterfaceKey;

/*---------------------------------------------------------------------------*\
                         Class phaseInterface Declaration
\*---------------------------------------------------------------------------*/

class phaseInterface
:
    public compressibleTwoPhases
{
private:

    // Private Static Data

        //- List of head separators. This is the first separator in an
        //  interface name, and it delimits the names of phases on either side
        //  of the interface. Other separators are modifiers (e.g.,
        //  displacedBy, inThe, ...).
        static wordList headSeparators_;

        //- Map from old-format separators to separators
        static HashTable<word> oldSeparatorToSeparator_;


public:

    // Public Static Functions

        //- Get a reference to phase1 after sorting the phases by index
        static const phaseModel& getPhase1
        (
            const phaseModel& phase1,
            const phaseModel& phase2
        );

        //- Get a reference to phase2 after sorting the phases by index
        static const phaseModel& getPhase2
        (
            const phaseModel& phase1,
            const phaseModel& phase2
        );

        //- Add a head separator to the list
        static bool addHeadSeparator(const word& separator);

        //- Add a old separator to separator to the table
        static bool addOldSeparatorToSeparator
        (
            const word& oldSeparator,
            const word& separator
        );

        //- Split an interface name and return all its parts
        static wordList nameToNameParts
        (
            const phaseSystem& fluid,
            const word& name
        );

        //- Split an interface name and return its separators
        static wordList nameToSeparators
        (
            const phaseSystem& fluid,
            const word& name
        );

        //- Convert a list of separators into a type name
        static word separatorsToTypeName
        (
            const wordList& separators
        );

        //- Convert an interface name into a type name. Essentially just
        //  replaces valid phase names with a "<phase>" placeholder.
        static word nameToTypeName
        (
            const phaseSystem& fluid,
            const word& name
        );

        //- Convert interface name parts to an interface name
        static word namePartsToName
        (
            const phaseSystem& fluid,
            const wordList& nameParts
        );

        //- Convert old-format interface name parts to an interface name. Used
        //  in phaseSystem to provide backwards compatible input.
        static word oldNamePartsToName
        (
            const phaseSystem& fluid,
            const wordList& oldNameParts
        );

        //- Return references to the phases associated with a given name, and a
        //  list of valid separators
        static Tuple2<const phaseModel&, const phaseModel&> identifyPhases
        (
            const phaseSystem& fluid,
            const word& name,
            const wordList& separators
        );


private:

    // Private Data

        //- Phase 1
        const phaseModel& phase1_;

        //- Phase 2
        const phaseModel& phase2_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//
        //- Light phase
        const phaseModel& lightPhase_;

        //- Heavy phase
        const phaseModel& heavyPhase_;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//


protected:

    // Protected Member Functions

        //- Return true if the phase interfaces are the same
        virtual bool same(const phaseInterface& interface, bool strict) const;


public:

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


    // Declare runtime construction

        declareRunTimeSelectionTable
        (
            autoPtr,
            phaseInterface,
            word,
            (
                const phaseSystem& fluid,
                const word& name
            ),
            (fluid, name)
        );


    // Constructors

        //- Construct from phases
        phaseInterface
        (
            const phaseModel& phase1,
            const phaseModel& phase2
        );

        //- Construct from phases
        phaseInterface
        (
            const Tuple2<const phaseModel&, const phaseModel&>& phases
        );

        //- Construct from fluid and name
        phaseInterface
        (
            const phaseSystem& fluid,
            const word& name
        );

        //- Construct from fluid and key
        phaseInterface
        (
            const phaseSystem& fluid,
            const phaseInterfaceKey& name
        );

        //- Clone function
        virtual autoPtr<phaseInterface> clone() const;


    //- Destructor
    virtual ~phaseInterface();


    // Selectors

        //- Select given fluid and name
        static autoPtr<phaseInterface> New
        (
            const phaseSystem& fluid,
            const word& name
        );

        //- Select by combining two interfaces
        static autoPtr<phaseInterface> New
        (
            const phaseInterface& interface1,
            const phaseInterface& interface2
        );

        //- Class used for construction of PtrLists of phaseInterfaces
        class iNew
        {
            const phaseSystem& fluid_;

        public:

            iNew(const phaseSystem& fluid)
            :
                fluid_(fluid)
            {}

            autoPtr<phaseInterface> operator()(Istream& is) const
            {
                return phaseInterface::New(fluid_, word(is));
            }
        };


    // Static Member Functions

        //- Return the separator that delimits this interface's name
        static word separator()
        {
            return word::null;
        }


    // Member Functions

        //- Name
        virtual word name() const;

        //- Cast to derived type for use in a model
        template<class ModelType, class Derived>
        const Derived& modelCast() const
        {
            if (!isA<Derived>(*this))
            {
                FatalErrorInFunction
                    << "Constructing " << ModelType::typeName
                    << " for interface " << name()
                    << " which is not of the required type "
                    << Derived::typeName << exit(FatalError);
            }

            return refCast<const Derived>(*this);
        }


        // Access

            //- Return the volume fraction of phase 1
            virtual inline const volScalarField& alpha1() const;

            //- Return the volume fraction of phase 2
            virtual inline const volScalarField& alpha2() const;

            //- Return the thermo for phase 1
            virtual inline const rhoFluidThermo& thermo1() const;

            //- Return the thermo for phase 2
            virtual inline const rhoFluidThermo& thermo2() const;

            //- Return the density of phase 1
            virtual inline const volScalarField& rho1() const;

            //- Return the density of phase 2
            virtual inline const volScalarField& rho2() const;

            //- Return phase 1
            inline const phaseModel& phase1() const;

            //- Return phase 2
            inline const phaseModel& phase2() const;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//
            //- Return light phase
            inline const phaseModel& lightPhase() const;

            //- Return heavy phase
            inline const phaseModel& heavyPhase() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//

            //- Return true if this phaseInterface contains the given phase
            inline bool contains(const phaseModel& phase) const;

            //- Return true if the phase interfaces are the same
            inline bool operator==(const phaseInterface& interface) const;

            //- Return true if the phase interfaces are different
            inline bool operator!=(const phaseInterface& interface) const;

            //- Return the other phase relative to the given phase
            //  Generates a FatalError if this phaseInterface does not contain
            //  the given phase
            inline const phaseModel& otherPhase(const phaseModel& phase) const;

            //- Return the index of the given phase. Generates a FatalError if
            //  this phaseInterface does not contain the given phase
            inline label index(const phaseModel& phase) const;

            //- Access the phase for the given index. Generates a FatalError if
            //  the index is not 0 or 1.
            inline const phaseModel& operator[](const label index) const;

            //- Return the phase system
            inline const phaseSystem& fluid() const;

            //- Return the mesh
            inline const fvMesh& mesh() const;


        // Properties

            //- Average density
            tmp<volScalarField> rho() const;

            //- Relative velocity magnitude
            tmp<volScalarField> magUr() const;

            //- Surface tension coefficient
            tmp<volScalarField> sigma() const;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//
            //- Average thermal conductivity
            tmp<volScalarField> kappa() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//

    // Iterators

        //- STL const_iterator
        class const_iterator
        {
            // Private Data

                //- Reference to the interface for which this is an iterator
                const phaseInterface& interface_;

                //- Current index
                label index_;

                //- Construct an iterator with the given index
                inline const_iterator(const phaseInterface&, const label index);

        public:

            friend class phaseInterface;

            // Constructors

                //- Construct from interface, moving to its 'begin' position
                inline explicit const_iterator(const phaseInterface&);


            // Access

                //- Return the current index
                inline label index() const;


            // Member Operators

                inline bool operator==(const const_iterator&) const;

                inline bool operator!=(const const_iterator&) const;

                inline const phaseModel& operator*() const;
                inline const phaseModel& operator()() const;

                inline const phaseModel& otherPhase() const;

                inline const_iterator& operator++();
                inline const_iterator operator++(int);
        };


        //- const_iterator set to the beginning of the interface
        inline const_iterator cbegin() const;

        //- const_iterator set to beyond the end of the interface
        inline const_iterator cend() const;

        //- const_iterator set to the beginning of the interface
        inline const_iterator begin() const;

        //- const_iterator set to beyond the end of the interface
        inline const_iterator end() const;
};


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

} // End namespace Foam

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

#include "phaseInterfaceI.H"

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

#endif

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