From 489b396d3a03cc6eddd439eeea7014c4ea67d51d Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Wed, 14 Jun 2006 14:43:56 +0000
Subject: [PATCH] implement infrastructure for reduced integration -- fixed a
 bug in the shear strain energy

[[Imported from SVN: r838]]
---
 src/rodassembler.cc | 108 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 99 insertions(+), 9 deletions(-)

diff --git a/src/rodassembler.cc b/src/rodassembler.cc
index 6cea8711..ba4d125c 100644
--- a/src/rodassembler.cc
+++ b/src/rodassembler.cc
@@ -658,19 +658,23 @@ computeEnergy(const std::vector<Configuration>& sol) const
         for (int i=0; i<numOfBaseFct; i++)
             localSolution[i] = sol[indexSet.template subIndex<gridDim>(*it,i)];
 
-        // Get quadrature rule
-        const int polOrd = 2;
-        const QuadratureRule<double, gridDim>& quad = QuadratureRules<double, gridDim>::rule(it->geometry().type(), polOrd);
+        // ///////////////////////////////////////////////////////////////////////////////
+        //   The following two loops are a reduced integration scheme.  We integrate
+        //   the transverse shear and extensional energy with a first-order quadrature
+        //   formula, even though it should be second order.  This prevents shear-locking
+        // ///////////////////////////////////////////////////////////////////////////////
+        const int shearingPolOrd = 2;
+        const QuadratureRule<double, gridDim>& shearingQuad = QuadratureRules<double, gridDim>::rule(it->geometry().type(), shearingPolOrd);
 
-        for (int pt=0; pt<quad.size(); pt++) {
+        for (int pt=0; pt<shearingQuad.size(); pt++) {
 
             // Local position of the quadrature point
-            const FieldVector<double,gridDim>& quadPos = quad[pt].position();
+            const FieldVector<double,gridDim>& quadPos = shearingQuad[pt].position();
             
             const FieldMatrix<double,1,1>& inv = it->geometry().jacobianInverseTransposed(quadPos);
             const double integrationElement = it->geometry().integrationElement(quadPos);
         
-            double weight = quad[pt].weight() * integrationElement;
+            double weight = shearingQuad[pt].weight() * integrationElement;
             
             // ///////////////////////////////////////
             //   Compute deformation gradient
@@ -681,13 +685,11 @@ computeEnergy(const std::vector<Configuration>& sol) const
                 
                 for (int i=0; i<gridDim; i++)
                     shapeGrad[dof][i] = baseSet[dof].evaluateDerivative(0,i,quadPos);
-                //std::cout << "Gradient " << dof << ": " << shape_grads[dof] << std::endl;
                 
                 // multiply with jacobian inverse 
                 FieldVector<double,gridDim> tmp(0);
                 inv.umv(shapeGrad[dof], tmp);
                 shapeGrad[dof] = tmp;
-                //std::cout << "Gradient " << dof << ": " << shape_grads[dof] << std::endl;
 
             }
 
@@ -733,10 +735,98 @@ computeEnergy(const std::vector<Configuration>& sol) const
             v[1] = r_s * q.director(1);    // shear strain
             v[2] = r_s * q.director(2);    // stretching strain
 
+            energy += weight * 0.5 * (A1*v[0]*v[0] + A2*v[1]*v[1] + A3*(v[2]-1)*(v[2]-1));
+
+#if 0
+            // Part II: the bending and twisting energy
+            
+            FieldVector<double,3> u;  // The Darboux vector
+            u[0] = 2 * ( q[3]*q_s[0] + q[2]*q_s[1] - q[1]*q_s[2] - q[0]*q_s[3]);
+            u[1] = 2 * (-q[2]*q_s[0] + q[3]*q_s[1] + q[0]*q_s[2] - q[1]*q_s[3]);
+            u[2] = 2 * ( q[1]*q_s[0] - q[0]*q_s[1] + q[3]*q_s[2] - q[2]*q_s[3]);
+
+            //std::cout << "Darboux vector : " << u << std::endl;
+
+            energy += weight * 0.5 * (K1*u[0]*u[0] + K2*u[1]*u[1] + K3*u[2]*u[2]);
+#endif
+        }
+
+        // Get quadrature rule
+        const int polOrd = 2;
+        const QuadratureRule<double, gridDim>& bendingQuad = QuadratureRules<double, gridDim>::rule(it->geometry().type(), polOrd);
+
+        for (int pt=0; pt<bendingQuad.size(); pt++) {
+
+            // Local position of the quadrature point
+            const FieldVector<double,gridDim>& quadPos = bendingQuad[pt].position();
+            
+            const FieldMatrix<double,1,1>& inv = it->geometry().jacobianInverseTransposed(quadPos);
+        
+            double weight = bendingQuad[pt].weight() * it->geometry().integrationElement(quadPos);
+            
+            // ///////////////////////////////////////
+            //   Compute deformation gradient
+            // ///////////////////////////////////////
+            std::vector<FieldVector<double,gridDim> > shapeGrad(numOfBaseFct);
+            
+            for (int dof=0; dof<numOfBaseFct; dof++) {
+                
+                for (int i=0; i<gridDim; i++)
+                    shapeGrad[dof][i] = baseSet[dof].evaluateDerivative(0,i,quadPos);
+                
+                // multiply with jacobian inverse 
+                FieldVector<double,gridDim> tmp(0);
+                inv.umv(shapeGrad[dof], tmp);
+                shapeGrad[dof] = tmp;
+
+            }
+
+            // Get the value of the shape functions
+            double shapeFunction[2];
+            for(int i=0; i<2; i++) 
+                shapeFunction[i] = baseSet[i].evaluateFunction(0,quadPos);
+
+            // //////////////////////////////////
+            //   Interpolate
+            // //////////////////////////////////
+
+            FieldVector<double,3> r_s;
+            r_s[0] = localSolution[0].r[0]*shapeGrad[0][0] + localSolution[1].r[0]*shapeGrad[1][0];
+            r_s[1] = localSolution[0].r[1]*shapeGrad[0][0] + localSolution[1].r[1]*shapeGrad[1][0];
+            r_s[2] = localSolution[0].r[2]*shapeGrad[0][0] + localSolution[1].r[2]*shapeGrad[1][0];
+
+            // Get the rotation at the quadrature point by interpolating in $H$ and normalizing
+            Quaternion<double> q;
+            q[0] = localSolution[0].q[0]*shapeFunction[0] + localSolution[1].q[0]*shapeFunction[1];
+            q[1] = localSolution[0].q[1]*shapeFunction[0] + localSolution[1].q[1]*shapeFunction[1];
+            q[2] = localSolution[0].q[2]*shapeFunction[0] + localSolution[1].q[2]*shapeFunction[1];
+            q[3] = localSolution[0].q[3]*shapeFunction[0] + localSolution[1].q[3]*shapeFunction[1];
+
+            // The interpolated quaternion is not a unit quaternion anymore.  We simply normalize
+            q.normalize();
+            
+            // Get the derivative of the rotation at the quadrature point by interpolating in $H$
+            Quaternion<double> q_s;
+            q_s[0] = localSolution[0].q[0]*shapeGrad[0][0] + localSolution[1].q[0]*shapeGrad[1][0];
+            q_s[1] = localSolution[0].q[1]*shapeGrad[0][0] + localSolution[1].q[1]*shapeGrad[1][0];
+            q_s[2] = localSolution[0].q[2]*shapeGrad[0][0] + localSolution[1].q[2]*shapeGrad[1][0];
+            q_s[3] = localSolution[0].q[3]*shapeGrad[0][0] + localSolution[1].q[3]*shapeGrad[1][0];
+
+            // /////////////////////////////////////////////
+            //   Sum it all up
+            // /////////////////////////////////////////////
+#if 0
+            // Part I: the shearing and stretching energy
+            //std::cout << "tangent : " << r_s << std::endl;
+            FieldVector<double,3> v;
+            v[0] = r_s * q.director(0);    // shear strain
+            v[1] = r_s * q.director(1);    // shear strain
+            v[2] = r_s * q.director(2);    // stretching strain
+
             //std::cout << "strain : " << v << std::endl;
 
             energy += weight * 0.5*A1*v[0]*v[0] + 0.5*A2*v[1]*v[1] + 0.5*A3*(v[2]-1)*(v[2]-1);
-
+#endif
             // Part II: the bending and twisting energy
             
             FieldVector<double,3> u;  // The Darboux vector
-- 
GitLab