From bfce852992d931ac8c36a82c6ab03dec8a6eeae7 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Sat, 13 Feb 2010 17:41:27 +0000 Subject: [PATCH] make a specialization for TargetSpace==UnitVector. I hope this doesn't have to stay forever [[Imported from SVN: r5564]] --- src/localgeodesicfestiffness.hh | 278 ++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) diff --git a/src/localgeodesicfestiffness.hh b/src/localgeodesicfestiffness.hh index 6ab21e27..b8d2043d 100644 --- a/src/localgeodesicfestiffness.hh +++ b/src/localgeodesicfestiffness.hh @@ -8,6 +8,7 @@ #include "localstiffness.hh" #include "rigidbodymotion.hh" +#include "unitvector.hh" template<class GridView, class TargetSpace> class LocalGeodesicFEStiffness @@ -285,5 +286,282 @@ assemble(const Entity& element, } + +/** \brief Specialization for unit vectors */ +template<class GridView, int dim> +class LocalGeodesicFEStiffness <GridView,UnitVector<dim> > + : public Dune::LocalStiffness<GridView,double,UnitVector<dim>::TangentVector::size> +{ + typedef UnitVector<dim> TargetSpace; + + // grid types + typedef typename GridView::Grid::ctype DT; + typedef typename TargetSpace::ctype RT; + typedef typename GridView::template Codim<0>::Entity Entity; + + // some other sizes + enum {gridDim=GridView::dimension}; + + /** \brief For the fd approximations + */ + static void infinitesimalVariation(UnitVector<dim>& c, double eps, int i) + { + DUNE_THROW(Dune::NotImplemented, "infinitesimalVariation"); +#if 0 + c = c.mult(Rotation<3,double>::exp((i==0)*eps, + (i==1)*eps, + (i==2)*eps)); +#endif + } + +public: + + //! Each block is x, y, theta in 2d, T (R^3 \times SO(3)) in 3d + enum { blocksize = TargetSpace::TangentVector::size }; + + // define the number of components of your system, this is used outside + // to allocate the correct size of (dense) blocks with a FieldMatrix + enum {m=blocksize}; + + // types for matrics, vectors and boundary conditions + typedef Dune::FieldMatrix<RT,m,m> MBlockType; // one entry in the stiffness matrix + typedef Dune::FieldVector<RT,m> VBlockType; // one entry in the global vectors + + /** \brief Assemble the local stiffness matrix at the current position + + This default implementation used finite-difference approximations to compute the second derivatives + */ + virtual void assemble(const Entity& e, + const std::vector<TargetSpace>& localSolution); + + /** \brief assemble local stiffness matrix for given element and order + */ + void assemble (const Entity& e, + const Dune::BlockVector<Dune::FieldVector<double, blocksize> >& localSolution, + int k=1) + { + DUNE_THROW(Dune::NotImplemented, "!"); + } + + /** \todo Remove this once this methods is not in base class LocalStiffness anymore */ + void assemble (const Entity& e, int k=1) + { + DUNE_THROW(Dune::NotImplemented, "!"); + } + + void assembleBoundaryCondition (const Entity& e, int k=1) + { + DUNE_THROW(Dune::NotImplemented, "!"); + } + + + virtual RT energy (const Entity& e, + const std::vector<TargetSpace>& localSolution) const = 0; + + /** \brief Assemble the element gradient of the energy functional + + The default implementation in this class uses a finite difference approximation */ + virtual void assembleGradient(const Entity& element, + const std::vector<TargetSpace>& solution, + std::vector<Dune::FieldVector<double,blocksize> >& gradient) const; + +}; + +template <class GridView, int dim> +void LocalGeodesicFEStiffness<GridView, UnitVector<dim> >:: +assembleGradient(const Entity& element, + const std::vector<TargetSpace>& localSolution, + std::vector<Dune::FieldVector<double,blocksize> >& localGradient) const +{ + DUNE_THROW(Dune::NotImplemented, "!"); +#if 0 + // /////////////////////////////////////////////////////////// + // Compute gradient by finite-difference approximation + // /////////////////////////////////////////////////////////// + + double eps = 1e-6; + + localGradient.resize(localSolution.size()); + + std::vector<TargetSpace> forwardSolution = localSolution; + std::vector<TargetSpace> backwardSolution = localSolution; + + for (size_t i=0; i<localSolution.size(); i++) { + + for (int j=0; j<blocksize; j++) { + + infinitesimalVariation(forwardSolution[i], eps, j); + infinitesimalVariation(backwardSolution[i], -eps, j); + + localGradient[i][j] = (energy(element,forwardSolution) - energy(element,backwardSolution)) + / (2*eps); + + forwardSolution[i] = localSolution[i]; + backwardSolution[i] = localSolution[i]; + } + + } +#endif +} + + +template <class GridType, int dim> +void LocalGeodesicFEStiffness<GridType,UnitVector<dim> >:: +assemble(const Entity& element, + const std::vector<TargetSpace>& localSolution) +{ + DUNE_THROW(Dune::NotImplemented, "!"); +#if 0 + + // 1 degree of freedom per element vertex + int nDofs = element.template count<gridDim>(); + + // Clear assemble data + this->setcurrentsize(nDofs); + + this->A = 0; + + double eps = 1e-4; + + typedef typename Dune::Matrix<Dune::FieldMatrix<double,blocksize,blocksize> >::row_type::iterator ColumnIterator; + + // /////////////////////////////////////////////////////////// + // Compute gradient by finite-difference approximation + // /////////////////////////////////////////////////////////// + std::vector<TargetSpace> forwardSolution = localSolution; + std::vector<TargetSpace> backwardSolution = localSolution; + + std::vector<TargetSpace> forwardForwardSolution = localSolution; + std::vector<TargetSpace> forwardBackwardSolution = localSolution; + std::vector<TargetSpace> backwardForwardSolution = localSolution; + std::vector<TargetSpace> 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<blocksize; j++) { + + for (int k=0; k<blocksize; 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); + + double solutionEnergy = energy(element, localSolution); + + double backwardEnergy = energy(element, backwardSolution); + + // 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); + + double forwardBackwardEnergy = energy(element, forwardBackwardSolution); + + double backwardForwardEnergy = energy(element, backwardForwardSolution); + + double backwardBackwardEnergy = energy(element, backwardBackwardSolution); + + (*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<blocksize; j++) + for (int k=0; k<j; k++) + (*cIt)[j][k] = (*cIt)[k][j]; + + } else { + + const Dune::FieldMatrix<double,blocksize,blocksize>& other = this->A[cIt.index()][i]; + + for (int j=0; j<blocksize; j++) + for (int k=0; k<blocksize; k++) + (*cIt)[j][k] = other[k][j]; + + + } + + + } + + } +#endif +} + + #endif -- GitLab