diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp
index 5a6d09da7976996570438a115f7105538b8a74e4..f81ba6d8b7b6a464f152141fb9f77c0e69762cbd 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.cpp
@@ -28,7 +28,19 @@ double NonWettingPhaseBrookCoreyOilGas::getValue(
     const double Se = (S - _Sr) / (_Smax - _Sr);
     const double krel =
         (1.0 - Se) * (1.0 - Se) * (1.0 - std::pow(Se, 1.0 + 2.0 / _mm));
-    return krel < _krel_min ? _krel_min : krel;
+    return std::max(_krel_min,  krel);
+}
+
+double NonWettingPhaseBrookCoreyOilGas::getdValue(
+    const double saturation_w) const
+{
+    const double S = MathLib::limitValueInInterval(
+        saturation_w, _Sr + _minor_offset, _Smax - _minor_offset);
+    const double Se = (S - _Sr) / (_Smax - _Sr);
+    return (-2. * (1.0 - Se) * (1.0 - std::pow(Se, 1.0 + 2.0 / _mm)) -
+            (1.0 + 2.0 / _mm) * (1.0 - Se) * (1.0 - Se) *
+                std::pow(Se, 2.0 / _mm)) /
+           (_Smax - _Sr);
 }
 
 }  // end namespace
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h
index 32a91922a796eba81e641bf057ba042f3f837a19..9b34f2e54f9c36e6139d154d57f1ce09a377e0d2 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseBrookCoreyOilGas.h
@@ -60,6 +60,10 @@ public:
     /// \param saturation_w Wetting phase saturation
     double getValue(const double saturation_w) const override;
 
+    /// Get the derivative of relative permeability with respect to saturation.
+    /// \param saturation_w Wetting phase saturation
+    double getdValue(const double saturation_w) const override;
+
 private:
     const double _Sr;        ///< Residual saturation of wetting phase, 1-Snmax.
     const double _Smax;      ///< Maximum saturation of wetting phase, 1-Snr.
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp
index 435c52dc3872e47de4db2a03ceef3a5f953e9775..f3d397ad26abfde45c492d07ebd29c2c63f59df9 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.cpp
@@ -27,7 +27,20 @@ double NonWettingPhaseVanGenuchten::getValue(const double saturation_w) const
     const double Se = (S - _Sr) / (_Smax - _Sr);
     const double krel = std::cbrt(1.0 - Se) *
                         std::pow(1.0 - std::pow(Se, 1.0 / _mm), 2.0 * _mm);
-    return krel < _krel_min ? _krel_min : krel;
+    return std::max(_krel_min,  krel);
+}
+
+double NonWettingPhaseVanGenuchten::getdValue(const double saturation_w) const
+{
+    const double S = MathLib::limitValueInInterval(
+        saturation_w, _Sr + _minor_offset, _Smax - _minor_offset);
+    const double Se = (S - _Sr) / (_Smax - _Sr);
+    const double cbrt1_Se = std::cbrt(1.0 - Se);
+    const double temp_val = 1.0 - std::pow(Se, 1.0 / _mm);
+    return (-std::pow(temp_val, 2. * _mm) / (3. * cbrt1_Se * cbrt1_Se) -
+            2. * cbrt1_Se * std::pow(temp_val, 2. * _mm - 1.) *
+                std::pow(Se, (1. - _mm) / _mm)) /
+           (_Smax - _Sr);
 }
 }  // end namespace
 }  // end namespace
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h
index f24ecd4d22c73687d64ba8ac71b012fca6a30a87..a039616fdb6ce4d127769b0405462373debd0c1f 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/NonWettingPhaseVanGenuchten.h
@@ -62,6 +62,10 @@ public:
     /// \param saturation_w Wetting phase saturation
     double getValue(const double saturation_w) const override;
 
+    /// Get the derivative of relative permeability with respect to saturation.
+    /// \param saturation_w Wetting phase saturation
+    double getdValue(const double saturation_w) const override;
+
 private:
     const double _Sr;        ///< Residual saturation of wetting phase, 1-Snmax.
     const double _Smax;      ///< Maximum saturation of wetting phase, 1-Snr.
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h
index 0b62d8ac50ba0e1e20cc6f4bb4616b5901bf8f36..da69bb2a25be16b6b1ce68af25e3ae135342b6e9 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeability.h
@@ -32,6 +32,10 @@ public:
     /// \param saturation Wetting phase saturation
     virtual double getValue(const double saturation) const = 0;
 
+    /// Get the derivative of relative permeability with respect to saturation.
+    /// \param saturation Wetting phase saturation
+    virtual double getdValue(const double saturation) const = 0;
+
 protected:
     /** A small number for an offset:
      *  1. to set the bound of S, the saturation, such that
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h
index 8232932a5ef3a91af62e2961860f709e6f906228..b89b4c7524eb1b61fb97e39e65c5106d12a0113e 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/RelativePermeabilityCurve.h
@@ -49,6 +49,16 @@ public:
         return _curve_data->getValue(S);
     }
 
+    /// Get the derivative of relative permeability with respect to saturation.
+    /// \param saturation Wetting phase saturation
+    double getdValue(const double saturation) const override
+    {
+        const double S = MathLib::limitValueInInterval(
+            saturation, _Sr + _minor_offset, _Smax - _minor_offset);
+
+        return _curve_data->getDerivative(S);
+    }
+
 private:
     const double _Sr;    ///< Residual saturation.
     const double _Smax;  ///< Maximum saturation.
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp
index 938bf57d2505b8e040b25ee297bddc473b595a57..cb8cebc589a2cc4156acb64c15824c5c61d83972 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.cpp
@@ -26,8 +26,15 @@ double WettingPhaseBrookCoreyOilGas::getValue(const double saturation) const
         saturation, _Sr + _minor_offset, _Smax - _minor_offset);
     const double Se = (S - _Sr) / (_Smax - _Sr);
     const double krel = std::pow(Se, 3.0 + 2.0 / _mm);
-    return krel < _krel_min ? _krel_min : krel;
+    return std::max(_krel_min,  krel);
 }
 
+double WettingPhaseBrookCoreyOilGas::getdValue(const double saturation) const
+{
+    const double S = MathLib::limitValueInInterval(
+        saturation, _Sr + _minor_offset, _Smax - _minor_offset);
+    const double Se = (S - _Sr) / (_Smax - _Sr);
+    return ((3.0 + 2.0 / _mm) * std::pow(Se, 2.0 + 2.0 / _mm)) / (_Smax - _Sr);
+}
 }  // end namespace
 }  // end namespace
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h
index 28b095d9982e1670e7bd985352e0807f768df88a..93283367763b4b5062f4bd9e5d5dbfa1dc6a1aaa 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseBrookCoreyOilGas.h
@@ -56,6 +56,10 @@ public:
     /// Get relative permeability value.
     double getValue(const double saturation) const override;
 
+    /// Get the derivative of relative permeability with respect to saturation.
+    /// \param saturation Wetting phase saturation
+    double getdValue(const double saturation) const override;
+
 private:
     const double _Sr;        ///< Residual saturation.
     const double _Smax;      ///< Maximum saturation.
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp
index fdcb70908ac17d658756c9425a3c01c44312f99c..e1429bce38b1d9fbd72f3d1535a9b36f9771b9a0 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.cpp
@@ -27,7 +27,21 @@ double WettingPhaseVanGenuchten::getValue(const double saturation) const
     const double Se = (S - _Sr) / (_Smax - _Sr);
     const double val = 1.0 - std::pow(1.0 - std::pow(Se, 1.0 / _mm), _mm);
     const double krel = std::sqrt(Se) * val * val;
-    return krel < _krel_min ? _krel_min : krel;
+    return std::max(_krel_min,  krel);
+}
+
+double WettingPhaseVanGenuchten::getdValue(const double saturation) const
+{
+    const double S = MathLib::limitValueInInterval(
+        saturation, _Sr + _minor_offset, _Smax - _minor_offset);
+    const double Se = (S - _Sr) / (_Smax - _Sr);
+    const double sqrtSe = std::sqrt(Se);
+    const double temp_val = 1.0 - std::pow(1.0 - std::pow(Se, 1.0 / _mm), _mm);
+    return (0.5 * temp_val * temp_val / sqrtSe +
+            2. * sqrtSe * temp_val *
+                std::pow(1.0 - std::pow(Se, 1.0 / _mm), _mm - 1.) *
+                std::pow(Se, (1.0 - _mm) / _mm)) /
+           (_Smax - _Sr);
 }
 
 }  // end namespace
diff --git a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h
index 8fd580f378e0bfa0c03dd284f5aa630de67e7b65..c69b0850b8d6d7521918b81d312fc84e5c9c7b4a 100644
--- a/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h
+++ b/MaterialLib/PorousMedium/UnsaturatedProperty/RelativePermeability/WettingPhaseVanGenuchten.h
@@ -59,6 +59,10 @@ public:
     /// Get relative permeability value.
     double getValue(const double saturation) const override;
 
+    /// Get the derivative of relative permeability with respect to saturation.
+    /// \param saturation Wetting phase saturation
+    double getdValue(const double saturation) const override;
+
 private:
     const double _Sr;        ///< Residual saturation.
     const double _Smax;      ///< Maximum saturation.
diff --git a/Tests/MaterialLib/TestRelativePermeabilityModel.cpp b/Tests/MaterialLib/TestRelativePermeabilityModel.cpp
index ae340266fab13e01d2aa5928b0cfcbfba6b15a56..7612ed4d8e010f28b8d1f32e67599413cdd2969a 100644
--- a/Tests/MaterialLib/TestRelativePermeabilityModel.cpp
+++ b/Tests/MaterialLib/TestRelativePermeabilityModel.cpp
@@ -58,9 +58,16 @@ TEST(MaterialPorousMedium, checkWettingPhaseVanGenuchten)
                                 0.0074049488610241927,
                                 0.13546615958442240};
 
+    const double purterbation = 1.e-9;
     for (std::size_t i = 0; i < S.size(); i++)
     {
         ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);
+
+        // Compare the derivative with numerical one.
+        ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) -
+                     perm_model->getValue(S[i])) /
+                        purterbation,
+                    perm_model->getdValue(S[i]), 1.e-6);
     }
 }
 
@@ -81,9 +88,16 @@ TEST(MaterialPorousMedium, checkNonWettingPhaseVanGenuchten)
                                 0.59527539448807487, 0.49976666464188485,
                                 0.38520070797257489, 0.041219134248319585};
 
+    const double purterbation = 1.e-9;
     for (std::size_t i = 0; i < S.size(); i++)
     {
         ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);
+
+        // Compare the derivative with numerical one.
+        ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) -
+                     perm_model->getValue(S[i])) /
+                        purterbation,
+                    perm_model->getdValue(S[i]), 1.e-6);
     }
 }
 
@@ -107,9 +121,20 @@ TEST(MaterialPorousMedium, checkWettingPhaseBrookCoreyOilGas)
                                 0.19753086419753069,
                                 1.0};
 
+    const double purterbation = 1.e-9;
     for (std::size_t i = 0; i < S.size(); i++)
     {
         ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);
+
+        // i ==  S.size() -1, S(=0.85) is limited to 0.8, and the numerical
+        // derivative of krel is unavailable.
+        if (i == S.size() - 1)
+            continue;
+        // Compare the derivative with numerical one.
+        ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) -
+                     perm_model->getValue(S[i])) /
+                        purterbation,
+                    perm_model->getdValue(S[i]), 1.e-6);
     }
 }
 
@@ -133,9 +158,16 @@ TEST(MaterialPorousMedium, checkNonWettingPhaseBrookCoreyOilGas)
                                 0.061728395061728412,
                                 .0};
 
+    const double purterbation = 1.e-9;
     for (std::size_t i = 0; i < S.size(); i++)
     {
         ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);
+
+        // Compare the derivative with numerical one.
+        ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) -
+                     perm_model->getValue(S[i])) /
+                        purterbation,
+                    perm_model->getdValue(S[i]), 1.e-6);
     }
 }
 
@@ -155,8 +187,15 @@ TEST(MaterialPorousMedium, checkReletivePermeabilityCurve)
     std::vector<double> S = {0.2, 0.33, 0.45, 0.52, 0.6, 0.85};
     std::vector<double> krel = {0.7, 0.57, 0.451, 0.3824, 0.304, 0.059};
 
+    const double purterbation = 1.e-9;
     for (std::size_t i = 0; i < S.size(); i++)
     {
         ASSERT_NEAR(krel[i], perm_model->getValue(S[i]), 1.e-9);
+
+        // Compare the derivative with numerical one.
+        ASSERT_NEAR((perm_model->getValue(S[i] + purterbation) -
+                     perm_model->getValue(S[i])) /
+                        purterbation,
+                    perm_model->getdValue(S[i]), 1.e-6);
     }
 }