diff --git a/ProcessLib/Deformation/SolidMaterialInternalToSecondaryVariables.h b/ProcessLib/Deformation/SolidMaterialInternalToSecondaryVariables.h
new file mode 100644
index 0000000000000000000000000000000000000000..d1dff264edada8aaeb8b8e6d3dc52c5587832b6b
--- /dev/null
+++ b/ProcessLib/Deformation/SolidMaterialInternalToSecondaryVariables.h
@@ -0,0 +1,84 @@
+/**
+ * \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 "MathLib/LinAlg/Eigen/EigenMapTools.h"
+
+namespace ProcessLib::Deformation
+{
+template <typename LocalAssemblerInterface,
+          typename AddSecondaryVariableCallback, int DisplacementDim>
+void solidMaterialInternalToSecondaryVariables(
+    std::map<int, std::unique_ptr<MaterialLib::Solids::MechanicsBase<
+                      DisplacementDim>>> const& solid_materials,
+    AddSecondaryVariableCallback const& add_secondary_variable)
+{
+    // Collect the internal variables for all solid materials.
+    std::vector<typename MaterialLib::Solids::MechanicsBase<
+        DisplacementDim>::InternalVariable>
+        internal_variables;
+    for (auto const& material_id__solid_material : solid_materials)
+    {
+        auto const variables =
+            material_id__solid_material.second->getInternalVariables();
+        copy(begin(variables), end(variables),
+             back_inserter(internal_variables));
+    }
+
+    // Register the internal variables.
+    for (auto const& internal_variable : internal_variables)
+    {
+        auto const& name = internal_variable.name;
+        auto const& fct = internal_variable.getter;
+        auto const num_components = internal_variable.num_components;
+        DBUG("Registering internal variable %s.", name.c_str());
+
+        auto getIntPtValues =
+            [fct, num_components](
+                LocalAssemblerInterface const& loc_asm,
+                const double /*t*/,
+                std::vector<GlobalVector*> const& /*x*/,
+                std::vector<
+                    NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
+                std::vector<double>& cache) -> std::vector<double> const& {
+            const unsigned num_int_pts = loc_asm.getNumberOfIntegrationPoints();
+
+            cache.clear();
+            auto cache_mat = MathLib::createZeroedMatrix<Eigen::Matrix<
+                double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(
+                cache, num_components, num_int_pts);
+
+            // TODO avoid the heap allocation (one per finite element)
+            std::vector<double> cache_column(num_int_pts);
+
+            for (unsigned i = 0; i < num_int_pts; ++i)
+            {
+                auto const& state = loc_asm.getMaterialStateVariablesAt(i);
+
+                auto const& int_pt_values = fct(state, cache_column);
+                assert(int_pt_values.size() == num_components);
+                auto const int_pt_values_vec = MathLib::toVector(int_pt_values);
+
+                cache_mat.col(i).noalias() = int_pt_values_vec;
+            }
+
+            return cache;
+        };
+
+        add_secondary_variable(name, num_components, std::move(getIntPtValues));
+    }
+
+}
+
+}  // namespace ProcessLib::Deformation
diff --git a/ProcessLib/SmallDeformation/SmallDeformationProcess.cpp b/ProcessLib/SmallDeformation/SmallDeformationProcess.cpp
index 6d58551a2946a91905153bd290864d769f1a444e..d12ecc5bd5a8e1601c4625be7bc9c677f126193e 100644
--- a/ProcessLib/SmallDeformation/SmallDeformationProcess.cpp
+++ b/ProcessLib/SmallDeformation/SmallDeformationProcess.cpp
@@ -13,10 +13,10 @@
 #include <cassert>
 #include <nlohmann/json.hpp>
 
+#include "ProcessLib/Deformation/SolidMaterialInternalToSecondaryVariables.h"
 #include "ProcessLib/Output/IntegrationPointWriter.h"
 #include "ProcessLib/Process.h"
 #include "ProcessLib/SmallDeformation/CreateLocalAssemblers.h"
-
 #include "SmallDeformationFEM.h"
 
 namespace ProcessLib
@@ -120,65 +120,19 @@ void SmallDeformationProcess<DisplacementDim>::initializeConcreteProcess(
     //
     // enable output of internal variables defined by material models
     //
-
-    // Collect the internal variables for all solid materials.
-    std::vector<typename MaterialLib::Solids::MechanicsBase<
-        DisplacementDim>::InternalVariable>
-        internal_variables;
-    for (auto const& material_id__solid_material :
-         _process_data.solid_materials)
-    {
-        auto const variables =
-            material_id__solid_material.second->getInternalVariables();
-        copy(begin(variables), end(variables),
-             back_inserter(internal_variables));
-    }
-
-    // Register the internal variables.
-    for (auto const& internal_variable : internal_variables)
-    {
-        auto const& name = internal_variable.name;
-        auto const& fct = internal_variable.getter;
-        auto const num_components = internal_variable.num_components;
-        DBUG("Registering internal variable %s.", name.c_str());
-
-        auto getIntPtValues =
-            [fct, num_components](
-                LocalAssemblerInterface const& loc_asm,
-                const double /*t*/,
-                std::vector<GlobalVector*> const& /*x*/,
-                std::vector<
-                    NumLib::LocalToGlobalIndexMap const*> const& /*dof_table*/,
-                std::vector<double>& cache) -> std::vector<double> const& {
-            const unsigned num_int_pts = loc_asm.getNumberOfIntegrationPoints();
-
-            cache.clear();
-            auto cache_mat = MathLib::createZeroedMatrix<Eigen::Matrix<
-                double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>(
-                cache, num_components, num_int_pts);
-
-            // TODO avoid the heap allocation (one per finite element)
-            std::vector<double> cache_column(num_int_pts);
-
-            for (unsigned i = 0; i < num_int_pts; ++i)
-            {
-                auto const& state = loc_asm.getMaterialStateVariablesAt(i);
-
-                auto const& int_pt_values = fct(state, cache_column);
-                assert(int_pt_values.size() == num_components);
-                auto const int_pt_values_vec = MathLib::toVector(int_pt_values);
-
-                cache_mat.col(i).noalias() = int_pt_values_vec;
-            }
-
-            return cache;
-        };
-
+    auto add_secondary_variable = [&](std::string const& name,
+                                      int const num_components,
+                                      auto get_ip_values_function) {
         _secondary_variables.addSecondaryVariable(
             name,
             makeExtrapolator(num_components, getExtrapolator(),
-                             _local_assemblers, std::move(getIntPtValues)));
-    }
+                             _local_assemblers,
+                             std::move(get_ip_values_function)));
+    };
+
+    ProcessLib::Deformation::solidMaterialInternalToSecondaryVariables<
+        LocalAssemblerInterface>(_process_data.solid_materials,
+                                 add_secondary_variable);
 
     // Set initial conditions for integration point data.
     for (auto const& ip_writer : _integration_point_writer)