diff --git a/Documentation/ProjectFile/properties/property/Function/c_Function.md b/Documentation/ProjectFile/properties/property/Function/c_Function.md
new file mode 100644
index 0000000000000000000000000000000000000000..5a7b4408a4c2d8414113e3d55e8aa1e6e0b03e41
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/Function/c_Function.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::Function
diff --git a/Documentation/ProjectFile/properties/property/Function/dvalue/i_dvalue.md b/Documentation/ProjectFile/properties/property/Function/dvalue/i_dvalue.md
new file mode 100644
index 0000000000000000000000000000000000000000..25a872c3e27fa47b051a927dffe7bb4a8f159805
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/Function/dvalue/i_dvalue.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::Function::dvalue_expressions_
diff --git a/Documentation/ProjectFile/properties/property/Function/dvalue/t_expression.md b/Documentation/ProjectFile/properties/property/Function/dvalue/t_expression.md
new file mode 100644
index 0000000000000000000000000000000000000000..25a872c3e27fa47b051a927dffe7bb4a8f159805
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/Function/dvalue/t_expression.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::Function::dvalue_expressions_
diff --git a/Documentation/ProjectFile/properties/property/Function/dvalue/t_variable_name.md b/Documentation/ProjectFile/properties/property/Function/dvalue/t_variable_name.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a95bbbd5692fee4c6a26126938cc2704a3e8a1f
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/Function/dvalue/t_variable_name.md
@@ -0,0 +1,2 @@
+Variable name for the derivative of the function with respect to the named
+variable.
diff --git a/Documentation/ProjectFile/properties/property/Function/value/i_value.md b/Documentation/ProjectFile/properties/property/Function/value/i_value.md
new file mode 100644
index 0000000000000000000000000000000000000000..c3f64a5050683d2969460dc58884223c7820ee95
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/Function/value/i_value.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::Function::value_expressions_
diff --git a/Documentation/ProjectFile/properties/property/Function/value/t_expression.md b/Documentation/ProjectFile/properties/property/Function/value/t_expression.md
new file mode 100644
index 0000000000000000000000000000000000000000..c3f64a5050683d2969460dc58884223c7820ee95
--- /dev/null
+++ b/Documentation/ProjectFile/properties/property/Function/value/t_expression.md
@@ -0,0 +1 @@
+\copydoc MaterialPropertyLib::Function::value_expressions_
diff --git a/MaterialLib/CMakeLists.txt b/MaterialLib/CMakeLists.txt
index f44b84266f246111f35353217a9a0d4c765167ed..6767d5f4dd544a0af4ab50a75b06c4e8a4124611 100644
--- a/MaterialLib/CMakeLists.txt
+++ b/MaterialLib/CMakeLists.txt
@@ -40,5 +40,5 @@ ogs_add_library(MaterialLib ${SOURCES})
 
 target_link_libraries(
     MaterialLib PUBLIC MaterialLib_SolidModels MaterialLib_FractureModels
-    PRIVATE MathLib MeshLib ParameterLib spdlog::spdlog
+    PRIVATE MathLib MeshLib ParameterLib exprtk spdlog::spdlog
 )
diff --git a/MaterialLib/MPL/CreateProperty.cpp b/MaterialLib/MPL/CreateProperty.cpp
index 4ea28761befab9e3fce62a479cc72a9773a4e000..d3dba9812fd12426e3c7812df070a689e37161be 100644
--- a/MaterialLib/MPL/CreateProperty.cpp
+++ b/MaterialLib/MPL/CreateProperty.cpp
@@ -56,6 +56,10 @@ std::unique_ptr<MaterialPropertyLib::Property> createProperty(
     {
         return createExponential(config);
     }
+    if (property_type == "Function")
+    {
+        return createFunction(config);
+    }
 
     if (property_type == "Parameter")
     {
diff --git a/MaterialLib/MPL/Properties/CreateFunction.cpp b/MaterialLib/MPL/Properties/CreateFunction.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e6048cb4f4e290ada11e962284c41f89db7d04c6
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateFunction.cpp
@@ -0,0 +1,60 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, 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 "Function.h"
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<Function> createFunction(BaseLib::ConfigTree const& config)
+{
+    //! \ogs_file_param{properties__property__type}
+    config.checkConfigParameter("type", "Function");
+
+    // Second access for storage.
+    //! \ogs_file_param{properties__property__name}
+    auto property_name = config.peekConfigParameter<std::string>("name");
+
+    DBUG("Create Function property {:s}.", property_name);
+
+    std::vector<std::string> value_expressions;
+    //! \ogs_file_param{properties__property__Function__value}
+    auto const& value_config = config.getConfigSubtree("value");
+
+    //! \ogs_file_param{properties__property__Function__value__expression}
+    for (auto const& p : value_config.getConfigSubtreeList("expression"))
+    {
+        value_expressions.emplace_back(p.getValue<std::string>());
+    }
+
+    // For each derivative a name of the variable and the list of expressions.
+    std::vector<std::pair<std::string, std::vector<std::string>>>
+        dvalue_expressions;
+    //! \ogs_file_param{properties__property__Function__dvalue}
+    for (auto const& dvalue_config : config.getConfigSubtreeList("dvalue"))
+    {
+        auto variable_name =
+            //! \ogs_file_param{properties__property__Function__dvalue__variable_name}
+            dvalue_config.getConfigParameter<std::string>("variable_name");
+
+        std::vector<std::string> expressions;
+        //! \ogs_file_param{properties__property__Function__dvalue__expression}
+        for (auto const& p : dvalue_config.getConfigSubtreeList("expression"))
+        {
+            expressions.emplace_back(p.getValue<std::string>());
+        }
+        dvalue_expressions.emplace_back(std::move(variable_name),
+                                        std::move(expressions));
+    }
+
+    return std::make_unique<MaterialPropertyLib::Function>(
+        std::move(property_name), std::move(value_expressions),
+        std::move(dvalue_expressions));
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/CreateFunction.h b/MaterialLib/MPL/Properties/CreateFunction.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f86f3d02b6bf9368178c1a843c32854233087fb
--- /dev/null
+++ b/MaterialLib/MPL/Properties/CreateFunction.h
@@ -0,0 +1,27 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, 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 Function;
+}
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<Function> createFunction(BaseLib::ConfigTree const& config);
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/CreateProperties.h b/MaterialLib/MPL/Properties/CreateProperties.h
index 7b45b0a11a45babcb05cb7b645c3c792f065a6f4..de51caa288965ead42d885d79c624f2a7c5ad733 100644
--- a/MaterialLib/MPL/Properties/CreateProperties.h
+++ b/MaterialLib/MPL/Properties/CreateProperties.h
@@ -27,6 +27,7 @@
 #include "CreateEffectiveThermalConductivityPorosityMixing.h"
 #include "CreateEmbeddedFracturePermeability.h"
 #include "CreateExponential.h"
+#include "CreateFunction.h"
 #include "CreateGasPressureDependentPermeability.h"
 #include "CreateIdealGasLaw.h"
 #include "CreateKozenyCarmanModel.h"
diff --git a/MaterialLib/MPL/Properties/Function.cpp b/MaterialLib/MPL/Properties/Function.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bbdb668e633c182ae7f20a9bc45388e56b72e629
--- /dev/null
+++ b/MaterialLib/MPL/Properties/Function.cpp
@@ -0,0 +1,216 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, 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/Function.h"
+
+#include <numeric>
+
+#include "BaseLib/Algorithm.h"
+
+namespace MaterialPropertyLib
+{
+// Passing symbol table by reference as required by register_symbol_table()
+// call.
+template <typename T>
+static std::vector<exprtk::expression<T>> compileExpressions(
+    exprtk::symbol_table<T>& symbol_table,
+    std::vector<std::string> const& string_expressions)
+{
+    exprtk::parser<T> parser;
+
+    std::vector<exprtk::expression<T>> expressions(string_expressions.size());
+    expressions.resize(string_expressions.size());
+    for (unsigned i = 0; i < string_expressions.size(); ++i)
+    {
+        expressions[i].register_symbol_table(symbol_table);
+        if (!parser.compile(string_expressions[i], expressions[i]))
+        {
+            OGS_FATAL("Error: {:s}\tExpression: {:s}\n",
+                      parser.error(),
+                      string_expressions[i]);
+        }
+    }
+    return expressions;
+}
+
+static void updateVariableValues(
+    std::vector<std::pair<int, double*>> const& symbol_values,
+    VariableArray const& variable_array)
+{
+    for (auto& index_value_ptr_pair : symbol_values)
+    {
+        auto const index = index_value_ptr_pair.first;
+
+        double* value_ptr = index_value_ptr_pair.second;
+        std::visit(
+            [&value_ptr, &index](auto&& v) {
+                using T = std::decay_t<decltype(v)>;
+                if constexpr (std::is_same_v<T, std::monostate>)
+                {
+                    OGS_FATAL(
+                        "Function property: variable {:s} value needed for "
+                        "evaluation of the expression was not set by the "
+                        "caller.",
+                        variable_enum_to_string[index]);
+                }
+                else if constexpr (std::is_same_v<T, double>)
+                {
+                    *value_ptr = v;
+                }
+                else
+                {
+                    OGS_FATAL(
+                        "Function property: not implemented handling for a "
+                        "type {:s} of variable {:s}.",
+                        typeid(T).name(), variable_enum_to_string[index]);
+                }
+            },
+            variable_array[index]);
+    }
+}
+
+static PropertyDataType evaluateExpressions(
+    std::vector<std::pair<int, double*>> const& symbol_values,
+    VariableArray const& variable_array,
+    std::vector<exprtk::expression<double>> const& expressions)
+{
+    updateVariableValues(symbol_values, variable_array);
+
+    std::vector<double> result(expressions.size());
+    std::transform(begin(expressions), end(expressions), begin(result),
+                   [](auto const& e) { return e.value(); });
+
+    switch (result.size())
+    {
+        case 1:
+        {
+            return result[0];
+        }
+        case 2:
+        {
+            return Eigen::Vector2d{result[0], result[1]};
+        }
+        case 3:
+        {
+            return Eigen::Vector3d{result[0], result[1], result[2]};
+        }
+        case 4:
+        {
+            Eigen::Matrix<double, 2, 2> m;
+            m = Eigen::Map<Eigen::Matrix<double, 2, 2> const>(result.data(), 2,
+                                                              2);
+            return m;
+        }
+        case 9:
+        {
+            Eigen::Matrix<double, 3, 3> m;
+            m = Eigen::Map<Eigen::Matrix<double, 3, 3> const>(result.data(), 3,
+                                                              3);
+            return m;
+        }
+    }
+    OGS_FATAL("Cannot convert a vector of size {} to a PropertyDataType",
+              result.size());
+}
+
+static std::vector<std::string> collectVariables(
+    std::vector<std::string> const& value_string_expressions,
+    std::vector<std::pair<std::string, std::vector<std::string>>> const&
+        dvalue_string_expressions)
+{
+    std::vector<std::string> variables;
+
+    auto collect_variables = [&](auto string_expressions) {
+        for (auto const& string_expression : string_expressions)
+        {
+            if (!exprtk::collect_variables(string_expression, variables))
+            {
+                OGS_FATAL("Collecting variables didn't work.");
+            }
+        }
+    };
+
+    collect_variables(value_string_expressions);
+    for (auto const& var_name_string_expression : dvalue_string_expressions)
+    {
+        collect_variables(var_name_string_expression.second);
+    }
+
+    BaseLib::makeVectorUnique(variables);
+    return variables;
+}
+
+Function::Function(std::string name,
+                   std::vector<std::string>
+                       value_string_expressions,
+                   std::vector<std::pair<std::string, std::vector<std::string>>>
+                       dvalue_string_expressions)
+{
+    name_ = std::move(name);
+
+    // Create symbol table for used variables.
+    exprtk::symbol_table<double> symbol_table;
+
+    for (auto const& v :
+         collectVariables(value_string_expressions, dvalue_string_expressions))
+    {
+        symbol_table.create_variable(v);
+        // Store variables index in the variable array and the pointer to the
+        // value in the symbol table for fast access later.
+        int const variable_array_index =
+            static_cast<int>(convertStringToVariable(v));
+        symbol_values_.emplace_back(variable_array_index,
+                                    &symbol_table.get_variable(v)->ref());
+    }
+
+    // value expressions.
+    value_expressions_ =
+        compileExpressions(symbol_table, value_string_expressions);
+
+    // dValue expressions.
+    for (auto const& [variable_name, string_expressions] :
+         dvalue_string_expressions)
+    {
+        dvalue_expressions_.emplace_back(
+            convertStringToVariable(variable_name),
+            compileExpressions(symbol_table, string_expressions));
+    }
+}
+
+PropertyDataType Function::value(VariableArray const& variable_array,
+                                 ParameterLib::SpatialPosition const& /*pos*/,
+                                 double const /*t*/, double const /*dt*/) const
+{
+    return evaluateExpressions(symbol_values_, variable_array,
+                               value_expressions_);
+}
+
+PropertyDataType Function::dValue(VariableArray const& variable_array,
+                                  Variable const primary_variable,
+                                  ParameterLib::SpatialPosition const& /*pos*/,
+                                  double const /*t*/, double const /*dt*/) const
+{
+    auto const it = std::find_if(begin(dvalue_expressions_),
+                                 end(dvalue_expressions_),
+                                 [&primary_variable](auto const& v) {
+                                     return v.first == primary_variable;
+                                 });
+
+    if (it == end(dvalue_expressions_))
+    {
+        OGS_FATAL(
+            "Requested derivative with respect to the variable {:s} not "
+            "provided for Function-type property {:s}.",
+            variable_enum_to_string[static_cast<int>(primary_variable)], name_);
+    }
+
+    return evaluateExpressions(symbol_values_, variable_array, it->second);
+}
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/Function.h b/MaterialLib/MPL/Properties/Function.h
new file mode 100644
index 0000000000000000000000000000000000000000..27ad4c1fa2ef1fa693de63df0870da1e9cd77606
--- /dev/null
+++ b/MaterialLib/MPL/Properties/Function.h
@@ -0,0 +1,59 @@
+/**
+ * \file
+ * \copyright
+ * Copyright (c) 2012-2021, 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 <exprtk.hpp>
+#include <utility>
+#include <vector>
+
+#include "MaterialLib/MPL/Property.h"
+#include "MaterialLib/MPL/VariableType.h"
+
+namespace MaterialPropertyLib
+{
+/// A function property defined by mathematical expression. For the evaluation
+/// of the expressions the exprtk library is used. In the expressions all
+/// variables defined in MaterialPropertyLib::Variable enum can be used.
+///
+/// \warning The evaluation calls are not to be used in parallel (openMP),
+/// because the values' updates are using the same space.
+class Function final : public Property
+{
+public:
+    Function(std::string name,
+             std::vector<std::string>
+                 value_string_expressions,
+             std::vector<std::pair<std::string, std::vector<std::string>>>
+                 dvalue_string_expressions);
+
+    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 primary_variable,
+                            ParameterLib::SpatialPosition const& pos,
+                            double const t,
+                            double const dt) const override;
+
+private:
+    using Expression = exprtk::expression<double>;
+
+    /// Mapping from variable array index to symbol table values.
+    std::vector<std::pair<int, double*>> symbol_values_;
+    /// Value expressions.
+    /// Multiple expressions are representing vector-valued functions.
+    std::vector<Expression> value_expressions_;
+    /// Derivative expressions with respect to the variable.
+    /// Multiple expressions are representing vector-valued functions.
+    std::vector<std::pair<Variable, std::vector<Expression>>>
+        dvalue_expressions_;
+};
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/Properties.h b/MaterialLib/MPL/Properties/Properties.h
index f22a6061d3cb2521b16c797f66eb45094d62f81b..290a0e43669170910f8b7c85b75302b9e4cefcc7 100644
--- a/MaterialLib/MPL/Properties/Properties.h
+++ b/MaterialLib/MPL/Properties/Properties.h
@@ -28,6 +28,7 @@
 #include "Enthalpy/LinearWaterVapourLatentHeat.h"
 #include "Enthalpy/WaterVapourLatentHeatWithCriticalTemperature.h"
 #include "Exponential.h"
+#include "Function.h"
 #include "GasPressureDependentPermeability.h"
 #include "IdealGasLaw.h"
 #include "Linear.h"