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

Description
    This model controls the total integral mass of a given list of phases. The
    deviation of the total mass from the target value is evaluated at each
    iteration to compute volume sources/sinks for the controlled phases and
    complementarily for the buffer phase, such that the total target mass is
    reached. The target mass is set to the initially existing mass and might be
    updated taking boundary fluxes (resulting from inflow and outflow boundary
    conditions) and sources or sinks into account if they are related to the
    phases under consideration. If boundary fluxes and sources/sinks are not
    taken into account, the controller aims at a constant hold-up.

    The sources and sinks are designed such that the controlled phases are
    substituted with the buffer phase in a volume-equivalent way or vice-versa.
    The substitution takes place in cells, where any kind of interface is
    present between a controlled phase and the buffer phase, i.e., both phases
    are present in the same location.

Usage
    \table
        Property | Description | Required | Default value
        controlledPhases | list of mass-controlled phases | yes | -
        bufferPhase | phase compensating volume changes | yes | -
        accountBoundaryFluxes | take boundary fluxes into balance | no | yes
        accountVolumeSources | take sinks/sources into balance | no | yes
    \endtable

    Example specification:
    \verbatim
    <fvModelName>
    {
        type                phaseMassController;
        libs                ("libaddonMultiphaseEulerFvModels.so");

        controlledPhases    (liquidC liquidD);
        bufferPhase         gasC;
    }
    \endverbatim

SourceFiles
    phaseMassController.C

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

#ifndef phaseMassController_H
#define phaseMassController_H

#include "fvModel.H"
#include "surfaceFields.H"
#include "volFields.H"
#include "phaseSystem.H"

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

namespace Foam
{
namespace fv
{

/*---------------------------------------------------------------------------*\
                     Class phaseMassController Declaration
\*---------------------------------------------------------------------------*/

class phaseMassController
:
    public fvModel
{
    // Private Member Data

        //- Names of phases their integral mass is controlled
        const wordList controlledPhases_;

        //- Name of the phase that compensates mass corrections
        const word bufferPhase_;

        //- Name of phase fraction field
        const word alphaName_;

        //- Access to phaseSystem
        const phaseSystem& fluid_;

        //- Names of alpha fields
        wordList fieldNames_;

        //- Account for fluxes across domain boundaries
        const Switch accountBoundaryFluxes_;

        //- Account for sources/sinks of controlled phases in the domain volume
        const Switch accountVolumeSources_;

        //- Total control rate
        dimensionedScalar rate_;

        //- Time level
        label timeIndex0_;

        //- Total target mass of controlled phases of recent iteration
        dimensionedScalar MTarget_;

        //- Total target mass of controlled phases of recent time step
        dimensionedScalar MTarget0_;


    // Private Member Functions

        //- Check if the phase is a controlled phase
        bool isControlledPhase(const word& fieldName) const;


public:

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


    // Constructors

        //- Construct from components
        phaseMassController
        (
            const word& name,
            const word& modelType,
            const fvMesh& mesh,
            const dictionary& dict
        );

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


    //- Destructor
    virtual ~phaseMassController();


    // Member Functions

        // Checks

            //- Return true if the option adds a source term to the given
            //  field's transport equation
            virtual bool addsSupToField(const word& fieldName) const;

            //- Return the list of fields for which the option adds source term
            //  to the transport equation
            virtual wordList addSupFields() const;


        // Sources

            //- Add a source term to an incompressible phase equation
            void addSup
            (
                const volScalarField& alpha,
                const volScalarField& field,
                fvMatrix<scalar>& eqn
            ) const;



        // Mesh changes

            //- Update for mesh motion
            virtual bool movePoints(){return true;}

            //- 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&){}


        //- Correct the fvModel
        virtual void correct();


    // Member Operators

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


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

} // End namespace fv
} // End namespace Foam

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

#endif

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