diff --git a/rod3d.cc b/rod3d.cc index d58b0fa2c5329c1c2cadba056d665613ab580716..e6921ee7b89d17d2c158cc9339fde2227728fd3e 100644 --- a/rod3d.cc +++ b/rod3d.cc @@ -168,7 +168,7 @@ int main (int argc, char *argv[]) try MatrixIndexSet indices(exactSolution.size(), exactSolution.size()); rodAssembler.getNeighborsPerVertex(indices); indices.exportIdx(hessian); - rodAssembler.assembleMatrixFD(exactSolution, hessian); + rodAssembler.assembleMatrix(exactSolution, hessian); double error = std::numeric_limits<double>::max(); diff --git a/src/rodassembler.cc b/src/rodassembler.cc index ff1f4ddeece48214873650243da4200465a78087..ca3c0cc20207d1dd5a3e60a9070c4f58b92da693 100644 --- a/src/rodassembler.cc +++ b/src/rodassembler.cc @@ -51,11 +51,17 @@ void RodAssembler<GridType>:: assembleMatrix(const std::vector<RigidBodyMotion<3> >& sol, Dune::BCRSMatrix<MatrixBlock>& matrix) const { - using namespace Dune; + // //////////////////////////////////////////////////// + // Create local assembler + // //////////////////////////////////////////////////// + + Dune::array<double,3> K = {K_[0], K_[1], K_[2]}; + Dune::array<double,3> A = {A_[0], A_[1], A_[2]}; + RodLocalStiffness<typename GridType::LeafGridView,double> localStiffness(K, A); const typename GridType::Traits::LevelIndexSet& indexSet = grid_->levelIndexSet(grid_->maxLevel()); - MatrixIndexSet neighborsPerVertex; + Dune::MatrixIndexSet neighborsPerVertex; getNeighborsPerVertex(neighborsPerVertex); matrix = 0; @@ -63,35 +69,35 @@ assembleMatrix(const std::vector<RigidBodyMotion<3> >& sol, ElementIterator it = grid_->template lbegin<0>( grid_->maxLevel() ); ElementIterator endit = grid_->template lend<0> ( grid_->maxLevel() ); - Matrix<MatrixBlock> mat; - for( ; it != endit; ++it ) { - const LagrangeShapeFunctionSet<double, double, gridDim> & baseSet + const Dune::LagrangeShapeFunctionSet<double, double, gridDim> & baseSet = Dune::LagrangeShapeFunctions<double, double, gridDim>::general(it->type(), elementOrder); const int numOfBaseFct = baseSet.size(); - mat.setSize(numOfBaseFct, numOfBaseFct); - // Extract local solution std::vector<RigidBodyMotion<3> > localSolution(numOfBaseFct); for (int i=0; i<numOfBaseFct; i++) - localSolution[i] = sol[indexSet.template subIndex<gridDim>(*it,i)]; + localSolution[i] = sol[indexSet.subIndex(*it,i,gridDim)]; + + localStiffness.localReferenceConfiguration_.resize(numOfBaseFct); + + for (int i=0; i<numOfBaseFct; i++) + localStiffness.localReferenceConfiguration_[i] = referenceConfiguration_[indexSet.subIndex(*it,i,gridDim)]; // setup matrix - //getLocalMatrix( it, localSolution, sol, numOfBaseFct, mat); - DUNE_THROW(NotImplemented, "getLocalMatrix"); + localStiffness.assemble(*it, localSolution); // Add element matrix to global stiffness matrix for(int i=0; i<numOfBaseFct; i++) { - int row = indexSet.template subIndex<gridDim>(*it,i); + int row = indexSet.subIndex(*it,i,gridDim); for (int j=0; j<numOfBaseFct; j++ ) { - int col = indexSet.template subIndex<gridDim>(*it,j); - matrix[row][col] += mat[i][j]; + int col = indexSet.subIndex(*it,j,gridDim); + matrix[row][col] += localStiffness.mat(i,j); } } @@ -100,257 +106,6 @@ assembleMatrix(const std::vector<RigidBodyMotion<3> >& sol, } -template <class GridType> -void RodAssembler<GridType>:: -assembleMatrixFD(const std::vector<RigidBodyMotion<3> >& sol, - Dune::BCRSMatrix<MatrixBlock>& matrix) const -{ - using namespace Dune; - - double eps = 1e-4; - - typedef typename Dune::BCRSMatrix<Dune::FieldMatrix<double,6,6> >::row_type::iterator ColumnIterator; - - // /////////////////////////////////////////////////////////// - // Compute gradient by finite-difference approximation - // /////////////////////////////////////////////////////////// - std::vector<RigidBodyMotion<3> > forwardSolution = sol; - std::vector<RigidBodyMotion<3> > backwardSolution = sol; - - std::vector<RigidBodyMotion<3> > forwardForwardSolution = sol; - std::vector<RigidBodyMotion<3> > forwardBackwardSolution = sol; - std::vector<RigidBodyMotion<3> > backwardForwardSolution = sol; - std::vector<RigidBodyMotion<3> > backwardBackwardSolution = sol; - - // //////////////////////////////////////////////////// - // Create local assembler - // //////////////////////////////////////////////////// - - Dune::array<double,3> K = {K_[0], K_[1], K_[2]}; - Dune::array<double,3> A = {A_[0], A_[1], A_[2]}; - RodLocalStiffness<typename GridType::LeafGridView,double> localStiffness(K, A); - - // ////////////////////////////////////////////////////////////////// - // Store pointers to all elements so we can access them by index - // ////////////////////////////////////////////////////////////////// - - const typename GridType::Traits::LeafIndexSet& indexSet = grid_->leafIndexSet(); - - std::vector<EntityPointer> elements(grid_->size(0),grid_->template leafbegin<0>()); - - typename GridType::template Codim<0>::LeafIterator eIt = grid_->template leafbegin<0>(); - typename GridType::template Codim<0>::LeafIterator eEndIt = grid_->template leafend<0>(); - - for (; eIt!=eEndIt; ++eIt) - elements[indexSet.index(*eIt)] = eIt; - - Dune::array<RigidBodyMotion<3>,2> localReferenceConfiguration; - Dune::array<RigidBodyMotion<3>,2> localSolution; - - // /////////////////////////////////////////////////////////////// - // Loop over all blocks of the outer matrix - // /////////////////////////////////////////////////////////////// - for (int i=0; i<matrix.N(); i++) { - - ColumnIterator cIt = matrix[i].begin(); - ColumnIterator cEndIt = matrix[i].end(); - - for (; cIt!=cEndIt; ++cIt) { - - // compute only the upper right triangular matrix - if (cIt.index() < i) - continue; - - // //////////////////////////////////////////////////////////////////////////// - // Compute a finite-difference approximation of this hessian matrix block - // //////////////////////////////////////////////////////////////////////////// - - for (int j=0; j<6; j++) { - - for (int k=0; k<6; k++) { - - // compute only the upper right triangular matrix - if (i==cIt.index() && k<j) - continue; - - if (i==cIt.index() && j==k) { - - double forwardEnergy = 0; - double solutionEnergy = 0; - double backwardEnergy = 0; - - infinitesimalVariation(forwardSolution[i], eps, j); - infinitesimalVariation(backwardSolution[i], -eps, j); - - if (i != grid_->size(1)-1) { - - localReferenceConfiguration[0] = referenceConfiguration_[i]; - localReferenceConfiguration[1] = referenceConfiguration_[i+1]; - - localSolution[0] = forwardSolution[i]; - localSolution[1] = forwardSolution[i+1]; - - forwardEnergy += localStiffness.energy(*elements[i], localSolution, localReferenceConfiguration); - - localSolution[0] = sol[i]; - localSolution[1] = sol[i+1]; - - solutionEnergy += localStiffness.energy(*elements[i], localSolution, localReferenceConfiguration); - - localSolution[0] = backwardSolution[i]; - localSolution[1] = backwardSolution[i+1]; - - backwardEnergy += localStiffness.energy(*elements[i], localSolution, localReferenceConfiguration); - - } - - if (i != 0) { - - localReferenceConfiguration[0] = referenceConfiguration_[i-1]; - localReferenceConfiguration[1] = referenceConfiguration_[i]; - - localSolution[0] = forwardSolution[i-1]; - localSolution[1] = forwardSolution[i]; - - forwardEnergy += localStiffness.energy(*elements[i-1], localSolution, localReferenceConfiguration); - - localSolution[0] = sol[i-1]; - localSolution[1] = sol[i]; - - solutionEnergy += localStiffness.energy(*elements[i-1], localSolution, localReferenceConfiguration); - - localSolution[0] = backwardSolution[i-1]; - localSolution[1] = backwardSolution[i]; - - backwardEnergy += localStiffness.energy(*elements[i-1], localSolution, localReferenceConfiguration); - - } - - // Second derivative - (*cIt)[j][k] = (forwardEnergy - 2*solutionEnergy + backwardEnergy) / (eps*eps); - - forwardSolution[i] = sol[i]; - backwardSolution[i] = sol[i]; - - } else { - - double forwardForwardEnergy = 0; - double forwardBackwardEnergy = 0; - double backwardForwardEnergy = 0; - double backwardBackwardEnergy = 0; - - infinitesimalVariation(forwardForwardSolution[i], eps, j); - infinitesimalVariation(forwardForwardSolution[cIt.index()], eps, k); - infinitesimalVariation(forwardBackwardSolution[i], eps, j); - infinitesimalVariation(forwardBackwardSolution[cIt.index()], -eps, k); - infinitesimalVariation(backwardForwardSolution[i], -eps, j); - infinitesimalVariation(backwardForwardSolution[cIt.index()], eps, k); - infinitesimalVariation(backwardBackwardSolution[i], -eps, j); - infinitesimalVariation(backwardBackwardSolution[cIt.index()],-eps, k); - - std::set<int> elementsInvolved; - if (i>0) - elementsInvolved.insert(i-1); - if (i<grid_->size(1)-1) - elementsInvolved.insert(i); - if (cIt.index()>0) - elementsInvolved.insert(cIt.index()-1); - if (cIt.index()<grid_->size(1)-1) - elementsInvolved.insert(cIt.index()); - - for (typename std::set<int>::iterator it = elementsInvolved.begin(); - it != elementsInvolved.end(); - ++it) { - - localReferenceConfiguration[0] = referenceConfiguration_[*it]; - localReferenceConfiguration[1] = referenceConfiguration_[*it+1]; - - localSolution[0] = forwardForwardSolution[*it]; - localSolution[1] = forwardForwardSolution[*it+1]; - - forwardForwardEnergy += localStiffness.energy(*elements[*it], localSolution, localReferenceConfiguration); - - localSolution[0] = forwardBackwardSolution[*it]; - localSolution[1] = forwardBackwardSolution[*it+1]; - - forwardBackwardEnergy += localStiffness.energy(*elements[*it], localSolution, localReferenceConfiguration); - - localSolution[0] = backwardForwardSolution[*it]; - localSolution[1] = backwardForwardSolution[*it+1]; - - backwardForwardEnergy += localStiffness.energy(*elements[*it], localSolution, localReferenceConfiguration); - - localSolution[0] = backwardBackwardSolution[*it]; - localSolution[1] = backwardBackwardSolution[*it+1]; - - backwardBackwardEnergy += localStiffness.energy(*elements[*it], localSolution, localReferenceConfiguration); - - - } - - (*cIt)[j][k] = (forwardForwardEnergy + backwardBackwardEnergy - - forwardBackwardEnergy - backwardForwardEnergy) / (4*eps*eps); - - forwardForwardSolution[i] = sol[i]; - forwardForwardSolution[cIt.index()] = sol[cIt.index()]; - forwardBackwardSolution[i] = sol[i]; - forwardBackwardSolution[cIt.index()] = sol[cIt.index()]; - backwardForwardSolution[i] = sol[i]; - backwardForwardSolution[cIt.index()] = sol[cIt.index()]; - backwardBackwardSolution[i] = sol[i]; - backwardBackwardSolution[cIt.index()] = sol[cIt.index()]; - - } - - } - - } - - } - - } - - // /////////////////////////////////////////////////////////////// - // Symmetrize the matrix - // This is possible expensive, but I want to be absolute sure - // that the matrix is symmetric. - // /////////////////////////////////////////////////////////////// - for (int i=0; i<matrix.N(); i++) { - - ColumnIterator cIt = matrix[i].begin(); - ColumnIterator cEndIt = matrix[i].end(); - - for (; cIt!=cEndIt; ++cIt) { - - if (cIt.index()>i) - continue; - - - if (cIt.index()==i) { - - for (int j=1; j<6; j++) - for (int k=0; k<j; k++) - (*cIt)[j][k] = (*cIt)[k][j]; - - } else { - - const FieldMatrix<double,6,6>& other = matrix[cIt.index()][i]; - - for (int j=0; j<6; j++) - for (int k=0; k<6; k++) - (*cIt)[j][k] = other[k][j]; - - - } - - - } - - } - -} - - template <class GridType> void RodAssembler<GridType>:: assembleGradient(const std::vector<RigidBodyMotion<3> >& sol, @@ -385,13 +140,13 @@ assembleGradient(const std::vector<RigidBodyMotion<3> >& sol, const int nDofs = 2; // Extract local solution - array<RigidBodyMotion<3>,nDofs> localSolution; + std::vector<RigidBodyMotion<3> > localSolution(nDofs); for (int i=0; i<nDofs; i++) localSolution[i] = sol[indexSet.subIndex(*it,i,gridDim)]; // Extract local reference configuration - array<RigidBodyMotion<3>,nDofs> localReferenceConfiguration; + std::vector<RigidBodyMotion<3> > localReferenceConfiguration(nDofs); for (int i=0; i<nDofs; i++) localReferenceConfiguration[i] = referenceConfiguration_[indexSet.subIndex(*it,i,gridDim)]; @@ -431,8 +186,8 @@ computeEnergy(const std::vector<RigidBodyMotion<3> >& sol) const Dune::array<double,3> A = {A_[0], A_[1], A_[2]}; RodLocalStiffness<typename GridType::LeafGridView,double> localStiffness(K, A); - Dune::array<RigidBodyMotion<3>,2> localReferenceConfiguration; - Dune::array<RigidBodyMotion<3>,2> localSolution; + std::vector<RigidBodyMotion<3> > localReferenceConfiguration(2); + std::vector<RigidBodyMotion<3> > localSolution(2); ElementLeafIterator it = grid_->template leafbegin<0>(); ElementLeafIterator endIt = grid_->template leafend<0>(); @@ -493,7 +248,7 @@ getStrain(const std::vector<RigidBodyMotion<3> >& sol, = Dune::LagrangeShapeFunctions<double, double, gridDim>::general(it->type(), elementOrder); int numOfBaseFct = baseSet.size(); - array<RigidBodyMotion<3>,2> localSolution; + std::vector<RigidBodyMotion<3> > localSolution(2); for (int i=0; i<numOfBaseFct; i++) localSolution[i] = sol[indexSet.subIndex(*it,i,gridDim)]; diff --git a/src/rodassembler.hh b/src/rodassembler.hh index a466fc18a4a5a92da638005b52b838268351a9ba..ca8346fed099ec7e9aaa307ccbca6781ac09eaa5 100644 --- a/src/rodassembler.hh +++ b/src/rodassembler.hh @@ -43,17 +43,6 @@ /** \brief The stress-free configuration */ std::vector<RigidBodyMotion<3> > referenceConfiguration_; - /** \todo Only for the fd approximations */ - static void infinitesimalVariation(RigidBodyMotion<3>& c, double eps, int i) - { - if (i<3) - c.r[i] += eps; - else - c.q = c.q.mult(Rotation<3,double>::exp((i==3)*eps, - (i==4)*eps, - (i==5)*eps)); - } - public: //! ??? @@ -121,11 +110,6 @@ void assembleMatrix(const std::vector<RigidBodyMotion<3> >& sol, Dune::BCRSMatrix<MatrixBlock>& matrix) const; - /** \brief Assemble the tangent stiffness matrix using a finite difference approximation - */ - void assembleMatrixFD(const std::vector<RigidBodyMotion<3> >& sol, - Dune::BCRSMatrix<MatrixBlock>& matrix) const; - void assembleGradient(const std::vector<RigidBodyMotion<3> >& sol, Dune::BlockVector<Dune::FieldVector<double, blocksize> >& grad) const; diff --git a/src/rodlocalstiffness.hh b/src/rodlocalstiffness.hh index 6c7c7e592183804cf1ea78016d02f0ec31dcceca..d44826f950fe956f8e609d662685125e650cb417 100644 --- a/src/rodlocalstiffness.hh +++ b/src/rodlocalstiffness.hh @@ -6,6 +6,7 @@ #include <dune/istl/matrixindexset.hh> #include <dune/istl/matrix.hh> #include <dune/disc/operators/localstiffness.hh> +#include<dune/disc/operators/boundaryconditions.hh> #include "rigidbodymotion.hh" @@ -13,6 +14,8 @@ template<class GridView, class RT> class RodLocalStiffness : public Dune::LocalStiffness<GridView,RT,6> { + typedef RigidBodyMotion<3> TargetSpace; + // grid types typedef typename GridView::Grid::ctype DT; typedef typename GridView::template Codim<0>::Entity Entity; @@ -27,6 +30,22 @@ class RodLocalStiffness // Quadrature order used for the bending and torsion energy enum {bendingQuadOrder = 2}; +public: + /** \brief For the fd approximations + \todo This is public because RodAssembler uses it + */ + static void infinitesimalVariation(RigidBodyMotion<3>& c, double eps, int i) + { + if (i<3) + c.r[i] += eps; + else + c.q = c.q.mult(Rotation<3,double>::exp((i==3)*eps, + (i==4)*eps, + (i==5)*eps)); + } + + std::vector<RigidBodyMotion<3> > localReferenceConfiguration_; + public: //! Each block is x, y, theta in 2d, T (R^3 \times SO(3)) in 3d @@ -61,17 +80,11 @@ public: A_[i] = A[i]; } } + + void assemble(const Entity& e, + const std::vector<TargetSpace>& localSolution); - //! assemble local stiffness matrix for given element and order - /*! On exit the following things have been done: - - The stiffness matrix for the given entity and polynomial degree has been assembled and is - accessible with the mat() method. - - The boundary conditions have been evaluated and are accessible with the bc() method - - The right hand side has been assembled. It contains either the value of the essential boundary - condition or the assembled source term and neumann boundary condition. It is accessible via the rhs() method. - @param[in] e a codim 0 entity reference - \param[in] localSolution Current local solution, because this is a nonlinear assembler - @param[in] k order of Lagrange basis + /** \brief assemble local stiffness matrix for given element and order */ void assemble (const Entity& e, const Dune::BlockVector<Dune::FieldVector<double, 6> >& localSolution, @@ -93,8 +106,8 @@ public: RT energy (const Entity& e, - const Dune::array<RigidBodyMotion<3>,2>& localSolution, - const Dune::array<RigidBodyMotion<3>,2>& localReferenceConfiguration, + const std::vector<RigidBodyMotion<3> >& localSolution, + const std::vector<RigidBodyMotion<3> >& localReferenceConfiguration, int k=1); static void interpolationDerivative(const Rotation<3,RT>& q0, const Rotation<3,RT>& q1, double s, @@ -103,14 +116,14 @@ public: static void interpolationVelocityDerivative(const Rotation<3,RT>& q0, const Rotation<3,RT>& q1, double s, double intervalLength, Dune::array<Quaternion<double>,6>& grad); - Dune::FieldVector<double, 6> getStrain(const Dune::array<RigidBodyMotion<3>,2>& localSolution, + Dune::FieldVector<double, 6> getStrain(const std::vector<RigidBodyMotion<3> >& localSolution, const Entity& element, const Dune::FieldVector<double,1>& pos) const; /** \brief Assemble the element gradient of the energy functional */ void assembleGradient(const Entity& element, - const Dune::array<RigidBodyMotion<3>,2>& solution, - const Dune::array<RigidBodyMotion<3>,2>& referenceConfiguration, + const std::vector<RigidBodyMotion<3> >& solution, + const std::vector<RigidBodyMotion<3> >& referenceConfiguration, Dune::array<Dune::FieldVector<double,6>, 2>& gradient) const; template <class T> @@ -130,8 +143,8 @@ public: template <class GridType, class RT> RT RodLocalStiffness<GridType, RT>:: energy(const Entity& element, - const Dune::array<RigidBodyMotion<3>,2>& localSolution, - const Dune::array<RigidBodyMotion<3>,2>& localReferenceConfiguration, + const std::vector<RigidBodyMotion<3> >& localSolution, + const std::vector<RigidBodyMotion<3> >& localReferenceConfiguration, int k) { RT energy = 0; @@ -403,7 +416,7 @@ interpolationVelocityDerivative(const Rotation<3,RT>& q0, const Rotation<3,RT>& template <class GridType, class RT> Dune::FieldVector<double, 6> RodLocalStiffness<GridType, RT>:: -getStrain(const Dune::array<RigidBodyMotion<3>,2>& localSolution, +getStrain(const std::vector<RigidBodyMotion<3> >& localSolution, const Entity& element, const Dune::FieldVector<double,1>& pos) const { @@ -479,8 +492,8 @@ getStrain(const Dune::array<RigidBodyMotion<3>,2>& localSolution, template <class GridType, class RT> void RodLocalStiffness<GridType, RT>:: assembleGradient(const Entity& element, - const Dune::array<RigidBodyMotion<3>,2>& solution, - const Dune::array<RigidBodyMotion<3>,2>& referenceConfiguration, + const std::vector<RigidBodyMotion<3> >& solution, + const std::vector<RigidBodyMotion<3> >& referenceConfiguration, Dune::array<Dune::FieldVector<double,6>, 2>& gradient) const { using namespace Dune; @@ -666,5 +679,167 @@ assembleGradient(const Entity& element, } } + +template <class GridType, class RT> +void RodLocalStiffness<GridType,RT>:: +assemble(const Entity& element, + const std::vector<TargetSpace>& localSolution) +{ + // 1 degree of freedom per element vertex + int nDofs = element.template count<dim>(); + + // Clear assemble data + this->setcurrentsize(nDofs); + + this->A = 0; + + for (int i=0; i<nDofs; i++) { + this->b[i] = 0; + for (int j=0; j<this->bctype[i].size(); j++) + this->bctype[i][j] = Dune::BoundaryConditions::neumann; + } + + double eps = 1e-4; + + typedef typename Dune::Matrix<Dune::FieldMatrix<double,6,6> >::row_type::iterator ColumnIterator; + + // /////////////////////////////////////////////////////////// + // Compute gradient by finite-difference approximation + // /////////////////////////////////////////////////////////// + std::vector<RigidBodyMotion<3> > forwardSolution = localSolution; + std::vector<RigidBodyMotion<3> > backwardSolution = localSolution; + + std::vector<RigidBodyMotion<3> > forwardForwardSolution = localSolution; + std::vector<RigidBodyMotion<3> > forwardBackwardSolution = localSolution; + std::vector<RigidBodyMotion<3> > backwardForwardSolution = localSolution; + std::vector<RigidBodyMotion<3> > backwardBackwardSolution = localSolution; + + // /////////////////////////////////////////////////////////////// + // Loop over all blocks of the element matrix + // /////////////////////////////////////////////////////////////// + for (int i=0; i<this->A.N(); i++) { + + ColumnIterator cIt = this->A[i].begin(); + ColumnIterator cEndIt = this->A[i].end(); + + for (; cIt!=cEndIt; ++cIt) { + + // compute only the upper right triangular matrix + if (cIt.index() < i) + continue; + + // //////////////////////////////////////////////////////////////////////////// + // Compute a finite-difference approximation of this hessian matrix block + // //////////////////////////////////////////////////////////////////////////// + + for (int j=0; j<6; j++) { + + for (int k=0; k<6; k++) { + + // compute only the upper right triangular matrix + if (i==cIt.index() && k<j) + continue; + + // Diagonal entries + if (i==cIt.index() && j==k) { + + infinitesimalVariation(forwardSolution[i], eps, j); + infinitesimalVariation(backwardSolution[i], -eps, j); + + double forwardEnergy = energy(element, forwardSolution, localReferenceConfiguration_); + + double solutionEnergy = energy(element, localSolution, localReferenceConfiguration_); + + double backwardEnergy = energy(element, backwardSolution, localReferenceConfiguration_); + + // Second derivative + (*cIt)[j][k] = (forwardEnergy - 2*solutionEnergy + backwardEnergy) / (eps*eps); + + forwardSolution[i] = localSolution[i]; + backwardSolution[i] = localSolution[i]; + + } else { + + // Off-diagonal entries + infinitesimalVariation(forwardForwardSolution[i], eps, j); + infinitesimalVariation(forwardForwardSolution[cIt.index()], eps, k); + infinitesimalVariation(forwardBackwardSolution[i], eps, j); + infinitesimalVariation(forwardBackwardSolution[cIt.index()], -eps, k); + infinitesimalVariation(backwardForwardSolution[i], -eps, j); + infinitesimalVariation(backwardForwardSolution[cIt.index()], eps, k); + infinitesimalVariation(backwardBackwardSolution[i], -eps, j); + infinitesimalVariation(backwardBackwardSolution[cIt.index()],-eps, k); + + double forwardForwardEnergy = energy(element, forwardForwardSolution, localReferenceConfiguration_); + + double forwardBackwardEnergy = energy(element, forwardBackwardSolution, localReferenceConfiguration_); + + double backwardForwardEnergy = energy(element, backwardForwardSolution, localReferenceConfiguration_); + + double backwardBackwardEnergy = energy(element, backwardBackwardSolution, localReferenceConfiguration_); + + (*cIt)[j][k] = (forwardForwardEnergy + backwardBackwardEnergy + - forwardBackwardEnergy - backwardForwardEnergy) / (4*eps*eps); + + forwardForwardSolution[i] = localSolution[i]; + forwardForwardSolution[cIt.index()] = localSolution[cIt.index()]; + forwardBackwardSolution[i] = localSolution[i]; + forwardBackwardSolution[cIt.index()] = localSolution[cIt.index()]; + backwardForwardSolution[i] = localSolution[i]; + backwardForwardSolution[cIt.index()] = localSolution[cIt.index()]; + backwardBackwardSolution[i] = localSolution[i]; + backwardBackwardSolution[cIt.index()] = localSolution[cIt.index()]; + + } + + } + + } + + } + + } + + // /////////////////////////////////////////////////////////////// + // Symmetrize the matrix + // This is possible expensive, but I want to be absolute sure + // that the matrix is symmetric. + // /////////////////////////////////////////////////////////////// + for (int i=0; i<this->A.N(); i++) { + + ColumnIterator cIt = this->A[i].begin(); + ColumnIterator cEndIt = this->A[i].end(); + + for (; cIt!=cEndIt; ++cIt) { + + if (cIt.index()>i) + continue; + + + if (cIt.index()==i) { + + for (int j=1; j<6; j++) + for (int k=0; k<j; k++) + (*cIt)[j][k] = (*cIt)[k][j]; + + } else { + + const Dune::FieldMatrix<double,6,6>& other = this->A[cIt.index()][i]; + + for (int j=0; j<6; j++) + for (int k=0; k<6; k++) + (*cIt)[j][k] = other[k][j]; + + + } + + + } + + } + +} + + #endif diff --git a/src/rodsolver.cc b/src/rodsolver.cc index cd94020613badcc93883471743d7a7af00c13c9b..f048fedb9affd9e55bb121db50ef4bd6813b5b50 100644 --- a/src/rodsolver.cc +++ b/src/rodsolver.cc @@ -189,8 +189,8 @@ void RodSolver<GridType>::solve() corr = 0; rodAssembler_->assembleGradient(x_, rhs); - //rodAssembler_->assembleMatrix(x_, *hessianMatrix_); - rodAssembler_->assembleMatrixFD(x_, *hessianMatrix_); + rodAssembler_->assembleMatrix(x_, *hessianMatrix_); + //rodAssembler_->assembleMatrixFD(x_, *hessianMatrix_); //gradientFDCheck(x_, rhs, *rodAssembler_); //hessianFDCheck(x_, *hessianMatrix_, *rodAssembler_);