-
Youett, Jonathan authored
[[Imported from SVN: r8070]]
Youett, Jonathan authored[[Imported from SVN: r8070]]
globalgfetestfunction.hh 4.58 KiB
#ifndef GLOBAL_GEODESIC_FINITE_ELEMENT_TEST_FUNCTION_HH
#define GLOBAL_GEODESIC_FINITE_ELEMENT_TEST_FUNCTION_HH
#include <vector>
#include <dune/istl/bvector.hh>
#include <dune/common/fvector.hh>
#include <dune/common/fmatrix.hh>
#include <dune/common/array.hh>
/** \brief Global geodesic finite element test function.
*
* \tparam B - The global basis type.
* \tparam TargetSpace - The manifold that this functions takes its values in.
*/
template<class B, class TargetSpace, class CoefficientType>
class GlobalGFETestFunction
{
public:
typedef B Basis;
private:
typedef typename Basis::LocalFiniteElement LocalFiniteElement;
typedef typename Basis::GridView GridView;
typedef typename GridView::template Codim<0>::Entity Element;
typedef typename GridView::Grid::ctype ctype;
typedef typename TargetSpace::TangentVector TangentVector;
typedef typename TargetSpace::EmbeddedTangentVector EmbeddedTangentVector;
//! Dimension of the grid.
enum { gridDim = GridView::dimension };
//! Dimension of the embedded tanget space
enum { embeddedDim = EmbeddedTangentVector::dimension };
enum { tangentDim = TargetSpace::TangentVector::dimension };
public:
//! Create global function by a global gfe test basis and the corresponding coefficient vectors
GlobalGFETestFunction(const Basis& basis, const CoefficientType& coefficients) :
basis_(basis),
coefficients_(coefficients)
{}
/** \brief Evaluate the function at local coordinates. */
void evaluateLocal(const Element& element, const Dune::FieldVector<ctype,gridDim>& local, EmbeddedTangentVector& out) const;
/** \brief Evaluate the derivative of the function at local coordinates. */
void evaluateDerivativeLocal(const Element& element, const Dune::FieldVector<ctype,gridDim>& local,
Dune::FieldMatrix<ctype, embeddedDim, gridDim>& out) const;
/** \brief Export the basis. */
const Basis& basis() const {return basis_;}
/** \brief Export the coefficient vector. */
const CoefficientType& coefficientVector() const {return coefficients_;}
private:
const Basis& basis_;
const CoefficientType& coefficients_;
};
template<class Basis, class TargetSpace, class CoefficientType>
void GlobalGFETestFunction<Basis,TargetSpace,CoefficientType>::evaluateLocal(const Element& element, const Dune::FieldVector<ctype,gridDim>& local,
EmbeddedTangentVector& out) const
{
// values of the test basis functions
std::vector<Dune::array<EmbeddedTangentVector, tangentDim> > values;
// create local gfe test function
basis_.getLocalFiniteElement(element).localBasis().evaluateFunction(local, values);
// multiply values with the corresponding test coefficients and sum them up
out = 0.0;
for (size_t i=0; i<values.size(); i++) {
int index = basis_.index(element,i);
for (int j=0; j<tangentDim; j++) {
values[i][j] *= coefficients_[index][j];
out += values[i][j];
}
}
}
template<class Basis, class TargetSpace , class CoefficientType>
void GlobalGFETestFunction<Basis,TargetSpace,CoefficientType>::evaluateDerivativeLocal(const Element& element,
const Dune::FieldVector<ctype,gridDim>& local,
Dune::FieldMatrix<ctype, embeddedDim, gridDim>& out) const
{
// jacobians of the test basis function - a lot of dims here...
std::vector<Dune::array<Dune::FieldMatrix<ctype, embeddedDim, gridDim>, tangentDim> > refJacobians,jacobians;
// evaluate local gfe test function basis
basis_.getLocalFiniteElement(element).localBasis().evaluateJacobian(local, refJacobians);
const Dune::FieldMatrix<double,gridDim,gridDim>& jacInvTrans = element.geometry().jacobianInverseTransposed(local);
//transform the gradients
jacobians.resize(refJacobians.size());
for (size_t i = 0; i<jacobians.size(); i++)
for (int j=0; j<tangentDim; j++) {// the local basis has a block structure
jacobians[i][j] = 0;
for (size_t comp=0; comp<jacobians[i][j].N(); comp++)
jacInvTrans.umv(refJacobians[i][j][comp], jacobians[i][j][comp]);
}
// multiply values with the corresponding test coefficients and sum them up
out = 0.0;
for (int i=0; i<jacobians.size(); i++) {
int index = basis_.index(element,i);
for (int j=0; j<tangentDim; j++) {
jacobians[i][j] *= coefficients_[index][j];
out += jacobians[i][j];
}
}
}
#endif