/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     | Website:  https://openfoam.org
    \\  /    A nd           | Version:  9
     \\/     M anipulation  |
\*---------------------------------------------------------------------------*/

libs            ("libutilityFunctionObjects.so");

type            coded;

writeControl    timeStep;
writeInterval   1;

codeOptions
#{
    -I$(LIB_SRC)/transportModels/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/thermophysicalProperties/lnInclude \
    -I$(LIB_SRC)/thermophysicalModels/basic/lnInclude
#};

codeInclude
#{
    #include "rhoThermo.H"

    namespace Foam
    {
        tmp<volScalarField> ea(const rhoThermo& thermo)
        {
            tmp<volScalarField> tEa = thermo.he() + thermo.hc();

            if (thermo.he().name() == thermo.phasePropertyName("h"))
            {
                tEa.ref() -= thermo.p()/thermo.rho();
            }

            return tEa;
        }
    }
#};

codeRead
#{
    volScalarField* dMass =
        new volScalarField
        (
            IOobject("dMass", mesh().time().timeName(), mesh()),
            mesh(),
            dimensionedScalar(dimMass/dimVolume, 0)
        );
    volScalarField* dMassGas = new volScalarField("dMass.gas", *dMass);
    volScalarField* mass0Gas = new volScalarField("mass0.gas", *dMass);
    volScalarField* dMassLiq = new volScalarField("dMass.liquid", *dMass);
    volScalarField* mass0Liq = new volScalarField("mass0.liquid", *dMass);
    volScalarField* dEnergy =
        new volScalarField
        (
            IOobject("dEnergy", mesh().time().timeName(), mesh()),
            mesh(),
            dimensionedScalar(dimEnergy/dimVolume, 0)
        );
    volScalarField* dEnergyLiq = new volScalarField("dEnergy.liquid", *dEnergy);
    volScalarField* energy0Liq = new volScalarField("energy0.liquid", *dEnergy);
    volScalarField* dEnergyGas = new volScalarField("dEnergy.gas", *dEnergy);
    volScalarField* energy0Gas = new volScalarField("energy0.gas", *dEnergy);

    const volScalarField& alphaGas =
        mesh().lookupObject<volScalarField>("alpha.gas");
    const volScalarField& alphaLiq =
        mesh().lookupObject<volScalarField>("alpha.liquid");
    const rhoThermo& thermoGas =
        mesh().lookupObject<rhoThermo>("thermophysicalProperties.gas");
    const rhoThermo& thermoLiq =
        mesh().lookupObject<rhoThermo>("thermophysicalProperties.liquid");

    *mass0Gas = alphaGas*thermoGas.rho();
    *mass0Liq = alphaLiq*thermoLiq.rho();

    // !!! Note that this is only a valid measure of energy
    // conservation because the case is of fixed volume and has no
    // kinetic energy
    *energy0Gas = alphaGas*thermoGas.rho()*ea(thermoGas);
    *energy0Liq = alphaLiq*thermoLiq.rho()*ea(thermoLiq);

    dMass->store();
    dMassGas->store();
    mass0Gas->store();
    dMassLiq->store();
    mass0Liq->store();
    dEnergy->store();
    dEnergyGas->store();
    energy0Gas->store();
    dEnergyLiq->store();
    energy0Liq->store();
#};

codeExecute
#{
    volScalarField& dMass =
        mesh().lookupObjectRef<volScalarField>("dMass");
    volScalarField& dMassGas =
        mesh().lookupObjectRef<volScalarField>("dMass.gas");
    const volScalarField& mass0Gas =
        mesh().lookupObject<volScalarField>("mass0.gas");
    volScalarField& dMassLiq =
        mesh().lookupObjectRef<volScalarField>("dMass.liquid");
    const volScalarField& mass0Liq =
        mesh().lookupObject<volScalarField>("mass0.liquid");

    volScalarField& dEnergy =
        mesh().lookupObjectRef<volScalarField>("dEnergy");
    volScalarField& dEnergyGas =
        mesh().lookupObjectRef<volScalarField>("dEnergy.gas");
    const volScalarField& energy0Gas =
        mesh().lookupObject<volScalarField>("energy0.gas");
    volScalarField& dEnergyLiq =
        mesh().lookupObjectRef<volScalarField>("dEnergy.liquid");
    const volScalarField& energy0Liq =
        mesh().lookupObject<volScalarField>("energy0.liquid");

    const volScalarField& alphaGas =
        mesh().lookupObject<volScalarField>("alpha.gas");
    const volScalarField& alphaLiq =
        mesh().lookupObject<volScalarField>("alpha.liquid");
    const rhoThermo& thermoGas =
        mesh().lookupObject<rhoThermo>("thermophysicalProperties.gas");
    const rhoThermo& thermoLiq =
        mesh().lookupObject<rhoThermo>("thermophysicalProperties.liquid");

    dMassGas = alphaGas*thermoGas.rho() - mass0Gas;
    dMassLiq = alphaLiq*thermoLiq.rho() - mass0Liq;
    dMass = dMassGas + dMassLiq;

    // !!! Note that this is only a valid measure of energy
    // conservation because the case is of fixed volume and has no
    // kinetic energy
    dEnergyGas = alphaGas*thermoGas.rho()*ea(thermoGas) - energy0Gas;
    dEnergyLiq = alphaLiq*thermoLiq.rho()*ea(thermoLiq) - energy0Liq;
    dEnergy = dEnergyGas + dEnergyLiq;
#};

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