diff --git a/Applications/ApplicationsLib/ProjectData.cpp b/Applications/ApplicationsLib/ProjectData.cpp
index 78e8d58f7dadbb4d1fae61499ae92a553d09491f..2408ccafed5d48a6753284401ef76d4b9a62a2ea 100644
--- a/Applications/ApplicationsLib/ProjectData.cpp
+++ b/Applications/ApplicationsLib/ProjectData.cpp
@@ -26,7 +26,7 @@
 #include "BaseLib/FileTools.h"
 
 #include "GeoLib/GEOObjects.h"
-#include "MaterialLib/MPL/mpMedium.h"
+#include "MaterialLib/MPL/CreateMedium.h"
 #include "MathLib/Curve/CreatePiecewiseLinearCurve.h"
 #include "MeshGeoToolsLib/ConstructMeshesFromGeometries.h"
 #include "MeshGeoToolsLib/CreateSearchLength.h"
@@ -328,32 +328,28 @@ void ProjectData::parseMedia(
     }
 
     for (auto const& medium_config :
-         //! \ogs_file_param{material__media__medium}
+         //! \ogs_file_param{prj__media__medium}
          media_config->getConfigSubtreeList("medium"))
     {
+        //! \ogs_file_attr{prj__media__medium__id}
         auto const material_id = medium_config.getConfigAttribute<int>("id", 0);
 
         if (_media.find(material_id) != _media.end())
         {
             OGS_FATAL(
-                "Multiple media were specified for the same "
-                "material id %d. Keep in mind, that if no material id is "
-                "specified, it is assumed to be 0 by default.",
+                "Multiple media were specified for the same material id %d. "
+                "Keep in mind, that if no material id is specified, it is "
+                "assumed to be 0 by default.",
                 material_id);
         }
 
-        _media[material_id] =
-            std::make_unique<MaterialPropertyLib::Medium>(medium_config);
+        _media[material_id] = MaterialPropertyLib::createMedium(medium_config);
     }
 
     if (_media.empty())
+    {
         OGS_FATAL("No entity is found inside <media>.");
-
-    if (_media.rbegin()->first != static_cast<int>(_media.size()) - 1)
-           OGS_FATAL(
-               "The ids in the porous media definitions in the project file have "
-               "to be sequential, starting with the id zero.");
-
+    }
 }
 
 void ProjectData::parseProcesses(BaseLib::ConfigTree const& processes_config,
diff --git a/Applications/ApplicationsLib/ProjectData.h b/Applications/ApplicationsLib/ProjectData.h
index 7dd6472d28ad6856b32dcd1c2cdbf861009c9e39..1ce3fcbd01aaeb034879d09e77954ac1a6b54ae0 100644
--- a/Applications/ApplicationsLib/ProjectData.h
+++ b/Applications/ApplicationsLib/ProjectData.h
@@ -18,7 +18,7 @@
 #include <string>
 
 #include "BaseLib/ConfigTree.h"
-#include "MaterialLib/MPL/mpMedium.h"
+#include "MaterialLib/MPL/Medium.h"
 #include "MathLib/InterpolationAlgorithms/PiecewiseLinearInterpolation.h"
 
 #include "ProcessLib/Parameter/Parameter.h"
diff --git a/MaterialLib/MPL/Component.cpp b/MaterialLib/MPL/Component.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d3135a9aa01d2b29549074331bb2dc721f928df
--- /dev/null
+++ b/MaterialLib/MPL/Component.cpp
@@ -0,0 +1,48 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "Component.h"
+#include "Components/Components.h"
+#include "Properties/Properties.h"
+
+namespace MaterialPropertyLib
+{
+Component::Component()
+{
+    // Some properties can be initialized by other default properties:
+    _properties[PropertyType::name] = std::make_unique<Constant>("no_name");
+}
+
+Component::Component(std::string const& component_name,
+                     std::unique_ptr<PropertyArray>&& properties)
+{
+    // Some properties can be initialized by other default properties:
+    _properties[PropertyType::name] =
+        std::make_unique<Constant>(component_name);
+
+    if (properties)
+    {
+        overwriteExistingProperties(_properties, *properties);
+    }
+}
+
+Property const& Component::property(PropertyType const& p) const
+{
+    return *_properties[p];
+}
+
+std::string Component::name() const
+{
+    return boost::get<std::string>(_properties[PropertyType::name]->value());
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpComponent.h b/MaterialLib/MPL/Component.h
similarity index 53%
rename from MaterialLib/MPL/mpComponent.h
rename to MaterialLib/MPL/Component.h
index 9d315653f108bc0236a335c7ecb3c128a2feac3b..98c264760d265f5542697c74a4bb20f6de99397b 100644
--- a/MaterialLib/MPL/mpComponent.h
+++ b/MaterialLib/MPL/Component.h
@@ -1,9 +1,10 @@
 /**
+ * \file
  * \author Norbert Grunwald
  * \date   Sep 7, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -11,8 +12,7 @@
  */
 #pragma once
 
-#include "BaseLib/ConfigTree.h"
-#include "mpProperty.h"
+#include "Property.h"
 
 namespace MaterialPropertyLib
 {
@@ -23,32 +23,54 @@ namespace MaterialPropertyLib
 /// located in the 'components' subfolder).
 class Component
 {
-protected:
-    /// The property array of the component.
-    PropertyArray _properties;
-
 public:
     /// Default constructor of Component. This constructor is used
     /// when the component is not specified via the 'name'-tag.
     Component();
 
     /// Constructor for a custom component
-    explicit Component(std::string const& component_name);
+    Component(std::string const& component_name,
+              std::unique_ptr<PropertyArray>&& properties);
     virtual ~Component() = default;
 
-    /// The method reads the 'properties' tag in the prj-file and creates
-    /// component properties accordingly.
-    ///
-    /// First, a new property iy created based on the specified property type.
-    /// Then, the property name is evaluated and the property is copied into the
-    /// properties array.
-    void createProperties(BaseLib::ConfigTree const& /*config*/);
+    /// A get-function for retrieving a certain property.
+    Property const& property(PropertyType const& /*p*/) const;
+
+    template <typename T>
+    T value(PropertyType const p) const
+    {
+        return property(p).template value<T>();
+    }
+
+    template <typename T>
+    T value(PropertyType const p, VariableArray const& variable_array) const
+    {
+        return property(p).template value<T>(variable_array);
+    }
 
-    /// This method initializes the component property array with constant
-    /// functions of value zero.
-    void createDefaultProperties();
-    /// A get-function for retrieving a cartain property.
-    Property& property(PropertyEnum const& /*p*/) const;
+    template <typename T>
+    T dValue(PropertyType const p,
+             VariableArray const& variable_array,
+             Variables const variables) const
+    {
+        return property(p).template dValue<T>(variable_array, variables);
+    }
+
+    template <typename T>
+    T d2Value(PropertyType const p,
+              VariableArray const& variable_array,
+              Variables const variables1,
+              Variables const variables2) const
+    {
+        return property(p).template d2Value<T>(variable_array, variables1,
+                                               variables2);
+    }
+
+    std::string name() const;
+
+protected:
+    /// The property array of the component.
+    PropertyArray _properties;
 };
 
 /// Method for creating a new component based on the specified component name.
@@ -60,6 +82,6 @@ public:
 /// constructors of the derived component classes (if found) or that of the base
 /// class (if no name is specified).
 std::unique_ptr<Component> newComponent(std::string const& component_name,
-                                        bool& isNewComponent);
+                                        bool& isCustomComponent);
 
 }  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Components/components.h b/MaterialLib/MPL/Components/Components.h
similarity index 77%
rename from MaterialLib/MPL/Components/components.h
rename to MaterialLib/MPL/Components/Components.h
index 7a330186731f49f3e0b114bff5725f889ad03d5a..2d243ee441f549e1f051b7c7adae4b4133352d25 100644
--- a/MaterialLib/MPL/Components/components.h
+++ b/MaterialLib/MPL/Components/Components.h
@@ -4,7 +4,7 @@
  * \date   Sep 7, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -12,4 +12,4 @@
  */
 #pragma once
 
-#include "cWater.h"
+#include "Water.h"
diff --git a/MaterialLib/MPL/Components/Water.cpp b/MaterialLib/MPL/Components/Water.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b51f36127e2bc6753ed4b36fe38409e1ad2dba10
--- /dev/null
+++ b/MaterialLib/MPL/Components/Water.cpp
@@ -0,0 +1,28 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "Water.h"
+#include "MaterialLib/MPL/Properties/Properties.h"
+
+namespace MaterialPropertyLib
+{
+Water::Water(std::unique_ptr<PropertyArray>&& properties)
+{
+    _properties[PropertyType::name] = std::make_unique<Constant>("Water");
+
+    if (properties)
+    {
+        overwriteExistingProperties(_properties, *properties);
+    }
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Components/cWater.h b/MaterialLib/MPL/Components/Water.h
similarity index 76%
rename from MaterialLib/MPL/Components/cWater.h
rename to MaterialLib/MPL/Components/Water.h
index 91279e448de6f3be72def679b0a38b18682a3326..de14d8c24b6321ee171858d7f14ea22e3c5ebe0b 100644
--- a/MaterialLib/MPL/Components/cWater.h
+++ b/MaterialLib/MPL/Components/Water.h
@@ -4,7 +4,7 @@
  * \date   Sep 7, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -12,7 +12,7 @@
  */
 #pragma once
 
-#include "MaterialLib/MPL/mpComponent.h"
+#include "MaterialLib/MPL/Component.h"
 
 namespace MaterialPropertyLib
 {
@@ -22,6 +22,6 @@ namespace MaterialPropertyLib
 /// water.
 struct Water final : public Component
 {
-    Water();
+    explicit Water(std::unique_ptr<PropertyArray>&& properties);
 };
 }  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Components/cWater.cpp b/MaterialLib/MPL/Components/cWater.cpp
deleted file mode 100644
index cc36f45473dcf35eb942119a5cbd29cc1c908fda..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/Components/cWater.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   Sep 7, 2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 "cWater.h"
-#include "MaterialLib/MPL/Properties/properties.h"
-
-namespace MaterialPropertyLib
-{
-Water::Water()
-{
-    _properties[name] = std::make_unique<Constant>("Water");
-}
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreateComponent.cpp b/MaterialLib/MPL/CreateComponent.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1364eb9c45ca0415b21d5f732d44026d0fc2ef23
--- /dev/null
+++ b/MaterialLib/MPL/CreateComponent.cpp
@@ -0,0 +1,99 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "CreateComponent.h"
+
+#include "BaseLib/ConfigTree.h"
+
+#include "Components/Components.h"
+#include "CreateProperty.h"
+
+namespace
+{
+std::unique_ptr<MaterialPropertyLib::Component> createComponent(
+    BaseLib::ConfigTree const& config)
+{
+    using namespace MaterialPropertyLib;
+    // Parsing the component name
+    //! \ogs_file_param{prj__media__medium__phases__phase__components__component__name}
+    auto const& component_name = config.getConfigParameter<std::string>("name");
+
+    // Check whether a name is given or not
+    if (component_name.empty())
+    {
+        OGS_FATAL("Component name is a mandatory field and cannot be empty.");
+    }
+
+    // Parsing component properties. If a component name is given and this
+    // component is predefined in the class implementation, properties
+    // become optional. The default values of properties will be overwritten
+    // if specified.
+    std::unique_ptr<PropertyArray> properties =
+        //! \ogs_file_param{prj__media__medium__phases__phase__components__component__properties}
+        createProperties(config.getConfigSubtreeOptional("properties"));
+
+    // If a name is given, it must conform with one of the derived component
+    // names in the following list:
+    if (boost::iequals(component_name, "water"))
+    {
+        return std::make_unique<Water>(std::move(properties));
+    }
+
+    if (!properties)
+    {
+        // No component properties are provided. If the component is not
+        // specified, this results in a fatal error, since an unspecified
+        // component has no properties.
+        OGS_FATAL("No Properties defined for unspecified component");
+    }
+
+    return std::make_unique<Component>(component_name, std::move(properties));
+}
+}
+
+namespace MaterialPropertyLib
+{
+std::vector<std::unique_ptr<Component>> createComponents(
+    boost::optional<BaseLib::ConfigTree> const& config)
+{
+    if (!config)
+    {
+        return {};
+    }
+
+    std::vector<std::unique_ptr<Component>> components;
+
+    // Collect component's names to avoid duplicate components.
+    std::set<std::string> component_names;
+
+    for (
+        auto const& component_config :
+        //! \ogs_file_param{prj__media__medium__phases__phase__components__component}
+        config->getConfigSubtreeList("component"))
+    {
+        auto component = createComponent(component_config);
+
+        bool new_insertion = false;
+        std::tie(std::ignore, new_insertion) =
+            component_names.insert(component->name());
+        if (!new_insertion)
+        {
+            OGS_FATAL("Found duplicates with the same component name tag '%s'.",
+                      component->name().c_str());
+        }
+
+        components.push_back(std::move(component));
+    }
+    return components;
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreateComponent.h b/MaterialLib/MPL/CreateComponent.h
new file mode 100644
index 0000000000000000000000000000000000000000..1109c58e69b786b69cfacb57582a0b7cb31be6f8
--- /dev/null
+++ b/MaterialLib/MPL/CreateComponent.h
@@ -0,0 +1,37 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 <boost/optional.hpp>
+#include <memory>
+
+#include "Component.h"
+
+namespace BaseLib
+{
+class ConfigTree;
+}
+
+namespace MaterialPropertyLib
+{
+/// The method creates components based on config subtree.
+///
+/// Just like a phase, a component can have a name. But, in this case, the name
+/// has an important task. If a name is given, a specific component class
+/// referring to that name with corresponding physical material properties is
+/// created.
+/// Assigning a name is optional; If no name is given, a custom component
+/// without predefined properties is created.
+std::vector<std::unique_ptr<Component>> createComponents(
+    boost::optional<BaseLib::ConfigTree> const& config);
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.cpp b/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.cpp
index bece8854a86dfb027442428de9be1082e7c953e9..9eb5510763ca0e9a7815eff5472254e8359377d4 100644
--- a/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.cpp
+++ b/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.cpp
@@ -3,7 +3,7 @@
  * \date   Nov 28, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -28,12 +28,14 @@ createMaterialSpatialDistributionMap(
             : *std::max_element(begin(*material_ids), end(*material_ids));
 
     if (max_material_id > static_cast<int>(media.size() - 1))
+    {
         OGS_FATAL(
-            "The maximum value of MaterialIDs in mesh is %d. As the "
-            "given number of porous media definitions in the project "
-            "file is %d, the maximum value of MaterialIDs in mesh must be %d "
-            "(index starts with zero).",
+            "The maximum value of MaterialIDs in mesh is %d. As the given "
+            "number of porous media definitions in the project file is %d, the "
+            "maximum value of MaterialIDs in mesh must be %d (index starts "
+            "with zero).",
             max_material_id, media.size(), max_material_id - 1);
+    }
 
     if (max_material_id < static_cast<int>(media.size() - 1))
         WARN(
diff --git a/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.h b/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.h
index 97dc2f44b90cc9dc948860fedf0ffd2885fb6eaf..aad1ea6d4aa622d3b74f66f11b3ad62869197032 100644
--- a/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.h
+++ b/MaterialLib/MPL/CreateMaterialSpatialDistributionMap.h
@@ -3,7 +3,7 @@
  * \date   Nov 28, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
diff --git a/MaterialLib/MPL/CreateMedium.cpp b/MaterialLib/MPL/CreateMedium.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b6c8507b38c7669b69b2771b494b8cf6bd05d0ff
--- /dev/null
+++ b/MaterialLib/MPL/CreateMedium.cpp
@@ -0,0 +1,46 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   07.09.2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "Medium.h"
+
+#include <string>
+#include "BaseLib/ConfigTree.h"
+
+#include "Properties/Properties.h"
+
+#include "CreatePhase.h"
+#include "CreateProperty.h"
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<Medium> createMedium(BaseLib::ConfigTree const& config)
+{
+    // Parsing the phases
+    // Properties of phases may be not required in all the cases.
+    //! \ogs_file_param{prj__media__medium__phases}
+    auto&& phases = createPhases(config.getConfigSubtreeOptional("phases"));
+
+    // Parsing medium properties, overwriting the defaults.
+    auto&& properties =
+        //! \ogs_file_param{prj__media__medium__properties}
+        createProperties(config.getConfigSubtreeOptional("properties"));
+
+    if (phases.empty() && !properties)
+    {
+        OGS_FATAL("Neither tag <phases> nor tag <properties> has been found.");
+    }
+
+    return std::make_unique<Medium>(std::move(phases), std::move(properties));
+}
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreateMedium.h b/MaterialLib/MPL/CreateMedium.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b5c7b94c0c34d80d71cf939146d00f2e296d038
--- /dev/null
+++ b/MaterialLib/MPL/CreateMedium.h
@@ -0,0 +1,32 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   07.09.2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 <memory>
+
+namespace BaseLib
+{
+class ConfigTree;
+}
+namespace MaterialPropertyLib
+{
+class Medium;
+}
+
+namespace MaterialPropertyLib
+{
+/// This function parses the "phases" and "properties" subtrees of the config
+/// tree and calls create methods for the phase vector and the properties array.
+/// Medium properties are optional. If not defined, default properties are
+/// assigned.
+std::unique_ptr<Medium> createMedium(BaseLib::ConfigTree const& config);
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreatePhase.cpp b/MaterialLib/MPL/CreatePhase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8423aef48119571a0f193053888e7eda99e31c28
--- /dev/null
+++ b/MaterialLib/MPL/CreatePhase.cpp
@@ -0,0 +1,112 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   07.09.2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "CreatePhase.h"
+
+#include <set>
+#include <string>
+
+#include "BaseLib/ConfigTree.h"
+
+#include "CreateComponent.h"
+#include "CreateProperty.h"
+#include "Phase.h"
+
+namespace
+{
+std::unique_ptr<MaterialPropertyLib::Phase> createPhase(
+    BaseLib::ConfigTree const& config)
+{
+    using namespace MaterialPropertyLib;
+
+    //! \ogs_file_param{prj__media__medium__phases__phase__type}
+    auto&& phase_type = config.getConfigParameter<std::string>("type");
+
+    if (phase_type.empty())
+    {
+        OGS_FATAL("Phase type is a mandatory field and cannot be empty.");
+    }
+
+    std::array<std::string, 4> const allowed_phase_types = {
+        {"Solid", "AqueousLiquid", "NonAqueousLiquid", "Gas"}};
+
+    if (std::none_of(allowed_phase_types.begin(),
+                     allowed_phase_types.end(),
+                     [&phase_type](std::string const& type) {
+                         return phase_type == type;
+                     }))
+    {
+        ERR("Phase type should be one of:");
+        for (auto const type : allowed_phase_types)
+        {
+            ERR(type.c_str());
+        }
+        OGS_FATAL("Wrong phase type '%s' given.", phase_type.c_str());
+    }
+
+    // Parsing of optional components.
+    auto components =
+        //! \ogs_file_param{prj__media__medium__phases__phase__components}
+        createComponents(config.getConfigSubtreeOptional("components"));
+
+    // Properties of optional properties.
+    auto properties =
+        //! \ogs_file_param{prj__media__medium__phases__phase__properties}
+        createProperties(config.getConfigSubtreeOptional("properties"));
+
+    if (components.empty() && !properties)
+    {
+        OGS_FATAL(
+            "Neither tag <components> nor tag <properties> has been set for "
+            "the phase '%s'.",
+            phase_type.c_str());
+    }
+
+    return std::make_unique<Phase>(
+        std::move(phase_type), std::move(components), std::move(properties));
+}
+}
+
+namespace MaterialPropertyLib
+{
+std::vector<std::unique_ptr<Phase>> createPhases(
+    boost::optional<BaseLib::ConfigTree> const& config)
+{
+    if (!config)
+    {
+        return {};
+    }
+
+    std::vector<std::unique_ptr<Phase>> phases;
+
+    std::set<std::string> phase_names;
+
+    //! \ogs_file_param{prj__media__medium__phases__phase}
+    for (auto phase_config : config->getConfigSubtreeList("phase"))
+    {
+        auto phase = createPhase(phase_config);
+        bool new_insertion = false;
+        std::tie(std::ignore, new_insertion) =
+            phase_names.insert(phase->name());
+
+        if (!new_insertion)
+        {
+            OGS_FATAL("Found duplicates with the same phase name tag '%s'.",
+                      phase->name().c_str());
+        }
+
+        phases.push_back(std::move(phase));
+    }
+    return phases;
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreatePhase.h b/MaterialLib/MPL/CreatePhase.h
new file mode 100644
index 0000000000000000000000000000000000000000..4ea426ef6ce64853ff7a305980b5fb4fbe425798
--- /dev/null
+++ b/MaterialLib/MPL/CreatePhase.h
@@ -0,0 +1,41 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   07.09.2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 <boost/optional.hpp>
+#include <memory>
+#include <vector>
+
+namespace BaseLib
+{
+class ConfigTree;
+}
+namespace MaterialPropertyLib
+{
+class Phase;
+}
+
+namespace MaterialPropertyLib
+{
+/// A method that parses the phase details and stores them in the private
+/// _phases member.
+///
+/// This method creates the phases of the medium. Unlike a medium, a phase may
+/// have a name. However, this is silly at the moment since this name still has
+/// no effect (except of some benefits in regard of readability).
+/// Phase components are required (a phase consists of at least one component).
+/// Phase properties are optional. If not given, default properties are
+/// assigned. These default properties average the component properties,
+/// weighted by mole fraction.
+std::vector<std::unique_ptr<Phase>> createPhases(
+    boost::optional<BaseLib::ConfigTree> const& config);
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreateProperty.cpp b/MaterialLib/MPL/CreateProperty.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..44b3258fce42ba138e1a4b7c12d68b1f6493e892
--- /dev/null
+++ b/MaterialLib/MPL/CreateProperty.cpp
@@ -0,0 +1,151 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "CreateProperty.h"
+
+#include <string>
+#include <vector>
+#include "BaseLib/ConfigTree.h"
+
+#include "Properties/Properties.h"
+
+#include "Component.h"
+#include "Medium.h"
+#include "Phase.h"
+
+namespace
+{
+std::unique_ptr<MaterialPropertyLib::Property> createProperty(
+    BaseLib::ConfigTree const& config)
+{
+    using namespace MaterialPropertyLib;
+    // Parsing the property type:
+    //! \ogs_file_param{properties__property__type}
+    auto const property_type = config.getConfigParameter<std::string>("type");
+
+    // If (and only if) the given property type is 'constant', a
+    // corresponding value is needed.
+    if (property_type == "Constant")
+    {
+        //! \ogs_file_param{properties__property__Constant__value}
+        std::vector<double> const values =
+            config.getConfigParameter<std::vector<double>>("value");
+
+        switch (values.size())
+        {
+            case 1:
+            {
+                // scalar
+                PropertyDataType property_value = values[0];
+                return std::make_unique<Constant>(property_value);
+            }
+            case 2:
+            {
+                // Pair
+                PropertyDataType property_value = Pair{values[0], values[1]};
+                return std::make_unique<Constant>(property_value);
+            }
+            case 3:
+            {
+                // Vector
+                PropertyDataType property_value =
+                    Vector{values[0], values[1], values[2]};
+                return std::make_unique<Constant>(property_value);
+            }
+            case 6:
+            {
+                // Symmetric Tensor - xx, yy, zz, xy, xz, yz
+                PropertyDataType property_value =
+                    SymmTensor{values[0], values[1], values[2],
+                               values[3], values[4], values[5]};
+                return std::make_unique<Constant>(property_value);
+            }
+            case 9:
+            {
+                // Tensor
+                PropertyDataType property_value = Tensor{
+                    values[0], values[1], values[2], values[3], values[4],
+                    values[5], values[6], values[7], values[8]};
+                return std::make_unique<Constant>(property_value);
+            }
+
+            default:
+            {
+                OGS_FATAL(
+                    "Creation of a constant property with %i components is not "
+                    "implemented.",
+                    values.size());
+            }
+        }
+
+        PropertyDataType property_value;
+        return std::make_unique<Constant>(property_value);
+    }
+    // Properties can be medium, phase, or component properties.
+    // Some of them require information about the respective material.
+    // Thus, we pass a pointer to the material that requests the property.
+    // In this method, this pointer is realized via typename MaterialType, which
+    // replaces either Medium*, Phase*, or Component*.
+    // Note that most property constructors (only those that request material
+    // pointers) must be overloaded for any type of material.
+
+    /* TODO Additional properties go here, for example:
+    if (boost::iequals(property_type, "BilinearTemperaturePressure"))
+    {
+        return createBilinearTemperaturePressure(config, material_type);
+    }
+    */
+
+    // 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());
+}
+}  // namespace
+
+namespace MaterialPropertyLib
+{
+std::unique_ptr<PropertyArray> createProperties(
+    boost::optional<BaseLib::ConfigTree> const& config)
+{
+    if (!config)
+    {
+        return nullptr;
+    }
+
+    //! \ogs_file_param{properties__property}
+    auto const& property_configs = config->getConfigSubtreeList("property");
+    if (property_configs.empty())
+    {
+        return nullptr;
+    }
+
+    auto properties = std::make_unique<PropertyArray>();
+
+    for (auto property_config : property_configs)
+    {
+        // Parsing the property name:
+        auto const property_name =
+            //! \ogs_file_param{properties__property__name}
+            property_config.getConfigParameter<std::string>("name");
+        // Create a new property based on the configuration subtree:
+        auto property = createProperty(property_config);
+
+        // Insert the new property at the right position into the components
+        // private PropertyArray:
+        (*properties)[convertStringToProperty(property_name)] =
+            std::move(property);
+    }
+    return properties;
+}
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/CreateProperty.h b/MaterialLib/MPL/CreateProperty.h
new file mode 100644
index 0000000000000000000000000000000000000000..777e9181c67149e1f333105d43b2d439e2a71998
--- /dev/null
+++ b/MaterialLib/MPL/CreateProperty.h
@@ -0,0 +1,43 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 <boost/optional/optional.hpp>
+#include <memory>
+#include "PropertyType.h"
+
+namespace BaseLib
+{
+class ConfigTree;
+}
+
+namespace MaterialPropertyLib
+{
+class Property;
+
+/// This data type is based on a std::array. It can hold pointers to objects of
+/// class Property or its inheritors. The size of this array is determined by
+/// the number of entries of the PropertyType enumerator.
+using PropertyArray =
+    std::array<std::unique_ptr<Property>, PropertyType::number_of_properties>;
+
+/// The method reads the 'properties' tag in the prj-file and creates component
+/// properties accordingly.
+///
+/// First, a new property iy created based on the specified property type.
+/// Then, the property name is evaluated and the property is copied into the
+/// properties array.
+std::unique_ptr<PropertyArray> createProperties(
+    boost::optional<BaseLib::ConfigTree> const& config);
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/MaterialSpatialDistributionMap.cpp b/MaterialLib/MPL/MaterialSpatialDistributionMap.cpp
index 0a81d547026ada9dca1a04da37f0051a40027116..7e791a0b8d9839b8512e69034549bd03b5f2d8cb 100644
--- a/MaterialLib/MPL/MaterialSpatialDistributionMap.cpp
+++ b/MaterialLib/MPL/MaterialSpatialDistributionMap.cpp
@@ -3,7 +3,7 @@
  * \date   Nov 28, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
diff --git a/MaterialLib/MPL/MaterialSpatialDistributionMap.h b/MaterialLib/MPL/MaterialSpatialDistributionMap.h
index b49da6d8bd0eeccb2f328edbb799d938e3545ac6..fd9976226fb9e9162222fc09b118e07df744f9d1 100644
--- a/MaterialLib/MPL/MaterialSpatialDistributionMap.h
+++ b/MaterialLib/MPL/MaterialSpatialDistributionMap.h
@@ -3,7 +3,7 @@
  * \date   Nov 28, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -27,10 +27,6 @@ class Medium;
 
 class MaterialSpatialDistributionMap
 {
-private:
-    std::map<int, std::unique_ptr<Medium>> const& _media;
-    MeshLib::PropertyVector<int> const* const _material_ids;
-
 public:
     MaterialSpatialDistributionMap(
         std::map<int, std::unique_ptr<Medium>> const& media,
@@ -40,5 +36,9 @@ public:
     }
 
     Medium* getMedium(std::size_t element_id);
+
+private:
+    std::map<int, std::unique_ptr<Medium>> const& _media;
+    MeshLib::PropertyVector<int> const* const _material_ids;
 };
 }  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Medium.cpp b/MaterialLib/MPL/Medium.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7830cb85bb91d687bc40ed3d5b588886a2407306
--- /dev/null
+++ b/MaterialLib/MPL/Medium.cpp
@@ -0,0 +1,55 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   07.09.2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "Medium.h"
+
+#include "BaseLib/Algorithm.h"
+#include "Properties/Properties.h"
+
+namespace MaterialPropertyLib
+{
+Medium::Medium(std::vector<std::unique_ptr<Phase>>&& phases,
+               std::unique_ptr<PropertyArray>&& properties)
+    : _phases(std::move(phases))
+{
+    if (properties)
+    {
+        overwriteExistingProperties(_properties, *properties);
+    }
+}
+
+Phase const& Medium::phase(std::size_t const index) const
+{
+    return *_phases[index];
+}
+
+Phase const& Medium::phase(std::string const& name) const
+{
+    return *BaseLib::findElementOrError(
+        _phases.begin(), _phases.end(),
+        [&name](std::unique_ptr<MaterialPropertyLib::Phase> const& phase) {
+            return phase->name() == name;
+        },
+        "Could not find phase name '" + name + "'.");
+}
+
+Property const& Medium::property(PropertyType const& p) const
+{
+    return *_properties[p];
+}
+
+std::size_t Medium::numberOfPhases() const
+{
+    return _phases.size();
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Medium.h b/MaterialLib/MPL/Medium.h
new file mode 100644
index 0000000000000000000000000000000000000000..49c5eeec8e00b60cae395fb50d4ca3bfc83759fa
--- /dev/null
+++ b/MaterialLib/MPL/Medium.h
@@ -0,0 +1,91 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   07.09.2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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>
+#include <string>
+#include <vector>
+
+#include "Phase.h"
+
+namespace MaterialPropertyLib
+{
+class Property;
+}
+namespace MaterialPropertyLib
+{
+/// This class is for material objects on the Medium scale.
+///
+/// A Medium consists of an arbitrarily long vector of phases and an array of
+/// properties.
+class Medium final
+{
+public:
+    Medium(std::vector<std::unique_ptr<Phase>>&& phases,
+           std::unique_ptr<PropertyArray>&& properties);
+
+    /// A get-function for a particular phase. The ul argument specifies the
+    /// index within the _phases vector.
+    Phase const& phase(std::size_t index) const;
+    /// A get-function for a particular phase by phase name.
+    Phase const& phase(std::string const& phase_name) const;
+    /// A get-function for a property. The argument refers to the name of the
+    /// property.
+    Property const& property(PropertyType const& p) const;
+
+    /// A simple get-function for retrieving the number of phases the medium
+    /// consists of.
+    std::size_t numberOfPhases() const;
+
+    template <typename T>
+    T value(PropertyType const p) const
+    {
+        return property(p).template value<T>();
+    }
+
+    template <typename T>
+    T value(PropertyType const p, VariableArray const& variable_array) const
+    {
+        return property(p).template value<T>(variable_array);
+    }
+
+    template <typename T>
+    T dValue(PropertyType const p,
+             VariableArray const& variable_array,
+             Variables const variables) const
+    {
+        return property(p).template dValue<T>(variable_array, variables);
+    }
+
+    template <typename T>
+    T d2Value(PropertyType const p,
+              VariableArray const& variable_array,
+              Variables const variables1,
+              Variables const variables2) const
+    {
+        return property(p).template d2Value<T>(variable_array, variables1,
+                                               variables2);
+    }
+
+private:
+    /// The vector that holds the phases.
+    std::vector<std::unique_ptr<Phase>> const _phases;
+    /// The array that holds the medium properties.
+    ///
+    /// Currently, these defaults is the volume fraction average.
+    ///
+    /// Most properties are fine with the volume fraction average, but
+    /// special-defaults are allowed as well...
+    PropertyArray _properties;
+};
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Phase.cpp b/MaterialLib/MPL/Phase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..203bd92f51b0098ae8fc3d2f4cb092c62b9259d2
--- /dev/null
+++ b/MaterialLib/MPL/Phase.cpp
@@ -0,0 +1,64 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "Phase.h"
+#include "BaseLib/Algorithm.h"
+#include "Properties/Properties.h"
+
+#include "Component.h"
+
+namespace MaterialPropertyLib
+{
+Phase::Phase(std::string&& phase_name,
+             std::vector<std::unique_ptr<Component>>&& components,
+             std::unique_ptr<PropertyArray>&& properties)
+    : _components(std::move(components))
+{
+    _properties[PropertyType::name] = std::make_unique<Constant>(phase_name);
+
+    if (properties)
+    {
+        overwriteExistingProperties(_properties, *properties);
+    }
+}
+
+Component const& Phase::component(const std::size_t& index) const
+{
+    return *_components[index];
+}
+
+Component const& Phase::component(std::string const& name) const
+{
+    return *BaseLib::findElementOrError(
+        _components.begin(), _components.end(),
+        [&name](std::unique_ptr<Component> const& component) {
+            return component->name() == name;
+        },
+        "Could not find component name '" + name + "'.");
+}
+
+Property const& Phase::property(PropertyType const& p) const
+{
+    return *_properties[p];
+}
+
+std::size_t Phase::numberOfComponents() const
+{
+    return _components.size();
+}
+
+std::string Phase::name() const
+{
+    return boost::get<std::string>(_properties[PropertyType::name]->value());
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Phase.h b/MaterialLib/MPL/Phase.h
new file mode 100644
index 0000000000000000000000000000000000000000..12eddbe4b81ee1bdf747583cf8b5f97cf0b498c4
--- /dev/null
+++ b/MaterialLib/MPL/Phase.h
@@ -0,0 +1,66 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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>
+#include <string>
+#include <vector>
+
+#include "Component.h"
+
+namespace MaterialPropertyLib
+{
+class Property;
+}
+namespace MaterialPropertyLib
+{
+/// This class defines material phases.
+///
+/// The Phase class consists of a vector of components and an array of
+/// properties.
+class Phase final
+{
+public:
+    /// The Phase constructor is called with the optional phase name.
+    Phase(std::string&& phase_name,
+          std::vector<std::unique_ptr<Component>>&& components,
+          std::unique_ptr<PropertyArray>&& properties);
+
+    /// A simple get-function for a component. The argument refers to the
+    /// Index of the component in the components vector.
+    Component const& component(std::size_t const& index) const;
+
+    /// A get-function for a component by component name.
+    Component const& component(std::string const& name) const;
+
+    /// A get-function for a property. The argument refers to the name of the
+    /// property.
+    Property const& property(PropertyType const& p) const;
+
+    /// A get-function for retrieving the number of components in this phase.
+    std::size_t numberOfComponents() const;
+
+    std::string name() const;
+
+private:
+    std::vector<std::unique_ptr<Component>> const _components;
+
+    /// Here, all for all properties listed in the Properties enumerator are
+    /// initialized by mole average functions of value zero. However,
+    /// 'special-default' properties are allowed to be set.
+    ///
+    /// After this, other special properties can be set as exceptional defaults.
+    PropertyArray _properties;
+};
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Properties/pConstant.cpp b/MaterialLib/MPL/Properties/Constant.cpp
similarity index 85%
rename from MaterialLib/MPL/Properties/pConstant.cpp
rename to MaterialLib/MPL/Properties/Constant.cpp
index 603ff60cdbe801c138e444751d26c2bd2ef33131..fe63a021bc22253c87e1976763eb1f5fcd83c525 100644
--- a/MaterialLib/MPL/Properties/pConstant.cpp
+++ b/MaterialLib/MPL/Properties/Constant.cpp
@@ -4,14 +4,14 @@
  * \date   Sep 7, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, 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 "pConstant.h"
+#include "Constant.h"
 
 namespace MaterialPropertyLib
 {
diff --git a/MaterialLib/MPL/Properties/pConstant.h b/MaterialLib/MPL/Properties/Constant.h
similarity index 89%
rename from MaterialLib/MPL/Properties/pConstant.h
rename to MaterialLib/MPL/Properties/Constant.h
index 17bda74f57df56ddddaebdffa9a58e044211ee01..880806d5441aea41fb44f31c61444f98685e726b 100644
--- a/MaterialLib/MPL/Properties/pConstant.h
+++ b/MaterialLib/MPL/Properties/Constant.h
@@ -4,7 +4,7 @@
  * \date   Sep 7, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -12,7 +12,7 @@
  */
 #pragma once
 
-#include "MaterialLib/MPL/mpProperty.h"
+#include "MaterialLib/MPL/Property.h"
 
 namespace MaterialPropertyLib
 {
diff --git a/MaterialLib/MPL/Properties/properties.h b/MaterialLib/MPL/Properties/Properties.h
similarity index 71%
rename from MaterialLib/MPL/Properties/properties.h
rename to MaterialLib/MPL/Properties/Properties.h
index 0e919e5aa7ad7ab240fe117498b5d8c59660137a..d56c81083a7768eeca174ffcc0cbb64e6b5c7efc 100644
--- a/MaterialLib/MPL/Properties/properties.h
+++ b/MaterialLib/MPL/Properties/Properties.h
@@ -4,7 +4,7 @@
  * \date   Sep 7, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -12,5 +12,4 @@
  */
 #pragma once
 
-#include "pConstant.h"
-#include "pUndefined.h"
+#include "Constant.h"
diff --git a/MaterialLib/MPL/Properties/pUndefined.cpp b/MaterialLib/MPL/Properties/pUndefined.cpp
deleted file mode 100644
index d4546ce9d2354742ae7ddabf07e4f9468ae1dbb5..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/Properties/pUndefined.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   July 3rd, 2018
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 "pUndefined.h"
-#include <string>
-#include "MaterialLib/MPL/mpEnums.h"
-
-namespace MaterialPropertyLib
-{
-Undefined::Undefined(PropertyEnum const& pEnum)
-{
-    thisPropertyEnum = pEnum;
-}
-
-PropertyDataType Undefined::value() const
-{
-    std::string property = convertEnumToString[thisPropertyEnum];
-
-    OGS_FATAL(
-        "The property \'%s\' (property-enum no. %i in "
-        "MaterialLib/MPL/mpEnums.h) was requested, but is not defined in the "
-        "project file.",
-        property.c_str(), (int)thisPropertyEnum);
-}
-
-PropertyDataType Undefined::value(VariableArray const& /*v*/)
-{
-    return value();
-}
-}  // MaterialPropertyLib
-
-
diff --git a/MaterialLib/MPL/Properties/pUndefined.h b/MaterialLib/MPL/Properties/pUndefined.h
deleted file mode 100644
index d614cf30176dd5011a76949d89f88854b084a975..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/Properties/pUndefined.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   July 3rd, 2018
- *
- * \copyright
- * Copyright (c) 2012-2018, 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/mpProperty.h"
-
-namespace MaterialPropertyLib
-{
-/// The constant property class. This property simply retrieves the stored
-/// constant value. It accepts all datatypes defined in PropertyDataType.
-class Undefined final : public Property
-{
-private:
-    PropertyEnum thisPropertyEnum;
-public:
-    explicit Undefined(PropertyEnum const&);
-    PropertyDataType value() const override;
-    PropertyDataType value(VariableArray const&) override;
-};
-}  // MaterialPropertyLib
diff --git a/MaterialLib/MPL/Property.cpp b/MaterialLib/MPL/Property.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..53c0e46c072f6b7c2f927788345b0b2bf367bf80
--- /dev/null
+++ b/MaterialLib/MPL/Property.cpp
@@ -0,0 +1,54 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 "Property.h"
+
+#include <string>
+
+namespace MaterialPropertyLib
+{
+
+PropertyDataType Property::value() const
+{
+    return _value;
+}
+/// The default implementation of this method only returns the property value
+/// without altering it.
+PropertyDataType Property::value(VariableArray const& /*variable_array*/) const
+{
+    return _value;
+}
+
+/// The default implementation of this method only returns the
+/// property value derivative without altering it.
+PropertyDataType Property::dValue(VariableArray const& /*variable_array*/,
+                                  Variables const /*variables*/) const
+{
+    return _dvalue;
+}
+
+/// Default implementation: 2nd derivative of any constant property is zero.
+PropertyDataType Property::d2Value(VariableArray const& /*variable_array*/,
+                                   Variables const /*variables*/,
+                                   Variables const /*variables*/) const
+{
+    return 0.0;
+}
+
+void Property::notImplemented(const std::string& property,
+                              const std::string& material) const
+{
+    OGS_FATAL("The property '%s' is not available on the '%s' scale",
+              property.c_str(), material.c_str());
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/Property.h b/MaterialLib/MPL/Property.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc8f9c45f610d17d772043e5f300a37427aa122c
--- /dev/null
+++ b/MaterialLib/MPL/Property.h
@@ -0,0 +1,116 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 <array>
+#include <boost/variant.hpp>
+#include <string>
+
+#include "PropertyType.h"
+#include "VariableType.h"
+
+namespace MaterialPropertyLib
+{
+/// This is a custom data type for arbitrary properties, based on the
+/// boost::variant container. It can hold scalars, vectors, tensors, and so
+/// forth.
+enum PropertyDataTypeName
+{
+    nScalar,
+    nPair,
+    nVector,
+    nSymmTensor,
+    nTensor
+};
+
+using PropertyDataType =
+    boost::variant<double, Pair, Vector, SymmTensor, Tensor, std::string>;
+
+/// This class is the base class for any material property of any
+/// scale (i.e. components, phases, media, ...). The single value of
+/// that Property can hold scalars, vectors, tensors, strings, etc.
+class Property
+{
+public:
+    virtual ~Property() = default;
+    /// This method is called when a property is used for the wrong kind of
+    /// material, or if the property is not implemented on this kind of material
+    /// yet.
+    void notImplemented(const std::string& property,
+                        const std::string& material) const;
+    /// This virtual method simply returns the private _value attribute without
+    /// changing it.
+    virtual PropertyDataType value() const;
+    /// This virtual method will compute the property value based on the primary
+    /// variables that are passed as arguments.
+    virtual PropertyDataType value(VariableArray const& variable_array) const;
+    /// This virtual method will compute the derivative of a property
+    /// with respect to the given variables pv.
+    virtual PropertyDataType dValue(VariableArray const& variable_array,
+                                    Variables const variables) const;
+    /// This virtual method will compute the second derivative of a
+    /// property with respect to the given variables pv1 and pv2.
+    virtual PropertyDataType d2Value(VariableArray const& variable_array,
+                                     Variables const variables1,
+                                     Variables const variables2) const;
+
+    template <typename T>
+    T value() const
+    {
+        return boost::get<T>(value());
+    }
+    template <typename T>
+    T value(VariableArray const& variable_array) const
+    {
+        return boost::get<T>(value(variable_array));
+    }
+    template <typename T>
+    T dValue(VariableArray const& variable_array,
+             Variables const variables) const
+    {
+        return boost::get<T>(dValue(variable_array, variables));
+    }
+    template <typename T>
+    T d2Value(VariableArray const& variable_array,
+              Variables const& variables1,
+              Variables const& variables2) const
+    {
+        return boost::get<T>(d2Value(variable_array, variables1, variables2));
+    }
+
+protected:
+    /// The single value of a property.
+    PropertyDataType _value;
+    PropertyDataType _dvalue;
+};
+
+/// This method returns the 0-based index of the variant data types. Can be
+/// enhanced by using enums.
+inline std::size_t getType(Property const& p)
+{
+    return p.value().which();
+}
+
+inline void overwriteExistingProperties(PropertyArray& properties,
+                                        PropertyArray& new_properties)
+{
+    for (std::size_t i = 0; i < properties.size(); ++i)
+    {
+        if (new_properties[i] != nullptr)
+        {
+            properties[i] = std::move(new_properties[i]);
+        }
+    }
+}
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/PropertyType.h b/MaterialLib/MPL/PropertyType.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ab8534019f071cb31d506261dc46031ef6c3cca
--- /dev/null
+++ b/MaterialLib/MPL/PropertyType.h
@@ -0,0 +1,274 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 <array>
+#include <boost/algorithm/string/predicate.hpp>
+#include <memory>
+#include <string>
+#include "BaseLib/Error.h"
+
+namespace MaterialPropertyLib
+{
+class Property;
+}
+
+namespace MaterialPropertyLib
+{
+/// PropertyType is an enumerator list of all known properties of a substance.
+/// This includes all properties on all scales (i.e. component, phase, and
+/// medium scales). It is used as an index for the PropertyArray of the
+/// materials. If a necessary property is not in the list, simply add a new one
+/// in alphabetical order (of course, except for the last entry). Please note
+/// that any of these entries must also appear in below convert functions.
+enum PropertyType : int
+{
+    acentric_factor,
+    binary_interaction_coefficient,
+    biot_coefficient,
+    brooks_corey_exponent,
+    bulk_modulus,
+    critical_density,
+    critical_pressure,
+    critical_temperature,
+    compressibility,
+    density,
+    drhodT,
+    effective_stress,
+    entry_pressure,
+    fredlund_parameters,
+    heat_capacity,
+    longitudinal_dispersivity,
+    molar_mass,
+    mole_fraction,
+    molecular_diffusion,
+    name,
+    permeability,
+    phase_velocity,
+    porosity,
+    reference_density,
+    reference_temperature,
+    reference_pressure,
+    relative_permeability,
+    residual_gas_saturation,
+    residual_liquid_saturation,
+    saturation,
+    specific_heat_capacity,
+    thermal_conductivity,
+    thermal_expansivity,
+    transversal_dispersivity,
+    viscosity,
+    number_of_properties
+};
+
+/// This function converts a string (e.g. a string from the configuration-tree)
+/// into one of the entries of the PropertyType enumerator. To avoid confusion,
+/// I suggest that the syntax of the properties in the input-files (i.e. the
+/// strings) have to be identical to the syntax of the entries in the
+/// enumerator.
+inline PropertyType convertStringToProperty(std::string const& inString)
+{
+    if (boost::iequals(inString, "acentric_factor"))
+    {
+        return PropertyType::acentric_factor;
+    }
+    if (boost::iequals(inString, "binary_interaction_coefficient"))
+    {
+        return PropertyType::binary_interaction_coefficient;
+    }
+    if (boost::iequals(inString, "biot_coefficient"))
+    {
+        return PropertyType::biot_coefficient;
+    }
+    if (boost::iequals(inString, "brooks_corey_exponent"))
+    {
+        return PropertyType::brooks_corey_exponent;
+    }
+    if (boost::iequals(inString, "bulk_modulus"))
+    {
+        return PropertyType::bulk_modulus;
+    }
+    if (boost::iequals(inString, "critical_density"))
+    {
+        return PropertyType::critical_density;
+    }
+    if (boost::iequals(inString, "critical_pressure"))
+    {
+        return PropertyType::critical_pressure;
+    }
+    if (boost::iequals(inString, "critical_temperature"))
+    {
+        return PropertyType::critical_temperature;
+    }
+    if (boost::iequals(inString, "compressibility"))
+    {
+        return PropertyType::compressibility;
+    }
+    if (boost::iequals(inString, "density"))
+    {
+        return PropertyType::density;
+    }
+    if (boost::iequals(inString, "drhodT"))
+    {
+        return PropertyType::drhodT;
+    }
+    if (boost::iequals(inString, "effective_stress"))
+    {
+        return PropertyType::effective_stress;
+    }
+    if (boost::iequals(inString, "entry_pressure"))
+    {
+        return PropertyType::entry_pressure;
+    }
+    if (boost::iequals(inString, "fredlund_parameters"))
+    {
+        return PropertyType::fredlund_parameters;
+    }
+    if (boost::iequals(inString, "heat_capacity"))
+    {
+        return PropertyType::heat_capacity;
+    }
+    if (boost::iequals(inString, "longitudinal_dispersivity"))
+    {
+        return PropertyType::longitudinal_dispersivity;
+    }
+    if (boost::iequals(inString, "molar_mass"))
+    {
+        return PropertyType::molar_mass;
+    }
+    if (boost::iequals(inString, "mole_fraction"))
+    {
+        return PropertyType::mole_fraction;
+    }
+    if (boost::iequals(inString, "molecular_diffusion"))
+    {
+        return PropertyType::molecular_diffusion;
+    }
+    if (boost::iequals(inString, "name"))
+    {
+        return PropertyType::name;
+    }
+    if (boost::iequals(inString, "permeability"))
+    {
+        return PropertyType::permeability;
+    }
+    if (boost::iequals(inString, "porosity"))
+    {
+        return PropertyType::porosity;
+    }
+    if (boost::iequals(inString, "phase_velocity"))
+    {
+        return PropertyType::phase_velocity;
+    }
+    if (boost::iequals(inString, "reference_density"))
+    {
+        return PropertyType::reference_density;
+    }
+    if (boost::iequals(inString, "reference_temperature"))
+    {
+        return PropertyType::reference_temperature;
+    }
+    if (boost::iequals(inString, "reference_pressure"))
+    {
+        return PropertyType::reference_pressure;
+    }
+    if (boost::iequals(inString, "relative_permeability"))
+    {
+        return PropertyType::relative_permeability;
+    }
+    if (boost::iequals(inString, "residual_gas_saturation"))
+    {
+        return PropertyType::residual_gas_saturation;
+    }
+    if (boost::iequals(inString, "residual_liquid_saturation"))
+    {
+        return PropertyType::residual_liquid_saturation;
+    }
+    if (boost::iequals(inString, "saturation"))
+    {
+        return PropertyType::saturation;
+    }
+    if (boost::iequals(inString, "specific_heat_capacity"))
+    {
+        return PropertyType::specific_heat_capacity;
+    }
+    if (boost::iequals(inString, "thermal_conductivity"))
+    {
+        return PropertyType::thermal_conductivity;
+    }
+    if (boost::iequals(inString, "thermal_expansivity"))
+    {
+        return PropertyType::thermal_expansivity;
+    }
+    if (boost::iequals(inString, "transversal_dispersivity"))
+    {
+        return PropertyType::transversal_dispersivity;
+    }
+    if (boost::iequals(inString, "viscosity"))
+    {
+        return PropertyType::viscosity;
+    }
+
+    OGS_FATAL(
+        "The property name '%s' does not correspond to any known property",
+        inString.c_str());
+
+    return PropertyType::number_of_properties;  // to avoid the 'no return'
+                                                // warning
+}
+
+static const std::array<std::string, PropertyType::number_of_properties>
+    property_enum_to_string{{"acentric_factor",
+                             "binary_interaction_coefficient",
+                             "biot_coefficient",
+                             "brooks_corey_exponent",
+                             "bulk_modulus",
+                             "critical_density",
+                             "critical_pressure",
+                             "critical_temperature",
+                             "compressibility",
+                             "density",
+                             "drhodT",
+                             "effective_stress",
+                             "entry_pressure",
+                             "fredlund_parameters",
+                             "heat_capacity",
+                             "longitudinal_dispersivity",
+                             "molar_mass",
+                             "mole_fraction",
+                             "molecular_diffusion",
+                             "name",
+                             "permeability",
+                             "phase_velocity",
+                             "porosity",
+                             "reference_density",
+                             "reference_temperature",
+                             "reference_pressure",
+                             "relative_permeability",
+                             "residual_gas_saturation",
+                             "residual_liquid_saturation",
+                             "saturation",
+                             "specific_heat_capacity",
+                             "thermal_conductivity",
+                             "thermal_expansivity",
+                             "transversal_dispersivity",
+                             "viscosity"}};
+
+/// This data type is based on a std::array. It can hold pointers to objects of
+/// class Property or its inheritors. The size of this array is determined by
+/// the number of entries of the PropertyType enumerator.
+using PropertyArray =
+    std::array<std::unique_ptr<Property>, PropertyType::number_of_properties>;
+
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/VariableType.h b/MaterialLib/MPL/VariableType.h
new file mode 100644
index 0000000000000000000000000000000000000000..539a94ca036e7b01210de8626904db1d1c456e7f
--- /dev/null
+++ b/MaterialLib/MPL/VariableType.h
@@ -0,0 +1,66 @@
+/**
+ * \file
+ * \author Norbert Grunwald
+ * \date   Sep 7, 2017
+ *
+ * \copyright
+ * Copyright (c) 2012-2019, 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 <array>
+#include <boost/variant.hpp>
+
+namespace MaterialPropertyLib
+{
+/// Very simple vector data type for holding
+/// a pair of values.
+using Pair = std::array<double, 2>;
+
+/// Very simple vector data type for holding
+/// vector components.
+using Vector = std::array<double, 3>;
+
+/// Simple symmetric tensor data type for holding
+/// xx, yy, zz, xy, xz, yz tensor components.
+using SymmTensor = std::array<double, 6>;
+
+/// Very simple tensor data type for holding
+/// tensor components.
+using Tensor = std::array<double, 9>;
+
+/// Variables is simply a list of all commonly used variables that are used to
+/// determine the size of the VariableArray. If the variable of your choice is
+/// missing, simply add it somewhere at the list, but above the last entry.
+enum Variables : int
+{
+    phase_pressure,
+    capillary_pressure,
+    gas_density,
+    liquid_density,
+    temperature,
+    liquid_saturation,
+    u,
+    number_of_variables
+};
+
+/// Data type for primary variables, designed to contain both scalar and vector
+/// data.
+using VariableType = boost::variant<double, Vector>;
+
+/// The VariableArray is a std::array of fixed size. Its size is determined by
+/// the Variables enumerator list. Data type of that array is defined by the
+/// VariableType definition.
+using VariableArray = std::array<VariableType, Variables::number_of_variables>;
+
+/// This method returns a value of type double from the variables array
+inline double getScalar(VariableType pv)
+{
+    return boost::get<double>(pv);
+}
+}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpComponent.cpp b/MaterialLib/MPL/mpComponent.cpp
deleted file mode 100644
index 940927db78e1565a6825fa33da3b95b1e6bc6695..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpComponent.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   Sep 7, 2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 "mpComponent.h"
-#include "Components/components.h"
-#include "Properties/properties.h"
-
-namespace MaterialPropertyLib
-{
-Component::Component()
-{
-    // Default properties are set to zero.
-    createDefaultProperties();
-
-    // Some properties can be initialized by other default properties:
-    _properties[name] = std::make_unique<Constant>("no_name");
-}
-Component::Component(std::string const& component_name)
-{
-    // Default properties are set to zero.
-    createDefaultProperties();
-
-    // Some properties can be initialized by other default properties:
-    _properties[name] = std::make_unique<Constant>(component_name);
-}
-
-void Component::createProperties(BaseLib::ConfigTree const& config)
-{
-    for (auto property_config : config.getConfigSubtreeList("property"))
-    {
-        // Parsing the property name:
-        auto const property_name =
-            property_config.getConfigParameter<std::string>("name");
-        // Create a new property based on the configuration subtree:
-        auto property = newProperty(property_config, this);
-
-        // Insert the new property at the right position into the components
-        // private PropertyArray:
-        _properties[convertStringToProperty(property_name)] =
-            std::move(property);
-    }
-}
-
-void Component::createDefaultProperties()
-{
-    for (std::size_t i = 0; i < number_of_property_enums; ++i)
-    {
-        _properties[i] =
-            std::make_unique<Undefined>(static_cast<PropertyEnum>(i));
-    }
-}
-
-Property& Component::property(PropertyEnum const& p) const
-{
-    return *_properties[p];
-}
-
-std::unique_ptr<Component> newComponent(std::string const& component_name,
-                                        bool& isCustomComponent)
-{
-    // If a name is given, it must conform with one of the derived component
-    // names in the following list:
-    if (boost::iequals(component_name, "water"))
-    {
-        return std::make_unique<Water>();
-    }
-
-    // If the given name does not appear in the list (which is common), the
-    // method creates a custom component, where all properties have to be
-    // specified manually.
-    isCustomComponent = true;
-    return std::make_unique<Component>(component_name);
-}
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpEnums.h b/MaterialLib/MPL/mpEnums.h
deleted file mode 100644
index 9f185f4c5bde6564220a5a8ca73dae1ec00d7199..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpEnums.h
+++ /dev/null
@@ -1,311 +0,0 @@
-/**
- * \author Norbert Grunwald
- * \date   Sep 7, 2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 <boost/algorithm/string/predicate.hpp>
-#include <boost/variant.hpp>
-#include <array>
-#include <cstddef>
-#include <string>
-#include "BaseLib/Error.h"
-
-namespace MaterialPropertyLib
-{
-/// Very simple vector data type for holding
-/// a pair of values.
-using Pair = std::array<double, 2>;
-
-/// Very simple vector data type for holding
-/// vector components.
-using Vector = std::array<double, 3>;
-
-/// Simple symmetric tensor data type for holding
-/// xx, yy, zz, xy, xz, yz tensor components.
-using SymmTensor = std::array<double, 9>;
-
-/// Very simple tensor data type for holding
-/// tensor components.
-using Tensor = std::array<double, 9>;
-
-/// Variables is simply a list of all commonly used variables that are used to
-/// determine the size of the VariableArray. If the variable of your choice is
-/// missing, simply add it somewhere at the list, but above the last entry
-/// 'numberOfVariables'
-enum Variables : std::size_t
-{
-    phase_pressure,
-    capillary_pressure,
-    gas_density,
-    liquid_density,
-    temperature,
-    liquid_saturation,
-    u,
-    numberOfVariables
-};
-
-/// Data type for primary variables, designed to contain both scalar and vector
-/// data.
-using VariableType = boost::variant<double, Vector>;
-
-/// The VariableArray is a std::array of fixed size. Its size is determined by
-/// the Variables enumerator list. Data type of that array is defined by the
-/// VariableType definition.
-using VariableArray = std::array<VariableType, numberOfVariables>;
-
-/// This method returns a value of type double from the variables array
-inline double getScalar(VariableType pv)
-{
-    return boost::get<double>(pv);
-}
-
-/// PropertyEnum is an enumerator list of all known properties of a substance.
-/// This includes all properties on all scales (i.e. component, phase, and
-/// medium scales). It is used as an indexer for the PropertyArray of the
-/// materials. If a necessary property is not in the list, simply add a new one
-/// in alphabetical order (of course, except for the last entry
-/// 'number_of_property_enums'). Please note that any of these entries must also
-/// appear in below convert functions.
-enum PropertyEnum : std::size_t
-{
-    acentric_factor,
-    binary_interaction_coefficient,
-    biot_coefficient,
-    brooks_corey_exponent,
-    bulk_modulus,
-    critical_density,
-    critical_pressure,
-    critical_temperature,
-    compressibility,
-    density,
-    drhodT,
-    effective_stress,
-    entry_pressure,
-    fredlund_parameters,
-    heat_capacity,
-    longitudinal_dispersivity,
-    molar_mass,
-    mole_fraction,
-    molecular_diffusion,
-    name,
-    permeability,
-    phase_velocity,
-    porosity,
-    reference_density,
-    reference_temperature,
-    reference_pressure,
-    relative_permeability,
-    residual_gas_saturation,
-    residual_liquid_saturation,
-    saturation,
-    specific_heat_capacity,
-    thermal_conductivity,
-    thermal_expansivity,
-    transveral_dispersivity,
-    viscosity,
-    number_of_property_enums
-};
-
-/// This function converts a string (e.g. a string from the configuration-tree)
-/// into one of the entries of the PropertyEnum enumerator. To avoid confusion,
-/// I suggest that the syntax of the properties in the input-files (i.e. the
-/// strings) have to be identical to the syntax of the entries in the
-/// enumerator.
-inline PropertyEnum convertStringToProperty(std::string const& inString)
-{
-    if (boost::iequals(inString, "acentric_factor"))
-    {
-        return acentric_factor;
-    }
-    if (boost::iequals(inString, "binary_interaction_coefficient"))
-    {
-        return binary_interaction_coefficient;
-    }
-    if (boost::iequals(inString, "biot_coefficient"))
-    {
-        return biot_coefficient;
-    }
-    if (boost::iequals(inString, "brooks_corey_exponent"))
-    {
-        return brooks_corey_exponent;
-    }
-    if (boost::iequals(inString, "bulk_modulus"))
-    {
-        return bulk_modulus;
-    }
-    if (boost::iequals(inString, "critical_density"))
-    {
-        return critical_density;
-    }
-    if (boost::iequals(inString, "critical_pressure"))
-    {
-        return critical_pressure;
-    }
-    if (boost::iequals(inString, "critical_temperature"))
-    {
-        return critical_temperature;
-    }
-    if (boost::iequals(inString, "compressibility"))
-    {
-        return compressibility;
-    }
-    if (boost::iequals(inString, "density"))
-    {
-        return density;
-    }
-    if (boost::iequals(inString, "drhodT"))
-    {
-        return drhodT;
-    }
-    if (boost::iequals(inString, "effective_stress"))
-    {
-        return effective_stress;
-    }
-    if (boost::iequals(inString, "entry_pressure"))
-    {
-        return entry_pressure;
-    }
-    if (boost::iequals(inString, "fredlund_parameters"))
-    {
-        return fredlund_parameters;
-    }
-    if (boost::iequals(inString, "heat_capacity"))
-    {
-        return heat_capacity;
-    }
-    if (boost::iequals(inString, "longitudinal_dispersivity"))
-    {
-        return longitudinal_dispersivity;
-    }
-    if (boost::iequals(inString, "molar_mass"))
-    {
-        return molar_mass;
-    }
-    if (boost::iequals(inString, "mole_fraction"))
-    {
-        return mole_fraction;
-    }
-    if (boost::iequals(inString, "molecular_diffusion"))
-    {
-        return molecular_diffusion;
-    }
-    if (boost::iequals(inString, "name"))
-    {
-        return name;
-    }
-    if (boost::iequals(inString, "permeability"))
-    {
-        return permeability;
-    }
-    if (boost::iequals(inString, "porosity"))
-    {
-        return porosity;
-    }
-    if (boost::iequals(inString, "phase_velocity"))
-    {
-        return phase_velocity;
-    }
-    if (boost::iequals(inString, "reference_density"))
-    {
-        return reference_density;
-    }
-    if (boost::iequals(inString, "reference_temperature"))
-    {
-        return reference_temperature;
-    }
-    if (boost::iequals(inString, "reference_pressure"))
-    {
-        return reference_pressure;
-    }
-    if (boost::iequals(inString, "relative_permeability"))
-    {
-        return relative_permeability;
-    }
-    if (boost::iequals(inString, "residual_gas_saturation"))
-    {
-        return residual_gas_saturation;
-    }
-    if (boost::iequals(inString, "residual_liquid_saturation"))
-    {
-        return residual_liquid_saturation;
-    }
-    if (boost::iequals(inString, "saturation"))
-    {
-        return saturation;
-    }
-    if (boost::iequals(inString, "specific_heat_capacity"))
-    {
-        return specific_heat_capacity;
-    }
-    if (boost::iequals(inString, "thermal_conductivity"))
-    {
-        return thermal_conductivity;
-    }
-    if (boost::iequals(inString, "thermal_expansivity"))
-    {
-        return thermal_expansivity;
-    }
-    if (boost::iequals(inString, "transveral_dispersivity"))
-    {
-        return transveral_dispersivity;
-    }
-    if (boost::iequals(inString, "viscosity"))
-    {
-        return viscosity;
-    }
-
-    OGS_FATAL(
-        "The property name \"%s\" does not correspond to any known "
-        "property",
-        inString.c_str());
-
-    return number_of_property_enums;  // to avoid the 'no return' warning
-}
-
-const static std::vector<std::string> convertEnumToString{
-    {"acentric_factor"},
-    {"binary_interaction_coefficient"},
-    {"biot_coefficient"},
-    {"brooks_corey_exponent"},
-    {"bulk_modulus"},
-    {"critical_density"},
-    {"critical_pressure"},
-    {"critical_temperature"},
-    {"compressibility"},
-    {"density"},
-    {"drhodT"},
-    {"effective_stress"},
-    {"entry_pressure"},
-    {"fredlund_parameters"},
-    {"heat_capacity"},
-    {"longitudinal_dispersivity"},
-    {"molar_mass"},
-    {"mole_fraction"},
-    {"molecular_diffusion"},
-    {"name"},
-    {"permeability"},
-    {"phase_velocity"},
-    {"porosity"},
-    {"reference_density"},
-    {"reference_temperature"},
-    {"reference_pressure"},
-    {"relative_permeability"},
-    {"residual_gas_saturation"},
-    {"residual_liquid_saturation"},
-    {"saturation"},
-    {"specific_heat_capacity"},
-    {"thermal_conductivity"},
-    {"thermal_expansivity"},
-    {"transveral_dispersivity"},
-    {"viscosity"}};
-
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpMedium.cpp b/MaterialLib/MPL/mpMedium.cpp
deleted file mode 100644
index 602929c5b864061360dbd7cbcc8fe813986e6ca5..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpMedium.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   07.09.2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 "mpMedium.h"
-
-#include <boost/variant.hpp>
-#include <string>
-
-#include "BaseLib/Algorithm.h"
-
-#include "Properties/pUndefined.h"
-#include "Properties/pConstant.h"
-#include "mpComponent.h"
-#include "mpPhase.h"
-
-namespace MaterialPropertyLib
-{
-Medium::Medium(BaseLib::ConfigTree const& config)
-{
-    // Default properties are initialized in the first place, such
-    // that user-defined properties overwrite those defaults.
-    createDefaultProperties();
-
-    // A name of a medium is entirely optional and has no effects
-    // other than a small gain of clarity in case several media
-    // should be defined.
-    auto const medium_name =
-        config.getConfigParameter<std::string>("name", "no_name");
-
-    // 'name' is a constant property of the medium
-    _properties[name] = std::make_unique<Constant>(medium_name);
-
-    // Parsing the phases
-    // Properties of phases may be not required in all the cases.
-    auto const phases_config = config.getConfigSubtreeOptional("phases");
-    if (phases_config)
-        createPhases(*phases_config);
-
-    // Parsing medium properties, overwriting the defaults.
-    auto const properties_config =
-        config.getConfigSubtreeOptional("properties");
-    if (properties_config)
-    {
-        createProperties(*properties_config);
-    }
-
-    if (!phases_config && !properties_config)
-        OGS_FATAL("Neither tag <phases> nor tag <properties> has been found.");
-}
-void Medium::createPhases(BaseLib::ConfigTree const& config)
-{
-    std::set<std::string> phase_names;
-
-    for (auto phase_config : config.getConfigSubtreeList("phase"))
-    {
-        auto const phase_name =
-            phase_config.getConfigParameter<std::string>("name");
-
-        if (phase_name.empty())
-            OGS_FATAL("Phase name is a mandatory field and cannot be empty.");
-
-        auto newPhase = std::make_unique<Phase>(phase_name);
-        // Parsing the components
-        auto const components_config =
-            phase_config.getConfigSubtreeOptional("components");
-        if (components_config)
-            newPhase->createComponents(components_config.get());
-
-        // Properties of phases are optional
-        auto const properties_config =
-            phase_config.getConfigSubtreeOptional("properties");
-        if (properties_config)
-            newPhase->createProperties(properties_config.get());
-
-        if (!components_config && !properties_config)
-            OGS_FATAL(
-                "Neither tag <components> nor tag <properties> has been "
-                "found.");
-
-        phase_names.insert(phase_name);
-
-        _phases.push_back(std::move(newPhase));
-    }
-
-    if (phase_names.size() != _phases.size())
-        OGS_FATAL(
-            "Found duplicates with the same phase name tag inside a medium.");
-}
-void Medium::createProperties(BaseLib::ConfigTree const& config)
-{
-    for (auto property_config : config.getConfigSubtreeList("property"))
-    {
-        // create a new Property based on configuration tree
-        auto property = newProperty(property_config, this);
-        /// parse the name of the property
-        auto const property_name =
-            property_config.getConfigParameter<std::string>("name");
-        // insert the newly created property at the right place
-        // into the property array
-        _properties[convertStringToProperty(property_name)] =
-            std::move(property);
-    }
-}
-
-void Medium::createDefaultProperties()
-{
-    for (std::size_t i = 0; i < number_of_property_enums; ++i)
-    {
-        this->_properties[i] = std::make_unique<Undefined>((PropertyEnum)i);
-    }
-}
-
-Phase& Medium::phase(std::size_t const index) const
-{
-    return *_phases[index];
-}
-
-Phase& Medium::phase(std::string const& name) const
-{
-    return *BaseLib::findElementOrError(
-        _phases.begin(), _phases.end(),
-        [&name](std::unique_ptr<MaterialPropertyLib::Phase> const& p) {
-            return getString(p->property(
-                       MaterialPropertyLib::PropertyEnum::name)) == name;
-        },
-        "Could not find phase name '" + name + "'.");
-}
-
-Property& Medium::property(PropertyEnum const& p) const
-{
-    return *_properties[p];
-}
-
-std::size_t Medium::numberOfPhases() const
-{
-    return _phases.size();
-}
-
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpMedium.h b/MaterialLib/MPL/mpMedium.h
deleted file mode 100644
index 3737478a9450580200d7147b49c8951684d70702..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpMedium.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * \author Norbert Grunwald
- * \date   07.09.2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 "mpPhase.h"
-#include "mpProperty.h"
-
-#include <memory>
-#include <vector>
-
-namespace MaterialPropertyLib
-{
-/// This class is for material objects on the Medium scale.
-///
-/// A Medium consists of an arbitrarily long vector of phases and an array of
-/// properties.
-class Medium
-{
-private:
-    /// The vector that holds the phases.
-    std::vector<std::unique_ptr<Phase>> _phases;
-    /// The array that holds the medium properties.
-    PropertyArray _properties;
-
-public:
-    /// This constructor parses the "phases" and "properties" subtrees of the
-    /// config tree and calls create methods for the phase vector and the
-    /// properties array. Medium properties are optional. If not defined,
-    /// default properties are assigned.
-    Medium(BaseLib::ConfigTree const& config);
-
-    /// A method that parses the phase details and stores them in the
-    /// private _phases member.
-    ///
-    /// This method creates the phases of the medium. Unlike a medium, a phase
-    /// may have a name. However, this is silly at the moment since this name
-    /// still has no effect (except of some benefits in regard of readability).
-    /// Phase components are required (a phase consists of at least one
-    /// component). Phase properties are optional. If not given, default
-    /// properties are assigned. These default properties average the component
-    /// properties, weighted by mole fraction.
-    void createPhases(BaseLib::ConfigTree const& config);
-
-    /// A method that parses the medium property details and stores
-    /// them in the private _properties member.
-    ///
-    /// This method creates the properties of the Medium as defined in the
-    /// prj-file. Only specified properties overwrite the default properties.
-    void createProperties(BaseLib::ConfigTree const& config);
-
-    /// A method that creates the default properties of the medium.  Currently,
-    /// these defaults is the volume fraction average.
-    ///
-    /// Most properties are fine with the volume fraction average, but
-    /// special-defaults are allowed as well...
-    void createDefaultProperties();
-
-    /// A get-function for a particular phase. The ul argument specifies the
-    /// index within the _phases vector.
-    Phase& phase(std::size_t index) const;
-    /// A get-function for a particular phase by phase name.
-    Phase& phase(std::string const& phase_name) const;
-    /// A get-function for a property. The argument refers to the name of the
-    /// property.
-    Property& property(PropertyEnum const& p) const;
-
-    /// A simple get-function for retrieving the number of phases the medium
-    /// consists of.
-    std::size_t numberOfPhases() const;
-
-};
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpPhase.cpp b/MaterialLib/MPL/mpPhase.cpp
deleted file mode 100644
index 6fed18b783845569088d71afdd133736d316000c..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpPhase.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   Sep 7, 2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 "mpPhase.h"
-#include "BaseLib/Algorithm.h"
-#include "Properties/properties.h"
-
-#include "mpComponent.h"
-
-namespace MaterialPropertyLib
-{
-Phase::Phase(std::string const& phase_name)
-{
-    createDefaultProperties();
-
-    std::array<std::string, 4> allowed_phase_names = {
-        {"solid", "aqueous liquid", "non-aqueous liquid", "gas"}};
-
-    if (std::find(allowed_phase_names.begin(),
-                  allowed_phase_names.end(),
-                  phase_name) == allowed_phase_names.end())
-    {
-        ERR("Phase name should be one of:");
-        for (auto const name : allowed_phase_names)
-        {
-            ERR(name.c_str());
-        }
-        OGS_FATAL("Wrong phase name '%s' given.", phase_name.c_str());
-    }
-    _properties[name] = std::make_unique<Constant>(Constant(phase_name));
-}
-
-void Phase::createComponents(BaseLib::ConfigTree const& config)
-{
-    // collect names of components
-    std::set<std::string> component_names;
-
-    for (auto component_config : config.getConfigSubtreeList("component"))
-    {
-        // Parsing the component name
-        auto const component_name =
-            component_config.getConfigParameter<std::string>("name");
-
-        // Check whether a name is given or not
-        if (component_name.empty())
-            OGS_FATAL(
-                "Component name is a mandatory field and cannot be empty.");
-
-        bool isCustomComponent = false;
-        auto component = newComponent(component_name, isCustomComponent);
-
-        // Parsing component properties. If a component name is given and this
-        // component is predefined in the class implementation, properties
-        // become optional. The default values of properties will be overwritten
-        // if specified.
-        if (auto const properties_config =
-                component_config.getConfigSubtreeOptional("properties"))
-        {
-            component->createProperties(properties_config.get());
-        }
-        else
-        {
-            // No component properties are provided. If the component is
-            // not specified, this results in a fatal error, since an
-            // unspecified component has no properties.
-            if (isCustomComponent)
-            {
-                OGS_FATAL("No Properties defined for unspecified component");
-            }
-        }
-
-        component_names.insert(component_name);
-        _components.push_back(std::move(component));
-    }
-
-    if (component_names.size() != _components.size())
-    {
-        OGS_FATAL(
-            "Found duplicates with the same component name tag inside a "
-            "phase.");
-    }
-}
-
-void Phase::createProperties(BaseLib::ConfigTree const& config)
-{
-    for (auto property_config : config.getConfigSubtreeList("property"))
-    {
-        // create a new Property based on configuration tree
-        auto property = newProperty(property_config, this);
-        // parse the name of the property
-        auto const property_name =
-            property_config.getConfigParameter<std::string>("name");
-        // insert the newly created property at the right place into the
-        // property array
-        _properties[convertStringToProperty(property_name)] =
-            std::move(property);
-    }
-}
-
-void Phase::createDefaultProperties()
-{
-    for (std::size_t i = 0; i < number_of_property_enums; ++i)
-    {
-        _properties[i] = std::make_unique<Undefined>((PropertyEnum)i);
-    }
-
-    // After this, other special properties can
-    // be set as exceptional defaults
-}
-
-Component& Phase::component(const std::size_t& index) const
-{
-    return *_components[index];
-}
-
-Component& Phase::component(std::string const& name) const
-{
-    return *BaseLib::findElementOrError(
-        _components.begin(), _components.end(),
-        [&name](std::unique_ptr<Component> const& p) {
-            return getString(p->property(PropertyEnum::name)) == name;
-        },
-        "Could not find component name '" + name + "'.");
-}
-
-Property& Phase::property(PropertyEnum const& p) const
-{
-    return *_properties[p];
-}
-
-std::size_t Phase::numberOfComponents() const
-{
-    return _components.size();
-}
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpPhase.h b/MaterialLib/MPL/mpPhase.h
deleted file mode 100644
index 3dac8cb0cc790af337a9958b674860371294ce55..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpPhase.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * \author Norbert Grunwald
- * \date   Sep 7, 2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 <string>
-#include <vector>
-
-#include "BaseLib/ConfigTree.h"
-
-#include "mpComponent.h"
-#include "mpProperty.h"
-
-namespace MaterialPropertyLib
-{
-/// This class defines material phases.
-///
-/// The Phase class consists of a vector of components and an array of
-/// properties.
-class Phase final
-{
-private:
-    std::vector<std::unique_ptr<Component>> _components;
-    PropertyArray _properties;
-
-public:
-    /// The Phase constructor is called with the optional phase name.
-    explicit Phase(std::string const& phase_name);
-
-    /// The method creating phase components based on config subtree.
-    ///
-    /// Just like a phase, a component can have a name. But, in this case, the
-    /// name has an important task. If a name is given, a specific component
-    /// class referring to that name with corresponding physical material
-    /// properties is created.
-    /// Assigning a name is optional; If no name is given, a custom component
-    /// without predefined properties is created.
-    void createComponents(BaseLib::ConfigTree const& config);
-
-    /// The method creating phase properties based on config subtree.
-    ///
-    /// This method creates the properties of the Phase as defined in the
-    /// prj-file. Only specified properties overwrite the default properties.
-    void createProperties(BaseLib::ConfigTree const& config);
-
-    /// The method initializing the defaule phase properties.
-    /// Here, all for all properties listed in the Properties enumerator are
-    /// initialized by mole average functions of value zero. However,
-    /// 'special-default' properties are allowed to be set.
-    void createDefaultProperties();
-
-    /// A simple get-function for a component. The argument refers to the
-    /// Index of the component in the components vector.
-    Component& component(std::size_t const& index) const;
-
-    /// A get-function for a component by component name.
-    Component& component(std::string const& name) const;
-
-    /// A get-function for a property. The argument refers to the name of the
-    /// property.
-    Property& property(PropertyEnum const& p) const;
-
-    /// A get-function for retrieving the number of components in this phase.
-    std::size_t numberOfComponents() const;
-};
-
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpProperty.cpp b/MaterialLib/MPL/mpProperty.cpp
deleted file mode 100644
index 331682698b3a8415cf56cb508e426c474c0a25c2..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpProperty.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   Sep 7, 2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 "mpProperty.h"
-
-#include "Properties/properties.h"
-
-#include "mpComponent.h"
-#include "mpMedium.h"
-#include "mpPhase.h"
-
-#include <sstream>
-#include <string>
-#include <iostream>
-#include <vector>
-
-namespace MaterialPropertyLib
-{
-
-PropertyDataType Property::value() const
-{
-    return _value;
-}
-/// The default implementation of this method only returns the property value
-/// without altering it.
-PropertyDataType Property::value(VariableArray const&)
-{
-    return _value;
-}
-
-/// The default implementation of this method only returns the
-/// property value derivative without altering it.
-PropertyDataType Property::dvalue(VariableArray const&, Variables const)
-{
-    return _dvalue;
-}
-
-/// Default implementation: 2nd derivative of any constant property is zero.
-PropertyDataType Property::ddvalue(VariableArray const&, Variables const,
-                                   Variables const)
-{
-    return 0.0;
-}
-
-void Property::notImplemented(std::string property, std::string material)
-{
-    OGS_FATAL("The property \'%s\' is not available on the \'%s\' scale",
-              property.c_str(), material.c_str());
-}
-
-std::unique_ptr<Property> newProperty(BaseLib::ConfigTree const& config,
-                                      Medium* m)
-{
-    return selectProperty(config, m);
-}
-
-std::unique_ptr<Property> newProperty(BaseLib::ConfigTree const& config,
-                                      Phase* p)
-{
-    return selectProperty(config, p);
-}
-
-std::unique_ptr<Property> newProperty(BaseLib::ConfigTree const& config,
-                                      Component* c)
-{
-    return selectProperty(config, c);
-}
-
-template <typename MaterialType>
-std::unique_ptr<Property> selectProperty(BaseLib::ConfigTree const& config,
-                                         MaterialType /*material_type*/)
-{
-    // Parsing the property type:
-    auto const property_type = config.getConfigParameter<std::string>("type");
-
-    // If (and only if) the given property type is 'constant', a
-    // corresponding value is needed.
-    if (boost::iequals(property_type, "constant"))
-    {
-        // TODO (grunwald): Creating constant properties from prj-file is
-        // currently restricted to scalar values. The Constant constructor,
-        // however, can handle any datatype defined by PropertyDataType. This
-        // could be enhanced in order to define vectors or even tensors as
-        // constant properties.
-
-        auto const sValue = config.getConfigParameter<std::string>("value");
-
-        std::stringstream issValue(sValue);
-
-        std::vector<double> values;
-        double dummy(0);
-
-        while (issValue >> dummy)
-            values.push_back(dummy);
-
-        switch (values.size())
-        {
-        case 1:
-        {
-            // scalar
-            PropertyDataType property_value = values[0];
-            return std::make_unique<Constant>(Constant(property_value));
-        }
-        case 2:
-        {
-            // Pair
-            PropertyDataType property_value = (Pair){values[0], values[1]};
-            return std::make_unique<Constant>(Constant(property_value));
-        }
-        case 3:
-        {
-            // Vector
-            PropertyDataType property_value =
-                    (Vector){values[0], values[1], values[2]};
-            return std::make_unique<Constant>(Constant(property_value));
-        }
-        case 6:
-        {
-            // Symmetric Tensor - xx, yy, zz, xy, xz, yz
-            PropertyDataType property_value =
-                (SymmTensor){values[0], values[1], values[2],
-                             values[3], values[4], values[5]};
-            return std::make_unique<Constant>(Constant(property_value));
-        }
-        case 9:
-        {
-            // Tensor
-            PropertyDataType property_value =
-                (Tensor){values[0], values[1], values[2], values[3], values[4],
-                         values[5], values[6], values[7], values[8]};
-            return std::make_unique<Constant>(Constant(property_value));
-        }
-
-        default:
-        {
-            OGS_FATAL ("Given number of components for constant property. /%i", values.size());
-        }
-        }
-
-        PropertyDataType property_value;
-        return std::make_unique<Constant>(Constant(property_value));
-    }
-    // Properties can be medium, phase, or component properties.
-    // Some of them require information about the respective material.
-    // Thus, we pass a pointer to the material that requests the property.
-    // In this method, this pointer is realized via typename MaterialType, which
-    // replaces either Medium*, Phase*, or Component*.
-    // Note that most property constructors (only those that request material
-    // pointers) must be overloaded for any type of material.
-
-    /* TODO Additional properties go here, for example:
-    if (boost::iequals(property_type, "BilinearTemperaturePressure"))
-    {
-        return createBilinearTemperaturePressure(config, material_type);
-    }
-    */
-
-    // 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());
-}
-}  // namespace MaterialPropertyLib
diff --git a/MaterialLib/MPL/mpProperty.h b/MaterialLib/MPL/mpProperty.h
deleted file mode 100644
index e8be00e6f999d572abc25d0b35530f3c2cfb70e1..0000000000000000000000000000000000000000
--- a/MaterialLib/MPL/mpProperty.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/**
- * \file
- * \author Norbert Grunwald
- * \date   Sep 7, 2017
- *
- * \copyright
- * Copyright (c) 2012-2018, 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 <array>
-#include <boost/variant.hpp>
-#include <string>
-
-#include "BaseLib/ConfigTree.h"
-
-#include "mpEnums.h"
-
-namespace MaterialPropertyLib
-{
-class Medium;
-class Phase;
-class Component;
-
-/// This is a custom data type for arbitrary properties, based on the
-/// boost::variant container. It can hold scalars, vectors, tensors, and so
-/// forth.
-enum PropertyDataTypeName
-{
-    nScalar,
-    nPair,
-    nVector,
-    nSymmTensor,
-    nTensor
-};
-
-using PropertyDataType =
-    boost::variant<double, Pair, Vector, SymmTensor, Tensor, std::string>;
-
-/// This class is the base class for any material property of any
-/// scale (i.e. components, phases, media, ...). The single value of
-/// that Property can hold scalars, vectors, tensors, strings, etc.
-class Property
-{
-protected:
-    /// The single value of a property.
-    PropertyDataType _value;
-    PropertyDataType _dvalue;
-
-public:
-    virtual ~Property() = default;
-    /// This method is called when a property is used for the wrong kind of
-    /// material, or if the property is not implemented on this kind of material
-    /// yet.
-    void notImplemented(std::string /*property*/, std::string /*material*/);
-    /// This virtual method simply returns the private _value attribute without
-    /// changing it.
-    virtual PropertyDataType value() const;
-    /// This virtual method will compute the property value based on the primary
-    /// variables that are passed as arguments.
-    virtual PropertyDataType value(VariableArray const& /*unused*/);
-    /// This virtual method will compute the derivative of a property
-    /// with respect to the given variables pv.
-    virtual PropertyDataType dvalue(VariableArray const&, Variables const pv);
-    /// This virtual method will compute the second derivative of a
-    /// property with respect to the given variables pv1 and pv2.
-    virtual PropertyDataType ddvalue(VariableArray const&, Variables const pv1,
-                                     Variables const pv2);
-};
-
-/// This data type is based on a std::array. It can hold pointers to objects of
-/// class Property or its inheritors. The size of this array is determined by
-/// the number of entries of the PropertyEnum enumerator.
-using PropertyArray =
-    std::array<std::unique_ptr<Property>, number_of_property_enums>;
-
-/// Method to select a property by name and to call a derived property
-/// constructor.
-///
-/// This method creates a new Property. It uses the information stored inside
-/// the configuration tree to select the property that is specified by the user.
-/// It further passes a pointer to the material that requests the property.
-template <typename MaterialType>
-std::unique_ptr<Property> selectProperty(BaseLib::ConfigTree const& config,
-                                         MaterialType material_type);
-/// This method creates a new medium property.
-std::unique_ptr<Property> newProperty(BaseLib::ConfigTree const& config,
-                                      Medium* m);
-/// This method creates a new phase property.
-std::unique_ptr<Property> newProperty(BaseLib::ConfigTree const& config,
-                                      Phase* p);
-/// This method creates a new component property.
-std::unique_ptr<Property> newProperty(BaseLib::ConfigTree const& config,
-                                      Component* c);
-/// This method returns the 0-based index of the variant data types. Can be
-/// enhanced by using enums.
-inline std::size_t getType(Property const& p)
-{
-    return p.value().which();
-}
-
-/// This method returns a value of type double from the property value
-/// attribute.
-inline double getScalar(Property& p)
-{
-    assert((getType(p) == PropertyDataTypeName::nScalar) &&
-           "The requested "
-           "value type is not of type 'double'");
-
-    return boost::get<double>(p.value());
-}
-
-/// This method forces the computation of a value of type double and returns it.
-inline double getScalar(Property& p, VariableArray const& v)
-{
-    return boost::get<double>(p.value(v));
-}
-
-/// This method forces the computation of a value of type Pair and returns it
-inline Pair getPair(Property& p, VariableArray const& v)
-{
-    return boost::get<Pair>(p.value(v));
-}
-
-/// This method forces the computation of a value of type Vector and returns it.
-inline Vector getVector(Property& p)
-{
-    assert((getType(p) == PropertyDataTypeName::nVector) &&
-           "The requested value type is not of type 'Vector'");
-    return boost::get<Vector>(p.value());
-}
-
-/// This method forces the computation of a value of type Vector and returns it.
-inline Vector getVector(Property& p, VariableArray const& v)
-{
-    return boost::get<Vector>(p.value(v));
-}
-
-/// This method forces the computation the derivative of a value, returns a pair
-/// of double values. The derivative is computed with respect to variable pv.
-inline Pair getPairDerivative(Property& p, VariableArray const& v,
-                              Variables const pv)
-{
-    return boost::get<Pair>(p.dvalue(v, pv));
-}
-
-/// This method forces the computation the derivative of a value, returns a
-/// double value. The derivative is computed with respect to variable pv.
-inline double getScalarDerivative(Property& p, VariableArray const& v,
-                                  Variables const pv)
-{
-    return boost::get<double>(p.dvalue(v, pv));
-}
-
-/// This method forces the computation the second derivative of a value, returns
-/// a double value. The derivative is computed with respect to variables pv1 and
-/// pv2.
-inline double getScalarDerivative(Property& p, VariableArray const& v,
-                                  Variables const pv1, Variables const pv2)
-{
-    return boost::get<double>(p.ddvalue(v, pv1, pv2));
-}
-
-/// This method returns a value of type string from the property value
-/// attribute.
-inline std::string getString(Property const& p)
-{
-    return boost::get<std::string>(p.value());
-}
-
-/// This method returns a value of any valid type from the property value
-/// attribute. The data type is provided by the first parameter in the argument
-/// list.
-template <typename T>
-T getValue(T const&, Property const& p)
-{
-    return boost::get<T>(p.value());
-}
-
-}  // namespace MaterialPropertyLib
diff --git a/Tests/MaterialLib/TestMPL.cpp b/Tests/MaterialLib/TestMPL.cpp
index 19af610624592435e9cc15f192886c3d133709f9..3885b74a2402d60827495cbd0b3bf1ab82b2a390 100644
--- a/Tests/MaterialLib/TestMPL.cpp
+++ b/Tests/MaterialLib/TestMPL.cpp
@@ -1,10 +1,11 @@
 /**
+ * \file
  * \author Norbert Grunwald
  * \date   Oct 22, 2018
  * \brief
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -13,12 +14,15 @@
 
 #include "TestMPL.h"
 
-MPL::Medium createTestMaterial(std::string const& xml)
+#include "BaseLib/ConfigTree.h"
+#include "MaterialLib/MPL/CreateMedium.h"
+
+std::unique_ptr<MPL::Medium> createTestMaterial(std::string const& xml)
 {
     auto const ptree = readXml(xml.c_str());
     BaseLib::ConfigTree conf(ptree, "", BaseLib::ConfigTree::onerror,
                              BaseLib::ConfigTree::onwarning);
     auto const& config = conf.getConfigSubtree("medium");
 
-    return MPL::Medium(config);
+    return MPL::createMedium(config);
 }
diff --git a/Tests/MaterialLib/TestMPL.h b/Tests/MaterialLib/TestMPL.h
index 7820de6f3c2f1beb4dee653f52c3fb8073be5bcb..1d59754903b571a8c49d51c070e4f2e383eb3b83 100644
--- a/Tests/MaterialLib/TestMPL.h
+++ b/Tests/MaterialLib/TestMPL.h
@@ -4,7 +4,7 @@
  * \date   Oct 22, 2018
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -15,7 +15,7 @@
 
 #include "Tests/TestTools.h"
 
-#include "MaterialLib/MPL/mpMedium.h"
+#include "MaterialLib/MPL/Medium.h"
 namespace MPL = MaterialPropertyLib;
 
-MPL::Medium createTestMaterial(std::string const& xml);
+std::unique_ptr<MPL::Medium> createTestMaterial(std::string const& xml);
diff --git a/Tests/MaterialLib/TestMPLParseMaterial.cpp b/Tests/MaterialLib/TestMPLParseMaterial.cpp
index d918c9bed9473729fb7dcc65878c822ee911e554..ab25e27913678667b82709034eb93a8eb6554e57 100644
--- a/Tests/MaterialLib/TestMPLParseMaterial.cpp
+++ b/Tests/MaterialLib/TestMPLParseMaterial.cpp
@@ -1,9 +1,10 @@
 /**
+ * \file
  * \author Norbert Grunwald
  * \date   Sep 22, 2017
  *
  * \copyright
- * Copyright (c) 2012-2018, OpenGeoSys Community (http://www.opengeosys.org)
+ * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
  *              See accompanying file LICENSE.txt or
  *              http://www.opengeosys.org/project/license
@@ -17,27 +18,16 @@
 #include "TestMPL.h"
 #include "Tests/TestTools.h"
 
-#include "MaterialLib/MPL/mpMedium.h"
+#include "MaterialLib/MPL/Medium.h"
 
 namespace MPL = MaterialPropertyLib;
 
-//----------------------------------------------------------------------------
-// MPL::Medium createTestMaterial(std::string const& xml)
-//{
-//    auto const ptree = readXml(xml);
-//    BaseLib::ConfigTree conf(ptree, "", BaseLib::ConfigTree::onerror,
-//                             BaseLib::ConfigTree::onwarning);
-//    auto const& config =
-//        conf.getConfigSubtree("media").getConfigSubtree("medium");
-//
-//    return MPL::Medium(config);
-//}
 /// A simple structure for a string-based component used to create
 /// an XML-Structure.
 struct Component
 {
     std::vector<std::string> property;
-    Component() : property(MPL::number_of_property_enums) {}
+    Component() : property(MPL::number_of_properties) {}
 };
 /// A simple structure for a string-based phase used to create
 /// an XML-Structure.
@@ -45,162 +35,155 @@ struct Phase
 {
     std::vector<Component> component;
     std::vector<std::string> property;
-    Phase(std::size_t componentNumber)
-        : component(componentNumber), property(MPL::number_of_property_enums)
+    Phase(std::size_t const componentNumber)
+        : component(componentNumber), property(MPL::number_of_properties)
     {
     }
 };
+
 /// A simple structure for a string-based medium used to create
 /// an XML-Structure
 struct Medium
 {
     std::vector<Phase> phases;
     std::vector<std::string> property;
-    Medium(std::vector<std::size_t> topology)
-        : property(MPL::number_of_property_enums)
+    Medium(std::vector<std::size_t> const& phases_)
+        : property(MPL::number_of_properties)
     {
-        for (auto p : topology)
+        for (auto p : phases_)
+        {
             phases.push_back(Phase(p));
+        }
     }
 };
 
 /// Short method creating a number of blanks used for indentation.
-std::string indent(std::size_t ind)
+std::string indent(std::size_t const index)
 {
-    return std::string(ind, ' ');
+    return std::string(index, ' ');
 }
 
-/// This method creates an XML-snippet of a sigle property.
-std::string makeProperty(std::size_t ind, std::size_t index,
-                         std::string property)
+/// This method creates an XML-snippet of a single property.
+std::string makeProperty(std::size_t const ind, std::size_t const index,
+                         std::string const& property)
 {
     std::stringstream sProperty;
 
-    if (property == "")
+    if (property.empty())
+    {
         return "";
+    }
 
     sProperty << indent(ind) << "<property>\n";
-    sProperty << indent(ind + 2) << "<name>" << MPL::convertEnumToString[index]
-              << "</name>\n";
+    sProperty << indent(ind + 2) << "<name>"
+              << MPL::property_enum_to_string[index] << "</name>\n";
 
-    // What follows is a C-style string-to-double-conversion...
-    // seems so easy compared to c++-standard; Feel free to
-    // change it to latest standard..
-    if (double value = atof(property.c_str()))
+    if (double const value = std::atof(property.c_str()))
     {
-        sProperty << indent(ind + 2) << "<type>constant</type>\n";
+        sProperty << indent(ind + 2) << "<type>Constant</type>\n";
         sProperty << indent(ind + 2) << "<value>" << value << "</value>\n";
     }
     else
+    {
         sProperty << indent(ind + 2) << "<type>" << property << "</type>\n";
+    }
 
     sProperty << indent(ind) << "</property>\n";
     return sProperty.str();
 }
 
 /// This method creates an XML-snippet of a property section.
-std::string makeProperties(std::size_t ind, std::vector<std::string> properties)
+std::string makeProperties(std::size_t const ind,
+                           std::vector<std::string> const& properties)
 {
-    std::stringstream sProperties;
     std::vector<std::string> temp;
-    bool empty(true);
 
     for (std::size_t p = 0; p < properties.size(); ++p)
     {
         std::string property = makeProperty(ind + 2, p, properties[p]);
-        if ((property != "") && (p != static_cast<std::size_t>(MPL::name)))
+        if ((!property.empty()) && (p != static_cast<std::size_t>(MPL::name)))
         {
             temp.push_back(property);
-            empty = false;
         }
-        // If a property is not given, a default takes its place. Note
-        // also that 'name' is an exceptional property, since it determines
-        // specific components (thus it is defined outside of the properties-
-        // tag).
+        // If a property is not given, a default takes its place. Note also that
+        // 'name' is an exceptional property, since it determines specific
+        // components (thus it is defined outside of the properties- tag).
     }
 
-    if (empty)
+    if (temp.empty())
+    {
         return "";
+    }
+    std::stringstream sProperties;
     sProperties << indent(ind) << "<properties>\n";
-    for (auto str : temp)
+    for (auto const& str : temp)
+    {
         sProperties << str;
+    }
     sProperties << indent(ind) << "</properties>\n";
     return sProperties.str();
 }
 
 /// This method creates an XML-snippet of a single component.
-std::string makeComponent(Component c)
+std::string makeComponent(Component const& c)
 {
-    std::string componentProperties = makeProperties(14, c.property);
     std::stringstream component;
-
     component << indent(12) << "<component>\n";
     component << indent(14) << "<name>" << c.property[MPL::name] << "</name>\n";
-    component << componentProperties;
+    component << makeProperties(14, c.property);
     component << indent(12) << "</component>\n";
     return component.str();
 }
 
-/// This method creates an XML-snippet of the phase
-/// components.
-std::string makeComponents(std::vector<Component> components)
+/// This method creates an XML-snippet of the phase components.
+std::string makeComponents(std::vector<Component> const& components)
 {
     std::stringstream sComponents;
     sComponents << indent(10) << "<components>\n";
-    for (auto c : components)
+    for (auto const& c : components)
     {
-        std::string component = makeComponent(c);
-        sComponents << component;
+        sComponents << makeComponent(c);
     }
     sComponents << indent(10) << "</components>\n";
     return sComponents.str();
 }
 
-/// This method creates an XML-snippet of a sigle material
-/// phase.
-std::string makePhase(Phase p)
+/// This method creates an XML-snippet of a single material phase.
+std::string makePhase(Phase const& p)
 {
-    std::string phaseComponents = makeComponents(p.component);
-    std::string phaseProperties = makeProperties(8, p.property);
     std::stringstream phase;
 
     phase << indent(8) << "<phase>\n";
-    phase << indent(10) << "<name>" << p.property[MPL::name] << "</name>\n";
-    phase << phaseComponents;
-    phase << phaseProperties;
+    phase << indent(10) << "<type>" << p.property[MPL::name] << "</type>\n";
+    phase << makeComponents(p.component);
+    phase << makeProperties(8, p.property);
     phase << indent(8) << "</phase>\n";
     return phase.str();
 }
 
-/// This method creates an XML-snippet of the material
-/// phases.
-std::string makePhases(std::vector<Phase> phases)
+/// This method creates an XML-snippet of the material phases.
+std::string makePhases(std::vector<Phase> const& phases)
 {
     std::stringstream sPhases;
 
     sPhases << indent(6) << "<phases>\n";
-    for (auto p : phases)
+    for (auto const& p : phases)
     {
-        std::string phase = makePhase(p);
-        sPhases << phase;
+        sPhases << makePhase(p);
     }
     sPhases << indent(6) << "</phases>\n";
     return sPhases.str();
 }
 
-/// This method creates the entire XML-tree structure from the string-
-/// based medium specification object. I know, indentation is not
-/// necessary for this, but my OCD kicked in...
-std::string makeMedium(Medium m)
+/// This method creates the entire XML-tree structure from the string- based
+/// medium specification object. I know, indentation is not necessary for this,
+/// but my OCD kicked in...
+std::string makeMedium(Medium const& m)
 {
-    std::string mediumPhases = makePhases(m.phases);
-    std::string mediumProperties = makeProperties(6, m.property);
     std::stringstream medium;
     medium << indent(2) << "<medium>\n";
-    if (m.property[MPL::name] != "")
-        medium << indent(4) << "<name>" << m.property[MPL::name] << "</name>\n";
-    medium << mediumPhases;
-    medium << mediumProperties;
+    medium << makePhases(m.phases);
+    medium << makeProperties(6, m.property);
     medium << indent(2) << "</medium>\n";
     return medium.str();
 }
@@ -208,24 +191,27 @@ std::string makeMedium(Medium m)
 /// A method used to obtain the name of a medium, phase, or component of a
 /// material or of a specifier and to store them in two vectors for later
 /// comparison.
-void getNames(MPL::Property const& observation, std::string expectation,
-              std::string defaultName, std::vector<std::string>* obs,
-              std::vector<std::string>* exp)
+void getNames(std::string const& observed_name, std::string const& expectation,
+              std::string const& defaultName, std::vector<std::string>& obs,
+              std::vector<std::string>& exp)
 {
-    obs->push_back(MPL::getString(observation));
-    if (expectation == "")
-        exp->push_back(defaultName);
+    obs.push_back(observed_name);
+    if (expectation.empty())
+    {
+        exp.push_back(defaultName);
+    }
     else
-        exp->push_back(expectation);
+    {
+        exp.push_back(expectation);
+    }
 }
 
-// This test represents an invariant test. First, several phases,
-// components, and properties are generated (more or less randomly).
-// Then, an XML-tree is generated from those information. The XML
-// tree is then parsed into a configTree, from which an
-// MPL::MaterialObject is generated.
-// Last step compares the names (as well as the topology) of the
-// Material object with the specified parameters.
+// This test represents an invariant test. First, several phases, components,
+// and properties are generated (more or less randomly).
+// Then, an XML-tree is generated from those information. The XML tree is then
+// parsed into a configTree, from which an MPL::MaterialObject is generated.
+// Last step compares the names (as well as the topology) of the Material object
+// with the specified parameters.
 TEST(Material, parseMaterials)
 {
     // This is the topology of our new material: The size of the
@@ -236,17 +222,14 @@ TEST(Material, parseMaterials)
     // determined by the size of the PropertyEnum enumerator.
     std::vector<std::size_t> const mediumTopology = {1, 1, 1};
 
-    // make a string from every property enumerator
-    std::vector<std::string> property = MPL::convertEnumToString;
-
     Medium medium(mediumTopology);
 
     // the omnivagant medium:
     medium.property[MPL::name] = "luminiferous_aether";
 
-    medium.phases[0].property[MPL::name] = "solid";
-    medium.phases[1].property[MPL::name] = "aqueous liquid";
-    medium.phases[2].property[MPL::name] = "gas";
+    medium.phases[0].property[MPL::name] = "Solid";
+    medium.phases[1].property[MPL::name] = "AqueousLiquid";
+    medium.phases[2].property[MPL::name] = "Gas";
 
     medium.phases[0].component[0].property[MPL::thermal_conductivity] = "0.654";
     medium.phases[0].component[0].property[MPL::reference_temperature] = "333";
@@ -260,34 +243,26 @@ TEST(Material, parseMaterials)
     medium.property[MPL::permeability] = "1.0e-12";
 
     // create an actual MaterialProperty-Medium out of the specifier object
-    auto m = createTestMaterial(makeMedium(medium));
+    auto const m = createTestMaterial(makeMedium(medium));
 
     // those two vectors will actually be compared
     std::vector<std::string> expected;
     std::vector<std::string> observed;
 
-    // get the names of the specifier and that of the medium and store
-    // them in two vectors. If a name of the medium, one of the phases
-    // or components is not specified, it is automatically replaced by
-    // the default (which has to be the same as the default of the MPL
-    getNames(m.property(MPL::name), medium.property[MPL::name], "no_name",
-             &observed, &expected);
-
     // now we roam through all phases and components, finding their names
     // and storing them in the two vectors
-    for (std::size_t p = 0; p < m.numberOfPhases(); ++p)
+    for (std::size_t p = 0; p < m->numberOfPhases(); ++p)
     {
-        const auto& phase = m.phase(p);
-        getNames(phase.property(MPL::name),
-                 medium.phases[p].property[MPL::name], "no_name", &observed,
-                 &expected);
+        const auto& phase = m->phase(p);
+        getNames(phase.name(), medium.phases[p].property[MPL::name], "no_name",
+                 observed, expected);
 
         for (std::size_t c = 0; c < phase.numberOfComponents(); ++c)
         {
             const auto& component = phase.component(c);
-            getNames(component.property(MPL::name),
+            getNames(component.name(),
                      medium.phases[p].component[c].property[MPL::name],
-                     "no_name", &observed, &expected);
+                     "no_name", observed, expected);
         }
     }