diff --git a/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/c_RelativePermeabilityVanGenuchten.md b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/c_RelativePermeabilityVanGenuchten.md
new file mode 100644
index 0000000000000000000000000000000000000000..aa3bffae1ae88769d43e7c20296d2fb4788e02ed
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/c_RelativePermeabilityVanGenuchten.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::RelativePermeabilityVanGenuchten
diff --git a/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_exponent.md b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_exponent.md
new file mode 100644
index 0000000000000000000000000000000000000000..0f0ec649ba83f9c2a0c3f7c2889980c807d1edda
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_exponent.md
@@ -0,0 +1 @@
+The exponent of the van Genuchten relative permeability function.
diff --git a/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_minimum_relative_permeability_liquid.md b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_minimum_relative_permeability_liquid.md
new file mode 100644
index 0000000000000000000000000000000000000000..926d443546280f308722c4265ec92e2cf8703deb
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_minimum_relative_permeability_liquid.md
@@ -0,0 +1 @@
+The minimum relative permeability of the liquid (or wetting) phase.
diff --git a/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_residual_gas_saturation.md b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_residual_gas_saturation.md
new file mode 100644
index 0000000000000000000000000000000000000000..d8631eb27f4627345443d3cb426330a84c325db1
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_residual_gas_saturation.md
@@ -0,0 +1 @@
+The smallest degree of saturation of the gas (or non-wetting) phase in the medium.
diff --git a/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_residual_liquid_saturation.md b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_residual_liquid_saturation.md
new file mode 100644
index 0000000000000000000000000000000000000000..95ce0ed4b319db3ecc0cfc87b42c611dcd572210
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/RelativePermeabilityVanGenuchten/t_residual_liquid_saturation.md
@@ -0,0 +1 @@
+The smallest degree of saturation of the liquid (or wetting) phase in the medium.
diff --git a/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/c_SaturationVanGenuchten.md b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/c_SaturationVanGenuchten.md
new file mode 100644
index 0000000000000000000000000000000000000000..2a8f10769050f001e0532878f196e583db65c309
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/c_SaturationVanGenuchten.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::SaturationVanGenuchten
diff --git a/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_entry_pressure.md b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_entry_pressure.md
new file mode 100644
index 0000000000000000000000000000000000000000..e3d246498cefcd2402e2df304f0047534317a04a
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_entry_pressure.md
@@ -0,0 +1 @@
+The required pressure for a non-wetting fluid to enter a porous medium (the capillary pressure at full saturation).
diff --git a/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_exponent.md b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_exponent.md
new file mode 100644
index 0000000000000000000000000000000000000000..260b1dd015e7c9cb8b04a65e4df7587dc81b9224
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_exponent.md
@@ -0,0 +1 @@
+The exponent of the van Genuchten saturation function.
diff --git a/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_residual_gas_saturation.md b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_residual_gas_saturation.md
new file mode 100644
index 0000000000000000000000000000000000000000..d8631eb27f4627345443d3cb426330a84c325db1
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_residual_gas_saturation.md
@@ -0,0 +1 @@
+The smallest degree of saturation of the gas (or non-wetting) phase in the medium.
diff --git a/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_residual_liquid_saturation.md b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_residual_liquid_saturation.md
new file mode 100644
index 0000000000000000000000000000000000000000..95ce0ed4b319db3ecc0cfc87b42c611dcd572210
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/SaturationVanGenuchten/t_residual_liquid_saturation.md
@@ -0,0 +1 @@
+The smallest degree of saturation of the liquid (or wetting) phase in the medium.
diff --git a/MaterialLib/MPL/CreateProperty.cpp b/MaterialLib/MPL/CreateProperty.cpp
index abdb35f6433a1175357f7c93b7b55db84aa27b0d..a31c10b166ab1168cef39dce02bf82324657c490 100644
--- a/MaterialLib/MPL/CreateProperty.cpp
+++ b/MaterialLib/MPL/CreateProperty.cpp
@@ -79,6 +79,16 @@ std::unique_ptr<MaterialPropertyLib::Property> createProperty(
         return createRelPermLiakopoulos(config);
     }
 
+    if (boost::iequals(property_type, "SaturationVanGenuchten"))
+    {
+        return createSaturationVanGenuchten(config);
+    }
+
+    if (boost::iequals(property_type, "RelativePermeabilityVanGenuchten"))
+    {
+        return createRelPermVanGenuchten(config);
+    }
+
     // If none of the above property types are found, OGS throws an error.
     OGS_FATAL("The specified component property type '%s' was not recognized",
               property_type.c_str());
diff --git a/MaterialLib/MPL/Properties/CreateProperties.h b/MaterialLib/MPL/Properties/CreateProperties.h
index ec8c0508cea1e14266fa167df8a53197ebd159c3..db967698b4f1fbdd8e98cbc979e9110818fef046 100644
--- a/MaterialLib/MPL/Properties/CreateProperties.h
+++ b/MaterialLib/MPL/Properties/CreateProperties.h
@@ -18,5 +18,7 @@
 #include "CreateParameterProperty.h"
 #include "CreateRelPermBrooksCorey.h"
 #include "CreateRelPermLiakopoulos.h"
+#include "CreateRelPermVanGenuchten.h"
 #include "CreateSaturationBrooksCorey.h"
-#include "CreateSaturationLiakopoulos.h"
\ No newline at end of file
+#include "CreateSaturationLiakopoulos.h"
+#include "CreateSaturationVanGenuchten.h"
diff --git a/MaterialLib/MPL/Properties/CreateRelPermVanGenuchten.cpp b/MaterialLib/MPL/Properties/CreateRelPermVanGenuchten.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..332f0180abaeda85ff32b179a16746162f505ea8
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateRelPermVanGenuchten.cpp
@@ -0,0 +1,47 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 "RelPermVanGenuchten.h"
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<RelPermVanGenuchten> createRelPermVanGenuchten(
+    BaseLib::ConfigTree const& config)
+{
+    //! \ogs_file_param{properties__property__type}
+    config.checkConfigParameter("type", "RelativePermeabilityVanGenuchten");
+    DBUG("Create RelativePermeabilityVanGenuchten medium property");
+
+    auto const residual_liquid_saturation =
+        //! \ogs_file_param{properties__property__RelativePermeabilityVanGenuchten__residual_liquid_saturation}
+        config.getConfigParameter<double>("residual_liquid_saturation");
+    auto const residual_gas_saturation =
+        //! \ogs_file_param{properties__property__RelativePermeabilityVanGenuchten__residual_gas_saturation}
+        config.getConfigParameter<double>("residual_gas_saturation");
+    auto const min_relative_permeability_liquid =
+        //! \ogs_file_param{properties__property__RelativePermeabilityVanGenuchten__minimum_relative_permeability_liquid}
+        config.getConfigParameter<double>(
+            "minimum_relative_permeability_liquid");
+    auto const exponent =
+        //! \ogs_file_param{properties__property__RelativePermeabilityVanGenuchten__exponent}
+        config.getConfigParameter<double>("exponent");
+    if (exponent <= 0. || exponent >= 1.)
+    {
+        OGS_FATAL("Exponent must be in the (0, 1) range.");
+    }
+
+    return std::make_unique<RelPermVanGenuchten>(
+        residual_liquid_saturation,
+        residual_gas_saturation,
+        min_relative_permeability_liquid,
+        exponent);
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/CreateRelPermVanGenuchten.h b/MaterialLib/MPL/Properties/CreateRelPermVanGenuchten.h
new file mode 100644
index 0000000000000000000000000000000000000000..046b31552bdbcd42fb4e621b1049e815b02d271d
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateRelPermVanGenuchten.h
@@ -0,0 +1,29 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 RelPermVanGenuchten;
+}
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<RelPermVanGenuchten> createRelPermVanGenuchten(
+    BaseLib::ConfigTree const& config);
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/CreateSaturationVanGenuchten.cpp b/MaterialLib/MPL/Properties/CreateSaturationVanGenuchten.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9b77c416906b13e37db49ca627fa1fcb1c7321e5
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateSaturationVanGenuchten.cpp
@@ -0,0 +1,41 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 "SaturationVanGenuchten.h"
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<SaturationVanGenuchten> createSaturationVanGenuchten(
+    BaseLib::ConfigTree const& config)
+{
+    //! \ogs_file_param{properties__property__type}
+    config.checkConfigParameter("type", "SaturationVanGenuchten");
+
+    DBUG("Create SaturationVanGenuchten medium property");
+
+    auto const residual_liquid_saturation =
+        //! \ogs_file_param{properties__property__SaturationVanGenuchten__residual_liquid_saturation}
+        config.getConfigParameter<double>("residual_liquid_saturation");
+    auto const residual_gas_saturation =
+        //! \ogs_file_param{properties__property__SaturationVanGenuchten__residual_gas_saturation}
+        config.getConfigParameter<double>("residual_gas_saturation");
+    auto const exponent =
+        //! \ogs_file_param{properties__property__SaturationVanGenuchten__exponent}
+        config.getConfigParameter<double>("exponent");
+    auto const entry_pressure =
+        //! \ogs_file_param{properties__property__SaturationVanGenuchten__entry_pressure}
+        config.getConfigParameter<double>("entry_pressure");
+
+    return std::make_unique<SaturationVanGenuchten>(residual_liquid_saturation,
+                                                    residual_gas_saturation,
+                                                    exponent, entry_pressure);
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/CreateSaturationVanGenuchten.h b/MaterialLib/MPL/Properties/CreateSaturationVanGenuchten.h
new file mode 100644
index 0000000000000000000000000000000000000000..01ffabffe1a515a902b8e95c663136704b72495b
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateSaturationVanGenuchten.h
@@ -0,0 +1,29 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 SaturationVanGenuchten;
+}
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<SaturationVanGenuchten> createSaturationVanGenuchten(
+    BaseLib::ConfigTree const& config);
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/Properties.h b/MaterialLib/MPL/Properties/Properties.h
index 271a4966fb4c48d575a8b5dc801114c0a9a59892..eab18c0c383aaae33ada9cf9b1c29d4fad3d63da 100644
--- a/MaterialLib/MPL/Properties/Properties.h
+++ b/MaterialLib/MPL/Properties/Properties.h
@@ -18,5 +18,7 @@
 #include "ParameterProperty.h"
 #include "RelPermBrooksCorey.h"
 #include "RelPermLiakopoulos.h"
+#include "RelPermVanGenuchten.h"
 #include "SaturationBrooksCorey.h"
 #include "SaturationLiakopoulos.h"
+#include "SaturationVanGenuchten.h"
diff --git a/MaterialLib/MPL/Properties/RelPermVanGenuchten.cpp b/MaterialLib/MPL/Properties/RelPermVanGenuchten.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..efc74563608b2203de4f4e79d90531c3acdb6a2b
--- /dev/null
+++ b/MaterialLib/MPL/Properties/RelPermVanGenuchten.cpp
@@ -0,0 +1,95 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 "RelPermVanGenuchten.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "MaterialLib/MPL/Medium.h"
+
+namespace MaterialPropertyLib
+{
+RelPermVanGenuchten::RelPermVanGenuchten(
+    double const residual_liquid_saturation,
+    double const residual_gas_saturation,
+    double const min_relative_permeability_liquid,
+    double const exponent)
+    : _S_L_res(residual_liquid_saturation),
+      _S_L_max(1. - residual_gas_saturation),
+      _k_rel_min(min_relative_permeability_liquid),
+      _m(exponent)
+{
+    if (!(_m > 0 && _m < 1))
+    {
+        OGS_FATAL(
+            "The exponent value m = %g of van Genuchten relative permeability "
+            "model, is out of its range of (0, 1)",
+            _m);
+    }
+}
+
+PropertyDataType RelPermVanGenuchten::value(
+    VariableArray const& variable_array,
+    ParameterLib::SpatialPosition const& /*pos*/,
+    double const /*t*/) const
+{
+    double const S_L = std::clamp(
+        std::get<double>(
+            variable_array[static_cast<int>(Variable::liquid_saturation)]),
+        _S_L_res, _S_L_max);
+
+    double const S_eff = (S_L - _S_L_res) / (_S_L_max - _S_L_res);
+    double const v = 1. - std::pow(1. - std::pow(S_eff, 1. / _m), _m);
+    double const k_rel = std::sqrt(S_eff) * v * v;
+    return std::max(_k_rel_min, k_rel);
+}
+
+PropertyDataType RelPermVanGenuchten::dValue(
+    VariableArray const& variable_array, Variable const primary_variable,
+    ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/) const
+{
+    (void)primary_variable;
+    assert((primary_variable == Variable::liquid_saturation) &&
+           "RelativePermeabilityVanGenuchten::dValue is implemented for "
+           "derivatives with respect to liquid saturation only.");
+    double const S_L = std::clamp(
+        std::get<double>(
+            variable_array[static_cast<int>(Variable::liquid_saturation)]),
+        _S_L_res, _S_L_max);
+
+    double const S_eff = (S_L - _S_L_res) / (_S_L_max - _S_L_res);
+    if (S_eff <= 0)  // prevent division by zero
+    {
+        return 0;
+    }
+
+    if (S_eff >= 1)  // prevent taking root of zero
+    {
+        return 0;
+    }
+
+    double const S_eff_to_1_over_m = std::pow(S_eff, 1. / _m);
+    double const v = 1. - std::pow(1. - S_eff_to_1_over_m, _m);
+    double const sqrt_S_eff = std::sqrt(S_eff);
+    double const k_rel = sqrt_S_eff * v * v;
+
+    if (k_rel < _k_rel_min)
+    {
+        return 0;
+    }
+
+    return (0.5 * v * v / sqrt_S_eff +
+            2. * sqrt_S_eff * v * std::pow(1. - S_eff_to_1_over_m, _m - 1.) *
+                S_eff_to_1_over_m / S_eff) /
+           (_S_L_max - _S_L_res);
+}
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/RelPermVanGenuchten.h b/MaterialLib/MPL/Properties/RelPermVanGenuchten.h
new file mode 100644
index 0000000000000000000000000000000000000000..a317527cad8068cc1471bf4569ce694485df1c1c
--- /dev/null
+++ b/MaterialLib/MPL/Properties/RelPermVanGenuchten.h
@@ -0,0 +1,66 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 Medium;
+class Phase;
+class Component;
+
+/// Van Genuchten relative permeability function.
+///
+/// This property must be a medium property, it computes the permeability
+/// reduction due to saturation as function of capillary pressure.
+class RelPermVanGenuchten final : public Property
+{
+private:
+    double const _S_L_res;
+    double const _S_L_max;
+    double const _k_rel_min;
+    double const _m;
+    Medium* _medium = nullptr;
+
+public:
+    RelPermVanGenuchten(double const residual_liquid_saturation,
+                        double const residual_gas_saturation,
+                        double const min_relative_permeability_liquid,
+                        double const exponent);
+    /// This method assigns a pointer to the material object that is the owner
+    /// of this property
+    void setScale(
+        std::variant<Medium*, Phase*, Component*> scale_pointer) override
+    {
+        if (std::holds_alternative<Medium*>(scale_pointer))
+        {
+            _medium = std::get<Medium*>(scale_pointer);
+        }
+        else
+        {
+            OGS_FATAL(
+                "The property 'RelativePermeabilityVanGenuchten' is "
+                "implemented on the 'media' 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) const override;
+    PropertyDataType dValue(VariableArray const& variable_array,
+                            Variable const variable,
+                            ParameterLib::SpatialPosition const& pos,
+                            double const t) const override;
+};
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/SaturationVanGenuchten.cpp b/MaterialLib/MPL/Properties/SaturationVanGenuchten.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7176b0bc65a226a4e3176408e5144eb4ae2b5227
--- /dev/null
+++ b/MaterialLib/MPL/Properties/SaturationVanGenuchten.cpp
@@ -0,0 +1,133 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 "SaturationVanGenuchten.h"
+
+#include <algorithm>
+#include <cmath>
+
+#include "MaterialLib/MPL/Medium.h"
+
+namespace MaterialPropertyLib
+{
+SaturationVanGenuchten::SaturationVanGenuchten(
+    double const residual_liquid_saturation,
+    double const residual_gas_saturation,
+    double const exponent,
+    double const entry_pressure)
+    : _S_L_res(residual_liquid_saturation),
+      _S_L_max(1. - residual_gas_saturation),
+      _m(exponent),
+      _p_b(entry_pressure)
+{
+    if (!(_m > 0 && _m < 1))
+    {
+        OGS_FATAL(
+            "The exponent value m = %g of van Genuchten saturation model, is "
+            "out of its range of (0, 1)",
+            _m);
+    }
+}
+
+PropertyDataType SaturationVanGenuchten::value(
+    VariableArray const& variable_array,
+    ParameterLib::SpatialPosition const& /*pos*/,
+    double const /*t*/) const
+{
+    const double p_cap = std::get<double>(
+        variable_array[static_cast<int>(Variable::capillary_pressure)]);
+
+    if (p_cap <= 0)
+    {
+        return _S_L_max;
+    }
+
+    double const p = p_cap / _p_b;
+    double const n = 1. / (1. - _m);
+    double const p_to_n = std::pow(p, n);
+
+    double const S_eff = std::pow(p_to_n + 1., -_m);
+    double const S = S_eff * _S_L_max - S_eff * _S_L_res + _S_L_res;
+    return std::clamp(S, _S_L_res, _S_L_max);
+}
+
+PropertyDataType SaturationVanGenuchten::dValue(
+    VariableArray const& variable_array, Variable const primary_variable,
+    ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/) const
+{
+    (void)primary_variable;
+    assert((primary_variable == Variable::capillary_pressure) &&
+           "SaturationVanGenuchten::dvalue is implemented for derivatives with "
+           "respect to capillary pressure only.");
+
+    const double p_cap = std::get<double>(
+        variable_array[static_cast<int>(Variable::capillary_pressure)]);
+
+    if (p_cap <= 0)
+    {
+        return 0;
+    }
+
+    double const p = p_cap / _p_b;
+    double const n = 1. / (1. - _m);
+    double const p_to_n = std::pow(p, n);
+
+    double const S_eff = std::pow(p_to_n + 1., -_m);
+    double const S = S_eff * _S_L_max - S_eff * _S_L_res + _S_L_res;
+
+    if (S < _S_L_res || S > _S_L_max)
+    {
+        return 0;
+    }
+
+    double const dS_eff_dp_cap = -_m * std::pow(p_cap / _p_b, n - 1) *
+                                 std::pow(1 + p_to_n, -1. - _m) /
+                                 (_p_b * (1. - _m));
+    return dS_eff_dp_cap * (_S_L_max - _S_L_res);
+}
+
+PropertyDataType SaturationVanGenuchten::d2Value(
+    VariableArray const& variable_array, Variable const primary_variable1,
+    Variable const primary_variable2,
+    ParameterLib::SpatialPosition const& /*pos*/, double const /*t*/) const
+{
+    (void)primary_variable1;
+    (void)primary_variable2;
+    assert((primary_variable1 == Variable::capillary_pressure) &&
+           (primary_variable2 == Variable::capillary_pressure) &&
+           "SaturationVanGenuchten::d2Value is implemented for "
+           " derivatives with respect to capillary pressure only.");
+
+    const double p_cap = std::get<double>(
+        variable_array[static_cast<int>(Variable::capillary_pressure)]);
+
+    if (p_cap <= 0)
+    {
+        return 0;
+    }
+
+    double const p = p_cap / _p_b;
+    double const n = 1. / (1. - _m);
+    double const p_to_n = std::pow(p, n);
+
+    double const S_eff = std::pow(p_to_n + 1., -_m);
+    double const S = S_eff * _S_L_max - S_eff * _S_L_res + _S_L_res;
+
+    if (S < _S_L_res || S > _S_L_max)
+    {
+        return 0;
+    }
+
+    double const d2S_eff_dp_cap2 =
+        _m * p_to_n * std::pow(p_to_n + 1., -_m - 2.) * (p_to_n - _m) /
+        (p_cap * p_cap * (_m - 1.) * (_m - 1.));
+    return d2S_eff_dp_cap2 * (_S_L_max - _S_L_res);
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/SaturationVanGenuchten.h b/MaterialLib/MPL/Properties/SaturationVanGenuchten.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a792d3a7ce69cbe6f73b8404651dc9fc457eba2
--- /dev/null
+++ b/MaterialLib/MPL/Properties/SaturationVanGenuchten.h
@@ -0,0 +1,65 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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 "MaterialLib/MPL/Property.h"
+
+namespace MaterialPropertyLib
+{
+class Medium;
+class Phase;
+class Component;
+
+/// The van Genuchten soil characteristics function.
+///
+/// This property must be a medium property, it computes the saturation of the
+/// wetting phase as function of capillary pressure.
+class SaturationVanGenuchten final : public Property
+{
+private:
+    Medium* _medium = nullptr;
+    double const _S_L_res;
+    double const _S_L_max;
+    double const _m;
+    double const _p_b;
+
+public:
+    SaturationVanGenuchten(double const residual_liquid_saturation,
+                           double const residual_gas_saturation,
+                           double const exponent,
+                           double const entry_pressure);
+
+    void setScale(
+        std::variant<Medium*, Phase*, Component*> scale_pointer) override
+    {
+        if (!std::holds_alternative<Medium*>(scale_pointer))
+        {
+            OGS_FATAL(
+                "The property 'SaturationVanGenuchten' is implemented on the "
+                "'media' scale only.");
+        }
+        _medium = std::get<Medium*>(scale_pointer);
+    }
+
+    /// 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*/) const override;
+    PropertyDataType dValue(VariableArray const& variable_array,
+                            Variable const variable,
+                            ParameterLib::SpatialPosition const& /*pos*/,
+                            double const /*t*/) const override;
+    PropertyDataType d2Value(VariableArray const& variable_array,
+                             Variable const variable1,
+                             Variable const variable2,
+                             ParameterLib::SpatialPosition const& /*pos*/,
+                             double const /*t*/) const override;
+};
+}  // namespace MaterialPropertyLib
diff --git a/Tests/MaterialLib/TestMPLRelPermVanGenuchten.cpp b/Tests/MaterialLib/TestMPLRelPermVanGenuchten.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..cab51d5cc8f274464003ee85a4b6dccf2e0f1eff
--- /dev/null
+++ b/Tests/MaterialLib/TestMPLRelPermVanGenuchten.cpp
@@ -0,0 +1,72 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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/Medium.h"
+#include "MaterialLib/MPL/Properties/RelPermVanGenuchten.h"
+#include "TestMPL.h"
+#include "Tests/TestTools.h"
+
+namespace MPL = MaterialPropertyLib;
+
+TEST(MaterialPropertyLib, RelPermVanGenuchten)
+{
+    double const residual_liquid_saturation = 0.1;
+    double const residual_gas_saturation = 0.05;
+    double const exponent = 0.79;
+    double const min_relative_permeability_liquid = 1e-12;
+
+    MPL::Property const& permeability = MPL::RelPermVanGenuchten{
+        residual_liquid_saturation, residual_gas_saturation,
+        min_relative_permeability_liquid, exponent};
+
+    MPL::VariableArray variable_array;
+    ParameterLib::SpatialPosition const pos;
+    double const t = std::numeric_limits<double>::quiet_NaN();
+
+    double const S_0 = -0.1;
+    double const S_max = 1.1;
+    int const n_steps = 1000;
+    for (int i = 0; i <= n_steps; ++i)
+    {
+        double const S_L = S_0 + i * (S_max - S_0) / n_steps;
+        variable_array[static_cast<int>(MPL::Variable::liquid_saturation)] =
+            S_L;
+
+        double const k_rel =
+            permeability.template value<double>(variable_array, pos, t);
+        double const dk_rel = permeability.template dValue<double>(
+            variable_array, MPL::Variable::liquid_saturation, pos, t);
+
+        double const eps = 1e-8;
+        variable_array[static_cast<int>(MPL::Variable::liquid_saturation)] =
+            S_L - eps;
+        double const k_rel_minus =
+            permeability.template value<double>(variable_array, pos, t);
+        variable_array[static_cast<int>(MPL::Variable::liquid_saturation)] =
+            S_L + eps;
+        double const k_rel_plus =
+            permeability.template value<double>(variable_array, pos, t);
+
+        double const Dk_rel = (k_rel_plus - k_rel_minus) / 2 / eps;
+
+        if (S_L < 1 - residual_gas_saturation)
+        {
+            ASSERT_LE(std::abs(dk_rel - Dk_rel), 1e-7)
+                << "for saturation " << S_L << " and relative permeability "
+                << k_rel;
+        }
+        else
+        {
+            ASSERT_EQ(dk_rel, 0.) << "for saturation " << S_L
+                                  << " and relative permeability " << k_rel;
+        }
+    }
+}
diff --git a/Tests/MaterialLib/TestMPLSaturationVanGenuchten.cpp b/Tests/MaterialLib/TestMPLSaturationVanGenuchten.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f197e5f70083b6921dee10dabe6575d82884f251
--- /dev/null
+++ b/Tests/MaterialLib/TestMPLSaturationVanGenuchten.cpp
@@ -0,0 +1,69 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2020, 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/Medium.h"
+#include "MaterialLib/MPL/Properties/SaturationVanGenuchten.h"
+#include "TestMPL.h"
+#include "Tests/TestTools.h"
+
+namespace MPL = MaterialPropertyLib;
+
+TEST(MaterialPropertyLib, SaturationVanGenuchten)
+{
+    double const residual_liquid_saturation = 0.1;
+    double const residual_gas_saturation = 0.05;
+    double const exponent = 0.79;
+    double const entry_pressure = 5000;
+
+    MPL::Property const& pressure_saturation = MPL::SaturationVanGenuchten{
+        residual_liquid_saturation, residual_gas_saturation, exponent,
+        entry_pressure};
+
+    MPL::VariableArray variable_array;
+    ParameterLib::SpatialPosition const pos;
+    double const t = std::numeric_limits<double>::quiet_NaN();
+
+    double const p_0 = -1e6;
+    double const p_max = 10000;
+    int const n_steps = 10000;
+    for (int i = 0; i <= n_steps; ++i)
+    {
+        double const p_L = p_0 + i * (p_max - p_0) / n_steps;
+        variable_array[static_cast<int>(MPL::Variable::capillary_pressure)] =
+            -p_L;
+
+        double const S =
+            pressure_saturation.template value<double>(variable_array, pos, t);
+        double const dS = pressure_saturation.template dValue<double>(
+            variable_array, MPL::Variable::capillary_pressure, pos, t);
+        double const dS2 = pressure_saturation.template d2Value<double>(
+            variable_array, MPL::Variable::capillary_pressure,
+            MPL::Variable::capillary_pressure, pos, t);
+
+        double const eps = 1e-1;
+        variable_array[static_cast<int>(MPL::Variable::capillary_pressure)] =
+            -p_L - eps;
+        double const S_minus =
+            pressure_saturation.template value<double>(variable_array, pos, t);
+        variable_array[static_cast<int>(MPL::Variable::capillary_pressure)] =
+            -p_L + eps;
+        double const S_plus =
+            pressure_saturation.template value<double>(variable_array, pos, t);
+
+        double const DS = (S_plus - S_minus) / 2 / eps;
+        double const DS2 = (S_plus - 2 * S + S_minus) / (eps * eps);
+
+        ASSERT_LE(std::abs(dS - DS), 1e-9)
+            << "for capillary pressure " << -p_L << " and saturation " << S;
+        ASSERT_LE(std::abs(dS2 - DS2), 1e-9)
+            << "for capillary pressure " << -p_L << " and saturation " << S;
+    }
+}