diff --git a/MaterialLib/SolidModels/Ehlers-impl.h b/MaterialLib/SolidModels/Ehlers-impl.h
index 938dc03730eb7d9b009804cd8461ef237d6a03af..48abe75b5852764f2440392d7d93145e55a54e1e 100644
--- a/MaterialLib/SolidModels/Ehlers-impl.h
+++ b/MaterialLib/SolidModels/Ehlers-impl.h
@@ -43,6 +43,16 @@ namespace Solids
 {
 namespace Ehlers
 {
+/// Special product of \c v with itself: \f$v \odot v\f$.
+/// The tensor \c v is given in Kelvin mapping.
+/// \note Implementation only for 2 and 3 dimensions.
+/// \attention Pay attention to the sign of the result, which normally would be
+/// negative, but the returned value is not negated. This has to do with \f$
+/// d(A^{-1})/dA = -A^{-1} \odot A^{-1} \f$.
+template <int DisplacementDim>
+ProcessLib::KelvinMatrixType<DisplacementDim> sOdotS(
+    ProcessLib::KelvinVectorType<DisplacementDim> const& v);
+
 template <int DisplacementDim>
 struct PhysicalStressWithInvariants final
 {
@@ -216,46 +226,6 @@ void calculatePlasticResidual(
         yieldFunction<DisplacementDim>(s, _mp, t, x) / G;
 }
 
-/// Special product of \p v with itself: \f$v \odot v\f$.
-/// v is given in \p Kelvin mapping.
-template <int DisplacementDim>
-ProcessLib::KelvinMatrixType<DisplacementDim> s_odot_s(
-    ProcessLib::KelvinVectorType<DisplacementDim> const& v)
-{
-    ProcessLib::KelvinMatrixType<DisplacementDim> result;
-
-    result(0, 0) = v(0) * v(0);
-    result(0, 1) = result(1, 0) = v(3) * v(3) / 2.;
-    result(0, 2) = result(2, 0) = v(5) * v(5) / 2.;
-    result(0, 3) = result(3, 0) = v(0) * v(3);
-    result(0, 4) = result(4, 0) = v(3) * v(5) / std::sqrt(2.);
-    result(0, 5) = result(5, 0) = v(0) * v(5);
-
-    result(1, 1) = v(1) * v(1);
-    result(1, 2) = result(2, 1) = v(4) * v(4) / 2.;
-    result(1, 3) = result(3, 1) = v(3) * v(1);
-    result(1, 4) = result(4, 1) = v(1) * v(4);
-    result(1, 5) = result(5, 1) = v(3) * v(4) / std::sqrt(2.);
-
-    result(2, 2) = v(2) * v(2);
-    result(2, 3) = result(3, 2) = v(5) * v(4) / std::sqrt(2.);
-    result(2, 4) = result(4, 2) = v(4) * v(2);
-    result(2, 5) = result(5, 2) = v(5) * v(2);
-
-    result(3, 3) = v(0) * v(1) + v(3) * v(3) / 2.;
-    result(3, 4) = result(4, 3) =
-        v(3) * v(4) / 2. + v(5) * v(1) / std::sqrt(2.);
-    result(3, 5) = result(5, 3) =
-        v(0) * v(4) / std::sqrt(2.) + v(3) * v(5) / 2.;
-
-    result(4, 4) = v(1) * v(2) + v(4) * v(4) / 2.;
-    result(4, 5) = result(5, 4) =
-        v(3) * v(2) / std::sqrt(2.) + v(5) * v(4) / 2.;
-
-    result(5, 5) = v(0) * v(2) + v(5) * v(5) / 2.;
-    return result;
-}
-
 template <int DisplacementDim>
 void calculatePlasticJacobian(
     double const dt,
@@ -351,7 +321,7 @@ void calculatePlasticJacobian(
         one_gt.pow_m_p * (P_dev + s.D * gm_p * M0.transpose());
     // second derivative of theta
     KelvinMatrix const d2theta_dsigma2 =
-        theta * P_dev * s_odot_s<DisplacementDim>(sigma_D_inverse) * P_dev +
+        theta * P_dev * sOdotS<DisplacementDim>(sigma_D_inverse) * P_dev +
         sigma_D_inverse_D * dtheta_dsigma.transpose() -
         3. / 2. * theta / s.J_2 * P_dev -
         3. / 2. * dtheta_dsigma / s.J_2 * s.D.transpose() +
diff --git a/MaterialLib/SolidModels/Ehlers.cpp b/MaterialLib/SolidModels/Ehlers.cpp
index af91297bbd6d64e3b9dacfdc46027dd105d0e87b..3151990fadbadffe59fec5b215036e3baf029383 100644
--- a/MaterialLib/SolidModels/Ehlers.cpp
+++ b/MaterialLib/SolidModels/Ehlers.cpp
@@ -18,6 +18,67 @@ namespace Ehlers
 template class SolidEhlers<2>;
 template class SolidEhlers<3>;
 
+template <>
+ProcessLib::KelvinMatrixType<3> sOdotS<3>(
+    ProcessLib::KelvinVectorType<3> const& v)
+{
+    ProcessLib::KelvinMatrixType<3> result;
+
+    result(0, 0) = v(0) * v(0);
+    result(0, 1) = result(1, 0) = v(3) * v(3) / 2.;
+    result(0, 2) = result(2, 0) = v(5) * v(5) / 2.;
+    result(0, 3) = result(3, 0) = v(0) * v(3);
+    result(0, 4) = result(4, 0) = v(3) * v(5) / std::sqrt(2.);
+    result(0, 5) = result(5, 0) = v(0) * v(5);
+
+    result(1, 1) = v(1) * v(1);
+    result(1, 2) = result(2, 1) = v(4) * v(4) / 2.;
+    result(1, 3) = result(3, 1) = v(3) * v(1);
+    result(1, 4) = result(4, 1) = v(1) * v(4);
+    result(1, 5) = result(5, 1) = v(3) * v(4) / std::sqrt(2.);
+
+    result(2, 2) = v(2) * v(2);
+    result(2, 3) = result(3, 2) = v(5) * v(4) / std::sqrt(2.);
+    result(2, 4) = result(4, 2) = v(4) * v(2);
+    result(2, 5) = result(5, 2) = v(5) * v(2);
+
+    result(3, 3) = v(0) * v(1) + v(3) * v(3) / 2.;
+    result(3, 4) = result(4, 3) =
+        v(3) * v(4) / 2. + v(5) * v(1) / std::sqrt(2.);
+    result(3, 5) = result(5, 3) =
+        v(0) * v(4) / std::sqrt(2.) + v(3) * v(5) / 2.;
+
+    result(4, 4) = v(1) * v(2) + v(4) * v(4) / 2.;
+    result(4, 5) = result(5, 4) =
+        v(3) * v(2) / std::sqrt(2.) + v(5) * v(4) / 2.;
+
+    result(5, 5) = v(0) * v(2) + v(5) * v(5) / 2.;
+    return result;
+}
+
+template <>
+ProcessLib::KelvinMatrixType<2> sOdotS<2>(
+    ProcessLib::KelvinVectorType<2> const& v)
+{
+    ProcessLib::KelvinMatrixType<2> result;
+
+    result(0, 0) = v(0) * v(0);
+    result(0, 1) = result(1, 0) = v(3) * v(3) / 2.;
+    result(0, 2) = result(2, 0) = 0;
+    result(0, 3) = result(3, 0) = v(0) * v(3);
+
+    result(1, 1) = v(1) * v(1);
+    result(1, 2) = result(2, 1) = 0;
+    result(1, 3) = result(3, 1) = v(3) * v(1);
+
+    result(2, 2) = v(2) * v(2);
+    result(2, 3) = result(3, 2) = 0;
+
+    result(3, 3) = v(0) * v(1) + v(3) * v(3) / 2.;
+
+    return result;
+}
+
 }  // namespace Ehlers
 }  // namespace Solids
 }  // namespace MaterialLib