<!-- Important: This file has been automatically generated by generate_example_docs.py. Do not edit this file directly! -->


| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 3](setup.md) | [:arrow_right: Continue with part 5](solidmaterial.md) |
|---|---|---:|

# Biomineralization - Fluids

The main idea of biomineralization revolves around
biologically-induced mineral precipitation.
I our example, it is about precipitation of calcite
due to urea hydrolysis.
The resulting overall reaction equation is:

```math
\mathrm{CO(NH_2)_2} + 2\mathrm{H_2O} + \mathrm{Ca^{2+}} \xrightarrow{urease}
2\mathrm{NH_{4}^{+}} + \mathrm{CaCO_{3}} \downarrow.
```

To describe the processes, the minimum set of components is:
water (w), dissolved inorganic carbon (C<sub>tot</sub>),
sodium (Na), chloride (Cl), calcium (Ca), urea (u), glucose as a substrate (s), oxygen (O<sub>2</sub>), and suspended biomass (b),
as well as the solid components biofilm and calcite.
Thus, there are many components involved and keeping track of the components and their interactions,
necessitates a sophisticated handling.
This is why the material folder in this example is both separated from the regular material folder in dumux/dumux/material
and also documented separately.
For further specialization, the overview over the material subfolder is split into solid and fluid, this description considering the fluids.

## Fluids in the folder `material`

As this example is about biomineralization involving many components with complex inteactions, some specific fluid material files are necessary.
A CO_2-Table file provides tabulated CO_2 properties according to @Span1996 in `material/co2tableslaboratory.hh`
In the component subfolder, `material/components/suspendedbiomass.hh` defines the component suspended biomass, which is the mobile form of biomass being transported suspended in the aqueous fluid phase.
In the fluidsystem subfolder, the biomineralization fluidsystem `material/fluidsystems/biominsimplechemistry.hh` as well as
the complex salinity brine adapter `material/fluidsystems/icpcomplexsalinitybrine.hh` can be found.
The biomineralization fluidsystem `material/fluidsystems/biominsimplechemistry.hh`
contains the fluid related properties and the interactions of the components in the fluids.
The complex salinity brine adapter `material/fluidsystems/icpcomplexsalinitybrine.hh`
adapts the brine fluidsystem (dumux/dumux/material/fluidsystems/brine.hh) expecting a single non-aqueous component defining salinity to be reused for biomineralization with three ions (calcium, sodium, chloride) being assumed to contribute to salinity.


The subsequent documentation is structured as follows:

[[_TOC_]]


[@Span1996]: https://aip.scitation.org/doi/abs/10.1063/1.555991 "A new equation of state for carbon dioxide covering the fluid region from the triple-point temperature to 1100 K at pressures up to 800 MPa"


## The CO2 tables (`co2tableslaboratory.hh`)

This file contains the __co2table class__ which forwards to tabulated properties of CO2 according to Span and Wagner 1996.
The real work (creating the tables) is done by some external program by Span and Wagner 1996 which provides the ready-to-use tables.


<details open>
<summary><b>Click to hide/show the file documentation</b> (or inspect the [source code](../material/co2tableslaboratory.hh))</summary>



```cpp

#include <assert.h>
namespace Dumux::ICP {
#include "co2valueslaboratory.inc"
}// end namespace Dumux::ICP
```


</details>



## The suspended biomass component (`suspendedbiomass.hh`)

This file contains the __ component class__ which defines the name and molar mass of suspended biomass


<details open>
<summary><b>Click to hide/show the file documentation</b> (or inspect the [source code](../material/components/suspendedbiomass.hh))</summary>


### Include files

```cpp
// including the base component
#include <dumux/material/components/base.hh>

#include <dumux/common/parameters.hh>
```

### The suspended biomass component

```cpp
namespace Dumux::Components {

// In SuspendedBiomass, we define the properties of the component suspended biomass
template <class Scalar>
class SuspendedBiomass
: public Components::Base<Scalar, SuspendedBiomass<Scalar> >
{
public:
    // the name
    static std::string name()
    { return "Suspended_Biomass"; }
```

### The suspended biomass component's properties

```cpp
    // The molar mass, which is not really defined for suspended biomass. Thus, we read it from params.input or use a default of 1.
    // Based on a cell mass of 2.5e-16, the molar mass of cells would be 1.5e8 kg/mol, but such high molar masses would lead to numerical problems.
    static Scalar molarMass()
    {
        Scalar molarMass = getParam<Scalar>("BioCoefficients.SuspendedBiomassMolarMass", 1);
        return molarMass;
    }
};


} // end namespace Dumux::Components
```


</details>



## The fluid system (`biominsimplechemistry.hh`)

This file contains the __fluidsystem class__ which defines all functions needed to describe the fluids and their properties,
which are needed to model biomineralization.


<details open>
<summary><b>Click to hide/show the file documentation</b> (or inspect the [source code](../material/fluidsystems/biominsimplechemistry.hh))</summary>


### Include files
<details><summary> Click to show </summary>

```cpp
#include <dumux/material/idealgas.hh>

// we include the base fluid system
#include <dumux/material/fluidsystems/base.hh>
// we include the brine adapter adapting component indices to use the brine fluidsystem
#include "icpcomplexsalinitybrine.hh"

// we include all necessary fluid components
#include <dumux/material/fluidstates/adapter.hh>
#include <dumux/material/components/co2.hh>
#include <dumux/material/components/h2o.hh>
#include <dumux/material/components/tabulatedcomponent.hh>
#include <dumux/material/components/co2tablereader.hh>
#include <dumux/material/components/sodiumion.hh>
#include <dumux/material/components/chlorideion.hh>
#include <dumux/material/components/calciumion.hh>
#include <dumux/material/components/urea.hh>
#include <dumux/material/components/o2.hh>
#include <dumux/material/components/glucose.hh>
#include <examples/biomineralization/material/components/suspendedbiomass.hh>

// we include brine-co2 and h2o-co2 binary coefficients
#include <dumux/material/binarycoefficients/brine_co2.hh>
#include <dumux/material/binarycoefficients/h2o_o2.hh>
```


```cpp

#include <dumux/material/fluidsystems/nullparametercache.hh>
#include <dumux/common/exceptions.hh>

#include <assert.h>
```

</details>

### The fluidsystem class
In the BioMinSimpleChemistryFluid fluid system, we define all functions needed to describe the fluids and their properties accounted for in our simulation.
The simplified biogeochemistry biomineralization fluid system requires the CO2 tables and the H2OType as template parameters.
We enter the namespace Dumux. All Dumux functions and classes are in a namespace Dumux, to make sure they don`t clash with symbols from other libraries you may want to use in conjunction with Dumux.

```cpp
namespace Dumux::FluidSystems {

template <class Scalar,
          class CO2Table,
          class H2OType = Components::TabulatedComponent<Components::H2O<Scalar>> >
class BioMinSimpleChemistryFluid
: public Base<Scalar, BioMinSimpleChemistryFluid<Scalar, CO2Table, H2OType> >
{
    using ThisType = BioMinSimpleChemistryFluid<Scalar, CO2Table, H2OType>;
    using Base = Dumux::FluidSystems::Base<Scalar, ThisType>;
    using IdealGas = Dumux::IdealGas<Scalar>;
```


#### Component and phase definitions
With the following function we define what phases and components will be used by the fluid system and define the indices used to distinguish  phases and components in the course of the simulation.

```cpp
public:
    // We use convenient declarations that we derive from the property system
    typedef Components::CO2<Scalar, CO2Table> CO2;
    using H2O = H2OType;
    // export the underlying brine fluid system for the liquid phase, as brine is used as a "pseudo component"
    using Brine = Dumux::FluidSystems::ICPComplexSalinityBrine<Scalar, H2OType>;
    using Na = Components::SodiumIon<Scalar>;
    using Cl = Components::ChlorideIon<Scalar>;
    using Ca = Components::CalciumIon<Scalar>;
    using Urea = Components::Urea<Scalar>;
    using O2 = Components::O2<Scalar>;
    using Glucose = Components::Glucose<Scalar>;
    using SuspendedBiomass = Components::SuspendedBiomass<Scalar>;

    // We define the binary coefficents file, which accounts for the interactions of the main fluids in our setup, water/brine and CO2
    using Brine_CO2 = BinaryCoeff::Brine_CO2<Scalar, CO2Table, true>;

    // the type of parameter cache objects. this fluid system does not
    // cache anything, so it uses Dumux::NullParameterCache
    typedef Dumux::NullParameterCache ParameterCache;

    // We define phase-related indices and properties
    static constexpr int numPhases = 2; // liquid and gas phases
    static constexpr int wPhaseIdx = 0; // index of the liquid phase
    static constexpr int nPhaseIdx = 1; // index of the gas phase
    static constexpr int phase0Idx = wPhaseIdx;
    static constexpr int phase1Idx = nPhaseIdx;

    // the phase names
    static std::string phaseName(int phaseIdx)
    {
        static std::string name[] = {
            "w",
            "n"
        };

        assert(0 <= phaseIdx && phaseIdx < numPhases);
        return name[phaseIdx];
    }

    // We define component-related indices and properties
    static constexpr int numComponents = 9; // H2O, TotalC, Na, Cl, Ca,...
    static constexpr int numSecComponents = 6;

    static constexpr int H2OIdx = 0;
    static constexpr int BrineIdx = 0;
    static constexpr int TCIdx = 1;
    static constexpr int wCompIdx = BrineIdx;
    static constexpr int nCompIdx = TCIdx;
    static constexpr int comp0Idx = wCompIdx;
    static constexpr int comp1Idx = nCompIdx;

    static constexpr int NaIdx  = 2;
    static constexpr int ClIdx  = 3;
    static constexpr int CaIdx  = 4;
    static constexpr int UreaIdx  = 5;
    static constexpr int O2Idx  = 6;
    static constexpr int GlucoseIdx  = 7;
    static constexpr int SuspendedBiomassIdx  = 8;
```


#### The Brine Adapter
With the brine adapter, we link water and the components sodium, chloride, and calcium to form brine, to be able to use the "brine.hh" fluidsystem expecting only water and a single salt.
Here, we define that the components water, sodium, chloride, and calcium contribute to brine.
The real work is done by the adapter "icpcomplexsalinitybrine.hh".

```cpp
private:
    struct BrineAdapterPolicy
    {
        using FluidSystem = Brine;

        static constexpr int phaseIdx(int brinePhaseIdx) { return wPhaseIdx; }
        static constexpr int compIdx(int brineCompIdx)
        {
            switch (brineCompIdx)
            {
                assert(brineCompIdx == Brine::H2OIdx
                        || brineCompIdx == Brine::NaIdx
                        || brineCompIdx == Brine::ClIdx
                        || brineCompIdx == Brine::CaIdx
                      );
                case Brine::H2OIdx: return H2OIdx;
                case Brine::NaIdx: return NaIdx;
                case Brine::ClIdx: return ClIdx;
                case Brine::CaIdx: return CaIdx;
                default: return 0; // this will never be reached, only needed to suppress compiler warning
            }
        }
    };

    template<class FluidState>
    using BrineAdapter = FluidStateAdapter<FluidState, BrineAdapterPolicy>;
```

#### Initializing the fluid system

```cpp
public:
    static void init()
    {
        init(/*startTemp=*/275.15, /*endTemp=*/455.15, /*tempSteps=*/30,
             /*startPressure=*/1e4, /*endPressure=*/99e6, /*pressureSteps=*/500);
    }
    static void init(Scalar startTemp, Scalar endTemp, int tempSteps,
                     Scalar startPressure, Scalar endPressure, int pressureSteps)
    {
        std::cout << "Initializing tables for the pure-water properties.\n";
        H2O::init(startTemp, endTemp, tempSteps,
                            startPressure, endPressure, pressureSteps);
     }
```

#### The Component-Phase Interactions
In the following, we define the component-phase interactions such as // each component's fugacity coefficient in each phase
and each component's and the phases' main components binary diffusion coefficient in the respective phase.

```cpp
    // The component fugacity coefficients
    template <class FluidState>
    static Scalar fugacityCoefficient(const FluidState &fluidState,
                                      const ParameterCache &paramCache,
                                      int phaseIdx,
                                      int compIdx)
    {
        assert(0 <= phaseIdx && phaseIdx < numPhases);
        assert(0 <= compIdx && compIdx < numComponents);

        if (phaseIdx == nPhaseIdx)
            // use the fugacity coefficients of an ideal gas. the
            // actual value of the fugacity is not relevant, as long
            // as the relative fluid compositions are observed,
            return 1.0;

        Scalar temperature = fluidState.temperature(phaseIdx);
        Scalar pressure = fluidState.pressure(phaseIdx);
        if (pressure<0)
        {
            typedef Dune::FieldVector<Scalar, numComponents> ComponentVector;
            ComponentVector moleFractionsw;
            ComponentVector massFractionsw;

            for (int compIdx = 0; compIdx<numComponents;++compIdx)
            {
                moleFractionsw[compIdx] = fluidState.moleFraction(wPhaseIdx,compIdx);
                massFractionsw[compIdx] = fluidState.massFraction(wPhaseIdx,compIdx);
            }
        }

        assert(temperature > 0);
        assert(pressure > 0);

        // calulate the equilibrium composition for the given
        // temperature and pressure.
        Scalar xgH2O, xlH2O;
        Scalar xlCO2, xgCO2;
        Scalar Xl_Sal =    fluidState.massFraction(wPhaseIdx, NaIdx)                    //Salinity= XNa+XCl+XCa
                        + fluidState.massFraction(wPhaseIdx, ClIdx)
                        + fluidState.massFraction(wPhaseIdx, CaIdx);
        Brine_CO2::calculateMoleFractions(temperature,
                                          pressure,
                                          Xl_Sal,
                                          /*knownPhaseIdx=*/ -1,
                                          xlCO2,
                                          xgH2O);

        xlCO2 = std::max(0.0, std::min(1.0, xlCO2));
        xgH2O = std::max(0.0, std::min(1.0, xgH2O));
        xlH2O = 1.0 - xlCO2;
        xgCO2 = 1.0 - xgH2O;

        // Only H2O, CO2, and O2 in the gas phase
        if (compIdx == BrineIdx) {
            Scalar phigH2O = 1.0;
            return phigH2O * xgH2O / xlH2O;
        }
        else if (compIdx == TCIdx)
        {
            Scalar phigCO2 = 1.0;
            return phigCO2 * xgCO2 / xlCO2;
        }
        else if (compIdx == O2Idx)
        {
            return Dumux::BinaryCoeff::H2O_O2::henry(temperature)/pressure;
        }
        // All other components are assumed not be present in the gas phase
        else
        {
            return 1e-20;
        }
    }

    template <class FluidState>
    static Scalar diffusionCoefficient(const FluidState &fluidState,
                                       const ParameterCache &paramCache,
                                       int phaseIdx,
                                       int compIdx)
    {
        DUNE_THROW(Dune::NotImplemented, "Diffusion coefficients");
    }

    // The binary diffusion coefficients of the components and the phases main component
    template <class FluidState>
    static Scalar binaryDiffusionCoefficient(const FluidState &fluidState,
                                             const ParameterCache &paramCache,
                                             int phaseIdx,
                                             int compIIdx,
                                             int compJIdx)
    {
        assert(0 <= phaseIdx && phaseIdx < numPhases);
        assert(0 <= compIIdx && compIIdx < numComponents);
        assert(0 <= compJIdx && compJIdx < numComponents);

       const Scalar temperature = fluidState.temperature(phaseIdx);
       const Scalar pressure = fluidState.pressure(phaseIdx);

        if (phaseIdx == wPhaseIdx)
        {
            assert(compIIdx == H2OIdx);
            if (compJIdx == TCIdx)
                return Brine_CO2::liquidDiffCoeff(temperature, pressure);
            else if(compJIdx == O2Idx)
                return Dumux::BinaryCoeff::H2O_O2::liquidDiffCoeff(temperature, pressure);
            else //all other components
                return 1.587e-9;  //[m²/s]    //J. Phys. D: Appl. Phys. 40 (2007) 2769-2776 //old Value from Anozie 1e-9
        }
        else
        {
            assert(phaseIdx == nPhaseIdx);
            assert(compIIdx == TCIdx);
            if (compJIdx == H2OIdx)
                return Brine_CO2::gasDiffCoeff(temperature, pressure);
            else if (compJIdx == O2Idx)
                return Dumux::BinaryCoeff::H2O_O2::gasDiffCoeff(temperature, pressure);
            else //all other components
                return 0.0;
        }
    }
```

#### The Fluid Properties
In the following, all functions defining the phase properties are given:
the density, viscosity, enthalpy, thermal conductivities, and heat capacities
of each phase depending on temperature, pressure, and phase composition

```cpp
    // The phase density of the liquid phase is calculated accounting for the impact of solutes in the brine as well as the contribution of CO2.
    // For the gas phase, a mixture of water and CO2 is considered, as solutes do not partition into the gas phase.
    template <class FluidState>
    static Scalar density(const FluidState &fluidState,
                          const ParameterCache &paramCache,
                          int phaseIdx)
    {
        assert(0 <= phaseIdx && phaseIdx < numPhases);

        const Scalar T = fluidState.temperature(phaseIdx);

        if (phaseIdx == wPhaseIdx)
        {
            const Scalar pl = fluidState.pressure(phaseIdx);
            const Scalar xlCO2 = fluidState.moleFraction(wPhaseIdx, TCIdx);
            const Scalar xlH2O = fluidState.moleFraction(wPhaseIdx, H2OIdx);
            if(T < 273.15) {
                DUNE_THROW(NumericalProblem,
                        "Liquid density for Brine and CO2 is only "
                        "defined above 273.15K (is" << T << ")");
            }
            if(pl >= 2.5e8) {
            DUNE_THROW(NumericalProblem,
                       "Liquid density for Brine and CO2 is only "
                       "defined below 250MPa (is" << pl << ")");
            }

            // calling the brine adapter for brine density
            Scalar rho_brine = Brine::molarDensity(BrineAdapter<FluidState>(fluidState), Brine::liquidPhaseIdx)
                       *(H2O::molarMass()*fluidState.moleFraction(wPhaseIdx, H2OIdx)
                         + Na::molarMass()*fluidState.moleFraction(wPhaseIdx, NaIdx)
                         + Cl::molarMass()*fluidState.moleFraction(wPhaseIdx, ClIdx)
                         + Ca::molarMass()*fluidState.moleFraction(wPhaseIdx, CaIdx)
                        );
            // the density of pure water
            Scalar rho_pure = H2O::liquidDensity(T, pl);
            //we also use a private helper function to calculate the liquid density of the same amount of CO2 in pure water
            Scalar rho_lCO2 = liquidDensityWaterCO2_(T, pl, xlH2O, xlCO2);
            // calculating the density contribution of CO2 in pure water
            Scalar contribCO2 = rho_lCO2 - rho_pure;
            // assuming CO2 increases the density for brine by the same amount as for pure water
            return rho_brine + contribCO2;
        }

        else if (phaseIdx == nPhaseIdx)
            return H2O::gasDensity(T, fluidState.partialPressure(nPhaseIdx, H2OIdx))
                   + CO2::gasDensity(T, fluidState.partialPressure(nPhaseIdx, TCIdx));
        else
            DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx);
    }

    // The phase molar density of the liquid phase is assumed to not change significantly from the molar density of the pure brine.
    // For the gas phase, a mixture of water and CO2 is considered, as solutes do not partition into the gas phase.
    using Base::molarDensity;
    template <class FluidState>
    static Scalar molarDensity(const FluidState& fluidState, int phaseIdx)
    {
        if (phaseIdx == wPhaseIdx)
            return Brine::molarDensity(BrineAdapter<FluidState>(fluidState), Brine::liquidPhaseIdx);
        else if (phaseIdx == nPhaseIdx)
            return H2O::gasMolarDensity(fluidState.temperature(phaseIdx),
                                        fluidState.partialPressure(phaseIdx, H2OIdx))
                   + CO2::gasMolarDensity(fluidState.temperature(phaseIdx),
                                          fluidState.partialPressure(phaseIdx, TCIdx));
        else
            DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx);
    }

    // The phase viscosities are assumed to not change significantly from those of the pure brine for the liquid and pure CO2 for the gas phase
    using Base::viscosity;
    template <class FluidState>
    static Scalar viscosity(const FluidState& fluidState, int phaseIdx)
    {
        assert(0 <= phaseIdx && phaseIdx < numPhases);

        if (phaseIdx == wPhaseIdx)
            return Brine::viscosity(BrineAdapter<FluidState>(fluidState), Brine::liquidPhaseIdx);
        else if (phaseIdx == nPhaseIdx)
        {
            return CO2::gasViscosity(fluidState.temperature(phaseIdx), fluidState.pressure(phaseIdx));
        }
        else
            DUNE_THROW(Dune::InvalidStateException, "Invalid phase index " << phaseIdx);

    }
```


</details>



## The brine adapter (`icpcomplexsalinitybrine.hh`)

This file contains the brineadapter class__ which defines
how to adapt values for communication between
the "full" fluidsystem accounting for 4 components influencing the brine properties
and the "brine" fluidsystem assuming water and a single salt determining the brine properties.


<details open>
<summary><b>Click to hide/show the file documentation</b> (or inspect the [source code](../material/fluidsystems/icpcomplexsalinitybrine.hh))</summary>


### Include files
<details><summary> Click to show includes</summary>
we include all necessary components

```cpp
#include <dune/common/math.hh>

#include <dumux/material/fluidsystems/base.hh>
#include <dumux/material/constants.hh>
#include <dumux/material/components/h2o.hh>
#include <dumux/material/components/sodiumion.hh>
#include <dumux/material/components/chlorideion.hh>
#include <dumux/material/components/calciumion.hh>
#include <dumux/material/components/tabulatedcomponent.hh>

#include <dumux/common/exceptions.hh>

#include <dumux/io/name.hh>
```

</details>

### The brine adapter class
In ICPComplexSalinityBrine we make the transition from 3 components additional to water contributing to salinity to the single component that is assumed in the brine fluid system.
We enter the namespace Dumux. All Dumux functions and classes are in a namespace Dumux, to make sure they don`t clash with symbols from other libraries you may want to use in conjunction with Dumux.

```cpp
namespace Dumux::FluidSystems {

template< class Scalar, class H2OType = Components::TabulatedComponent<Dumux::Components::H2O<Scalar>> >
class ICPComplexSalinityBrine : public Base< Scalar, ICPComplexSalinityBrine<Scalar, H2OType>>
{
    using ThisType = ICPComplexSalinityBrine<Scalar, H2OType>;
    using Base = Dumux::FluidSystems::Base<Scalar, ThisType>;

public:
    //! export the involved components
    using H2O = H2OType;
    using Na = Components::SodiumIon<Scalar>;
    using Cl = Components::ChlorideIon<Scalar>;
    using Ca = Components::CalciumIon<Scalar>;
```


#### Component and phase definitions
With the following function we define what phases and components will be used by the fluid system and define the indices used to distinguish  phases and components in the course of the simulation.

```cpp
    // We use convenient declarations that we derive from the property system.
    static constexpr int numPhases = 1;     //!< Number of phases in the fluid system
    static constexpr int numComponents = 4; //!< Number of components in the fluid system (H2O, Na, Cl, Ca)

    static constexpr int phase0Idx = 0; //!< Index of the first (and only) phase
    static constexpr int liquidPhaseIdx = phase0Idx; //!< The one considered phase is liquid

    static constexpr int H2OIdx = 0;         //!< index of the water component
    static constexpr int NaIdx = 1;        //!< index of the Na component
    static constexpr int ClIdx = 2;        //!< index of the Cl component
    static constexpr int CaIdx = 3;        //!< index of the Ca component
    static constexpr int comp0Idx = H2OIdx;  //!< index of the first component
    static constexpr int comp1Idx = NaIdx; //!< index of the second component
    static constexpr int comp2Idx = ClIdx; //!< index of the third component
    static constexpr int comp3Idx = CaIdx; //!< index of the fourth component

    // the fluid phase index
    static std::string phaseName(int phaseIdx = liquidPhaseIdx)
    {
        assert(phaseIdx == liquidPhaseIdx);
        return IOName::liquidPhase();
    }

    // the miscibility
    static constexpr bool isMiscible()
    {
        return false;
    }

    // we do not have a gas phase
    static constexpr bool isGas(int phaseIdx = liquidPhaseIdx)
    {
        assert(phaseIdx == liquidPhaseIdx);
        return false;
    }

    // We need a ideal mixture
    static constexpr bool isIdealMixture(int phaseIdx = liquidPhaseIdx)
    {
        assert(phaseIdx == liquidPhaseIdx);
        return true;
    }

    // phase compressibility
    static constexpr bool isCompressible(int phaseIdx = liquidPhaseIdx)
    {
        assert(phaseIdx == liquidPhaseIdx);
        return H2O::liquidIsCompressible();
    }

    // no gas, thus no ideal gas
    static constexpr bool isIdealGas(int phaseIdx = liquidPhaseIdx)
    {
        assert(phaseIdx == liquidPhaseIdx);
        return false; /*we're a liquid!*/
    }
```


#### The Component-Phase Interactions
In the following, we define the component-phase interactions such as // each component's fugacity coefficient in brine
and each component's binary diffusion coefficient with water in brine

```cpp
    // The component fugacity coefficients
    template <class FluidState>
    static Scalar fugacityCoefficient(const FluidState &fluidState,
                                      int phaseIdx,
                                      int compIdx)
    {
        assert(0 <= phaseIdx  && phaseIdx < numPhases);
        assert(0 <= compIdx  && compIdx < numComponents);

        if (phaseIdx == compIdx)
            // We could calculate the real fugacity coefficient of
            // the component in the fluid. Probably that's not worth
            // the effort, since the fugacity coefficient of the other
            // component is infinite anyway...
            return 1.0;
        return std::numeric_limits<Scalar>::infinity();
    }

    // The binary diffusion coefficients of the components and the phases main component
    template <class FluidState>
    static Scalar binaryDiffusionCoefficient(const FluidState& fluidState,
                                             int phaseIdx,
                                             int compIIdx,
                                             int compJIdx)
    {
        if (phaseIdx == liquidPhaseIdx)
        {
            if (compIIdx > compJIdx)
            {
                using std::swap;
                swap(compIIdx, compJIdx);
            }
            if (compJIdx == NaIdx || compJIdx == ClIdx || compJIdx == CaIdx)
                return 1.587e-9;  //[m²/s]    //J. Phys. D: Appl. Phys. 40 (2007) 2769-2776
            else
                DUNE_THROW(Dune::NotImplemented, "Binary diffusion coefficient of components "
                                                 << compIIdx << " and " << compJIdx
                                                 << " in phase " << phaseIdx);
         }

         DUNE_THROW(Dune::InvalidStateException, "Invalid phase index: " << phaseIdx);
    }
```


#### The Fluid (Brine) Properties
In the following, all functions defining the phase properties are given:
the density, viscosity, enthalpy, thermal conductivities, and heat capacities
of each phase depending on temperature, pressure, and phase composition

```cpp
    // The phase density
    template <class FluidState>
    static Scalar density(const FluidState& fluidState, int phaseIdx = liquidPhaseIdx)
    {
        assert(phaseIdx == liquidPhaseIdx);
        const Scalar temperature = fluidState.temperature(phaseIdx);
        const Scalar pressure = fluidState.pressure(phaseIdx);
        const Scalar xNaCl = fluidState.massFraction(phaseIdx, NaIdx)
                           + fluidState.massFraction(phaseIdx, ClIdx)
                           + fluidState.massFraction(phaseIdx, CaIdx);

        using std::max;
        const Scalar TempC = temperature - 273.15;
        const Scalar pMPa = pressure/1.0E6;
        const Scalar salinity = max(0.0, xNaCl);

        const Scalar rhow = H2O::liquidDensity(temperature, pressure);
        const Scalar density = rhow + 1000*salinity*(0.668 +
                                                     0.44*salinity +
                                                     1.0E-6*(300*pMPa -
                                                             2400*pMPa*salinity +
                                                             TempC*(80.0 +
                                                                    3*TempC -
                                                                    3300*salinity -
                                                                    13*pMPa +
                                                                    47*pMPa*salinity)));
        assert(density > 0.0);
        return density;
    }



    // The phase viscosity
    template <class FluidState>
    static Scalar viscosity(const FluidState& fluidState, int phaseIdx = liquidPhaseIdx)
    {
        assert(phaseIdx == liquidPhaseIdx);
        const Scalar temperature = fluidState.temperature(phaseIdx);
        const Scalar xNaCl = fluidState.massFraction(phaseIdx, NaIdx)
                           + fluidState.massFraction(phaseIdx, ClIdx)
                           + fluidState.massFraction(phaseIdx, CaIdx);

        using std::pow;
        using Dune::power;
        using std::exp;
        using std::max;
        const Scalar T = max(temperature, 275.0);
        const Scalar salinity = max(0.0, xNaCl);

        const Scalar T_C = T - 273.15;
        const Scalar A = ((0.42*power((pow(salinity, 0.8)-0.17), 2)) + 0.045)*pow(T_C, 0.8);
        const Scalar mu_brine = 0.1 + (0.333*salinity) + (1.65+(91.9*salinity*salinity*salinity))*exp(-A); // [cP]
        assert(mu_brine > 0.0);
        return mu_brine/1000.0; // [Pa·s]
    }
```


</details>


| [:arrow_left: Back to the main documentation](../README.md) | [:arrow_left: Go back to part 3](setup.md) | [:arrow_right: Continue with part 5](solidmaterial.md) |
|---|---|---:|

