From 70f528260decf5b344ca31f58687e0b78df8085c Mon Sep 17 00:00:00 2001
From: Oliver Sander <oliver.sander@tu-dresden.de>
Date: Sat, 20 Apr 2024 19:21:27 +0200
Subject: [PATCH] LocalIntegralEnergy: Remove special code for dune-elasticity
 densities

In the wake of this, remove all Cosserat nomenclature.

We keep the restriction to two factor spaces, because I see no
short-time need for more generality.
---
 dune/gfe/assemblers/localintegralenergy.hh | 150 ++++++++-------------
 1 file changed, 53 insertions(+), 97 deletions(-)

diff --git a/dune/gfe/assemblers/localintegralenergy.hh b/dune/gfe/assemblers/localintegralenergy.hh
index 385cb10b..a0561c4c 100644
--- a/dune/gfe/assemblers/localintegralenergy.hh
+++ b/dune/gfe/assemblers/localintegralenergy.hh
@@ -2,15 +2,12 @@
 #define DUNE_GFE_ASSEMBLERS_LOCALINTEGRALENERGY_HH
 
 #include <dune/common/fmatrix.hh>
-#include <dune/common/fmatrixev.hh>
 
 #include <dune/geometry/quadraturerules.hh>
 
 #include <dune/gfe/assemblers/localenergy.hh>
-#include <dune/gfe/densities/duneelasticitydensity.hh>
 #include <dune/gfe/densities/localdensity.hh>
-#include <dune/gfe/spaces/realtuple.hh>
-#include <dune/gfe/spaces/rotation.hh>
+
 
 namespace Dune::GFE {
 
@@ -36,7 +33,7 @@ namespace Dune::GFE {
     /** \brief Constructor with a Dune::GFE::LocalDensity
      */
     LocalIntegralEnergy(const std::shared_ptr<GFE::LocalDensity<FieldVector<DT,gridDim>,TargetSpace> >& ld)
-      : localDensityGFE_(ld)
+      : localDensity_(ld)
     {}
 
   private:
@@ -67,16 +64,18 @@ namespace Dune::GFE {
 
           const auto integrationElement = element.geometry().integrationElement(quadPos);
 
-          const auto jacobianInverse = element.geometry().jacobianInverse(quadPos);
+          const auto geometryJacobianInverse = element.geometry().jacobianInverse(quadPos);
 
           // Function value at the quadrature point
+          // This is always needed: Either directly, or to compute the derivative below
           TargetSpace q = localInterpolationRule.evaluate(quadPos);
 
           // The derivative of the finite element function at the quadrature point
-          auto referenceDerivative = localInterpolationRule.evaluateDerivative(quadPos, q);
-          auto derivative = referenceDerivative * jacobianInverse;
+          typename LocalInterpolationRule::DerivativeType derivative;
+          if (localDensity_->dependsOnDerivative())
+            derivative = localInterpolationRule.evaluateDerivative(quadPos, q) * geometryJacobianInverse;
 
-          energy += qp.weight() * integrationElement * (*localDensityGFE_)(quadPos,q,derivative);
+          energy += qp.weight() * integrationElement * (*localDensity_)(quadPos,q,derivative);
         }
       }
 
@@ -90,116 +89,73 @@ namespace Dune::GFE {
 
       if constexpr (Impl::LocalEnergyTypes<TargetSpace>::isProductManifold)
       {
-        // TODO: Cosserat materials are hard-wired here for historical reasons.
-        static_assert(TargetSpace::size() == 2, "LocalGeodesicIntegralEnergy needs two TargetSpaces!");
-        using TargetSpaceDeformation = typename std::tuple_element<0, TargetSpace>::type;
-        using TargetSpaceRotation = typename std::tuple_element<1, TargetSpace>::type;
+        static_assert(TargetSpace::size() == 2,
+                      "LocalIntegralEnergy only implemented for product spaces with two factors!");
 
         const auto& element = localView.element();
 
         using namespace Indices;
-        const std::vector<TargetSpaceDeformation>& localDeformationConfiguration = coefficients[_0];
-        const std::vector<TargetSpaceRotation>& localOrientationConfiguration = coefficients[_1];
 
         // composite Basis: grab the finite element of the first child
-        const auto& deformationLocalFiniteElement = localView.tree().child(_0,0).finiteElement();
-        const auto& orientationLocalFiniteElement = localView.tree().child(_1,0).finiteElement();
-
-        using LocalDeformationGFEFunctionType = typename std::tuple_element<0, LocalInterpolationRule>::type;
-        using LocalOrientationGFEFunctionType = typename std::tuple_element<1, LocalInterpolationRule>::type;
+        const auto& localFiniteElement0 = localView.tree().child(_0,0).finiteElement();
+        const auto& localFiniteElement1 = localView.tree().child(_1,0).finiteElement();
 
-        LocalDeformationGFEFunctionType localDeformationGFEFunction(deformationLocalFiniteElement,localDeformationConfiguration);
-        LocalOrientationGFEFunctionType localOrientationGFEFunction(orientationLocalFiniteElement,localOrientationConfiguration);
+        using LocalGFEFunctionType0 = typename std::tuple_element<0, LocalInterpolationRule>::type;
+        using LocalGFEFunctionType1 = typename std::tuple_element<1, LocalInterpolationRule>::type;
 
+        LocalGFEFunctionType0 localGFEFunction0(localFiniteElement0, coefficients[_0]);
+        LocalGFEFunctionType1 localGFEFunction1(localFiniteElement1, coefficients[_1]);
 
-        int quadOrder = (element.type().isSimplex()) ? deformationLocalFiniteElement.localBasis().order()
-                                                 : deformationLocalFiniteElement.localBasis().order() * gridDim;
+        int quadOrder = (element.type().isSimplex()) ? localFiniteElement0.localBasis().order()
+                                                 : localFiniteElement0.localBasis().order() * gridDim;
 
         const auto& quad = QuadratureRules<DT, gridDim>::rule(element.type(), quadOrder);
 
         for (size_t pt=0; pt<quad.size(); pt++)
         {
           // Local position of the quadrature point
-          const FieldVector<DT,gridDim>& quadPos = quad[pt].position();
+          const auto& quadPos = quad[pt].position();
 
           auto x = element.geometry().global(quadPos);
 
           const DT integrationElement = element.geometry().integrationElement(quadPos);
 
-          const auto jacobianInverseTransposed = element.geometry().jacobianInverseTransposed(quadPos);
+          const auto geometryJacobianInverse = element.geometry().jacobianInverse(quadPos);
 
           DT weightWithintegrationElement = quad[pt].weight() * integrationElement;
 
-          // The value of the local deformation
-          RealTuple<RT,gridDim> deformationValue = localDeformationGFEFunction.evaluate(quadPos);
-
-          // The derivative of the deformation defined on the reference element
-          typename LocalDeformationGFEFunctionType::DerivativeType deformationReferenceDerivative = localDeformationGFEFunction.evaluateDerivative(quadPos,deformationValue);
-
-          // The derivative of the deformation defined on the actual element
-          typename LocalDeformationGFEFunctionType::DerivativeType deformationDerivative;
-          for (size_t comp=0; comp<deformationReferenceDerivative.N(); comp++)
-            jacobianInverseTransposed.mv(deformationReferenceDerivative[comp], deformationDerivative[comp]);
-
-          typename LocalOrientationGFEFunctionType::DerivativeType orientationDerivative;
-
-          // Integrate the energy density
-          // We do a special-casing for DuneElasticityDensity:
-          // Of that one we know that it does not actually depend on the rotation.
-          using DEDensity = DuneElasticityDensity<FieldVector<DT,gridDim>,TargetSpace,0>;
-          std::shared_ptr<DEDensity> duneElasticityDensity = std::dynamic_pointer_cast<DEDensity>(localDensityGFE_);
-          if (duneElasticityDensity)
-          {
-            // Dummy local rotation value
-            ProductManifold<RealTuple<RT,gridDim>,Rotation<RT,gridDim> > value;
-            value[_0] = deformationValue;
-            value[_1] = TargetSpaceRotation::identity();
-
-            // Copy the two derivatives into a joint matrix object
-            // TODO: I am not sure about this.  May the densities should get the
-            // separate derivatives.
-            FieldMatrix<RT,deformationDerivative.rows+orientationDerivative.rows, deformationDerivative.cols> derivative;
-
-            for (int i=0; i<deformationDerivative.rows; i++)
-              derivative[i] = deformationDerivative[i];
-
-            for (int i=0; i<orientationDerivative.rows; i++)
-              derivative[i+deformationDerivative.rows] = 0.0;
-
-            energy += weightWithintegrationElement * (*duneElasticityDensity)(x,
-                                                                              value,
-                                                                              derivative);
-          }
-          else if (localDensityGFE_) {
-            // The value of the local rotation
-            Rotation<RT,gridDim>  orientationValue = localOrientationGFEFunction.evaluate(quadPos);
-
-            ProductManifold<RealTuple<RT,gridDim>,Rotation<RT,gridDim> > value;
-            value[_0] = deformationValue;
-            value[_1] = orientationValue;
-
-            // The derivative of the rotation defined on the reference element
-            typename LocalOrientationGFEFunctionType::DerivativeType orientationReferenceDerivative = localOrientationGFEFunction.evaluateDerivative(quadPos,orientationValue);
-
-            // The derivative of the rotation defined on the actual element
-            for (size_t comp=0; comp<orientationReferenceDerivative.N(); comp++)
-              jacobianInverseTransposed.mv(orientationReferenceDerivative[comp], orientationDerivative[comp]);
-
-            // Copy the two derivatives into a joint matrix object
-            // TODO: I am not sure about this.  May the densities should get the
-            // separate derivatives.
-            FieldMatrix<RT,deformationDerivative.rows+orientationDerivative.rows, deformationDerivative.cols> derivative;
-
-            for (int i=0; i<deformationDerivative.rows; i++)
-              derivative[i] = deformationDerivative[i];
-
-            for (int i=0; i<orientationDerivative.rows; i++)
-              derivative[i+deformationDerivative.rows] = orientationDerivative[i];
-
-            energy += weightWithintegrationElement * (*localDensityGFE_)(x,
-                                                                         value,
-                                                                         derivative);
-          }
+          // Compute the required values of the interpolation function
+          // A value is needed either directly, or for computing the derivative.
+          TargetSpace value;
+          if (localDensity_->dependsOnValue(0) || localDensity_->dependsOnDerivative(0))
+            value[_0] = localGFEFunction0.evaluate(quadPos);
+          if (localDensity_->dependsOnValue(1) || localDensity_->dependsOnDerivative(1))
+            value[_1] = localGFEFunction1.evaluate(quadPos);
+
+          // Compute the derivatives of the interpolation function factors
+          typename LocalGFEFunctionType0::DerivativeType derivative0;
+          typename LocalGFEFunctionType1::DerivativeType derivative1;
+
+          if (localDensity_->dependsOnDerivative(0))
+            derivative0 = localGFEFunction0.evaluateDerivative(quadPos,value[_0]) * geometryJacobianInverse;
+
+          if (localDensity_->dependsOnDerivative(1))
+            derivative1 = localGFEFunction1.evaluateDerivative(quadPos,value[_1]) * geometryJacobianInverse;
+
+          // Copy the two derivatives into a joint matrix object
+          // TODO: I am not sure about this.  May the densities should get the
+          // separate derivatives.
+          FieldMatrix<RT,derivative0.rows+derivative1.rows, derivative0.cols> derivative;
+
+          for (int i=0; i<derivative0.rows; i++)
+            derivative[i] = derivative0[i];
+
+          for (int i=0; i<derivative1.rows; i++)
+            derivative[i+derivative0.rows] = derivative1[i];
+
+          energy += weightWithintegrationElement * (*localDensity_)(x,
+                                                                    value,
+                                                                    derivative);
         }
       }
 
@@ -207,7 +163,7 @@ namespace Dune::GFE {
     }
 
   protected:
-    const std::shared_ptr<GFE::LocalDensity<FieldVector<DT,gridDim>,TargetSpace> > localDensityGFE_;
+    const std::shared_ptr<GFE::LocalDensity<FieldVector<DT,gridDim>,TargetSpace> > localDensity_;
   };
 
 }  // namespace Dune::GFE
-- 
GitLab