-
Thomas Witkowski authoredThomas Witkowski authored
Quadrature.h 15.56 KiB
// ============================================================================
// == ==
// == 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