From 26974e80678be50643b07eee6cc8d9616a55a948 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Mon, 27 Oct 2014 16:08:19 +0000 Subject: [PATCH] Interpolation functions that works by retracting onto a tangent space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is the interpolation method used by Ingo Münch and Wolfgang Müller for Cosserat materials. My implementation is only able to do all that I needed for the illustrations in the GAMM Rundbrief article. I'm sure there'll be more fixes needed if you actually want to do finite elements with this. [[Imported from SVN: r9940]] --- dune/gfe/localtangentfefunction.hh | 140 +++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 dune/gfe/localtangentfefunction.hh diff --git a/dune/gfe/localtangentfefunction.hh b/dune/gfe/localtangentfefunction.hh new file mode 100644 index 00000000..349a4644 --- /dev/null +++ b/dune/gfe/localtangentfefunction.hh @@ -0,0 +1,140 @@ +#ifndef DUNE_GFE_LOCALTANGENTFEFUNCTION_HH +#define DUNE_GFE_LOCALTANGENTFEFUNCTION_HH + +#include <vector> + +#include <dune/common/fvector.hh> + +#include <dune/geometry/type.hh> + +namespace Dune { + + namespace GFE { + + /** \brief Interpolate on a tangent space + * + * \tparam dim Dimension of the reference element + * \tparam ctype Type used for coordinates on the reference element + * \tparam LocalFiniteElement A Lagrangian finite element whose shape functions define the interpolation weights + * \tparam TargetSpace The manifold that the function takes its values in + */ + template <int dim, class ctype, class LocalFiniteElement, class TargetSpace> + class LocalTangentFEFunction + { + typedef typename TargetSpace::ctype RT; + + typedef typename TargetSpace::EmbeddedTangentVector EmbeddedTangentVector; + static const int embeddedDim = EmbeddedTangentVector::dimension; + + static const int spaceDim = TargetSpace::TangentVector::dimension; + + public: + + /** \brief The type used for derivatives */ + typedef Dune::FieldMatrix<RT, embeddedDim, dim> DerivativeType; + + /** \brief Constructor + * \param localFiniteElement A Lagrangian finite element that provides the interpolation points + * \param coefficients Values of the function at the Lagrange points + */ + LocalTangentFEFunction(const LocalFiniteElement& localFiniteElement, + const std::vector<TargetSpace>& coefficients) + : localFiniteElement_(localFiniteElement), + coefficients_(coefficients) + { + assert(localFiniteElement_.localBasis().size() == coefficients_.size()); + } + + /** \brief The number of Lagrange points */ + unsigned int size() const + { + return localFiniteElement_.localBasis().size(); + } + + /** \brief The type of the reference element */ + Dune::GeometryType type() const + { + return localFiniteElement_.type(); + } + + /** \brief Evaluate the function */ + TargetSpace evaluate(const Dune::FieldVector<ctype, dim>& local) const; + + /** \brief Evaluate the derivative of the function */ + DerivativeType evaluateDerivative(const Dune::FieldVector<ctype, dim>& local) const; + + /** \brief Evaluate the derivative of the function, if you happen to know the function value (much faster!) + * \param local Local coordinates in the reference element where to evaluate the derivative + * \param q Value of the local gfe function at 'local'. If you provide something wrong here the result will be wrong, too! + */ + DerivativeType evaluateDerivative(const Dune::FieldVector<ctype, dim>& local, + const TargetSpace& q) const; + + /** \brief Get the i'th base coefficient. */ + TargetSpace coefficient(int i) const + { + return coefficients_[i]; + } + private: + + /** \brief The scalar local finite element, which provides the weighting factors + * \todo We really only need the local basis + */ + const LocalFiniteElement& localFiniteElement_; + + /** \brief The coefficient vector */ + std::vector<TargetSpace> coefficients_; + + }; + + template <int dim, class ctype, class LocalFiniteElement, class TargetSpace> + TargetSpace LocalTangentFEFunction<dim,ctype,LocalFiniteElement,TargetSpace>:: + evaluate(const Dune::FieldVector<ctype, dim>& local) const + { + // Evaluate the weighting factors---these are the Lagrangian shape function values at 'local' + std::vector<Dune::FieldVector<ctype,1> > w; + localFiniteElement_.localBasis().evaluateFunction(local,w); + + // This is the base point of the tangent space that we are interpolating on + // HACK: This point is reasonable only for spheres + typename TargetSpace::CoordinateType baseEmb(0); + baseEmb[0] = 1.0; + TargetSpace base(baseEmb); + + // Map all points onto the tangent space at 'base' + std::vector<typename TargetSpace::EmbeddedTangentVector> tangentCoefficients(coefficients_.size()); + for (size_t i=0; i<coefficients_.size(); i++) + tangentCoefficients[i] = TargetSpace::log(base,coefficients_[i]); + + // Interpolate on the tangent space + typename TargetSpace::EmbeddedTangentVector c(0); + for (size_t i=0; i<tangentCoefficients.size(); i++) + c.axpy(w[i][0], tangentCoefficients[i]); + + return TargetSpace::exp(base,c); + } + + template <int dim, class ctype, class LocalFiniteElement, class TargetSpace> + typename LocalTangentFEFunction<dim,ctype,LocalFiniteElement,TargetSpace>::DerivativeType + LocalTangentFEFunction<dim,ctype,LocalFiniteElement,TargetSpace>:: + evaluateDerivative(const Dune::FieldVector<ctype, dim>& local) const + { + // the function value at the point where we are evaluating the derivative + TargetSpace q = evaluate(local); + + // Actually compute the derivative + return evaluateDerivative(local,q); + } + + template <int dim, class ctype, class LocalFiniteElement, class TargetSpace> + typename LocalTangentFEFunction<dim,ctype,LocalFiniteElement,TargetSpace>::DerivativeType + LocalTangentFEFunction<dim,ctype,LocalFiniteElement,TargetSpace>:: + evaluateDerivative(const Dune::FieldVector<ctype, dim>& local, const TargetSpace& q) const + { + DUNE_THROW(NotImplemented, "evaluateDerivative not implemented yet!"); + } + + } + +} +#endif -- GitLab