diff --git a/Applications/ApplicationsLib/ProjectData.cpp b/Applications/ApplicationsLib/ProjectData.cpp
index 2047cb8548b236a3b2390fd8e406bbd36bbc4787..de6d45adaa8c46c7ad637ac92f0e7d2bf29ae164 100644
--- a/Applications/ApplicationsLib/ProjectData.cpp
+++ b/Applications/ApplicationsLib/ProjectData.cpp
@@ -44,6 +44,7 @@
 
 #include "ParameterLib/ConstantParameter.h"
 #include "ParameterLib/Utils.h"
+#include "ProcessLib/CreateTimeLoop.h"
 #include "ProcessLib/TimeLoop.h"
 
 #ifdef OGS_BUILD_PROCESS_COMPONENTTRANSPORT
diff --git a/ProcessLib/CreateTimeLoop.cpp b/ProcessLib/CreateTimeLoop.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9a0de21c25335c649a53a6a9f3bd8f242d6edb09
--- /dev/null
+++ b/ProcessLib/CreateTimeLoop.cpp
@@ -0,0 +1,98 @@
+/**
+ * \file
+ *
+ * \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 "CreateTimeLoop.h"
+
+#include "BaseLib/ConfigTree.h"
+#include "ProcessLib/CreateProcessData.h"
+#include "ProcessLib/Output/CreateOutput.h"
+#include "ProcessLib/Output/Output.h"
+
+#include "TimeLoop.h"
+
+namespace ProcessLib
+{
+std::unique_ptr<TimeLoop> createTimeLoop(
+    BaseLib::ConfigTree const& config, std::string const& output_directory,
+    const std::map<std::string, std::unique_ptr<Process>>& processes,
+    const std::map<std::string, std::unique_ptr<NumLib::NonlinearSolverBase>>&
+        nonlinear_solvers,
+    std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes)
+{
+    auto const& coupling_config
+        //! \ogs_file_param{prj__time_loop__global_process_coupling}
+        = config.getConfigSubtreeOptional("global_process_coupling");
+
+    std::vector<std::unique_ptr<NumLib::ConvergenceCriterion>>
+        global_coupling_conv_criteria;
+    int max_coupling_iterations = 1;
+    if (coupling_config)
+    {
+        max_coupling_iterations
+            //! \ogs_file_param{prj__time_loop__global_process_coupling__max_iter}
+            = coupling_config->getConfigParameter<int>("max_iter");
+
+        auto const& coupling_convergence_criteria_config =
+            //! \ogs_file_param{prj__time_loop__global_process_coupling__convergence_criteria}
+            coupling_config->getConfigSubtree("convergence_criteria");
+
+        for (
+            auto coupling_convergence_criterion_config :
+            //! \ogs_file_param{prj__time_loop__global_process_coupling__convergence_criteria__convergence_criterion}
+            coupling_convergence_criteria_config.getConfigSubtreeList(
+                "convergence_criterion"))
+        {
+            global_coupling_conv_criteria.push_back(
+                NumLib::createConvergenceCriterion(
+                    coupling_convergence_criterion_config));
+        }
+    }
+
+    auto output =
+        //! \ogs_file_param{prj__time_loop__output}
+        createOutput(config.getConfigSubtree("output"), output_directory,
+                     meshes);
+
+    auto per_process_data = createPerProcessData(
+        //! \ogs_file_param{prj__time_loop__processes}
+        config.getConfigSubtree("processes"), processes, nonlinear_solvers);
+
+    if (coupling_config)
+    {
+        if (global_coupling_conv_criteria.size() != per_process_data.size())
+        {
+            OGS_FATAL(
+                "The number of convergence criteria of the global staggered "
+                "coupling loop is not identical to the number of the "
+                "processes! Please check the element by tag "
+                "global_process_coupling in the project file.");
+        }
+    }
+
+    const auto minmax_iter = std::minmax_element(
+        per_process_data.begin(),
+        per_process_data.end(),
+        [](std::unique_ptr<ProcessData> const& a,
+           std::unique_ptr<ProcessData> const& b) {
+            return (a->timestepper->end() < b->timestepper->end());
+        });
+    const double start_time =
+        per_process_data[minmax_iter.first - per_process_data.begin()]
+            ->timestepper->begin();
+    const double end_time =
+        per_process_data[minmax_iter.second - per_process_data.begin()]
+            ->timestepper->end();
+
+    return std::make_unique<TimeLoop>(
+        std::move(output), std::move(per_process_data), max_coupling_iterations,
+        std::move(global_coupling_conv_criteria), start_time, end_time);
+}
+}  // namespace ProcessLib
diff --git a/ProcessLib/CreateTimeLoop.h b/ProcessLib/CreateTimeLoop.h
new file mode 100644
index 0000000000000000000000000000000000000000..86f6d9d89316e045d4b6210da5114a0f5620c647
--- /dev/null
+++ b/ProcessLib/CreateTimeLoop.h
@@ -0,0 +1,50 @@
+/**
+ * \file
+ *
+ * \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 <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace BaseLib
+{
+class ConfigTree;
+}
+
+namespace MeshLib
+{
+class Mesh;
+}
+
+namespace NumLib
+{
+class NonlinearSolverBase;
+}
+
+namespace ProcessLib
+{
+class TimeLoop;
+class Process;
+}
+
+namespace ProcessLib
+{
+//! Builds a TimeLoop from the given configuration.
+std::unique_ptr<TimeLoop> createTimeLoop(
+    BaseLib::ConfigTree const& config, std::string const& output_directory,
+    std::map<std::string, std::unique_ptr<Process>> const& processes,
+    std::map<std::string, std::unique_ptr<NumLib::NonlinearSolverBase>> const&
+        nonlinear_solvers,
+    std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes);
+
+}  // namespace ProcessLib
diff --git a/ProcessLib/TimeLoop.cpp b/ProcessLib/TimeLoop.cpp
index 482cb1a4288ebbdb19bd2427fbc9c5917823a69f..c6081ebf097ed2ebfa1462e2f5507ea51e042402 100644
--- a/ProcessLib/TimeLoop.cpp
+++ b/ProcessLib/TimeLoop.cpp
@@ -1,4 +1,6 @@
 /**
+ * \file
+ *
  * \copyright
  * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
@@ -14,8 +16,6 @@
 #include "MathLib/LinAlg/LinAlg.h"
 #include "NumLib/ODESolver/ConvergenceCriterionPerComponent.h"
 #include "NumLib/ODESolver/TimeDiscretizedODESystem.h"
-#include "ProcessLib/CreateProcessData.h"
-#include "ProcessLib/Output/CreateOutput.h"
 
 #include "CoupledSolutionsForStaggeredScheme.h"
 #include "ProcessData.h"
@@ -114,82 +114,6 @@ void setTimeDiscretizedODESystem(ProcessData& process_data)
     setTimeDiscretizedODESystem(process_data, process_data.process);
 }
 
-std::unique_ptr<TimeLoop> createTimeLoop(
-    BaseLib::ConfigTree const& config, std::string const& output_directory,
-    const std::map<std::string, std::unique_ptr<Process>>& processes,
-    const std::map<std::string, std::unique_ptr<NumLib::NonlinearSolverBase>>&
-        nonlinear_solvers,
-    std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes)
-{
-    auto const& coupling_config
-        //! \ogs_file_param{prj__time_loop__global_process_coupling}
-        = config.getConfigSubtreeOptional("global_process_coupling");
-
-    std::vector<std::unique_ptr<NumLib::ConvergenceCriterion>>
-        global_coupling_conv_criteria;
-    int max_coupling_iterations = 1;
-    if (coupling_config)
-    {
-        max_coupling_iterations
-            //! \ogs_file_param{prj__time_loop__global_process_coupling__max_iter}
-            = coupling_config->getConfigParameter<int>("max_iter");
-
-        auto const& coupling_convergence_criteria_config =
-            //! \ogs_file_param{prj__time_loop__global_process_coupling__convergence_criteria}
-            coupling_config->getConfigSubtree("convergence_criteria");
-
-        for (
-            auto coupling_convergence_criterion_config :
-            //! \ogs_file_param{prj__time_loop__global_process_coupling__convergence_criteria__convergence_criterion}
-            coupling_convergence_criteria_config.getConfigSubtreeList(
-                "convergence_criterion"))
-        {
-            global_coupling_conv_criteria.push_back(
-                NumLib::createConvergenceCriterion(
-                    coupling_convergence_criterion_config));
-        }
-    }
-
-    auto output =
-        //! \ogs_file_param{prj__time_loop__output}
-        createOutput(config.getConfigSubtree("output"), output_directory,
-                     meshes);
-
-    auto per_process_data = createPerProcessData(
-        //! \ogs_file_param{prj__time_loop__processes}
-        config.getConfigSubtree("processes"), processes, nonlinear_solvers);
-
-    if (coupling_config)
-    {
-        if (global_coupling_conv_criteria.size() != per_process_data.size())
-        {
-            OGS_FATAL(
-                "The number of convergence criteria of the global staggered "
-                "coupling loop is not identical to the number of the "
-                "processes! Please check the element by tag "
-                "global_process_coupling in the project file.");
-        }
-    }
-
-    const auto minmax_iter = std::minmax_element(
-        per_process_data.begin(),
-        per_process_data.end(),
-        [](std::unique_ptr<ProcessData> const& a,
-           std::unique_ptr<ProcessData> const& b) {
-            return (a->timestepper->end() < b->timestepper->end());
-        });
-    const double start_time =
-        per_process_data[minmax_iter.first - per_process_data.begin()]
-            ->timestepper->begin();
-    const double end_time =
-        per_process_data[minmax_iter.second - per_process_data.begin()]
-            ->timestepper->end();
-
-    return std::make_unique<TimeLoop>(
-        std::move(output), std::move(per_process_data), max_coupling_iterations,
-        std::move(global_coupling_conv_criteria), start_time, end_time);
-}
-
 std::vector<GlobalVector*> setInitialConditions(
     double const t0,
     std::vector<std::unique_ptr<ProcessData>> const& per_process_data)
diff --git a/ProcessLib/TimeLoop.h b/ProcessLib/TimeLoop.h
index f70eac7a04df85bcb7d061d6d425b19f75998375..d764d9437be79dd0ff822ff68bbba54932287d1f 100644
--- a/ProcessLib/TimeLoop.h
+++ b/ProcessLib/TimeLoop.h
@@ -1,4 +1,6 @@
 /**
+ * \file
+ *
  * \copyright
  * Copyright (c) 2012-2019, OpenGeoSys Community (http://www.opengeosys.org)
  *            Distributed under a Modified BSD License.
@@ -132,13 +134,4 @@ private:
                          const double t, OutputClass& output_object,
                          OutputClassMember output_class_member) const;
 };
-
-//! Builds an TimeLoop from the given configuration.
-std::unique_ptr<TimeLoop> createTimeLoop(
-    BaseLib::ConfigTree const& config, std::string const& output_directory,
-    std::map<std::string, std::unique_ptr<Process>> const& processes,
-    std::map<std::string, std::unique_ptr<NumLib::NonlinearSolverBase>> const&
-        nonlinear_solvers,
-    std::vector<std::unique_ptr<MeshLib::Mesh>> const& meshes);
-
 }  // namespace ProcessLib