From 2860ae8d39fa66ca7bccf4d10736b36d571b413a Mon Sep 17 00:00:00 2001
From: Lisa Julia Nebel <lisa_julia.nebel@tu-dresden.de>
Date: Fri, 9 Jul 2021 09:13:32 +0200
Subject: [PATCH] Change nonplanarcosseratenergytest to make adaptions easier

---
 test/nonplanarcosseratenergytest.cc | 148 +++++++++++++---------------
 1 file changed, 71 insertions(+), 77 deletions(-)

diff --git a/test/nonplanarcosseratenergytest.cc b/test/nonplanarcosseratenergytest.cc
index 68b05569..a8dd5a48 100644
--- a/test/nonplanarcosseratenergytest.cc
+++ b/test/nonplanarcosseratenergytest.cc
@@ -1,5 +1,7 @@
 #include "config.h"
 
+#include <math.h>
+
 #include <dune/foamgrid/foamgrid.hh>
 
 #include <dune/geometry/type.hh>
@@ -34,8 +36,9 @@ std::unique_ptr<GridType> makeSingleElementGrid()
     constexpr auto triangle = Dune::GeometryTypes::triangle;
     GridFactory<GridType> factory;
 
+    //Create a triangle that is not parallel to the planes formed by the coordinate axes
     FieldVector<double,dimworld> vertex0{0,0,0};
-    FieldVector<double,dimworld> vertex1{0,1,0};
+    FieldVector<double,dimworld> vertex1{0,1,1}; 
     FieldVector<double,dimworld> vertex2{1,0,0};
     factory.insertVertex(vertex0);
     factory.insertVertex(vertex1);
@@ -50,50 +53,8 @@ std::unique_ptr<GridType> makeSingleElementGrid()
 //////////////////////////////////////////////////////////////////////////////////////
 //   Test energy computation for the same grid with different refinement levels
 //////////////////////////////////////////////////////////////////////////////////////
-
-TargetSpace getConfiguration(const FieldVector<double, dimworld>& point) {
-    FieldVector<double, dimworld> displacementAtPoint(0);
-    FieldVector<double,4> rotationVectorAtPoint(0);
-
-    if (point[0] == 0 and point[1] == 0 and point[2] == 0) {
-        //0 0 0
-        displacementAtPoint = {0, 0, 0};
-        rotationVectorAtPoint = {0, 0, 0, 1};
-    } else if (point[0] == 1 and point[1] == 0 and point[2] == 0) {
-        //1 0 0
-        displacementAtPoint = {0, 0, 1};
-        rotationVectorAtPoint = {0, 0, 0, 1};
-    } else if (point[0] == 0 and point[1] == 1 and point[2] == 0) {
-        //0 1 0
-        displacementAtPoint = {0, 0, 1};
-        rotationVectorAtPoint = {0, 0, 0, 1};
-    } else if (point[0] == 0.5 and point[1] == 0 and point[2] == 0) {
-        //0.5 0 0
-        displacementAtPoint = {0, 0, 0.5};
-        rotationVectorAtPoint = {0, 0, 0, 1};
-    } else if (point[0] == 0 and point[1] == 0.5 and point[2] == 0) {
-        //0 0.5 0
-        displacementAtPoint = {0, 0, 0.5};
-        rotationVectorAtPoint = {0, 0, 0, 1};
-    } else if (point[0] == 0.5 and point[1] == 0.5 and point[2] == 0) {
-        //0.5 0.5 0
-        displacementAtPoint = {0, 0, 1};
-        rotationVectorAtPoint = {0, 0, 0, 1};
-    }
-
-    TargetSpace configuration;
-    for (int i = 0; i < dimworld; i++)
-        configuration.r[i] = point[i] + displacementAtPoint[i];
-
-    Rotation<double,dimworld> rotation(rotationVectorAtPoint);
-    FieldMatrix<double,dimworld,dimworld> rotationMatrix(0);
-    rotation.matrix(rotationMatrix);
-    configuration.q.set(rotationMatrix);
-
-    return configuration;
-}
-
-double calculateEnergy(const int numLevels)
+template <class F1, class F2>
+double calculateEnergy(const int numLevels, const F1 referenceConfigurationFunction, const F2 configurationFunction)
 {
     ParameterTree materialParameters;
     materialParameters["thickness"] = "0.1";
@@ -111,7 +72,7 @@ double calculateEnergy(const int numLevels)
     grid->globalRefine(numLevels-1);
     GridType::LeafGridView gridView = grid->leafGridView();
 
-    using FEBasis = Dune::Functions::LagrangeBasis<typename GridType::LeafGridView,1>;
+    using FEBasis = Dune::Functions::LagrangeBasis<typename GridType::LeafGridView,2>;
     FEBasis feBasis(gridView);
 
     using namespace Dune::Functions::BasisFactory;
@@ -120,74 +81,107 @@ double calculateEnergy(const int numLevels)
     auto deformationPowerBasis = makeBasis(
         gridView,
         power<dimworld>(
-            lagrange<1>()
+            lagrange<2>()
     ));
 
-    BlockVector<FieldVector<double,3> > helperVector;
-    Dune::Functions::interpolate(deformationPowerBasis, helperVector, [](FieldVector<double,dimworld> x){
-        auto out = x;
-        out[2] += x[0];
-        return out;
-    });
-    //Dune::Functions::interpolate(deformationPowerBasis, helperVector, [](FieldVector<double,dimworld> x){ return x; });
+    BlockVector<FieldVector<double,3> > helperVector1(feBasis.size());
+    Dune::Functions::interpolate(deformationPowerBasis, helperVector1, referenceConfigurationFunction);
+    auto stressFreeConfiguration = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dimworld>>(deformationPowerBasis, helperVector1);
 
-    auto stressFreeConfiguration = Dune::Functions::makeDiscreteGlobalBasisFunction<FieldVector<double,dimworld>>(deformationPowerBasis, helperVector);
-
-    NonplanarCosseratShellEnergy<FEBasis, 3, double, decltype(stressFreeConfiguration)> localCosseratEnergyPlanar(materialParameters,
+    NonplanarCosseratShellEnergy<FEBasis, 3, double, decltype(stressFreeConfiguration)> nonplanarCosseratShellEnergy(materialParameters,
                                                                                                     &stressFreeConfiguration,
                                                                                                     nullptr,
                                                                                                     nullptr,
                                                                                                     nullptr);
-
-    BlockVector<FieldVector<double,3> > id;
-    Dune::Functions::interpolate(deformationPowerBasis, id, [](FieldVector<double,dimworld> x){ return x; });
     BlockVector<TargetSpace> sol(feBasis.size());
     TupleVector<std::vector<RealTuple<double,3> >,
                 std::vector<Rotation<double,3> > > solTuple;
     solTuple[_0].resize(feBasis.size());
     solTuple[_1].resize(feBasis.size());
+
+    BlockVector<FieldVector<double,3> > helperVector2(feBasis.size());
+    Dune::Functions::interpolate(deformationPowerBasis, helperVector2, configurationFunction);
     for (int i = 0; i < feBasis.size(); i++) {
-        sol[i] = getConfiguration(id[i]);
+        for (int j = 0; j < dimworld; j++)
+            sol[i].r[j] = helperVector2[i][j]; 
+
+        FieldVector<double,4> idRotation = {0, 0, 0, 1}; //set rotation = Id everywhere
+        Rotation<double,dimworld> rotation(idRotation);
+        FieldMatrix<double,dimworld,dimworld> rotationMatrix(0);
+        rotation.matrix(rotationMatrix);
+        sol[i].q.set(rotationMatrix);
         solTuple[_0][i] = sol[i].r;
         solTuple[_1][i] = sol[i].q;
     }
-
     CosseratVTKWriter<GridType>::write<FEBasis>(feBasis, solTuple, "configuration_l" + std::to_string(numLevels));
 
     double energy = 0;
-
     // A view on the FE basis on a single element
     auto localView = feBasis.localView();
-
     // Loop over all elements
-    for (const auto& element : elements(feBasis.gridView(), Dune::Partitions::interior))
-    {
+    for (const auto& element : elements(feBasis.gridView(), Dune::Partitions::interior)) {
         localView.bind(element);
-
         // Number of degrees of freedom on this element
         size_t nDofs = localView.tree().size();
-
         std::vector<TargetSpace> localSolution(nDofs);
-
         for (size_t i=0; i<nDofs; i++)
             localSolution[i] = sol[localView.index(i)[0]];
-
-        energy += localCosseratEnergyPlanar.energy(localView, localSolution);
-
+        energy += nonplanarCosseratShellEnergy.energy(localView, localSolution);
     }
-
     return energy;
 }
 
 int main(int argc, char** argv)
 {
     MPIHelper::instance(argc, argv);
+    auto configurationId = [](FieldVector<double,dimworld> x){ return x; };
+    auto configurationStretchY = [](FieldVector<double,dimworld> x){
+        auto out = x;
+        out[1] *= 2;
+        return out;
+    };
 
-    double energyFine = calculateEnergy(2);
-    double energyCoarse = calculateEnergy(1);
-    std::cout << "energyFine: " << energyFine << std::endl;
-    std::cout << "energyCoarse: " << energyCoarse << std::endl;
+    auto configurationTwist = [](FieldVector<double,dimworld> x){
+        auto out = x;
+        out[1] = x[2];
+        out[2] = -x[1];
+        return out;
+    };
 
+    auto configurationCurved = [](FieldVector<double,dimworld> x){
+        auto out = x;
+        out[1] = x[2];
+        out[2] = -x[1];
+        return out;
+    };
+    auto configurationSquare = [](FieldVector<double,dimworld> x){
+        auto out = x;
+        out[1] += x[1]*x[1];
+        return out;
+    };
 
+    auto configurationSin = [](FieldVector<double,dimworld> x){
+        auto out = x;
+        out[2] = sin(x[2]);
+        return out;
+    };
+
+    double energyFine = calculateEnergy(2, configurationId, configurationStretchY);
+    double energyCoarse = calculateEnergy(1, configurationId, configurationStretchY);
     assert(std::abs(energyFine - energyCoarse) < 1e-3);
+
+    double energyForZeroDifference = calculateEnergy(1,configurationId,configurationId);
+    assert(std::abs(energyForZeroDifference) < 1e-3);
+
+    double energyForZeroDifference2 = calculateEnergy(1,configurationStretchY,configurationStretchY);
+    assert(std::abs(energyForZeroDifference2) < 1e-3);
+
+    double energyForZeroDifference3 = calculateEnergy(1,configurationTwist,configurationTwist);
+    assert(std::abs(energyForZeroDifference3) < 1e-3);
+
+    double energyForZeroDifference4 = calculateEnergy(1,configurationSquare,configurationSquare);
+    assert(std::abs(energyForZeroDifference4) < 1e-3);
+
+    double energyForZeroDifference5 = calculateEnergy(1,configurationSin,configurationSin);
+    assert(std::abs(energyForZeroDifference5) < 1e-3);
 }
-- 
GitLab