From 121bc4feaa487f6ac3cbeee02edc340321818cdb Mon Sep 17 00:00:00 2001
From: Oliver Sander <oliver.sander@tu-dresden.de>
Date: Wed, 7 Aug 2024 09:44:24 +0200
Subject: [PATCH] Fix memory access errors when density does not depend on
 function value

If InterpolationDerivatives is told not to compute the derivatives
for the interpolation value, then it sometimes leaves the corresponding
matrix entries uninitialized.  That's okay: they shall not be used
anyway.

However, the code still did use them: It multiplied them by zero.
This is okay if the matrix entries are actual values, but they may
also be NaNs.  In that case, the NaNs propagate, leading to wrong
results.  Fix this by modifying the matrix products to really omit
the uninitialized values.
---
 dune/gfe/assemblers/localintegralstiffness.hh | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/dune/gfe/assemblers/localintegralstiffness.hh b/dune/gfe/assemblers/localintegralstiffness.hh
index e7ed2cfa..8d7cfd0c 100644
--- a/dune/gfe/assemblers/localintegralstiffness.hh
+++ b/dune/gfe/assemblers/localintegralstiffness.hh
@@ -177,6 +177,11 @@ namespace Dune::GFE
 
       const auto& element = localView.element();
 
+      // The range of input variables that the density depends on
+      const size_t begin = (localDensity_->dependsOnValue()) ? 0 : TargetSpace::CoordinateType::dimension;
+      const size_t end = (localDensity_->dependsOnDerivative()) ? m : TargetSpace::CoordinateType::dimension;
+
+      // The quadrature rule
       int quadOrder = (localFiniteElement.type().isSimplex())
            ? (localFiniteElement.localBasis().order()-1) * 2
            : (localFiniteElement.localBasis().order() * gridDim - 1) * 2;
@@ -237,21 +242,17 @@ namespace Dune::GFE
         // Store the Euclidean gradient for the conversion from the Euclidean to the Riemannian Hesse matrix.
         for (size_t i = 0; i < nDofs; i++)
           for (size_t ii=0; ii<embeddedBlocksize; ++ii)
-            for (size_t j = 0; j < m; j++)
+            for (size_t j = begin; j < end; j++)
               localEmbeddedGradient[i][ii] += densityGradient[j] * interpolationGradient[j][i*embeddedBlocksize+ii];
 
         for (size_t i = 0; i < nDofs*blocksize; i++)
-          for (size_t j = 0; j < m; j++)
+          for (size_t j = begin; j < end; j++)
             localGradient[i] += densityGradient[j] * interpolationGradientShort[j][i];
 
         ///////////////////////////////////////////////////////////////////////
         //  Chain rule to construct Hessian
         ///////////////////////////////////////////////////////////////////////
 
-        // The range of input variables that the density depends on
-        const size_t begin = (localDensity_->dependsOnValue()) ? 0 : TargetSpace::CoordinateType::dimension;
-        const size_t end = (localDensity_->dependsOnDerivative()) ? m : TargetSpace::CoordinateType::dimension;
-
         // tmp = hessianDensity * interpolationGradientShort
         Matrix<double> tmp(m,nDofs*blocksize);
         tmp = 0;
-- 
GitLab