From 17dde1b964eddb5b97928179a0dc1f322cf46429 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Tue, 20 Jun 2006 07:40:55 +0000
Subject: [PATCH] more fixes, more cleanup

[[Imported from SVN: r850]]
---
 src/rodassembler.cc | 127 +++++++++++++++++++++-----------------------
 src/rodassembler.hh |  11 ++++
 2 files changed, 73 insertions(+), 65 deletions(-)

diff --git a/src/rodassembler.cc b/src/rodassembler.cc
index 543a8246..a465e18b 100644
--- a/src/rodassembler.cc
+++ b/src/rodassembler.cc
@@ -79,12 +79,10 @@ assembleMatrix(const std::vector<Configuration>& sol,
         // Add element matrix to global stiffness matrix
         for(int i=0; i<numOfBaseFct; i++) { 
             
-            //int row = functionSpace_.mapToGlobal( *it , i );
             int row = indexSet.template subIndex<gridDim>(*it,i);
 
             for (int j=0; j<numOfBaseFct; j++ ) {
                 
-                //int col = functionSpace_.mapToGlobal( *it , j );    
                 int col = indexSet.template subIndex<gridDim>(*it,j);
                 matrix[row][col] += mat[i][j];
                 
@@ -274,7 +272,7 @@ getLocalMatrix( EntityType &entity,
         FixedArray<FixedArray<FixedArray<FieldVector<double,3>, 3>, 2>, 3> dd_dvij;
         getFirstDerivativesOfDirectors(hatq, dd_dvij, dq_dvij);
 
-        // Contains \parder dm \parder v^i_j
+        // Contains \parder {dm}{v^i_j}{v^k_l}
         FieldVector<double,3> dd_dvij_dvkl[3][2][3][2][3];
         
         for (int i=0; i<2; i++) {
@@ -328,18 +326,44 @@ getLocalMatrix( EntityType &entity,
         
         // The Darboux vector
         FieldVector<double,3> u = darboux(hatq, hatq_s);
+        FieldVector<double,3> darbouxCan = darbouxCanonical(hatq, hatq_s);
 
-        // Contains \partial q / \partial v^i_j  at v = 0
-        double dum_dvij[3][2][3];
+        // Contains \partial u (canonical) / \partial v^i_j  at v = 0
+        FieldVector<double,3> duCan_dvij[2][3];
+        FieldVector<double,3> duLocal_dvij[2][3];
+        FieldVector<double,3> duCan_dvij_dvkl[2][3][2][3];
+
+        for (int i=0; i<2; i++) {
 
-        for (int i=0; i<2; i++)
             for (int j=0; j<3; j++) {
                 
-                for (int m=0; m<3; m++) 
-                    dum_dvij[m][i][j] = B(m, dq_dvij[i][j].mult(hatq))*hatq_s + B(m,hatq)*(dq_dvij_ds[i][j].mult(hatq));
+                for (int m=0; m<3; m++) {
+                    duCan_dvij[i][j][m]  = 2*(B(m, dq_dvij[i][j].mult(hatq))*hatq_s);
+                    duCan_dvij[i][j][m] += 2*(B(m,hatq)*(dq_dvij_ds[i][j].mult(hatq) + dq_dvij[i][j].mult(hatq_s)));
+                }
+
+                // Don't fuse the two loops, we need the complete duCan_dvij[i][j]
+                for (int m=0; m<3; m++)
+                    duLocal_dvij[i][j][m] = duCan_dvij[i][j] * hatq.director(m) + darbouxCan*dd_dvij[m][i][j];
+
+                for (int k=0; k<2; k++) {
+
+                    for (int l=0; l<3; l++) {
+
+                        for (int m=0; m<3; m++)
+                            duCan_dvij_dvkl[i][j][k][l] = 2 * (B(m,dq_dvij_dvkl[i][j][k][l].mult(hatq)) * hatq_s)
+                                + 2 * (B(m,dq_dvij[i][j].mult(hatq)) * (dq_dvij_ds[k][l].mult(hatq) + dq_dvij[k][l].mult(hatq_s)))
+                                + 2 * (B(m,dq_dvij[k][l].mult(hatq)) * (dq_dvij_ds[i][j].mult(hatq) + dq_dvij[i][j].mult(hatq_s)))
+                                + 2 * (B(m,hatq) * (dq_dvij_dvkl_ds[i][j][k][l].mult(hatq) + dq_dvij_dvkl[i][j][k][l].mult(hatq_s)));
+
+                    }
+
+                }
                 
             }
 
+        }
+
         // ///////////////////////////////////
         //   Sum it all up
         // ///////////////////////////////////
@@ -370,7 +394,9 @@ getLocalMatrix( EntityType &entity,
                                + A3 * shapeGrad[k]*hatq.director(2)[l]*(r_s*dd_dvij[2][i][j])
                                + A3 * (r_s*hatq.director(2)-1) * shapeGrad[k] * dd_dvij[2][i][j][l]);
 
-                        localMat[i][k][j+3][l] = localMat[i][k][j][l+3];
+                        // This is programmed stupidly.  To ensure the equality it is enough to make
+                        // the following assignment once and not for each quadrature point
+                        localMat[k][i][l+3][j] = localMat[i][k][j][l+3];
 
                         // \partial W^2 \partial v^i_j \partial v^k_l
                         localMat[i][k][j+3][l+3] += weight
@@ -391,21 +417,14 @@ getLocalMatrix( EntityType &entity,
                         // All other derivatives are zero
                         for (int m=0; m<3; m++) {
 
-                            double sum = dum_dvij[m][k][l] * (B(m,dq_dvij[i][j].mult(hatq)) * hatq_s);
-                            
-                            sum += dum_dvij[m][k][l] * (B(m,hatq)*(dq_dvij_ds[i][j].mult(hatq) + dq_dvij[i][j].mult(hatq_s)));
-
-                            sum += u[m] * (B(m, dq_dvij_dvkl[i][j][k][l].mult(hatq)) * hatq_s);
-
-                            sum += u[m] * (B(m, dq_dvij[i][j].mult(hatq)) * dq_dvij_ds[k][l].mult(hatq));
-
-                            sum += u[m] * (B(m, dq_dvij[k][l].mult(hatq)) * 
-                                           (dq_dvij_ds[i][j].mult(hatq) + dq_dvij[i][j].mult(hatq_s)));
-
-                            sum += u[m] * (B(m, hatq) * 
-                                           (dq_dvij_dvkl_ds[i][j][k][l].mult(hatq) + (dq_dvij_dvkl[i][j][k][l].mult(hatq_s))));
+                            double sum = duLocal_dvij[k][l][m] * (duCan_dvij[i][j] * hatq.director(m) + darbouxCan*dd_dvij[m][i][j]);
                             
-                            localMat[i][k][j+3][l+3] += 2*weight *K[m] * sum;
+                            sum += u[m] * (duCan_dvij_dvkl[i][j][k][l] * hatq.director(m)
+                                                 + duCan_dvij[i][j] * dd_dvij[m][k][l]
+                                                 + duCan_dvij[k][l] * dd_dvij[m][i][j]
+                                                 + darbouxCan * dd_dvij_dvkl[m][i][j][k][l]);
+                       
+                            localMat[i][k][j+3][l+3] += weight *K[m] * sum;
 
                         }
 
@@ -535,13 +554,14 @@ assembleGradient(const std::vector<Configuration>& sol,
             FixedArray<FixedArray<FixedArray<FieldVector<double,3>, 3>, 2>, 3> dd_dvij;
             getFirstDerivativesOfDirectors(hatq, dd_dvij, dq_dvij);
 
+            
             // /////////////////////////////////////////////
             //   Sum it all up
             // /////////////////////////////////////////////
 
-            for (int dof=0; dof<numOfBaseFct; dof++) {
+            for (int i=0; i<numOfBaseFct; i++) {
 
-                int globalDof = indexSet.template subIndex<gridDim>(*it,dof);
+                int globalDof = indexSet.template subIndex<gridDim>(*it,i);
 
                 // /////////////////////////////////////////////
                 //   The translational part
@@ -551,9 +571,9 @@ assembleGradient(const std::vector<Configuration>& sol,
                 for (int j=0; j<3; j++) {
 
                     grad[globalDof][j] += weight 
-                        * ((A1 * (r_s*hatq.director(0)) * shapeGrad[dof] * hatq.director(0)[j])
-                           + (A2 * (r_s*hatq.director(1)) * shapeGrad[dof] * hatq.director(1)[j])
-                           + (A3 * (r_s*hatq.director(2) - 1) * shapeGrad[dof] * hatq.director(2)[j]));
+                        * ((A1 * (r_s*hatq.director(0)) * shapeGrad[i] * hatq.director(0)[j])
+                           + (A2 * (r_s*hatq.director(1)) * shapeGrad[i] * hatq.director(1)[j])
+                           + (A3 * (r_s*hatq.director(2) - 1) * shapeGrad[i] * hatq.director(2)[j]));
 
                 }
 
@@ -561,9 +581,9 @@ assembleGradient(const std::vector<Configuration>& sol,
                 for (int j=0; j<3; j++) {
 
                     grad[globalDof][3+j] += weight 
-                        * ((A1 * (r_s*hatq.director(0)) * (r_s*dd_dvij[0][dof][j]))
-                           + (A2 * (r_s*hatq.director(1)) * (r_s*dd_dvij[1][dof][j]))
-                           + (A3 * (r_s*hatq.director(2) - 1) * (r_s*dd_dvij[2][dof][j])));
+                        * ((A1 * (r_s*hatq.director(0)) * (r_s*dd_dvij[0][i][j]))
+                           + (A2 * (r_s*hatq.director(1)) * (r_s*dd_dvij[1][i][j]))
+                           + (A3 * (r_s*hatq.director(2) - 1) * (r_s*dd_dvij[2][i][j])));
 
                 }
 
@@ -577,10 +597,18 @@ assembleGradient(const std::vector<Configuration>& sol,
                 // \partial \bar{W}_v / \partial v^i_j
                 for (int j=0; j<3; j++) {
 
+                    FieldVector<double,3> du_dvij;
+                    for (int m=0; m<3; m++) {
+                        du_dvij[m] = B(m, dq_dvij[i][j].mult(hatq)) * hatq_s;
+                        du_dvij[m] += B(m, hatq) * (dq_dvij_ds[i][j].mult(hatq) + dq_dvij[i][j].mult(hatq_s));
+                    }
+                    du_dvij *= 2;
+
+                    FieldVector<double,3> darbouxCan = darbouxCanonical(hatq, hatq_s);
                     for (int m=0; m<3; m++) {
 
-                        double addend1 = B(m,(dq_dvij[dof][j].mult(hatq))) * hatq_s;
-                        double addend2 = B(m,hatq) * (dq_dvij_ds[dof][j].mult(hatq) + dq_dvij[dof][j].mult(hatq_s));
+                        double addend1 = du_dvij * hatq.director(m);
+                        double addend2 = darbouxCan * dd_dvij[m][i][j];
 
                         grad[globalDof][3+j] += 2*weight*K[m]*u[m] * (addend1 + addend2);
 
@@ -682,19 +710,12 @@ computeEnergy(const std::vector<Configuration>& sol) const
 
             // 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
+            // Part I: the shearing and stretching energy
             // /////////////////////////////////////////////
 
-            // 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
@@ -703,13 +724,6 @@ computeEnergy(const std::vector<Configuration>& sol) const
 
             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 = darboux(q, q_s);  // The Darboux vector
-
-            energy += weight * 0.5 * (K1*u[0]*u[0] + K2*u[1]*u[1] + K3*u[2]*u[2]);
-#endif
         }
 
         // Get quadrature rule
@@ -751,11 +765,6 @@ computeEnergy(const std::vector<Configuration>& sol) const
             //   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];
@@ -776,18 +785,6 @@ computeEnergy(const std::vector<Configuration>& sol) const
             // /////////////////////////////////////////////
             //   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 = darboux(q, q_s);  // The Darboux vector
diff --git a/src/rodassembler.hh b/src/rodassembler.hh
index d8f4192a..00bc6a27 100644
--- a/src/rodassembler.hh
+++ b/src/rodassembler.hh
@@ -143,6 +143,17 @@ namespace Dune
             u[2] = uCanonical*q.director(2);
             return u;
         }
+
+        template <class T>
+        static FieldVector<T,3> darbouxCanonical(const Quaternion<T>& q, const FieldVector<T,4>& q_s) 
+        {
+            FieldVector<double,3> uCanonical;  // The Darboux vector
+            uCanonical[0] = 2 * ( q[3]*q_s[0] + q[2]*q_s[1] - q[1]*q_s[2] - q[0]*q_s[3]);
+            uCanonical[1] = 2 * (-q[2]*q_s[0] + q[3]*q_s[1] + q[0]*q_s[2] - q[1]*q_s[3]);
+            uCanonical[2] = 2 * ( q[1]*q_s[0] - q[0]*q_s[1] + q[3]*q_s[2] - q[2]*q_s[3]);
+
+            return uCanonical;
+        }
         
         static void getFirstDerivativesOfDirectors(const Quaternion<double>& q, 
                                                    Dune::FixedArray<Dune::FixedArray<Dune::FixedArray<Dune::FieldVector<double,3>, 3>, 2>, 3>& dd_dvij,
-- 
GitLab