// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // == http://www.amdis-fem.org == // == == // ============================================================================ // // Software License for AMDiS // // Copyright (c) 2010 Dresden University of Technology // All rights reserved. // Authors: Simon Vey, Thomas Witkowski et al. // // This file is part of AMDiS // // See also license.opensource.txt in the distribution. /** \file Quadrature.h */ #ifndef AMDIS_QUADRATURE_H #define AMDIS_QUADRATURE_H #include <list> #include "AMDiS_fwd.h" #include "BasisFunction.h" #include "Flag.h" #include "FixVec.h" namespace AMDiS { /** * \ingroup Assembler * * \brief * For the assemblage of the system matrix and right hand side vector of the * linear system, we have to compute integrals, for example: * \f[ \int_{\Omega} f(x)\varphi_i(x) dx \f] * For general data A, b, c, and f, these integrals can not be calculated * exactly. Quadrature formulas have to be used in order to calculate the * integrals approximately. Numerical integration in finite element methods is * done by looping over all grid elements and using a quadrature formula on * each element. */ class Quadrature { protected: /// Avoids call of default constructor Quadrature(); /** \brief * Constructs a Quadrature with name name_ of degree degree_ for dim dim_. * The Quadrature has n_points_ quadrature points with barycentric * coordinates lambda_ and weights w_. The constructor is protected because * access to a Quadrature should be done via \ref provideQuadrature. */ Quadrature(const char* name_, int degree_, int dim_, int n_points_, VectorOfFixVecs<DimVec<double> > *lambda_, double* w_) : name(name_), degree(degree_), dim(dim_), n_points(n_points_), lambda(lambda_), w(w_) {} public: /// Copy constructor Quadrature(const Quadrature&); /// Destructor ~Quadrature(); /// Returns a Quadrature for dimension dim exact for degree degree. static Quadrature *provideQuadrature(int dim, int degree); /** \brief * Approximates an integral by the numerical quadrature described by quad; * f is a pointer to an AbstractFunction to be integrated, evaluated in * barycentric coordinates; the return value is * \f[ \sum_{k = 0}^{n_points-1} w[k] * (*f)(lambda[k]) \f] * For the approximation of \f$ \int_S f\f$ we have to multiply this value * with d!|S| for a simplex S; for a parametric simplex f should be a pointer * to a function which calculates * \f$ f(\lambda)|det DF_S(\hat{x}(\lambda))| \f$. */ double integrateStdSimplex(AbstractFunction<double, DimVec<double> > *f); /// Returns \ref name inline std::string getName() { return name; } /// Returns \ref n_points inline int getNumPoints() const { return n_points; } /// Returns \ref w[p] inline double getWeight(int p) const { return w[p]; } /// Returns \ref w. inline double* getWeight() const { return w; } /// Returns \ref dim inline int getDim() const { return dim; } /// Returns \ref degree inline int getDegree() const { return degree; } /** \brief * Returns a pointer to a vector storing the values of a doubled valued * function at all quadrature points; f is that AbstractFunction * , evaluated in barycentric coordinates; if vec is not NULL, the values are * stored in this vector, otherwise the values are stored in some static * local vector, which is overwritten on the next call */ const double *fAtQp(const AbstractFunction<double, DimVec<double> >& f, double *vec) const ; /** \brief * Returns a pointer to a vector storing the gradient (with respect to world * coordinates) of a double valued function at all quadrature points; * grdF is a pointer to a AbstractFunction, evaluated in barycentric * coordinates and returning a pointer to a WorldVector storing the gradient; * if vec is not NULL, the values are stored in this vector, otherwise the * values are stored in some local static vector, which is overwritten on the * next call */ const WorldVector<double> *grdFAtQp(const AbstractFunction<WorldVector<double>, DimVec<double> >& grdF, WorldVector<double>* vec) const; /** \brief * Returns \ref lambda[a][b] which is the b-th coordinate entry of the a-th * quadrature point */ inline double getLambda(int a, int b) const { return (lambda ? (*lambda)[a][b] : 0.0); } /** \brief * Returns \ref lambda[a] which is a DimVec<double> containing the * coordiantes of the a-th quadrature point */ inline const DimVec<double>& getLambda(int a) const { return (*lambda)[a]; } /// Returns \ref lambda which is a VectorOfFixvecs<DimVec<double> >. VectorOfFixVecs<DimVec<double> > *getLambda() const { return lambda; } public: /// Maximal number of quadrature points for the different dimensions static const int maxNQuadPoints[4]; protected: /// Name of this Quadrature std::string name; /// Quadrature is exact of this degree int degree; /// Quadrature for dimension dim int dim; /// Number of quadrature points int n_points; /// Vector of quadrature points given in barycentric coordinates VectorOfFixVecs<DimVec<double> > *lambda; /// Vector of quadrature weights double *w; protected: /** \brief * Initialisation of all static Quadrature objects which will be returned * by \ref provideQuadrature() */ static void initStaticQuadratures(); /** \name static quadratures, used weights, and barycentric coords * \{ */ static Quadrature **quad_nd[4]; static Quadrature *quad_0d[1]; static Quadrature *quad_1d[20]; static Quadrature *quad_2d[18]; static Quadrature *quad_3d[8]; static VectorOfFixVecs<DimVec<double> > *x_0d; static double *w_0d; static VectorOfFixVecs<DimVec<double> > *x0_1d; static VectorOfFixVecs<DimVec<double> > *x1_1d; static VectorOfFixVecs<DimVec<double> > *x2_1d; static VectorOfFixVecs<DimVec<double> > *x3_1d; static VectorOfFixVecs<DimVec<double> > *x4_1d; static VectorOfFixVecs<DimVec<double> > *x5_1d; static VectorOfFixVecs<DimVec<double> > *x6_1d; static VectorOfFixVecs<DimVec<double> > *x7_1d; static VectorOfFixVecs<DimVec<double> > *x8_1d; static VectorOfFixVecs<DimVec<double> > *x9_1d; static double *w0_1d; static double *w1_1d; static double *w2_1d; static double *w3_1d; static double *w4_1d; static double *w5_1d; static double *w6_1d; static double *w7_1d; static double *w8_1d; static double *w9_1d; static VectorOfFixVecs<DimVec<double> > *x1_2d; static VectorOfFixVecs<DimVec<double> > *x2_2d; static VectorOfFixVecs<DimVec<double> > *x3_2d; static VectorOfFixVecs<DimVec<double> > *x4_2d; static VectorOfFixVecs<DimVec<double> > *x5_2d; static VectorOfFixVecs<DimVec<double> > *x7_2d; static VectorOfFixVecs<DimVec<double> > *x8_2d; static VectorOfFixVecs<DimVec<double> > *x9_2d; static VectorOfFixVecs<DimVec<double> > *x10_2d; static VectorOfFixVecs<DimVec<double> > *x11_2d; static VectorOfFixVecs<DimVec<double> > *x12_2d; static VectorOfFixVecs<DimVec<double> > *x17_2d; static double *w1_2d; static double *w2_2d; static double *w3_2d; static double *w4_2d; static double *w5_2d; static double *w7_2d; static double *w8_2d; static double *w9_2d; static double *w10_2d; static double *w11_2d; static double *w12_2d; static double *w17_2d; static VectorOfFixVecs<DimVec<double> > *x1_3d; static VectorOfFixVecs<DimVec<double> > *x2_3d; static VectorOfFixVecs<DimVec<double> > *x3_3d; static VectorOfFixVecs<DimVec<double> > *x4_3d; static VectorOfFixVecs<DimVec<double> > *x5_3d; static VectorOfFixVecs<DimVec<double> > *x7_3d; static double *w1_3d; static double *w2_3d; static double *w3_3d; static double *w4_3d; static double *w5_3d; static double *w7_3d; /** \} */ }; /** \brief * Pre-compute the values of all basis functions at all quadrature nodes; */ const Flag INIT_PHI=1; /** \brief * Pre-compute the gradients (with respect to the barycentric coordinates) of * all basis functions at all quadrature nodes */ const Flag INIT_GRD_PHI=2; /** \brief * pre-compute all 2nd derivatives (with respect to the barycentric * coordinates) of all basis functions at all quadrature nodes; */ const Flag INIT_D2_PHI=4; /** * \ingroup Integration * *\brief * Often numerical integration involves basis functions, such as the assembling * of the system matrix and right hand side, or the integration of finite * element functions. Since numerical quadrature involves only the values at * the quadrature points and the values of basis functions and its derivatives * are the same at these points for all elements of the grid, such routines can * be much more efficient, if they can use pre-computed values of the basis * functions at the quadrature points. In this case the basis functions do not * have to be evaluated for each quadrature point on every element newly. * Information that should be pre-computed can be specified by the following * symbolic constants: * \ref INIT_PHI, \ref INIT_GRD_PHI, \ref INIT_D2_PHI */ class FastQuadrature { protected: /** \brief * Constructs a FastQuadrature for the given Quadrature, BasisFunction, and * flag. */ FastQuadrature(BasisFunction* basFcts, Quadrature* quad, Flag flag) : init_flag(flag), phi(NULL), grdPhi(NULL), D2Phi(NULL), quadrature(quad), basisFunctions(basFcts) {} /// Copy constructor FastQuadrature(const FastQuadrature&); /// Extended copy constructor FastQuadrature(const FastQuadrature&, const Flag); /// Destructor ~FastQuadrature(); public: /// Returns a FastQuadrature for the given BasisFunction, Quadrature, and flags. static FastQuadrature* provideFastQuadrature(const BasisFunction*, const Quadrature&, Flag); /// inits FastQuadrature like speciefied in flag void init(Flag init_flag); inline bool initialized(Flag flag) { if (flag == INIT_PHI) return (phi != NULL); if (flag == INIT_GRD_PHI) return (grdPhi != NULL); if (flag == INIT_D2_PHI) return (D2Phi != NULL); ERROR_EXIT("invalid flag\n"); return false; } /// Returns \ref quadrature inline const Quadrature* getQuadrature() const { return quadrature; } /// Returns \ref max_points inline int getMaxQuadPoints() { return max_points; } /// Returns (*\ref D2Phi)[q][i][j][m] const double getSecDer(int q, int i, int j, int m) const; /// Returns (*\ref D2Phi)[q] const VectorOfFixVecs<DimMat<double> > *getSecDer(int q) const; /// Returns (*\ref grdPhi)[q][i][j] inline const double getGradient(int q, int i ,int j) const { return (grdPhi) ? (*grdPhi)[q][i][j] : 0.0; } /// Returns (*\ref grdPhi)[q] inline VectorOfFixVecs<DimVec<double> >* getGradient(int q) const { return (grdPhi) ? &((*grdPhi)[q]) : NULL; } inline DimVec<double>& getGradient(int q, int i) const { return (*grdPhi)[q][i]; } /// Returns \ref phi[q][i] inline const double getPhi(int q, int i) const { return (phi) ? phi[q][i] : 0.0; } /// Returns \ref phi[q] inline const double *getPhi(int q) const { return (phi) ? phi[q] : NULL; } /// Returns \ref quadrature ->integrateStdSimplex(f) inline double integrateStdSimplex(AbstractFunction<double, DimVec<double> > *f) { return quadrature->integrateStdSimplex(f); } /// Returns \ref quadrature ->getNumPoints() inline int getNumPoints() const { return quadrature->getNumPoints(); } /// Returns \ref quadrature ->getWeight(p) inline double getWeight(int p) const { return quadrature->getWeight(p); } /// Returns \ref quadrature ->getDim() inline int getDim() const { return quadrature->getDim(); } /// Returns \ref quadrature ->getDegree() inline int getDegree() const { return quadrature->getDegree(); } /// Returns \ref quadrature ->grdFAtQp(f, vec) inline const WorldVector<double> *grdFAtQp(const AbstractFunction<WorldVector<double>, DimVec<double> >& f, WorldVector<double>* vec) const { return quadrature->grdFAtQp(f, vec); } /// Returns \ref quadrature ->fAtQp(f, vec) inline const double *fAtQp(const AbstractFunction<double, DimVec<double> >& f, double *vec) const { return quadrature->fAtQp(f, vec); } /// Returns \ref quadrature ->getLambda(a,b) inline double getLambda(int a,int b) const { return quadrature->getLambda(a,b); } /// Returns \ref quadrature ->getLambda(a) inline const DimVec<double>& getLambda(int a) const { return quadrature->getLambda(a); } /// Returns \ref basisFunctions inline BasisFunction* getBasisFunctions() const { return basisFunctions; } protected: /** \brief * Specifies which information should be pre-computed. Can be \ref INIT_PHI, * \ref INIT_GRD_PHI, or \ref INIT_D2_PHI */ Flag init_flag; /** \brief * Matrix storing function values if the flag \ref INIT_PHI is set; * phi[i][j] stores the value \ref basisFunctions->phi[j] * (quadrature->lambda[i]), 0 <= j < basisFunctions->getNumber() and * 0 <= i < n_points */ double **phi; /** \brief * Matrix storing all gradients (with respect to the barycentric coordinates) * if the flag \ref INIT_GRD_PHI is set; grdPhi[i][j][k] stores the value * basisFunctions->grdPhi[j](quadrature->lambda[i])[k] * for 0 <= j < basisFunctions->getNumber(), * 0 <= i < . . . , n_points, and 0 <= k < DIM */ MatrixOfFixVecs<DimVec<double> > *grdPhi; /** \brief * Matrix storing all second derivatives (with respect to the barycentric * coordinates) if the flag \ref INIT_D2_PHI is set; D2Phi[i][j][k][l] stores * the value basisFunctions->D2Phi[j](quadrature->lambda[i])[k][l] * for 0 <= j < basisFunctions->getNumber(), * 0 <= i < n_points, and 0 <= k,l < DIM */ MatrixOfFixVecs<DimMat<double> > *D2Phi; /** \brief * List of all used FastQuadratures */ static std::list<FastQuadrature*> fastQuadList; /** \brief * Maximal number of quadrature points for all yet initialised FastQuadrature * objects. This value may change after a new initialisation of a * FastQuadrature */ static int max_points; /// This FastQuadrature stores values for Quadrature quadrature Quadrature* quadrature; /// Values stored for basis functions basisFunctions BasisFunction* basisFunctions; }; } #endif // AMDIS_QUADRATURE_H