// ============================================================================ // == == // == 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 SystemVector.h */ #ifndef AMDIS_SYSTEMVECTOR_H #define AMDIS_SYSTEMVECTOR_H #include "MatrixVector.h" #include "DOFVector.h" #include "CreatorInterface.h" #include "Serializable.h" namespace AMDiS { /// A system vector is a vector of dof vectors used for vector valued problems. class SystemVector : public Serializable { public: /// Constructor. SystemVector(std::string name_, std::vector feSpace_, int size) : name(name_), feSpace(feSpace_), vectors(size) {} /// Copy Constructor. SystemVector(const SystemVector& rhs) : name(rhs.getName()), feSpace(rhs.getFeSpaces()), vectors(rhs.getNumVectors()) { for (unsigned int i = 0; i < vectors.size(); i++) vectors[i] = new DOFVector(*rhs.getDOFVector(i)); } ~SystemVector() { for (unsigned int i = 0; i < vectors.size(); i++) delete vectors[i]; } /// Sets \ref vectors[index] = vec. inline void setDOFVector(int index, DOFVector *vec) { TEST_EXIT_DBG(index < static_cast(vectors.size())) ("Invalid index %d!\n", index); vectors[index] = vec; } /// Returns \ref vectors[index]. inline DOFVector *getDOFVector(int index) { TEST_EXIT_DBG(index < static_cast(vectors.size())) ("Invalid index %d!\n", index); return vectors[index]; } /// Returns \ref vectors[index]. inline const DOFVector *getDOFVector(int index) const { TEST_EXIT_DBG(index < static_cast(vectors.size())) ("Invalid index %d!\n", index); return vectors[index]; } inline std::string getName() const { return name; } /// Returns sum of used vector sizes. inline int getUsedSize() const { int totalSize = 0; for (unsigned int i = 0; i < vectors.size(); i++) totalSize += vectors[i]->getUsedSize(); return totalSize; } /// Returns number of contained vectors. inline int getNumVectors() const { return static_cast(vectors.size()); } inline int getSize() const { return static_cast(vectors.size()); } /// Returns the fe space for a given component. inline const FiniteElemSpace *getFeSpace(int i) const { return feSpace[i]; } /// Returns the fe spaces for all components. inline std::vector getFeSpaces() const { return feSpace; } /// 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]; } /// 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]; } /// Sets all entries in all vectors to value. inline void set(double value) { for (unsigned int i = 0; i < vectors.size(); i++) vectors[i]->set(value); } inline void setCoarsenOperation(CoarsenOperation op) { for (int i = 0; i < static_cast(vectors.size()); i++) vectors[i]->setCoarsenOperation(op); } /// Sets all entries in all vectors to value. inline SystemVector& operator=(double value) { for (int i = 0; i < static_cast(vectors.size()); i++) (*(vectors[i])) = value; return *this; } /// Assignement operator. inline SystemVector& operator=(const SystemVector& rhs) { TEST_EXIT_DBG(rhs.vectors.size() == vectors.size())("Invalied sizes!\n"); for (int i = 0; i < static_cast(vectors.size()); i++) (*(vectors[i])) = (*(rhs.getDOFVector(i))); return *this; } void serialize(std::ostream &out); void deserialize(std::istream &in); void copy(const SystemVector& rhs) { int size = static_cast(vectors.size()); TEST_EXIT_DBG(size == rhs.getNumVectors())("Invalid sizes!\n"); for (int i = 0; i < size; i++) vectors[i]->copy(*(const_cast(rhs).getDOFVector(i))); } void interpol(std::vector >*> *f) { for (unsigned int i = 0; i < vectors.size(); i++) vectors[i]->interpol((*f)[i]); } void interpol(SystemVector *v, double factor) { for (int i = 0; i < v->getSize(); i++) vectors[i]->interpol(v->getDOFVector(i), factor); } void print() { for (unsigned int i = 0; i < vectors.size(); i++) vectors[i]->print(); } int calcMemoryUsage() { int result = 0; for (unsigned int i = 0; i < vectors.size(); i++) result += vectors[i]->calcMemoryUsage(); result += sizeof(SystemVector); return result; } protected: /// Name of the system vector std::string name; /// Finite element space. std::vector feSpace; /// Local dof vectors. std::vector*> vectors; }; /// 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; } /// 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; } /// 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; } /// 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; } /// 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; } /// 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; } /// Calls SystemVector::set(). Used for solving. inline void set(SystemVector& x, double value) { x.set(value); } /// Calls SystemVector::set(). Used for solving. inline void setValue(SystemVector& x, double value) { x.set(value); } /// 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); } /// 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); } /// 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 &matrix, const SystemVector &x, SystemVector &result, bool add = false) { FUNCNAME("mv()"); 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"); 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(NoTranspose, *(matrix[i][j]), *(x.getDOFVector(j)), *(result.getDOFVector(i)), true); } } /// 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; for (i = 0; i < size; i++) axpy(a, *(x.getDOFVector(i)), *(y.getDOFVector(i))); } /// 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))); } /// Returns SystemVector::getUsedSize(). inline int size(SystemVector* vec) { return vec->getUsedSize(); } inline void print(SystemVector* vec) { vec->print(); } } #endif // AMDIS_SYSTEMVECTOR_H