diff --git a/ProcessLib/ThermoMechanics/LocalAssemblerInterface.h b/ProcessLib/ThermoMechanics/LocalAssemblerInterface.h
index 23fcaa4b9d0aba263bb812ed897d08f4a752c6be..22a541c8cdcaa2a872f0518ee330e55a85971905 100644
--- a/ProcessLib/ThermoMechanics/LocalAssemblerInterface.h
+++ b/ProcessLib/ThermoMechanics/LocalAssemblerInterface.h
@@ -28,6 +28,10 @@ struct ThermoMechanicsLocalAssemblerInterface
 
     virtual std::vector<double> getSigma() const = 0;
 
+    virtual std::vector<double> getEpsilon() const = 0;
+
+    virtual std::vector<double> getEpsilonMechanical() const = 0;
+
     virtual std::vector<double> const& getIntPtSigma(
         const double /*t*/,
         GlobalVector const& /*current_solution*/,
diff --git a/ProcessLib/ThermoMechanics/ThermoMechanicsFEM.h b/ProcessLib/ThermoMechanics/ThermoMechanicsFEM.h
index ffdaf39ba3ad6b2ee1e506de08cd051b19c63327..82080cbc3767d999ca8e66caf8bbfe0eae1cbf0b 100644
--- a/ProcessLib/ThermoMechanics/ThermoMechanicsFEM.h
+++ b/ProcessLib/ThermoMechanics/ThermoMechanicsFEM.h
@@ -186,6 +186,14 @@ public:
         {
             return setSigma(values);
         }
+        else if (name == "epsilon_ip")
+        {
+            return setEpsilon(values);
+        }
+        else if (name == "epsilon_m_ip")
+        {
+            return setEpsilonMechanical(values);
+        }
 
         return 0;
     }
@@ -415,7 +423,6 @@ private:
         unsigned const n_integration_points =
             _integration_method.getNumberOfPoints();
 
-        std::vector<double> ip_sigma_values;
         auto sigma_values =
             Eigen::Map<Eigen::Matrix<double, kelvin_vector_size, Eigen::Dynamic,
                                      Eigen::ColMajor> const>(
@@ -484,6 +491,52 @@ private:
         return cache;
     }
 
+    std::size_t setEpsilon(double const* values)
+    {
+        auto const kelvin_vector_size =
+            MathLib::KelvinVector::KelvinVectorDimensions<
+                DisplacementDim>::value;
+        unsigned const n_integration_points =
+            _integration_method.getNumberOfPoints();
+
+        auto epsilon_values =
+            Eigen::Map<Eigen::Matrix<double, kelvin_vector_size, Eigen::Dynamic,
+                                     Eigen::ColMajor> const>(
+                values, kelvin_vector_size, n_integration_points);
+
+        for (unsigned ip = 0; ip < n_integration_points; ++ip)
+        {
+            _ip_data[ip].eps =
+                MathLib::KelvinVector::symmetricTensorToKelvinVector(
+                    epsilon_values.col(ip));
+        }
+
+        return n_integration_points;
+    }
+
+    std::vector<double> getEpsilon() const override
+    {
+        auto const kelvin_vector_size =
+            MathLib::KelvinVector::KelvinVectorDimensions<
+                DisplacementDim>::value;
+        unsigned const n_integration_points =
+            _integration_method.getNumberOfPoints();
+
+        std::vector<double> ip_epsilon_values;
+        auto cache_mat = MathLib::createZeroedMatrix<Eigen::Matrix<
+            double, Eigen::Dynamic, kelvin_vector_size, Eigen::RowMajor>>(
+            ip_epsilon_values, n_integration_points, kelvin_vector_size);
+
+        for (unsigned ip = 0; ip < n_integration_points; ++ip)
+        {
+            auto const& eps = _ip_data[ip].eps;
+            cache_mat.row(ip) =
+                MathLib::KelvinVector::kelvinVectorToSymmetricTensor(eps);
+        }
+
+        return ip_epsilon_values;
+    }
+
     virtual std::vector<double> const& getIntPtEpsilon(
         const double /*t*/,
         GlobalVector const& /*current_solution*/,
@@ -511,6 +564,52 @@ private:
         return cache;
     }
 
+    std::size_t setEpsilonMechanical(double const* values)
+    {
+        auto const kelvin_vector_size =
+            MathLib::KelvinVector::KelvinVectorDimensions<
+                DisplacementDim>::value;
+        unsigned const n_integration_points =
+            _integration_method.getNumberOfPoints();
+
+        auto epsilon_m_values =
+            Eigen::Map<Eigen::Matrix<double, kelvin_vector_size, Eigen::Dynamic,
+                                     Eigen::ColMajor> const>(
+                values, kelvin_vector_size, n_integration_points);
+
+        for (unsigned ip = 0; ip < n_integration_points; ++ip)
+        {
+            _ip_data[ip].eps_m =
+                MathLib::KelvinVector::symmetricTensorToKelvinVector(
+                    epsilon_m_values.col(ip));
+        }
+
+        return n_integration_points;
+    }
+
+    std::vector<double> getEpsilonMechanical() const override
+    {
+        auto const kelvin_vector_size =
+            MathLib::KelvinVector::KelvinVectorDimensions<
+                DisplacementDim>::value;
+        unsigned const n_integration_points =
+            _integration_method.getNumberOfPoints();
+
+        std::vector<double> ip_epsilon_m_values;
+        auto cache_mat = MathLib::createZeroedMatrix<Eigen::Matrix<
+            double, Eigen::Dynamic, kelvin_vector_size, Eigen::RowMajor>>(
+            ip_epsilon_m_values, n_integration_points, kelvin_vector_size);
+
+        for (unsigned ip = 0; ip < n_integration_points; ++ip)
+        {
+            auto const& eps_m = _ip_data[ip].eps_m;
+            cache_mat.row(ip) =
+                MathLib::KelvinVector::kelvinVectorToSymmetricTensor(eps_m);
+        }
+
+        return ip_epsilon_m_values;
+    }
+
     ThermoMechanicsProcessData<DisplacementDim>& _process_data;
 
     std::vector<
diff --git a/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.cpp b/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.cpp
index 042783e58534d37ec9e7ac97c9f6a85c363e83c2..c819806691ca022883bd20a5c9140e839e4bb153 100644
--- a/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.cpp
+++ b/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.cpp
@@ -39,7 +39,8 @@ ThermoMechanicsProcess<DisplacementDim>::ThermoMechanicsProcess(
       _process_data(std::move(process_data))
 {
     _integration_point_writer.emplace_back(
-        std::make_unique<SigmaIntegrationPointWriter>(
+        std::make_unique<KelvinVectorIntegrationPointWriter>(
+            "sigma_ip",
             static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/,
             2 /*integration order*/, [this]() {
                 // Result containing integration point data for each local
@@ -54,6 +55,46 @@ ThermoMechanicsProcess<DisplacementDim>::ThermoMechanicsProcess(
                     result[i] = local_asm.getSigma();
                 }
 
+                return result;
+            }));
+
+    _integration_point_writer.emplace_back(
+        std::make_unique<KelvinVectorIntegrationPointWriter>(
+            "epsilon_ip",
+            static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/,
+            2 /*integration order*/, [this]() {
+                // Result containing integration point data for each local
+                // assembler.
+                std::vector<std::vector<double>> result;
+                result.resize(_local_assemblers.size());
+
+                for (std::size_t i = 0; i < _local_assemblers.size(); ++i)
+                {
+                    auto const& local_asm = *_local_assemblers[i];
+
+                    result[i] = local_asm.getEpsilon();
+                }
+
+                return result;
+            }));
+
+    _integration_point_writer.emplace_back(
+        std::make_unique<KelvinVectorIntegrationPointWriter>(
+            "epsilon_m_ip",
+            static_cast<int>(mesh.getDimension() == 2 ? 4 : 6) /*n components*/,
+            2 /*integration order*/, [this]() {
+                // Result containing integration point data for each local
+                // assembler.
+                std::vector<std::vector<double>> result;
+                result.resize(_local_assemblers.size());
+
+                for (std::size_t i = 0; i < _local_assemblers.size(); ++i)
+                {
+                    auto const& local_asm = *_local_assemblers[i];
+
+                    result[i] = local_asm.getEpsilonMechanical();
+                }
+
                 return result;
             }));
 }
diff --git a/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.h b/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.h
index b124b068a473b877697f9be83a7bc40b6e0be095..869e7e7e41cc8ed2c880e481448d067bdded7d13 100644
--- a/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.h
+++ b/ProcessLib/ThermoMechanics/ThermoMechanicsProcess.h
@@ -20,14 +20,16 @@ namespace ThermoMechanics
 {
 struct ThermoMechanicsLocalAssemblerInterface;
 
-struct SigmaIntegrationPointWriter final : public IntegrationPointWriter
+struct KelvinVectorIntegrationPointWriter final : public IntegrationPointWriter
 {
-    explicit SigmaIntegrationPointWriter(
+    explicit KelvinVectorIntegrationPointWriter(
+        std::string const& name,
         int const n_components,
         int const integration_order,
         std::function<std::vector<std::vector<double>>()>
             callback)
-        : _n_components(n_components),
+        : _name(name),
+          _n_components(n_components),
           _integration_order(integration_order),
           _callback(callback)
     {
@@ -41,7 +43,7 @@ struct SigmaIntegrationPointWriter final : public IntegrationPointWriter
         // TODO (naumov) remove ip suffix. Probably needs modification of the
         // mesh properties, s.t. there is no "overlapping" with cell/point data.
         // See getOrCreateMeshProperty.
-        return "sigma_ip";
+        return _name;
     }
 
     std::vector<std::vector<double>> values() const override
@@ -50,6 +52,7 @@ struct SigmaIntegrationPointWriter final : public IntegrationPointWriter
     }
 
 private:
+    std::string const _name;
     int const _n_components;
     int const _integration_order;
     std::function<std::vector<std::vector<double>>()> _callback;