From 9ec5de080aa50ae1f2fc7b324243d37d70718cfa Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Wed, 11 Jan 2012 15:52:14 +0000 Subject: [PATCH] Add a second method evaluateDerivative which accepts the function value as input. To compute the derivative you need the function value (see my paper). Therefore, it is computed as the first thing in the evaluateDerivative method. However, frequently, the assembler also needs the function value, and also computes it. Hence the function value is computed twice. Since computing the function values takes quite a bit of time this patch removes that redundancy, at the price of a slightly more complicated API: if you happen to know the correct function value when calling evaluateDerivative, you can now hand over the value. Then evaluateDerivative uses that value instead of recomputing it. Short measurements have shown a speed increase between 25% and 45%. [[Imported from SVN: r8362]] --- dune/gfe/localgeodesicfefunction.hh | 47 +++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/dune/gfe/localgeodesicfefunction.hh b/dune/gfe/localgeodesicfefunction.hh index 9d7d5aed..eba6558b 100644 --- a/dune/gfe/localgeodesicfefunction.hh +++ b/dune/gfe/localgeodesicfefunction.hh @@ -67,6 +67,13 @@ public: /** \brief Evaluate the derivative of the function */ Dune::FieldMatrix<ctype, EmbeddedTangentVector::dimension, dim> 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! + */ + Dune::FieldMatrix<ctype, EmbeddedTangentVector::dimension, dim> evaluateDerivative(const Dune::FieldVector<ctype, dim>& local, + const TargetSpace& q) const; + /** \brief For debugging: Evaluate the derivative of the function using a finite-difference approximation*/ Dune::FieldMatrix<ctype, EmbeddedTangentVector::dimension, dim> evaluateDerivativeFD(const Dune::FieldVector<ctype, dim>& local) const; @@ -190,6 +197,17 @@ evaluate(const Dune::FieldVector<ctype, dim>& local) const template <int dim, class ctype, class LocalFiniteElement, class TargetSpace> Dune::FieldMatrix<ctype, TargetSpace::EmbeddedTangentVector::dimension, dim> LocalGeodesicFEFunction<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 + evaluateDerivative(local,q); +} + +template <int dim, class ctype, class LocalFiniteElement, class TargetSpace> +Dune::FieldMatrix<ctype, TargetSpace::EmbeddedTangentVector::dimension, dim> LocalGeodesicFEFunction<dim,ctype,LocalFiniteElement,TargetSpace>:: +evaluateDerivative(const Dune::FieldVector<ctype, dim>& local, const TargetSpace& q) const { Dune::FieldMatrix<ctype, embeddedDim, dim> result; @@ -209,9 +227,6 @@ evaluateDerivative(const Dune::FieldVector<ctype, dim>& local) const // Hence we need to solve a small system of linear equations. // //////////////////////////////////////////////////////////////////////// - // the function value at the point where we are evaluating the derivative - TargetSpace q = evaluate(local); - // the matrix that turns coordinates on the reference simplex into coordinates on the standard simplex std::vector<Dune::FieldMatrix<ctype,1,dim> > BNested(coefficients_.size()); localFiniteElement_.localBasis().evaluateJacobian(local, BNested); @@ -643,6 +658,32 @@ public: return result; } + /** \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! + */ + Dune::FieldMatrix<ctype, EmbeddedTangentVector::dimension, dim> evaluateDerivative(const Dune::FieldVector<ctype, dim>& local, + const TargetSpace& q) const + { + Dune::FieldMatrix<ctype, embeddedDim, dim> result(0); + + // get translation part + std::vector<Dune::FieldMatrix<ctype,1,dim> > sfDer(translationCoefficients_.size()); + localFiniteElement_.localBasis().evaluateJacobian(local, sfDer); + + for (size_t i=0; i<translationCoefficients_.size(); i++) + for (int j=0; j<3; j++) + result[j].axpy(translationCoefficients_[i][j], sfDer[i][0]); + + // get orientation part + Dune::FieldMatrix<ctype,4,dim> qResult = orientationFEFunction_->evaluateDerivative(local,q.q); + for (int i=0; i<4; i++) + for (int j=0; j<dim; j++) + result[3+i][j] = qResult[i][j]; + + return result; + } + /** \brief For debugging: Evaluate the derivative of the function using a finite-difference approximation*/ Dune::FieldMatrix<ctype, embeddedDim, dim> evaluateDerivativeFD(const Dune::FieldVector<ctype, dim>& local) const { -- GitLab