-
Thomas Witkowski authoredThomas Witkowski authored
DOFVector.h 21.91 KiB
// ============================================================================
// == ==
// == AMDiS - Adaptive multidimensional simulations ==
// == ==
// ============================================================================
// == ==
// == TU Dresden ==
// == ==
// == Institut fr Wissenschaftliches Rechnen ==
// == Zellescher Weg 12-14 ==
// == 01069 Dresden ==
// == germany ==
// == ==
// ============================================================================
// == ==
// == https://gforge.zih.tu-dresden.de/projects/amdis/ ==
// == ==
// ============================================================================
/** \file DOFVector.h */
#ifndef AMDIS_DOFVECTOR_H
#define AMDIS_DOFVECTOR_H
#include <vector>
#include <memory>
#include <list>
#include "AMDiS_fwd.h"
#include "FixVec.h"
#include "Global.h"
#include "Flag.h"
#include "RCNeighbourList.h"
#include "DOFIterator.h"
#include "DOFIndexed.h"
#include "DOFContainer.h"
#include "Boundary.h"
#include "CreatorInterface.h"
#include "Serializable.h"
#include "DOFMatrix.h"
#include "BasisFunction.h"
#include "FiniteElemSpace.h"
namespace AMDiS {
template<typename T>
class DOFVectorBase : public DOFIndexed<T>
{
public:
DOFVectorBase()
: feSpace(NULL),
elementVector(3),
boundaryManager(NULL),
nBasFcts(0)
{
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
rankDofs = NULL;
#endif
}
DOFVectorBase(const FiniteElemSpace *f, std::string n);
virtual ~DOFVectorBase();
/// Creates temporary used data structures.
void createTempData();
/** \brief
* For the given element, this function returns an array of all DOFs of this
* DOFVector that are defined on this element.
*/
virtual void getLocalVector(const Element *el,
mtl::dense_vector<T>& localVec) const;
/** \brief
* Evaluates the DOF vector at a set of quadrature points defined on the
* given element.
*/
void getVecAtQPs(const ElInfo *elInfo,
const Quadrature *quad,
const FastQuadrature *quadFast,
mtl::dense_vector<T>& vecAtQPs) const;
void getVecAtQPs(const ElInfo *smallElInfo,
const ElInfo *largeElInfo,
const Quadrature *quad,
const FastQuadrature *quadFast,
mtl::dense_vector<T>& vecAtQPs) const;
const WorldVector<T> *getGrdAtQPs(const ElInfo *elInfo,
const Quadrature *quad,
const FastQuadrature *quadFast,
WorldVector<T> *grdAtQPs) const;
const WorldVector<T> *getGrdAtQPs(const ElInfo *smallElInfo,
const ElInfo *largeElInfo,
const Quadrature *quad,
const FastQuadrature *quadFast,
WorldVector<T> *grdAtQPs) const;
const WorldMatrix<T> *getD2AtQPs(const ElInfo *elInfo,
const Quadrature *quad,
const FastQuadrature *quadFast,
WorldMatrix<T> *d2AtQPs) const;
/// Returns the FE space the DOF vector is defined on.
inline const FiniteElemSpace* getFeSpace() const
{
return feSpace;
}
/** \brief
* Assembles the element vector for the given ellement and adds the
* element matrix to the current DOF vector.
*/
void assemble(T factor, ElInfo *elInfo,
const BoundaryType *bound,
Operator *op = NULL);
void assemble2(T factor,
ElInfo *mainElInfo, ElInfo *auxElInfo,
ElInfo *smallElInfo, ElInfo *largeElInfo,
const BoundaryType *bound,
Operator *op = NULL);
void addElementVector(T sign,
const ElementVector& elVec,
const BoundaryType *bound,
ElInfo *elInfo,
bool add = true);
/* \brief
* That function must be called after the matrix assembling has been finished.
* This makes it possible to start some cleanup or matrix data compressing
* procedures.
*/
void finishAssembling();
inline void addOperator(Operator* op,
double *factor = NULL,
double *estFactor = NULL)
{
operators.push_back(op);
operatorFactor.push_back(factor);
operatorEstFactor.push_back(estFactor);
}
inline std::vector<double*>::iterator getOperatorFactorBegin()
{
return operatorFactor.begin();
}
inline std::vector<double*>::iterator getOperatorFactorEnd()
{
return operatorFactor.end();
}
inline std::vector<double*>::iterator getOperatorEstFactorBegin()
{
return operatorEstFactor.begin();
}
inline std::vector<double*>::iterator getOperatorEstFactorEnd()
{
return operatorEstFactor.end();
}
inline std::vector<Operator*>::iterator getOperatorsBegin()
{
return operators.begin();
}
inline std::vector<Operator*>::iterator getOperatorsEnd()
{
return operators.end();
}
Flag getAssembleFlag();
/** \brief
* Evaluates \f[ u_h(x(\lambda)) = \sum_{i=0}^{m-1} vec[ind[i]] *
* \varphi^i(\lambda) \f] where \f$ \varphi^i \f$ is the i-th basis function,
* \f$ x(\lambda) \f$ are the world coordinates of lambda and
* \f$ m \f$ is the number of basis functions
*/
T evalUh(const DimVec<double>& lambda, DegreeOfFreedom* ind);
inline std::vector<Operator*>& getOperators()
{
return operators;
}
inline std::vector<double*>& getOperatorFactor()
{
return operatorFactor;
}
inline std::vector<double*>& getOperatorEstFactor()
{
return operatorEstFactor;
}
/// Returns \ref name
inline std::string getName() const
{
return name;
}
inline void setName(std::string n)
{
name = n;
}
inline BoundaryManager* getBoundaryManager() const
{
return boundaryManager;
}
inline void setBoundaryManager(BoundaryManager *bm)
{
boundaryManager = bm;
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
inline void setRankDofs(std::map<DegreeOfFreedom, bool> &dofmap)
{
rankDofs = &dofmap;
}
inline bool isRankDof(DegreeOfFreedom dof)
{
TEST_EXIT_DBG(rankDofs)("No rank dofs set!\n");
return (*rankDofs)[dof];
}
#endif
protected:
///
const FiniteElemSpace *feSpace;
///
std::string name;
///
ElementVector elementVector;
///
std::vector<Operator*> operators;
///
std::vector<double*> operatorFactor;
///
std::vector<double*> operatorEstFactor;
///
BoundaryManager *boundaryManager;
/// Number of basis functions of the used finite element space.
int nBasFcts;
/// Are used to store temporary local dofs of an element. Thread safe.
std::vector<DegreeOfFreedom*> localIndices;
/// Are used to store temporary local values of an element. Thread safe.
std::vector<mtl::dense_vector<T> > localVectors;
/// Temporarly used in \ref getGrdAtQPs. Thread safe.
std::vector<DimVec<double>*> grdTmp;
/// Temporarly used in \ref getGrdAtQPs. Thread safe.
std::vector<DimVec<double>*> grdPhis;
/// Temporarly used in \ref getD2AtQPs. Thread safe.
std::vector<DimMat<double>*> D2Phis;
/// Dimension of the mesh this DOFVectorBase belongs to
int dim;
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
std::map<DegreeOfFreedom, bool> *rankDofs;
#endif
};
/// Specifies which operation should be done after coarsening
typedef enum{
NO_OPERATION = 0,
COARSE_RESTRICT = 1,
COARSE_INTERPOL = 2
} CoarsenOperation;
/** \ingroup DOFAdministration
* \brief
* The DOFs described above are just integers that can be used as indices into
* vectors and matrices. During refinement and coarsening of the mesh, the
* number of used DOFs, the meaning of one integer index, and even the total
* range of DOFs change. To be able to handle these changes automatically for
* all vectors, which are indexed by the DOFs, special data structures are
* used which contain such vector data. Lists of these structures are kept in
* DOFAdmin, so that all vectors in the lists can be resized together with the
* range of DOFs. During refinement and coarsening of elements, values can be
* interpolated automatically to new DOFs, and restricted from old DOFs.
*/
template<typename T>
class DOFVector : public DOFVectorBase<T>, public Serializable
{
public:
/** \ingroup DOFAdministration
* \brief
* Enables the access of DOFVector<T>::Iterator. Alias for DOFIterator<T>
*/
class Iterator : public DOFIterator<T> {
public:
Iterator(DOFIndexed<T> *c, DOFIteratorType type)
: DOFIterator<T>(c, type)
{}
Iterator(DOFAdmin *admin, DOFIndexed<T> *c, DOFIteratorType type)
: DOFIterator<T>(admin, c, type)
{}
};
class Creator : public CreatorInterface<DOFVector<T> > {
public:
Creator(FiniteElemSpace *feSpace_)
: feSpace(feSpace_)
{}
DOFVector<T> *create()
{
return new DOFVector<T>(feSpace, "");
}
void free(DOFVector<T> *vec)
{
delete vec;
}
private:
FiniteElemSpace *feSpace;
};
public:
/// Empty constructor. No initialization!
DOFVector()
: DOFVectorBase<T>(),
coarsenOperation(NO_OPERATION)
{}
/// Constructs a DOFVector with name n belonging to FiniteElemSpace f
DOFVector(const FiniteElemSpace* f, std::string n);
/// Initialization.
void init(const FiniteElemSpace* f, std::string n);
/// Copy Constructor
DOFVector(const DOFVector& rhs)
{
*this = rhs;
this->name = rhs.name + "copy";
if (this->feSpace && this->feSpace->getAdmin())
(dynamic_cast<DOFAdmin*>(this->feSpace->getAdmin()))->addDOFIndexed(this);
this->createTempData();
}
/// Destructor
virtual ~DOFVector();
/// Returns iterator to the begin of \ref vec
typename std::vector<T>::iterator begin()
{
return vec.begin();
}
/// Returns iterator to the end of \ref vec
typename std::vector<T>::iterator end()
{
return vec.end();
}
/** \brief
* Used by DOFAdmin to compress this DOFVector. Implementation of
* DOFIndexedBase::compress()
*/
virtual void compressDOFIndexed(int first, int last,
std::vector<DegreeOfFreedom> &newDof);
/// Sets \ref coarsenOperation to op
inline void setCoarsenOperation(CoarsenOperation op)
{
coarsenOperation = op;
}
/// Returns \ref coarsenOperation
inline CoarsenOperation getCoarsenOperation()
{
return coarsenOperation;
}
/// Restriction after coarsening. Implemented for DOFVector<double>
inline void coarseRestrict(RCNeighbourList&, int) {}
/// Interpolation after refinement.
inline void refineInterpol(RCNeighbourList&, int) {}
/// Returns \ref vec
std::vector<T>& getVector()
{
return vec;
}
/// Returns size of \ref vec
inline int getSize() const
{
return vec.size();
}
/// Returns used size of the vector.
inline int getUsedSize() const
{
return this->feSpace->getAdmin()->getUsedSize();
}
/// Resizes \ref vec to n
inline void resize(int n)
{
FUNCNAME("DOFVector<T>::resize()");
TEST_EXIT_DBG(n >= 0)("Can't resize DOFVector to negative size\n");
vec.resize(n);
}
/// Resizes \ref vec to n and inits new values with init
inline void resize(int n, T init)
{
FUNCNAME("DOFVector<T>::resize()");
TEST_EXIT_DBG(n >= 0)("Can't resize DOFVector to negative size\n");
vec.resize(n, init);
}
/// Returns \ref vec[i]
inline const T& operator[](DegreeOfFreedom i) const
{
FUNCNAME("DOFVector<T>::operator[]");
TEST_EXIT_DBG(i >= 0 && i < static_cast<int>(vec.size()))
("Illegal vector index %d.\n", i);
return vec[i];
}
/// Returns \ref vec[i]
inline T& operator[](DegreeOfFreedom i)
{
FUNCNAME("DOFVector<T>::operator[]");
TEST_EXIT_DBG(i >= 0 && i < static_cast<int>(vec.size()))
("Illegal vector index %d.\n", i);
return vec[i];
}
/// Calculates Integral of this DOFVector
double Int(Quadrature* q = NULL) const;
/// Calculates L1 norm of this DOFVector
double L1Norm(Quadrature* q = NULL) const;
/// Calculates L2 norm of this DOFVector
inline double L2Norm(Quadrature* q = NULL) const
{
return sqrt(L2NormSquare());
}
/// Calculates square of L2 norm of this DOFVector
double L2NormSquare(Quadrature* q = NULL) const;
/// Calculates H1 norm of this DOFVector
inline double H1Norm(Quadrature* q = NULL) const
{
return sqrt(H1NormSquare());
}
/// Calculates square of H1 norm of this DOFVector
double H1NormSquare(Quadrature* q = NULL) const;
/// Calculates euclidian norm of this DOFVector
double nrm2() const;
/// Returns square of the euclidian norm.
double squareNrm2() const;
/// Calculates l2 norm of this DOFVector
inline double l2norm() const
{
return nrm2();
}
/// Calculates the absolute sum of this DOFVector
T asum() const;
/// Calculates the l1 norm of this DOFVector
inline double l1norm() const
{
return asum();
}
/// Calculates doublewell of this DOFVector
double DoubleWell(Quadrature* q = NULL) const;
/// Calculates the sum of this DOFVector
T sum() const;
/// Sets \ref vec[i] = val, i=0 , ... , size
void set(T val);
/// Assignment operator for setting complete vector to a certain value d
inline DOFVector<T>& operator=(T d)
{
set(d);
return *this;
}
/// Assignment operator between two vectors
DOFVector<T>& operator=(const DOFVector<T>&);
/// vec[i] = v.vec[i]
void copy(const DOFVector<T>& v);
/// Returns minimum of DOFVector.
T min() const;
/// Returns maximum of DOFVector.
T max() const;
/// Returns absolute maximum of DOFVector.
T absMax() const;
/// Returns the average value of the DOFVector.
T average() const;
/// Used by interpol while mesh traversal.
void interpolFct(ElInfo* elinfo);
/// Prints \ref vec to stdout.
void print() const;
///
int calcMemoryUsage() const;
/** \brief
* Computes the coefficients of the interpolant of the function fct and
* stores these in the DOFVector
*/
void interpol(AbstractFunction<T, WorldVector<double> > *fct);
void interpol(DOFVector<T> *v, double factor = 1.0);
/// Writes the data of the DOFVector to an output stream.
void serialize(std::ostream &out)
{
unsigned int size = vec.size();
out.write(reinterpret_cast<const char*>(&size), sizeof(unsigned int));
out.write(reinterpret_cast<const char*>(&(vec[0])), size * sizeof(T));
}
/// Reads data of an DOFVector from an input stream.
void deserialize(std::istream &in)
{
unsigned int size;
in.read(reinterpret_cast<char*>(&size), sizeof(unsigned int));
vec.resize(size);
in.read(reinterpret_cast<char*>(&(vec[0])), size * sizeof(T));
}
DOFVector<WorldVector<T> > *getGradient(DOFVector<WorldVector<T> >*) const;
WorldVector<DOFVector<T>*> *getGradient(WorldVector<DOFVector<T>*> *grad) const;
DOFVector<WorldVector<T> >* getRecoveryGradient(DOFVector<WorldVector<T> >*) const;
protected:
/// Data container
std::vector<T> vec;
/// Specifies what operation should be performed after coarsening
CoarsenOperation coarsenOperation;
/// Used by \ref interpol
AbstractFunction<T, WorldVector<double> > *interFct;
/// Used for mesh traversal
static DOFVector<T> *traverseVector;
};
template<>
void DOFVector<double>::refineInterpol(RCNeighbourList&, int);
template<>
void DOFVector<double>::coarseRestrict(RCNeighbourList&, int);
inline double min(const DOFVector<double>& v)
{
return v.min();
}
inline double max(const DOFVector<double>& v)
{
return v.max();
}
/** \ingroup DOFAdministration
* \brief
* A DOFVector that stores DOF indices.
*/
class DOFVectorDOF : public DOFVector<DegreeOfFreedom>,
public DOFContainer
{
public:
/** \brief
* Calls constructor of DOFVector<DegreeOfFreedom> and registers itself
* as DOFContainer at DOFAdmin
*/
DOFVectorDOF(const FiniteElemSpace* feSpace_, std::string name_)
: DOFVector<DegreeOfFreedom>(feSpace_, name_)
{
feSpace->getAdmin()->addDOFContainer(this);
}
/// Deregisters itself at DOFAdmin.
~DOFVectorDOF()
{
feSpace->getAdmin()->removeDOFContainer(this);
}
/** \brief
* Implements DOFContainer::operator[]() by calling
* DOFVector<DegreeOfFreedom>::operator[]()
*/
DegreeOfFreedom& operator[](DegreeOfFreedom i)
{
return DOFVector<DegreeOfFreedom>::operator[](i);
}
const DegreeOfFreedom& operator[](DegreeOfFreedom i) const
{
return DOFVector<DegreeOfFreedom>::operator[](i);
}
/// Implements DOFIndexedBase::getSize()
int getSize() const
{
return DOFVector<DegreeOfFreedom>::getSize();
}
/// Implements DOFIndexedBase::resize()
void resize(int size)
{
DOFVector<DegreeOfFreedom>::resize(size);
}
void freeDOFContent(DegreeOfFreedom dof);
protected:
DOFVectorDOF();
};
template<typename T>
double norm(DOFVector<T> *vec)
{
return vec->nrm2();
}
template<typename T>
double L2Norm(DOFVector<T> *vec)
{
return vec->L2Norm();
}
template<typename T>
double H1Norm(DOFVector<T> *vec)
{
return vec->H1Norm();
}
template<typename T>
void print(DOFVector<T> *vec)
{
vec->print();
}
// point wise multiplication
template<typename T>
const DOFVector<T>& operator*=(DOFVector<T>& x, const DOFVector<T>& y);
// multiplication with scalar
template<typename T>
const DOFVector<T>& operator*=(DOFVector<T>& x, T scal);
// scalar product
template<typename T>
T operator*(DOFVector<T>& x, DOFVector<T>& y);
// addition
template<typename T>
const DOFVector<T>& operator+=(DOFVector<T>& x, const DOFVector<T>& y);
// subtraction
template<typename T>
const DOFVector<T>& operator-=(DOFVector<T>& x, const DOFVector<T>& y);
template<typename T>
const DOFVector<T>& operator*(const DOFVector<T>& v, double d);
template<typename T>
const DOFVector<T>& operator*(double d, const DOFVector<T>& v);
template<typename T>
const DOFVector<T>& operator+(const DOFVector<T>&v1 , const DOFVector<T>& v2);
// y = a*x + y
template<typename T>
void axpy(double a,const DOFVector<T>& x, DOFVector<T>& y);
// matrix vector product
template<typename T>
void mv(MatrixTranspose transpose,
const DOFMatrix &a,
const DOFVector<T> &x,
DOFVector<T> &result,
bool add = false);
template<typename T>
void xpay(double a,const DOFVector<T>& x,DOFVector<T>& y);
template<typename T>
inline void scal(T a, DOFVector<T>& y)
{
y *= a;
}
template<typename T>
inline const DOFVector<T>& mult(double scal,
const DOFVector<T>& v,
DOFVector<T>& result);
template<typename T>
inline const DOFVector<T>& add(const DOFVector<T>& v,
double scal,
DOFVector<T>& result);
template<typename T>
inline const DOFVector<T>& add(const DOFVector<T>& v1,
const DOFVector<T>& v2,
DOFVector<T>& result);
template<typename T>
inline const DOFVector<T>& mod(const DOFVector<T>& v,
DOFVector<T>& result);
template<typename T>
inline const DOFVector<T>& Tanh(const DOFVector<T>& v,
DOFVector<T>& result);
template<typename T>
inline void set(DOFVector<T>& vec, T d)
{
vec.set(d);
}
template<typename T>
inline void setValue(DOFVector<T>& vec, T d)
{
vec.set(d);
}
template<typename T>
inline int size(DOFVector<T> *vec)
{
return vec->getUsedSize();
}
template<typename T>
inline void checkFeSpace(const FiniteElemSpace* feSpace, const std::vector<T>& vec)
{
TEST_EXIT_DBG(feSpace)("feSpace is NULL\n");
TEST_EXIT_DBG(feSpace->getAdmin())("admin is NULL\n");
TEST_EXIT_DBG(static_cast<int>(vec.size()) >= feSpace->getAdmin()->getUsedSize())
("size = %d too small: admin->sizeUsed = %d\n", vec.size(),
feSpace->getAdmin()->getUsedSize());
}
WorldVector<DOFVector<double>*> *transform(DOFVector<WorldVector<double> > *vec,
WorldVector<DOFVector<double>*> *result);
/** \brief
* Computes the integral of a function that includes two different DOFVectors. This
* function works also for the case that the DOFVectors are defined on two different
* meshes.
*/
double integrate(const DOFVector<double> &vec1,
const DOFVector<double> &vec2,
BinaryAbstractFunction<double, double, double> *fct);
/// Computes the integral of a function with two DOFVectors defined on the same mesh.
double intSingleMesh(const DOFVector<double> &vec1,
const DOFVector<double> &vec2,
BinaryAbstractFunction<double, double, double> *fct);
/// Computes the integral of a function with two DOFVectors defined on different meshes.
double intDualMesh(const DOFVector<double> &vec1,
const DOFVector<double> &vec2,
BinaryAbstractFunction<double, double, double> *fct);
double integrate(const DOFVector<double> &vec,
AbstractFunction<double, WorldVector<double> > *fct);
}
#include "DOFVector.hh"
#endif // !_DOFVECTOR_H_