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

Description
    Class which provides interfacial momentum transfer between a number of
    phases. Drag, virtual mass, lift, wall lubrication and turbulent dispersion
    are all modelled. Access is provided to a various forces and coefficients
    needed by the solver.

SourceFiles
    momentumTransferSystem.C

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

#ifndef momentumTransferSystem_H
#define momentumTransferSystem_H

#include "phaseSystem.H"
#include "HashPtrTable.H"

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

namespace Foam
{

// Forward declaration of classes
class blendedDragModel;
class blendedVirtualMassModel;
class blendedLiftModel;
class blendedWallLubricationModel;
class blendedTurbulentDispersionModel;

/*---------------------------------------------------------------------------*\
                 Class momentumTransferSystem Declaration
\*---------------------------------------------------------------------------*/

class momentumTransferSystem
:
    public IOdictionary
{
    // Private Type Definitions

/*~~~~~~~~~~~~~~~~~~~~~~~ Begin Comment Code Repository ~~~~~~~~~~~~~~~~~~~~~*\
        typedef HashPtrTable
        <
            volScalarField,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > KdTable;
\*~~~~~~~~~~~~~~~~~~~~~~~~ End Comment Code Repository ~~~~~~~~~~~~~~~~~~~~~~*/

        typedef HashPtrTable
        <
            blendedDragModel,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > dragModelTable;

        typedef HashPtrTable
        <
            blendedVirtualMassModel,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > virtualMassModelTable;

        typedef HashPtrTable
        <
            blendedLiftModel,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > liftModelTable;

        typedef HashPtrTable
        <
            blendedWallLubricationModel,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > wallLubricationModelTable;

        typedef HashPtrTable
        <
            blendedTurbulentDispersionModel,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > turbulentDispersionModelTable;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//

public:

    // Public Typedefs

        typedef HashPtrTable
        <
            volScalarField,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > KdTable;

        typedef HashPtrTable
        <
            surfaceScalarField,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > KdfTable;

        typedef HashPtrTable
        <
            volScalarField,
            phaseInterfaceKey,
            phaseInterfaceKey::hash
        > VmTable;


private:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//


    // Private Data

        //- Reference to the phase system
        const phaseSystem& fluid_;

        //- Cached drag coefficients for dragCorrs
        mutable KdTable Kds_;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//
        //- Face drag coefficients
        KdfTable Kdfs_;

        //- Virtual mass coefficients
        VmTable Vms_;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//

        //- Drag models
        const dragModelTable dragModels_;

        //- Virtual mass models
        const virtualMassModelTable virtualMassModels_;

        //- Lift models
        const liftModelTable liftModels_;

        //- Wall lubrication models
        const wallLubricationModelTable wallLubricationModels_;

        //- Turbulent dispersion models
        const turbulentDispersionModelTable turbulentDispersionModels_;


    // Private Member Functions

        //- Create IO object for an optional constant/momentumTransfer file
        IOobject io(const phaseSystem&) const;

        //- Return the models dictionary
        template<class ModelType>
        const dictionary& modelsDict() const;

        //- Add a field to the given result. If the result is not valid then
        //  copy the field in as if the result was initially zero.
        void addTmpField
        (
            tmp<surfaceScalarField>& result,
            const tmp<surfaceScalarField>& field
        ) const;

        //- Invert the ADVs matrix inplace
        void invADVs(List<UPtrList<scalarField>>& ADVs) const;

        //- Invert the ADVs matrix inplace
        template<class GeoMesh>
        void invADVs
        (
            PtrList<PtrList<GeometricField<scalar, GeoMesh>>>& ADVs
        ) const;


public:

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


    //- Default name of the phase properties dictionary
    static const word propertiesName;


    // Constructors

        //- Construct from a phase system
        momentumTransferSystem(const phaseSystem&);


    //- Destructor
    virtual ~momentumTransferSystem();


    // Member Functions

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//
        //- Calculate and fill the model tables for momentum transfer
        virtual void fillMomentumTransferTables();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//

        //- Return the explicit force fluxes for the cell-based algorithm, that
        //  do not depend on phase mass/volume fluxes, and can therefore be
        //  evaluated outside the corrector loop. This includes things like
        //  lift, turbulent dispersion, and wall lubrication.
        PtrList<surfaceScalarField> Fs() const;

        //- As Fs, but for the face-based algorithm
        PtrList<surfaceScalarField> Ffs() const;

        //- Return the inverse of the central + drag + virtual mass
        //  coefficient matrix
        void invADVs
        (
            const PtrList<volScalarField>& As,
            PtrList<volVectorField>& HVms,
            PtrList<PtrList<volScalarField>>& invADVs,
            PtrList<PtrList<surfaceScalarField>>& invADVfs
        ) const;

        //- Return the inverse of the central + drag + virtual mass
        //  coefficient matrix
        PtrList<PtrList<surfaceScalarField>> invADVfs
        (
            const PtrList<surfaceScalarField>& Afs,
            PtrList<surfaceScalarField>& HVmfs
        ) const;

        //- Return the phase diffusivity
        //  divided by the momentum central coefficient
        virtual tmp<surfaceScalarField> alphaDByAf
        (
            const PtrList<volScalarField>& rAs
        ) const;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//
        //- Return alpha diffusivity
        virtual tmp<surfaceScalarField> alphaDiffusivity() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//

        //- Return the flux corrections for the cell-based algorithm. These
        //  depend on phase mass/volume fluxes, and must therefore be evaluated
        //  inside the corrector loop.
        PtrList<surfaceScalarField> ddtCorrs() const;

        //- Set the cell and faces drag correction fields
        void dragCorrs
        (
            PtrList<volVectorField>& dragCorrs,
            PtrList<surfaceScalarField>& dragCorrf
        ) const;

        //- Read base phaseProperties dictionary
        virtual bool read();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Begin Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~//
        //- Return the drag coefficient for all phase-pairs
        virtual const KdTable& KdsTable() const
        {
            return Kds_;
        };

        //- Return the face drag coefficient for all phase-pairs
        virtual const KdfTable& KdfsTable() const
        {
            return Kdfs_;
        };

        //- Return the virtual mass force coefficient for all phase-pairs
        virtual const VmTable& Vms() const
        {
            return Vms_;
        };
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ End Code Repository ~~~~~~~~~~~~~~~~~~~~~~~~~~//
};


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

} // End namespace Foam

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

#endif

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