diff --git a/Documentation/ProjectFile/properties/property/t_IdealGasLawBinaryMixture.md b/Documentation/ProjectFile/properties/property/t_IdealGasLawBinaryMixture.md
new file mode 100644
index 0000000000000000000000000000000000000000..a66be060fca297dbcfc79b3840760efb14d8669f
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/t_IdealGasLawBinaryMixture.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::IdealGasLawBinaryMixture
diff --git a/MaterialLib/MPL/CreateProperty.cpp b/MaterialLib/MPL/CreateProperty.cpp
index 7ca90c0f3600c0bfe4a64eba69fc3306a3081821..df6d8372b08e948f970557541f52234d57a9ede5 100644
--- a/MaterialLib/MPL/CreateProperty.cpp
+++ b/MaterialLib/MPL/CreateProperty.cpp
@@ -93,6 +93,11 @@ std::unique_ptr<MaterialPropertyLib::Property> createProperty(
         return createIdealGasLaw(config);
     }
 
+    if (boost::iequals(property_type, "IdealGasLawBinaryMixture"))
+    {
+        return createIdealGasLawBinaryMixture(config);
+    }
+
     if (boost::iequals(property_type, "StrainDependentPermeability"))
     {
         return createStrainDependentPermeability(
diff --git a/MaterialLib/MPL/Properties/CreateIdealGasLawBinaryMixture.cpp b/MaterialLib/MPL/Properties/CreateIdealGasLawBinaryMixture.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..14349de233bca5c0dce3b915ca975241258f12cc
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateIdealGasLawBinaryMixture.cpp
@@ -0,0 +1,34 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Jan, 2021
+ *
+ * \copyright
+ * Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#include "BaseLib/ConfigTree.h"
+#include "IdealGasLawBinaryMixture.h"
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<IdealGasLawBinaryMixture> createIdealGasLawBinaryMixture(
+    BaseLib::ConfigTree const& config)
+{
+    //! \ogs_file_param{properties__property__type}
+    config.checkConfigParameter("type", "IdealGasLawBinaryMixture");
+
+    // Second access for storage.
+    //! \ogs_file_param{properties__property__name}
+    auto property_name = config.peekConfigParameter<std::string>("name");
+
+    DBUG("Create IdealGasLawBinaryMixture medium property {:s}.",
+         property_name);
+
+    //! \ogs_file_param_special{properties__property__IdealGasLawBinaryMixture}
+    return std::make_unique<IdealGasLawBinaryMixture>(std::move(property_name));
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/CreateIdealGasLawBinaryMixture.h b/MaterialLib/MPL/Properties/CreateIdealGasLawBinaryMixture.h
new file mode 100644
index 0000000000000000000000000000000000000000..2faea27d056c6d99e0e3860431c36d92f7f637a1
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateIdealGasLawBinaryMixture.h
@@ -0,0 +1,31 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Jan, 2021
+ *
+ * \copyright
+ * Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ */
+
+#pragma once
+
+#include <memory>
+
+namespace BaseLib
+{
+class ConfigTree;
+}
+
+namespace MaterialPropertyLib
+{
+class IdealGasLawBinaryMixture;
+}
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<IdealGasLawBinaryMixture> createIdealGasLawBinaryMixture(
+    BaseLib::ConfigTree const& config);
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/CreateProperties.h b/MaterialLib/MPL/Properties/CreateProperties.h
index 71d1974f9cf125b138cbef86fab3e354f8f2826a..fbf83202de93fd6a05292f607af916bc505ff687 100644
--- a/MaterialLib/MPL/Properties/CreateProperties.h
+++ b/MaterialLib/MPL/Properties/CreateProperties.h
@@ -30,6 +30,7 @@
 #include "CreateFunction.h"
 #include "CreateGasPressureDependentPermeability.h"
 #include "CreateIdealGasLaw.h"
+#include "CreateIdealGasLawBinaryMixture.h"
 #include "CreateKozenyCarmanModel.h"
 #include "CreateLinear.h"
 #include "CreateOrthotropicEmbeddedFracturePermeability.h"
diff --git a/MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.cpp b/MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..00983323508a88d9812f3d70a6af64734bfc1daf
--- /dev/null
+++ b/MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.cpp
@@ -0,0 +1,146 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Jan, 2021
+ * \brief
+ *
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.h"
+
+#include "MaterialLib/PhysicalConstant.h"
+
+namespace MaterialPropertyLib
+{
+IdealGasLawBinaryMixture::IdealGasLawBinaryMixture(std::string name)
+{
+    name_ = std::move(name);
+}
+
+// Enums with indices for the sorting of the partial density and its derivatives
+// in the result vector or the result tensor of the functions value and dValue.
+enum class VariableIndex : int
+{
+    gas_pressure,
+    capillary_pressure,
+    temperature
+};
+enum class DensityIndex : int
+{
+    gas_phase_density,
+    vapour_density,
+    air_density
+};
+
+PropertyDataType IdealGasLawBinaryMixture::value(
+    VariableArray const& variable_array,
+    ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/,
+    double const /*dt*/) const
+{
+    const double R = MaterialLib::PhysicalConstant::IdealGasConstant;
+    const double pGR = std::get<double>(
+        variable_array[static_cast<int>(Variable::phase_pressure)]);
+    const double T = std::get<double>(
+        variable_array[static_cast<int>(Variable::temperature)]);
+    const double MW = std::get<double>(
+        variable_array[static_cast<int>(Variable::molar_mass_vapour)]);
+    const double MC = std::get<double>(
+        variable_array[static_cast<int>(Variable::molar_mass)]);
+    // mole fraction of the vapour component
+    const double xnWG = std::get<double>(
+        variable_array[static_cast<int>(Variable::molar_fraction)]);
+    const double xnCG = 1. - xnWG;
+
+    const double rhoWGR = xnWG * pGR * MW / R / T;
+    const double rhoCGR = xnCG * pGR * MC / R / T;
+    Eigen::Matrix<double, 3, 1> result;
+
+    result[static_cast<int>(DensityIndex::vapour_density)] = rhoWGR;
+    result[static_cast<int>(DensityIndex::air_density)] = rhoCGR;
+    result[static_cast<int>(DensityIndex::gas_phase_density)] = rhoWGR + rhoCGR;
+
+    return result;
+}
+
+PropertyDataType IdealGasLawBinaryMixture::dValue(
+    VariableArray const& variable_array, Variable const /*primary_variable*/,
+    ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/,
+    double const /*dt*/) const
+{
+    const double R = MaterialLib::PhysicalConstant::IdealGasConstant;
+    const double pGR = std::get<double>(
+        variable_array[static_cast<int>(Variable::phase_pressure)]);
+    const double T = std::get<double>(
+        variable_array[static_cast<int>(Variable::temperature)]);
+    const double MW = std::get<double>(
+        variable_array[static_cast<int>(Variable::molar_mass_vapour)]);
+    const double MC = std::get<double>(
+        variable_array[static_cast<int>(Variable::molar_mass)]);
+    // mole fraction of the vapour component
+    const double xnWG = std::get<double>(
+        variable_array[static_cast<int>(Variable::molar_fraction)]);
+    const double xnCG = 1. - xnWG;
+    const double dxnWG_dpGR =
+        std::get<double>(variable_array[static_cast<int>(Variable::dxn_dpGR)]);
+    const double dxnWG_dpCap =
+        std::get<double>(variable_array[static_cast<int>(Variable::dxn_dpCap)]);
+    const double dxnWG_dT =
+        std::get<double>(variable_array[static_cast<int>(Variable::dxn_dT)]);
+
+    Eigen::Matrix<double, 3, 3> result;
+
+    const double drhoCGR_dpGR = -MC / R / T * (pGR * dxnWG_dpGR - xnCG);
+    const double drhoCGR_dpCap = -pGR * MC / R / T * dxnWG_dpCap;
+    const double drhoCGR_dT = -pGR * MC / R / T * (dxnWG_dT + xnCG / T);
+
+    const double drhoWGR_dpGR = MW / R / T * (pGR * dxnWG_dpGR + xnWG);
+    const double drhoWGR_dpCap = pGR * MW / R / T * dxnWG_dpCap;
+    const double drhoWGR_dT = pGR * MW / R / T / T * (T * dxnWG_dT - xnWG);
+
+    const double drhoGR_dpGR = drhoCGR_dpGR + drhoWGR_dpGR;
+    const double drhoGR_dpCap = drhoCGR_dpCap + drhoWGR_dpCap;
+    const double drhoGR_dT = drhoCGR_dT + drhoWGR_dT;
+
+    result(static_cast<int>(DensityIndex::air_density),
+           static_cast<int>(VariableIndex::gas_pressure)) = drhoCGR_dpGR;
+    result(static_cast<int>(DensityIndex::air_density),
+           static_cast<int>(VariableIndex::capillary_pressure)) = drhoCGR_dpCap;
+    result(static_cast<int>(DensityIndex::air_density),
+           static_cast<int>(VariableIndex::temperature)) = drhoCGR_dT;
+
+    result(static_cast<int>(DensityIndex::vapour_density),
+           static_cast<int>(VariableIndex::gas_pressure)) = drhoWGR_dpGR;
+    result(static_cast<int>(DensityIndex::vapour_density),
+           static_cast<int>(VariableIndex::capillary_pressure)) = drhoWGR_dpCap;
+    result(static_cast<int>(DensityIndex::vapour_density),
+           static_cast<int>(VariableIndex::temperature)) = drhoWGR_dT;
+
+    result(static_cast<int>(DensityIndex::gas_phase_density),
+           static_cast<int>(VariableIndex::gas_pressure)) = drhoGR_dpGR;
+    result(static_cast<int>(DensityIndex::gas_phase_density),
+           static_cast<int>(VariableIndex::capillary_pressure)) = drhoGR_dpCap;
+    result(static_cast<int>(DensityIndex::gas_phase_density),
+           static_cast<int>(VariableIndex::temperature)) = drhoGR_dT;
+
+    return result;
+}
+
+PropertyDataType IdealGasLawBinaryMixture::d2Value(
+    VariableArray const& /*variable_array*/,
+    Variable const /*primary_variable1*/, Variable const /*primary_variable2*/,
+    ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/,
+    double const /*dt*/) const
+{
+    OGS_FATAL("IdealGasLawBinaryMixture::d2Value is not implemented.");
+
+    return 0.;
+}
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.h b/MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.h
new file mode 100644
index 0000000000000000000000000000000000000000..220729724e7ee214df4cc4c0a49b7e936058c8bd
--- /dev/null
+++ b/MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.h
@@ -0,0 +1,62 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Jan, 2021
+ * \brief
+ *
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+#pragma once
+
+#include "BaseLib/ConfigTree.h"
+#include "MaterialLib/MPL/Property.h"
+
+namespace MaterialPropertyLib
+{
+class Phase;
+/**
+ * \brief Density function for binary ideal gases.
+ * \details This property must be a phase property, it
+ * computes the density of a mixture of ideal gases as function of phase
+ * pressure, capillary pressure, and temperature.
+ */
+class IdealGasLawBinaryMixture final : public Property
+{
+public:
+    explicit IdealGasLawBinaryMixture(std::string name);
+
+    void checkScale() const override
+    {
+        if (!std::holds_alternative<Phase*>(scale_))
+        {
+            OGS_FATAL(
+                "The property 'IdealGasLawBinaryMixture' is implemented on the "
+                "'phase' scale only.");
+        }
+    }
+
+    /// Those methods override the base class implementations and
+    /// actually compute and set the property values_ and dValues_.
+    PropertyDataType value(VariableArray const& variable_array,
+                           ParameterLib::SpatialPosition const& /*pos*/,
+                           double const /*t*/,
+                           double const /*dt*/) const override;
+    PropertyDataType dValue(VariableArray const& variable_array,
+                            Variable const variable,
+                            ParameterLib::SpatialPosition const& /*pos*/,
+                            double const /*t*/,
+                            double const /*dt*/) const override;
+    PropertyDataType d2Value(VariableArray const& variable_array,
+                             Variable const variable1, Variable const variable2,
+                             ParameterLib::SpatialPosition const& /*pos*/,
+                             double const /*t*/,
+                             double const /*dt*/) const override;
+};
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/Properties.h b/MaterialLib/MPL/Properties/Properties.h
index 52e41f7bf25b91020964e084a6987fcaa719bf6f..da771ea6d3116e3facdc81dfcc67b897e5913495 100644
--- a/MaterialLib/MPL/Properties/Properties.h
+++ b/MaterialLib/MPL/Properties/Properties.h
@@ -31,6 +31,7 @@
 #include "Function.h"
 #include "GasPressureDependentPermeability.h"
 #include "IdealGasLaw.h"
+#include "IdealGasLawBinaryMixture.h"
 #include "Linear.h"
 #include "OrthotropicEmbeddedFracturePermeability.h"
 #include "Parameter.h"
diff --git a/MaterialLib/MPL/VariableType.h b/MaterialLib/MPL/VariableType.h
index c1288ab742adb6db5105ee95d45511487741d1e7..316196d2251f7dfd42bf2c90f347a808a8ff266b 100644
--- a/MaterialLib/MPL/VariableType.h
+++ b/MaterialLib/MPL/VariableType.h
@@ -47,6 +47,9 @@ enum class Variable : int
     concentration,
     density,
     displacement,
+    dxn_dT,     // xn - molar fraction
+    dxn_dpGR,   // derivatives w.r.t. temperature, gas pressure, and
+    dxn_dpCap,  // capillary pressure
     effective_pore_pressure,
     enthalpy_of_evaporation,
     equivalent_plastic_strain,
@@ -55,6 +58,7 @@ enum class Variable : int
     liquid_saturation,
     mechanical_strain,
     molar_mass,
+    molar_mass_vapour,
     molar_fraction,
     phase_pressure,
     porosity,
@@ -74,6 +78,9 @@ static const std::array<std::string,
     variable_enum_to_string{{"capillary_pressure",
                              "concentration",
                              "density",
+                             "dxn_dT",
+                             "dxn_dpGR",
+                             "dxn_dpCap",
                              "displacement",
                              "effective_pore_pressure",
                              "enthalpy_of_evaporation",
@@ -83,6 +90,7 @@ static const std::array<std::string,
                              "liquid_saturation",
                              "mechanical_strain",
                              "molar_mass",
+                             "molar_mass_vapour",
                              "molar_fraction",
                              "phase_pressure",
                              "porosity",
diff --git a/Tests/MaterialLib/TestMPLIdealGasLawBinaryMixture.cpp b/Tests/MaterialLib/TestMPLIdealGasLawBinaryMixture.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b8c1640baef4d08410371d4fab8784f55d9ac7ab
--- /dev/null
+++ b/Tests/MaterialLib/TestMPLIdealGasLawBinaryMixture.cpp
@@ -0,0 +1,268 @@
+/**
+ * \file
+ *
+ * \copyright
+ * Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+#include <gtest/gtest.h>
+
+#include "MaterialLib/MPL/Properties/IdealGasLawBinaryMixture.h"
+#include "MaterialLib/PhysicalConstant.h"
+#include "TestMPL.h"
+#include "Tests/TestTools.h"
+
+double molarFractionFantasy(const double pGR, const double pGR_min,
+                            const double pGR_max, const double pCap,
+                            const double pCap_min, const double pCap_max,
+                            const double T, const double T_min,
+                            const double T_max)
+{
+    auto const dpGR = pGR_max - pGR_min;
+    auto const dpCap = pCap_max - pCap_min;
+    auto const dT = T_max - T_min;
+
+    auto const a = 1. / (6. * std::pow(dpGR, 2.));
+    auto const b = 1. / (6. * dpGR);
+    auto const c = 1. / (6. * std::pow(dpCap, 2.));
+    auto const d = 1. / (6. * (dpCap));
+    auto const e = 1. / (6. * std::pow(dT, 2.));
+    auto const f = 1. / (6. * (dT));
+
+    return a * (pGR - pGR_min) * (pGR - pGR_min) + b * (pGR - pGR_min) +
+           c * (pCap - pCap_min) * (pCap - pCap_min) + d * (pCap - pCap_min) +
+           e * (T - T_min) * (T - T_min) + f * (T - T_min);
+}
+
+std::array<double, 3> molarMassFantasyDerivatives(
+    const double pGR, const double pGR_min, const double pGR_max,
+    const double pCap, const double pCap_min, const double pCap_max,
+    const double T, const double T_min, const double T_max)
+{
+    auto const dpGR = pGR_max - pGR_min;
+    auto const dpCap = pCap_max - pCap_min;
+    auto const dT = T_max - T_min;
+
+    auto const a = 1. / (6. * std::pow(dpGR, 2.));
+    auto const b = 1. / (6. * dpGR);
+    auto const c = 1. / (6. * std::pow(dpCap, 2.));
+    auto const d = 1. / (6. * (dpCap));
+    auto const e = 1. / (6. * std::pow(dT, 2.));
+    auto const f = 1. / (6. * (dT));
+
+    const double d_dpGR = 2 * a * (pGR - pGR_min) + b;
+    const double d_dpCap = 2 * c * (pCap - pCap_min) + d;
+    const double d_dT = 2 * e * (T - T_min) + f;
+
+    return {d_dpGR, d_dpCap, d_dT};
+}
+
+TEST(MaterialPropertyLib, IdealGasLawBinaryMixture)
+{
+    const double MC = 0.028949;
+    const double MW = 0.018052;
+
+    auto const density_model = MPL::IdealGasLawBinaryMixture("density");
+
+    enum
+    {
+        gas_pressure,
+        capillary_pressure,
+        temperature
+    };
+    enum
+    {
+        gas_phase_density,
+        vapour_density,
+        air_density
+    };
+
+    ParameterLib::SpatialPosition const pos;
+    double const t = std::numeric_limits<double>::quiet_NaN();
+    double const dt = std::numeric_limits<double>::quiet_NaN();
+    MPL::VariableArray vars;
+
+    vars[static_cast<int>(MPL::Variable::molar_mass_vapour)] = MW;
+    vars[static_cast<int>(MPL::Variable::molar_mass)] = MC;
+
+    // Density derivatives of gases are dependent on pressure and temperature.
+    // In the case of binary gases, there is also the dependence of the
+    // composition (e.g. molar fractions).
+
+    // The molar fraction of the vapour component in the gas phase is
+    // represented here by a fantasy function. In Reality, this is actually a
+    // physical quantity that depends on the temperature-dependent vapour
+    // pressure, the capillary pressure-dependent correction factor for curved
+    // menisci and the pressure of the gas phase.
+
+    // In this test, however, the function is merely a polynomial,
+    // which over the entire parameter space pGR-pCap-T assumes
+    // values in the range [0,1].
+
+    // Boundaries of the parameter space
+    auto const pGR_min = 80000.;
+    auto const pGR_max = 320000.;
+    auto const pCap_min = 100.;
+    auto const pCap_max = 1.e8;
+    auto const T_min = 270.;
+    auto const T_max = 520.;
+
+    // travel through the entire parameter space
+    for (double pGR = pGR_min; pGR <= pGR_max; pGR += 200.)
+    {
+        for (double pCap = pCap_min; pCap <= pCap_max; pCap *= 2.)
+        {
+            for (double T = T_min; T <= T_max; T += 0.2)
+            {
+                vars[static_cast<int>(MPL::Variable::phase_pressure)] = pGR;
+                vars[static_cast<int>(MPL::Variable::temperature)] = T;
+
+                // Molar fraction fantasy function
+                auto const xnWG =
+                    molarFractionFantasy(pGR, pGR_min, pGR_max, pCap, pCap_min,
+                                         pCap_max, T, T_min, T_max);
+
+                // ... and its derivatives
+                auto const dxnWG = molarMassFantasyDerivatives(
+                    pGR, pGR_min, pGR_max, pCap, pCap_min, pCap_max, T, T_min,
+                    T_max);
+
+                vars[static_cast<int>(MPL::Variable::molar_fraction)] = xnWG;
+                vars[static_cast<int>(MPL::Variable::dxn_dpGR)] =
+                    dxnWG[gas_pressure];
+                vars[static_cast<int>(MPL::Variable::dxn_dpCap)] =
+                    dxnWG[capillary_pressure];
+                vars[static_cast<int>(MPL::Variable::dxn_dT)] =
+                    dxnWG[temperature];
+
+                auto const density = std::get<Eigen::Matrix<double, 3, 1>>(
+                    density_model.value(vars, pos, t, dt));
+
+                auto const rhoGR = density[gas_phase_density];
+                auto const rhoCGR = density[air_density];
+                auto const rhoWGR = density[vapour_density];
+
+                const double R =
+                    MaterialLib::PhysicalConstant::IdealGasConstant;
+
+                auto const rhoCGR_ = (1. - xnWG) * pGR * MC / R / T;
+                auto const rhoWGR_ = xnWG * pGR * MW / R / T;
+                auto const rhoGR_ = rhoCGR_ + rhoWGR_;
+
+                ASSERT_NEAR(rhoGR, rhoGR_, 1.e-18);
+                ASSERT_NEAR(rhoCGR, rhoCGR_, 1.e-18);
+                ASSERT_NEAR(rhoWGR, rhoWGR_, 1.e-18);
+
+                auto const density_derivative =
+                    std::get<Eigen::Matrix<double, 3, 3>>(density_model.dValue(
+                        vars, MPL::Variable::phase_pressure, pos, t, dt));
+
+                // Check derivatives via central differences
+                // Pertubation of gas pressure
+                auto const eps_pGR = 1.;
+
+                auto const pGR_plus = pGR + eps_pGR;
+                auto const xnWG_plus =
+                    molarFractionFantasy(pGR_plus, pGR_min, pGR_max, pCap,
+                                         pCap_min, pCap_max, T, T_min, T_max);
+
+                vars[static_cast<int>(MPL::Variable::phase_pressure)] =
+                    pGR_plus;
+                vars[static_cast<int>(MPL::Variable::molar_fraction)] =
+                    xnWG_plus;
+
+                auto density_plus = std::get<Eigen::Matrix<double, 3, 1>>(
+                    density_model.value(vars, pos, t, dt));
+
+                auto const pGR_minus = pGR - eps_pGR;
+                vars[static_cast<int>(MPL::Variable::phase_pressure)] =
+                    pGR_minus;
+                vars[static_cast<int>(MPL::Variable::molar_fraction)] =
+                    molarFractionFantasy(pGR_minus, pGR_min, pGR_max, pCap,
+                                         pCap_min, pCap_max, T, T_min, T_max);
+
+                auto density_minus = std::get<Eigen::Matrix<double, 3, 1>>(
+                    density_model.value(vars, pos, t, dt));
+
+                for (std::size_t d = gas_phase_density; d <= air_density; d++)
+                {
+                    auto const drho_dpGR =
+                        (density_plus[d] - density_minus[d]) / (2 * eps_pGR);
+
+                    ASSERT_NEAR(drho_dpGR, density_derivative(d, gas_pressure),
+                                1.e-10);
+                }
+
+                // Pertubation of capillary pressure
+                auto const eps_pCap = 1.;
+                auto const pCap_plus = pCap + eps_pCap;
+
+                vars[static_cast<int>(MPL::Variable::phase_pressure)] = pGR;
+                vars[static_cast<int>(MPL::Variable::capillary_pressure)] =
+                    pCap_plus;
+                vars[static_cast<int>(MPL::Variable::molar_fraction)] =
+                    molarFractionFantasy(pGR, pGR_min, pGR_max, pCap_plus,
+                                         pCap_min, pCap_max, T, T_min, T_max);
+
+                density_plus = std::get<Eigen::Matrix<double, 3, 1>>(
+                    density_model.value(vars, pos, t, dt));
+
+                auto const pCap_minus = pCap - eps_pCap;
+                vars[static_cast<int>(MPL::Variable::capillary_pressure)] =
+                    pCap_minus;
+                vars[static_cast<int>(MPL::Variable::molar_fraction)] =
+                    molarFractionFantasy(pGR, pGR_min, pGR_max, pCap_minus,
+                                         pCap_min, pCap_max, T, T_min, T_max);
+
+                density_minus = std::get<Eigen::Matrix<double, 3, 1>>(
+                    density_model.value(vars, pos, t, dt));
+
+                for (std::size_t d = gas_phase_density; d <= air_density; d++)
+                {
+                    auto const drho_dpCap =
+                        (density_plus[d] - density_minus[d]) / (2 * eps_pCap);
+
+                    ASSERT_NEAR(drho_dpCap,
+                                density_derivative(d, capillary_pressure),
+                                1.e-10);
+                }
+
+                // Pertubation of temperature
+                auto const eps_T = 0.01;
+                auto const T_plus = T + eps_T;
+
+                vars[static_cast<int>(MPL::Variable::capillary_pressure)] =
+                    pCap;
+                vars[static_cast<int>(MPL::Variable::temperature)] = T_plus;
+                vars[static_cast<int>(MPL::Variable::molar_fraction)] =
+                    molarFractionFantasy(pGR, pGR_min, pGR_max, pCap, pCap_min,
+                                         pCap_max, T_plus, T_min, T_max);
+
+                density_plus = std::get<Eigen::Matrix<double, 3, 1>>(
+                    density_model.value(vars, pos, t, dt));
+
+                auto const T_minus = T - eps_T;
+                vars[static_cast<int>(MPL::Variable::temperature)] = T_minus;
+                vars[static_cast<int>(MPL::Variable::molar_fraction)] =
+                    molarFractionFantasy(pGR, pGR_min, pGR_max, pCap, pCap_min,
+                                         pCap_max, T_minus, T_min, T_max);
+
+                density_minus = std::get<Eigen::Matrix<double, 3, 1>>(
+                    density_model.value(vars, pos, t, dt));
+
+                for (std::size_t d = gas_phase_density; d <= air_density; d++)
+                {
+                    auto const drho_dT =
+                        (density_plus[d] - density_minus[d]) / (2 * eps_T);
+
+                    ASSERT_NEAR(drho_dT, density_derivative(d, temperature),
+                                1.e-10);
+                }
+
+            }  // end of T-loop
+        }      // end of pCap-loop
+    }          // end of pGR-loop
+}