diff --git a/ProcessLib/PhaseField/PhaseFieldProcess-impl.h b/ProcessLib/PhaseField/PhaseFieldProcess-impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..ddb38a15d0933841e9f585b1cb98b31939311733
--- /dev/null
+++ b/ProcessLib/PhaseField/PhaseFieldProcess-impl.h
@@ -0,0 +1,189 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2017, 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 <cassert>
+
+#include "ProcessLib/Process.h"
+#include "ProcessLib/SmallDeformation/CreateLocalAssemblers.h"
+
+#include "PhaseFieldFEM.h"
+
+namespace ProcessLib
+{
+namespace PhaseField
+{
+template <int DisplacementDim>
+PhaseFieldProcess<DisplacementDim>::PhaseFieldProcess(
+    MeshLib::Mesh& mesh,
+    std::unique_ptr<ProcessLib::AbstractJacobianAssembler>&& jacobian_assembler,
+    std::vector<std::unique_ptr<ParameterBase>> const& parameters,
+    unsigned const integration_order,
+    std::vector<std::reference_wrapper<ProcessVariable>>&& process_variables,
+    PhaseFieldProcessData<DisplacementDim>&& process_data,
+    SecondaryVariableCollection&& secondary_variables,
+    NumLib::NamedFunctionCaller&& named_function_caller)
+    : Process(mesh, std::move(jacobian_assembler), parameters,
+              integration_order, std::move(process_variables),
+              std::move(secondary_variables), std::move(named_function_caller)),
+      _process_data(std::move(process_data))
+{
+}
+
+template <int DisplacementDim>
+bool PhaseFieldProcess<DisplacementDim>::isLinear() const
+{
+    return false;
+}
+
+template <int DisplacementDim>
+void PhaseFieldProcess<DisplacementDim>::initializeConcreteProcess(
+    NumLib::LocalToGlobalIndexMap const& dof_table,
+    MeshLib::Mesh const& mesh,
+    unsigned const integration_order)
+{
+    ProcessLib::SmallDeformation::createLocalAssemblers<
+        DisplacementDim, PhaseFieldLocalAssembler>(
+        mesh.getElements(), dof_table, _local_assemblers,
+        mesh.isAxiallySymmetric(), integration_order, _process_data);
+
+    // TODO move the two data members somewhere else.
+    // for extrapolation of secondary variables
+    std::vector<MeshLib::MeshSubsets> all_mesh_subsets_single_component;
+    all_mesh_subsets_single_component.emplace_back(
+        _mesh_subset_all_nodes.get());
+    _local_to_global_index_map_single_component =
+        std::make_unique<NumLib::LocalToGlobalIndexMap>(
+            std::move(all_mesh_subsets_single_component),
+            // by location order is needed for output
+            NumLib::ComponentOrder::BY_LOCATION);
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "sigma_xx",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtSigmaXX));
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "sigma_yy",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtSigmaYY));
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "sigma_zz",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtSigmaZZ));
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "sigma_xy",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtSigmaXY));
+
+    if (DisplacementDim == 3)
+    {
+        Base::_secondary_variables.addSecondaryVariable(
+            "sigma_xz",
+            makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                             &LocalAssemblerInterface::getIntPtSigmaXZ));
+
+        Base::_secondary_variables.addSecondaryVariable(
+            "sigma_yz",
+            makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                             &LocalAssemblerInterface::getIntPtSigmaYZ));
+    }
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "epsilon_xx",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtEpsilonXX));
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "epsilon_yy",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtEpsilonYY));
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "epsilon_zz",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtEpsilonZZ));
+
+    Base::_secondary_variables.addSecondaryVariable(
+        "epsilon_xy",
+        makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                         &LocalAssemblerInterface::getIntPtEpsilonXY));
+
+    if (DisplacementDim == 3)
+    {
+        Base::_secondary_variables.addSecondaryVariable(
+            "epsilon_yz",
+            makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                             &LocalAssemblerInterface::getIntPtEpsilonYZ));
+
+        Base::_secondary_variables.addSecondaryVariable(
+            "epsilon_xz",
+            makeExtrapolator(1, getExtrapolator(), _local_assemblers,
+                             &LocalAssemblerInterface::getIntPtEpsilonXZ));
+    }
+}
+
+template <int DisplacementDim>
+void PhaseFieldProcess<DisplacementDim>::assembleConcreteProcess(
+    const double t, GlobalVector const& x, GlobalMatrix& M, GlobalMatrix& K,
+    GlobalVector& b)
+{
+    DBUG("Assemble PhaseFieldProcess.");
+
+    // Call global assembler for each local assembly item.
+    GlobalExecutor::executeMemberDereferenced(
+        _global_assembler, &VectorMatrixAssembler::assemble, _local_assemblers,
+        *_local_to_global_index_map, t, x, M, K, b, _coupling_term);
+}
+
+template <int DisplacementDim>
+void PhaseFieldProcess<DisplacementDim>::assembleWithJacobianConcreteProcess(
+    const double t, GlobalVector const& x, GlobalVector const& xdot,
+    const double dxdot_dx, const double dx_dx, GlobalMatrix& M, GlobalMatrix& K,
+    GlobalVector& b, GlobalMatrix& Jac)
+{
+    // DBUG("AssembleJacobian PhaseFieldProcess.");
+
+    // Call global assembler for each local assembly item.
+    GlobalExecutor::executeMemberDereferenced(
+        _global_assembler, &VectorMatrixAssembler::assembleWithJacobian,
+        _local_assemblers, *_local_to_global_index_map, t, x, xdot, dxdot_dx,
+        dx_dx, M, K, b, Jac, _coupling_term);
+}
+
+template <int DisplacementDim>
+void PhaseFieldProcess<DisplacementDim>::preTimestepConcreteProcess(
+    GlobalVector const& x, double const t, double const dt)
+{
+    DBUG("PreTimestep PhaseFieldProcess.");
+
+    _process_data.dt = dt;
+    _process_data.t = t;
+
+    GlobalExecutor::executeMemberOnDereferenced(
+        &LocalAssemblerInterface::preTimestep, _local_assemblers,
+        *_local_to_global_index_map, x, t, dt);
+}
+
+template <int DisplacementDim>
+void PhaseFieldProcess<DisplacementDim>::postTimestepConcreteProcess(
+    GlobalVector const& x)
+{
+    DBUG("PostTimestep PhaseFieldProcess.");
+
+    GlobalExecutor::executeMemberOnDereferenced(
+        &LocalAssemblerInterface::postTimestep, _local_assemblers,
+        *_local_to_global_index_map, x);
+}
+
+}  // namespace PhaseField
+}  // namespace ProcessLib
diff --git a/ProcessLib/PhaseField/PhaseFieldProcess.cpp b/ProcessLib/PhaseField/PhaseFieldProcess.cpp
index 6e3243e76ceb7dba633fd6c560456ef52594e8ee..eb05b810a244cd16d9637833c30ab99fa4881721 100644
--- a/ProcessLib/PhaseField/PhaseFieldProcess.cpp
+++ b/ProcessLib/PhaseField/PhaseFieldProcess.cpp
@@ -8,6 +8,7 @@
  */
 
 #include "PhaseFieldProcess.h"
+#include "PhaseFieldProcess-impl.h"
 
 namespace ProcessLib
 {
diff --git a/ProcessLib/PhaseField/PhaseFieldProcess.h b/ProcessLib/PhaseField/PhaseFieldProcess.h
index 6b02f7d187f34f1c0fbb8e085a7619f1ed377b75..303928bf55616e0d22223e2d6e6ebf4a79fc9a51 100644
--- a/ProcessLib/PhaseField/PhaseFieldProcess.h
+++ b/ProcessLib/PhaseField/PhaseFieldProcess.h
@@ -9,14 +9,8 @@
 
 #pragma once
 
-#include <cassert>
-
-#include "NumLib/DOF/DOFTableUtil.h"
-#include "ProcessLib/Process.h"
-#include "ProcessLib/SmallDeformation/CreateLocalAssemblers.h"
-
 #include "PhaseFieldFEM.h"
-#include "PhaseFieldProcessData.h"
+#include "ProcessLib/Process.h"
 
 namespace ProcessLib
 {
@@ -65,19 +59,11 @@ public:
             process_variables,
         PhaseFieldProcessData<DisplacementDim>&& process_data,
         SecondaryVariableCollection&& secondary_variables,
-        NumLib::NamedFunctionCaller&& named_function_caller)
-        : Process(mesh, std::move(jacobian_assembler), parameters,
-                  integration_order, std::move(process_variables),
-                  std::move(secondary_variables),
-                  std::move(named_function_caller)),
-          _process_data(std::move(process_data))
-    {
-    }
+        NumLib::NamedFunctionCaller&& named_function_caller);
 
     //! \name ODESystem interface
     //! @{
-
-    bool isLinear() const override { return false; }
+    bool isLinear() const override;
     //! @}
 
 private:
@@ -86,149 +72,21 @@ private:
     void initializeConcreteProcess(
         NumLib::LocalToGlobalIndexMap const& dof_table,
         MeshLib::Mesh const& mesh,
-        unsigned const integration_order) override
-    {
-        ProcessLib::SmallDeformation::createLocalAssemblers<
-                DisplacementDim, PhaseFieldLocalAssembler>(
-                mesh.getElements(), dof_table, _local_assemblers,
-                mesh.isAxiallySymmetric(), integration_order, _process_data);
-
-        // TODO move the two data members somewhere else.
-        // for extrapolation of secondary variables
-        std::vector<MeshLib::MeshSubsets> all_mesh_subsets_single_component;
-        all_mesh_subsets_single_component.emplace_back(
-            _mesh_subset_all_nodes.get());
-        _local_to_global_index_map_single_component.reset(
-            new NumLib::LocalToGlobalIndexMap(
-                std::move(all_mesh_subsets_single_component),
-                // by location order is needed for output
-                NumLib::ComponentOrder::BY_LOCATION));
-
-        Base::_secondary_variables.addSecondaryVariable(
-            "sigma_xx",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtSigmaXX));
-
-        Base::_secondary_variables.addSecondaryVariable(
-            "sigma_yy",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtSigmaYY));
-
-        Base::_secondary_variables.addSecondaryVariable(
-            "sigma_zz",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtSigmaZZ));
-
-        Base::_secondary_variables.addSecondaryVariable(
-            "sigma_xy",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtSigmaXY));
-
-        if (DisplacementDim == 3)
-        {
-            Base::_secondary_variables.addSecondaryVariable(
-                "sigma_xz",
-                makeExtrapolator(
-                    1, getExtrapolator(), _local_assemblers,
-                    &PhaseFieldLocalAssemblerInterface::getIntPtSigmaXZ));
-
-            Base::_secondary_variables.addSecondaryVariable(
-                "sigma_yz",
-                makeExtrapolator(
-                    1, getExtrapolator(), _local_assemblers,
-                    &PhaseFieldLocalAssemblerInterface::getIntPtSigmaYZ));
-        }
-        Base::_secondary_variables.addSecondaryVariable(
-            "epsilon_xx",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtEpsilonXX));
-
-        Base::_secondary_variables.addSecondaryVariable(
-            "epsilon_yy",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtEpsilonYY));
-
-        Base::_secondary_variables.addSecondaryVariable(
-            "epsilon_zz",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtEpsilonZZ));
-
-        Base::_secondary_variables.addSecondaryVariable(
-            "epsilon_xy",
-            makeExtrapolator(
-                1, getExtrapolator(), _local_assemblers,
-                &PhaseFieldLocalAssemblerInterface::getIntPtEpsilonXY));
-        if (DisplacementDim == 3)
-        {
-            Base::_secondary_variables.addSecondaryVariable(
-                "epsilon_yz",
-                makeExtrapolator(1, getExtrapolator(), _local_assemblers,
-                                 &PhaseFieldLocalAssemblerInterface::
-                                     getIntPtEpsilonYZ));
-
-            Base::_secondary_variables.addSecondaryVariable(
-                "epsilon_xz",
-                makeExtrapolator(1, getExtrapolator(), _local_assemblers,
-                                 &PhaseFieldLocalAssemblerInterface::
-                                     getIntPtEpsilonXZ));
-        }
-    }
+        unsigned const integration_order) override;
 
     void assembleConcreteProcess(
         const double t, GlobalVector const& x, GlobalMatrix& M, GlobalMatrix& K,
-        GlobalVector& b) override
-    {
-        DBUG("Assemble PhaseFieldProcess.");
-
-        // Call global assembler for each local assembly item.
-        GlobalExecutor::executeMemberDereferenced(
-            _global_assembler, &VectorMatrixAssembler::assemble,
-            _local_assemblers, *_local_to_global_index_map, t, x, M, K, b,
-            _coupling_term);
-    }
+        GlobalVector& b) override;
 
     void assembleWithJacobianConcreteProcess(
         const double t, GlobalVector const& x, GlobalVector const& xdot,
         const double dxdot_dx, const double dx_dx, GlobalMatrix& M,
-        GlobalMatrix& K, GlobalVector& b, GlobalMatrix& Jac) override
-    {
-        // DBUG("AssembleJacobian PhaseFieldProcess.");
-
-        // Call global assembler for each local assembly item.
-        GlobalExecutor::executeMemberDereferenced(
-            _global_assembler, &VectorMatrixAssembler::assembleWithJacobian,
-            _local_assemblers, *_local_to_global_index_map, t, x, xdot,
-            dxdot_dx, dx_dx, M, K, b, Jac, _coupling_term);
-    }
+        GlobalMatrix& K, GlobalVector& b, GlobalMatrix& Jac) override;
 
     void preTimestepConcreteProcess(GlobalVector const& x, double const t,
-                                    double const dt) override
-    {
-        DBUG("PreTimestep PhaseFieldProcess.");
-
-        _process_data.dt = dt;
-        _process_data.t = t;
-
-        GlobalExecutor::executeMemberOnDereferenced(
-            &PhaseFieldLocalAssemblerInterface::preTimestep, _local_assemblers,
-            *_local_to_global_index_map, x, t, dt);
-    }
+                                    double const dt) override;
 
-    void postTimestepConcreteProcess(GlobalVector const& x) override
-    {
-        DBUG("PostTimestep PhaseFieldProcess.");
-
-        GlobalExecutor::executeMemberOnDereferenced(
-            &PhaseFieldLocalAssemblerInterface::postTimestep, _local_assemblers,
-            *_local_to_global_index_map, x);
-    }
+    void postTimestepConcreteProcess(GlobalVector const& x) override;
 
 private:
     PhaseFieldProcessData<DisplacementDim> _process_data;
@@ -239,5 +97,8 @@ private:
         _local_to_global_index_map_single_component;
 };
 
+extern template class PhaseFieldProcess<2>;
+extern template class PhaseFieldProcess<3>;
+
 }  // namespace PhaseField
 }  // namespace ProcessLib