// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // ============================================================================ // == == // == crystal growth group == // == == // == Stiftung caesar == // == Ludwig-Erhard-Allee 2 == // == 53175 Bonn == // == germany == // == == // ============================================================================ // == == // == http://www.caesar.de/cg/AMDiS == // == == // ============================================================================ /** \file SystemVector.h */ #ifndef AMDIS_SYSTEMVECTOR_H #define AMDIS_SYSTEMVECTOR_H #include "MemoryManager.h" #include "MatrixVector.h" #include "DOFVector.h" #include "CreatorInterface.h" #include "Serializable.h" #include "OpenMP.h" namespace AMDiS { // ============================================================================ // ===== class SystemVector =================================================== // ============================================================================ /** \brief * A system vector is a vector of dof vectors used for vector valued * problems. */ class SystemVector : public Serializable { public: MEMORY_MANAGED(SystemVector); /** \brief * Creator. */ class Creator : public CreatorInterface<SystemVector> { public: MEMORY_MANAGED(Creator); /** \brief * Creators constructor. */ Creator(const ::std::string &name_, ::std::vector<FiniteElemSpace*> feSpace_, int size_) : name(name_), feSpace(feSpace_), size(size_) {}; /** \brief * Destructor */ virtual ~Creator() {}; /** \brief * Implementation of CreatorInterface::create(). */ SystemVector *create() { char number[10]; ::std::string numberedName; SystemVector *result = NEW SystemVector(name, feSpace, size); for (int i = 0; i < size; i++) { sprintf(number, "[%d]", i); numberedName = name + ::std::string(number); result->setDOFVector(i, NEW DOFVector<double>(feSpace[i], numberedName)); } return result; }; /** \brief * Implementation of CreatorInterface::free(). */ void free(SystemVector *vec) { for (int i = 0; i < size; i++) { DELETE vec->getDOFVector(i); vec->setDOFVector(i, NULL); } DELETE vec; }; private: /** \brief * Name of the system vector */ ::std::string name; /** \brief * Finite element space used for creation. */ ::std::vector<FiniteElemSpace*> feSpace; /** \brief * Number of component vectors to be created */ int size; }; public: /** \brief * Constructor. */ SystemVector(const ::std::string& name_, ::std::vector<FiniteElemSpace*> feSpace_, int size) : name(name_), feSpace(feSpace_), vectors(size) { vectors.set(NULL); }; /** \brief * Copy Constructor. */ SystemVector(const SystemVector& rhs) : name(rhs.name), feSpace(rhs.feSpace), vectors(rhs.vectors.getSize()) { for (int i = 0; i < vectors.getSize(); i++) { vectors[i] = new DOFVector<double>(*rhs.vectors[i]); } }; virtual ~SystemVector() {}; /** \brief * Sets \ref vectors[index] = vec. */ inline void setDOFVector(int index, DOFVector<double> *vec) { TEST_EXIT_DBG(index < vectors.getSize())("invalid index\n"); vectors[index] = vec; }; /** \brief * Returns \ref vectors[index]. */ inline DOFVector<double> *getDOFVector(int index) { TEST_EXIT_DBG(index < vectors.getSize())("invalid index\n"); return vectors[index]; }; /** \brief * Returns \ref vectors[index]. */ inline const DOFVector<double> *getDOFVector(int index) const { TEST_EXIT_DBG(index < vectors.getSize())("invalid index\n"); return vectors[index]; }; /** \brief * Returns sum of used vector sizes. */ inline int getUsedSize() const { int totalSize = 0; int size = vectors.getSize(); for (int i = 0; i < size; i++) { totalSize += vectors[i]->getUsedSize(); } return totalSize; }; /** \brief * Returns number of contained vectors. */ inline int getNumVectors() const { return vectors.getSize(); }; inline int getSize() const { return vectors.getSize(); }; /** \brief * Returns \ref feSpace. */ inline FiniteElemSpace *getFESpace(int i) const { return feSpace[i]; }; /** \brief * Here the system vector is interpreted as one large vector. The given * is used as a global index which indicates a local vector number and * a local index on this vector. The operator returns this local vector * at the local index. */ inline double& operator[](int index) { int localIndex = index; int vectorIndex = 0; while (localIndex >= vectors[vectorIndex]->getUsedSize()) { localIndex -= vectors[vectorIndex++]->getUsedSize(); } return (*(vectors[vectorIndex]))[localIndex]; }; /** \brief * For const access. */ inline double operator[](int index) const { int localIndex = index; int vectorIndex = 0; while (localIndex >= vectors[vectorIndex]->getUsedSize()) { localIndex -= vectors[vectorIndex++]->getUsedSize(); } return (*(vectors[vectorIndex]))[localIndex]; }; /** \brief * Sets all entries in all vectors to value. */ inline void set(double value) { int size = vectors.getSize(); for (int i = 0; i < size; i++) { vectors[i]->set(value); } }; /** \brief * Sets all entries in all vectors to value. */ inline SystemVector& operator=(double value) { int size = vectors.getSize(); for (int i = 0; i < size; i++) { (*(vectors[i])) = value; } return *this; }; /** \brief * Assignement operator. */ inline SystemVector& operator=(const SystemVector& rhs) { TEST_EXIT_DBG(rhs.vectors.getSize() == vectors.getSize())("invalied sizes\n"); int size = vectors.getSize(); for (int i = 0; i < size; i++) { (*(vectors[i])) = (*(rhs.getDOFVector(i))); } return *this; }; void serialize(::std::ostream &out) { int size = vectors.getSize(); out.write(reinterpret_cast<const char*>(&size), sizeof(int)); for (int i = 0; i < size; i++) { vectors[i]->serialize(out); } }; void deserialize(::std::istream &in) { int size, oldSize = vectors.getSize(); in.read(reinterpret_cast<char*>(&size), sizeof(int)); vectors.resize(size); for (int i = oldSize; i < size; i++) { vectors[i] = NEW DOFVector<double>(feSpace[i], ""); } for (int i = 0; i < size; i++) { vectors[i]->deserialize(in); } }; void copy(const SystemVector& rhs) { int size = vectors.getSize(); TEST_EXIT_DBG(size == rhs.getNumVectors())("invalid sizes\n"); for (int i = 0; i < size; i++) { vectors[i]->copy(*(const_cast<SystemVector&>(rhs).getDOFVector(i))); } }; void interpol(::std::vector<AbstractFunction<double, WorldVector<double> >*> *f) { int size = vectors.getSize(); for (int i = 0; i < size; i++) { vectors[i]->interpol((*f)[i]); } }; void print() { int size = vectors.getSize(); for (int i = 0; i < size; i++) { vectors[i]->print(); } }; protected: /** \brief * Name of the system vector */ ::std::string name; /** \brief * Finite element space. */ ::std::vector<FiniteElemSpace*> feSpace; /** \brief * Local dof vectors. */ Vector<DOFVector<double>*> vectors; }; /** \brief * multiplication with scalar */ inline const SystemVector& operator*=(SystemVector& x, double d) { int size = x.getNumVectors(); for (int i = 0; i < size; i++) { *(x.getDOFVector(i)) *= d; } return x; }; /** \brief * scalar product */ inline double operator*(SystemVector& x, SystemVector& y) { TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors()) ("invalid size\n"); double result = 0.0; int size = x.getNumVectors(); for (int i = 0; i < size; i++) { result += (*x.getDOFVector(i)) * (*y.getDOFVector(i)); }; return result; }; /** \brief * addition of two system vectors */ inline const SystemVector& operator+=(SystemVector& x, const SystemVector& y) { TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors()) ("invalid size\n"); int size = x.getNumVectors(); for (int i = 0; i < size; i++) { (*(x.getDOFVector(i))) += (*(y.getDOFVector(i))); } return x; }; /** * subtraction of two system vectors. */ inline const SystemVector& operator-=(SystemVector& x, SystemVector& y) { TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors()) ("invalid size\n"); int size = x.getNumVectors(); for (int i = 0; i < size; i++) { (*(x.getDOFVector(i))) -= (*(y.getDOFVector(i))); } return x; }; /** \brief * multiplication with a scalar */ inline SystemVector operator*(SystemVector& x, double d) { SystemVector result = x; int size = x.getNumVectors(); for (int i = 0; i < size; i++) { (*(result.getDOFVector(i))) *= d; } return result; }; /** \brief * multiplication with a scalar */ inline SystemVector operator*(double d, SystemVector& x) { SystemVector result = x; int size = x.getNumVectors(); for (int i = 0; i < size; i++) { (*(result.getDOFVector(i))) *= d; } return result; }; /** \brief * addition of two system vectors */ inline SystemVector operator+(const SystemVector& x, const SystemVector& y) { TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors()) ("invalid size\n"); SystemVector result = x; int size = x.getNumVectors(); for (int i = 0; i < size; i++) { (*(result.getDOFVector(i))) += (*(y.getDOFVector(i))); } return result; }; /** \brief * Calls SystemVector::set(). Used for solving. */ inline void set(SystemVector& x, double value) { x.set(value); }; /** \brief * Calls SystemVector::set(). Used for solving. */ inline void setValue(SystemVector& x, double value) { x.set(value); }; /** \brief * Norm of system vector. */ inline double norm(SystemVector* x) { double result = 0.0; int size = x->getNumVectors(); for (int i = 0; i < size; i++) { result += x->getDOFVector(i)->squareNrm2(); } return sqrt(result); }; /** \brief * L2 norm of system vector. */ inline double L2Norm(SystemVector* x) { double result = 0.0; int size = x->getNumVectors(); for (int i = 0; i < size; i++) { result += x->getDOFVector(i)->L2NormSquare(); } return sqrt(result); }; /** \brief * H1 norm of system vector. */ inline double H1Norm(SystemVector* x) { double result = 0.0; int size = x->getNumVectors(); for (int i = 0; i < size; i++) { result += x->getDOFVector(i)->H1NormSquare(); } return sqrt(result); }; inline void mv(Matrix<DOFMatrix*> &matrix, const SystemVector &x, SystemVector &result, bool add = false) { int size = x.getNumVectors(); int i; TEST_EXIT_DBG(size == result.getNumVectors())("incompatible sizes\n"); TEST_EXIT_DBG(size == matrix.getNumRows())("incompatible sizes\n"); TEST_EXIT_DBG(size == matrix.getNumCols())("incompatible sizes\n"); #ifdef _OPENMP #pragma omp parallel for schedule(static, 1) num_threads(size) #endif for (i = 0; i < size; i++) { if (!add) result.getDOFVector(i)->set(0.0); for (int j = 0; j < size; j++) { if (matrix[i][j]) { mv<double>(NoTranspose, *(matrix[i][j]), *(x.getDOFVector(j)), *(result.getDOFVector(i)), true); } } } }; /** \brief * y = a*x + y; */ inline void axpy(double a, SystemVector& x, SystemVector& y) { TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors()) ("invalid size\n"); int size = x.getNumVectors(); int i; #ifdef _OPENMP #pragma omp parallel for schedule(static, 1) num_threads(size) #endif for (i = 0; i < size; i++) { axpy(a, *(x.getDOFVector(i)), *(y.getDOFVector(i))); } }; /** \brief * y = x + a*y */ inline void xpay(double a, SystemVector& x, SystemVector& y) { TEST_EXIT_DBG(x.getNumVectors() == y.getNumVectors()) ("invalid size\n"); int size = x.getNumVectors(); for (int i = 0; i < size; i++) { xpay(a, *(x.getDOFVector(i)), *(y.getDOFVector(i))); } } /** \brief * Returns SystemVector::getUsedSize(). */ inline int size(SystemVector* vec) { return vec->getUsedSize(); }; inline void print(SystemVector* vec) { vec->print(); }; } #endif // AMDIS_SYSTEMVECTOR_H