// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // ============================================================================ // == == // == crystal growth group == // == == // == Stiftung caesar == // == Ludwig-Erhard-Allee 2 == // == 53175 Bonn == // == germany == // == == // ============================================================================ // == == // == http://www.caesar.de/cg/AMDiS == // == == // ============================================================================ /** \file FixVec.h */ #ifndef AMDIS_FIXVEC_H #define AMDIS_FIXVEC_H #include #include "Global.h" #include "MatrixVector.h" namespace AMDiS { class Mesh; template class DimMat; template class WorldVector; template class WorldMatrix; /** determines how to initialize a FixVec when constructed */ enum InitType { NO_INIT = 0, /**< no initialisation */ VALUE_LIST = 1, /**< a complete value list is given */ DEFAULT_VALUE = 2, /**< all values ar set to a given default value */ UNIT_VECTOR = 3, /**< the i-th value is 1, all other values are 0 */ UNIT_MATRIX = 4 /**< values at the diagonal of a matrix are set to one */ }; /** \ingroup Common * \brief * A FixVec is a template vector of a fixed size. * * The size is determined at construction time and depends on the dimension * and the template parameter d. So a FixVec is a integer vector * with 3 entries in 2d and with 4 entries in 3d. The dimension and the way * the vector should be initialized are specified by the constructor call. */ template class FixVec : public Vector { public: /** \brief * constructor without initialisation. initType must be NO_INIT. If dim is * not spezified, a FixVec for DIM_OF_WORLD is created. */ FixVec(int dim = -1, InitType initType = NO_INIT) : Vector(calcSize(dim)) { TEST_EXIT_DBG(initType == NO_INIT)("wrong initType or missing initializer\n"); } /** \brief * constructor with value list initialisation. initType must be VALUE_LIST. * ini is an array which contains the initialisation values. */ FixVec(int dim, InitType initType, const T* ini) : Vector(calcSize(dim)) { TEST_EXIT_DBG(initType == VALUE_LIST)("wrong initType or wrong initializer\n"); setValues(ini); } /** \brief * constructor with default value initialisation. initType must be * DEFAULT_VALUE. All vector entries are set to ini. */ FixVec(int dim, InitType initType, const T& ini) : Vector(calcSize(dim)) { TEST_EXIT_DBG(initType == DEFAULT_VALUE)("wrong initType or wrong initializer\n"); this->set(ini); } /// Initialisation for dim. inline void init(int dim) { this->resize(calcSize(dim)); } /// Initialisation for size inline void initSize(int size) { this->resize(size); } /// Returns the \ref size_ of the FixVec. inline int size() const { return this->getSize(); } protected: /// Determines needed vector size. static int calcSize(int dim) { if (dim < 0) { return Global::getGeo(WORLD); } else { return Global::getGeo(d, dim); } } public: friend class GLWindow; }; // =========================================================================== // ===== class VectorOfFixVecs =============================================== // =========================================================================== /** \ingroup Common * \brief * Contains an vector of FixVecs of same type. To simply allocate an array of * FixVecs * isn't possible, because the FixVec constructor normally needs at least * the corresponding dimension. So you must create an array of FixVec pointers * and call the constructor of each FixVec manually. When you use * VectorOfFixVecs, this work is done by VectorOfFixVecs's constructor. */ template class VectorOfFixVecs { public: /** \brief * constructs a VectorOfFixVecs without initialisation. dim is passed to * FixVec's constructors. size_ is the number of contained FixVecs. initType * must be NO_INIT. */ VectorOfFixVecs(int d, int s, InitType initType) : size(s), dim(d) { TEST_EXIT_DBG(initType == NO_INIT)("wrong initType or wrong initializer\n"); vec.resize(size); for (int i = 0; i < size; i++) vec[i] = new FixVecType(dim, NO_INIT); } /** \brief * constructs a VectorOfFixVecs via an value list. dim is passed to * FixVec's constructors. size_ is the number of contained FixVecs. initType * must be VALUE_LIST. ini contains the initialisation values. */ VectorOfFixVecs(int d, int s, InitType initType, const FixVecType* ini) : size(s), dim(d) { TEST_EXIT_DBG(initType == VALUE_LIST)("wrong initType or wrong initializer\n"); vec.resize(size); for (int i = 0; i < size; i++) vec[i] = new FixVecType(ini[i]); } /** \brief * constructs a VectorOfFixVecs with an default value. dim is passed to * FixVec's constructors. size_ is the number of contained FixVecs. initType * must be DEFAULT_VALUE. All entries are set to ini. */ VectorOfFixVecs(int d, int s, InitType initType, const FixVecType& ini) : size(s), dim(d) { TEST_EXIT_DBG(initType == DEFAULT_VALUE)("wrong initType or wrong initializer\n"); vec.resize(size); for (int i = 0; i < size; i++) vec[i] = new FixVecType(ini); } /// Copy constructor VectorOfFixVecs(const VectorOfFixVecs& rhs) { size = rhs.getSize(); dim = rhs.getDim(); vec.resize(size); for (int i = 0; i < size; i++) vec[i] = new FixVecType(*(rhs.vec[i])); } /// Destructor virtual ~VectorOfFixVecs() { for (int i = 0; i < size; i++) delete vec[i]; vec.clear(); } /// Allows the access like in a normal array via []. Used for const objects. inline const FixVecType& operator[](int index) const { TEST_EXIT_DBG(index >= 0 && index < size)("invalid index\n"); return *(vec[index]); } /// Allows the access like in a normal array via []. inline FixVecType& operator[](int index) { TEST_EXIT_DBG(index >= 0 && index < size)("invalid index\n"); return *(vec[index]); } /// Assignment operator VectorOfFixVecs& operator=(const VectorOfFixVecs& rhs) { TEST_EXIT_DBG(size == rhs.size)("vectors of different size\n"); if (this != &rhs) { for (int i = 0; i < size; i++) *(vec[i]) = *(rhs.vec[i]); } return *this; } /// Resize the vector inline void resize(int newsize) { vec.resize(newsize); for (int i = size; i < newsize; i++) vec[i] = new FixVecType(dim, NO_INIT); size = newsize; } /// Returns the \ref size of this VectorOfFixVecs inline int getSize() const { return size; } /// Returns \ref dim inline int getDim() const { return dim; } /// Returns the size of the contained FixVecs inline int getSizeOfFixVec() const { return vec[0]->getSize(); } protected: /// number of contained FixVecs int size; /// dimension of world int dim; /// array of pointers to FixVecs std::vector vec; }; // =========================================================================== // ===== class MatrixOfFixVecs =============================================== // =========================================================================== /** \ingroup Common * \brief * Like the class VectorOfFixVecs contains a vector of FixVecs, this class * contains a matrix of FixVecs of same type. */ template class MatrixOfFixVecs { public: /** \brief * Constructs the matrix without initialisation. r is the number of rows, * c is the number of columns. The other parameters are analog to the * VectorOfFixVecs constructors. */ MatrixOfFixVecs(int dim, int r, int c, InitType initType) : rows(r), columns(c) { TEST_EXIT_DBG(initType == NO_INIT)("wrong initType or wrong initializer\n"); vec = GET_MEMORY(VectorOfFixVecs*, rows); for (VectorOfFixVecs** i = &vec[0]; i < &vec[rows]; i++) { *i = new VectorOfFixVecs(dim, columns, NO_INIT); } } /// destructor virtual ~MatrixOfFixVecs() { for (VectorOfFixVecs** i = &vec[0]; i < &vec[rows]; i++) { delete *i; } FREE_MEMORY(vec, VectorOfFixVecs*, rows); } /// assignment operator inline VectorOfFixVecs& operator[](int index) { TEST_EXIT_DBG(index >= 0 && index < rows)("invalid index\n"); return *(vec[index]); } /// assignment operator inline const VectorOfFixVecs& operator[](int index) const { TEST_EXIT_DBG(index >= 0 && index < rows)("invalid index\n"); return *(vec[index]); } /// Returns \ref rows inline int getNumberOfRows() const { return rows; } /// Returns \ref columns inline int getNumberOfColumns() const { return columns; } private: /// number of rows of the matrix int rows; /// number of columns of the matrix int columns; /// array of pointers to VectorOfFixVecs VectorOfFixVecs **vec; }; /** \ingroup Common * \brief * A DimVec is a FixVec with dim + 1 entries. It can be used for storing * barycentric coordinates or information associated to vertices or * parts of an element. */ template class DimVec : public FixVec { public: DimVec() {} /// Calls the corresponding constructor of FixVec DimVec(int dim, InitType initType = NO_INIT) : FixVec(dim, initType) {} /// Calls the corresponding constructor of FixVec DimVec(int dim, InitType initType, T* ini) : FixVec(dim, initType, ini) {} /// Calls the corresponding constructor of FixVec DimVec(int dim, InitType initType, const T& ini) : FixVec(dim, initType, ini) {} /// Multplication of a matrix with a vector. void multMatrixVec(DimMat &m, DimVec &v); }; /** \ingroup Common * \brief * A DimMat is a VectorOfFixVecs of dim+1 DimVecs. */ template class DimMat : public Matrix { public: /// Calls the corresponding constructor of VectorOfFixVecs DimMat(int dim, InitType initType = NO_INIT) : Matrix(dim + 1, dim + 1) {} /// Calls the corresponding constructor of VectorOfFixVecs DimMat(int dim, InitType initType, const T& ini) : Matrix(dim + 1, dim + 1) { TEST_EXIT_DBG(initType == DEFAULT_VALUE) ("wrong initType or wrong initializer\n"); this->set(ini); } /// Calls the corresponding constructor of VectorOfFixVecs DimMat(int dim, InitType initType, T* ini) : Matrix(dim + 1, dim + 1) { TEST_EXIT_DBG(initType == VALUE_LIST)("wrong initType or wrong initializer\n"); setValues(ini); } }; // =========================================================================== // ===== class WorldVector =================================================== // =========================================================================== /** \ingroup Common * \brief * A WorldVector is an AlgoVec with DIM_OF_WORLD entries of type double. * Can be used for storing world coordinates. */ template class WorldVector : public FixVec { public: /** \brief * Calls the corresponding constructor of AlgoVec */ WorldVector() : FixVec(Global::getGeo(WORLD), NO_INIT) {} /** \brief * Calls the corresponding constructor of AlgoVec */ WorldVector(InitType initType, T* ini) : FixVec(Global::getGeo(WORLD), initType, ini) {} /** \brief * Calls the corresponding constructor of AlgoVec */ WorldVector(InitType initType, const T& ini) : FixVec(Global::getGeo(WORLD), initType, ini) {} /** \brief * Sets all entries to d */ inline const WorldVector& operator=(const T& d) { this->set(d); return (*this); } /** \brief * Sets the arrays value to the geometric midpoint of the points * p1 and p2; */ inline void setMidpoint(const WorldVector &p1, const WorldVector &p2) { int dow = Global::getGeo(WORLD); for (int i = 0; i < dow; i++) { this->valArray[i] = 0.5 * (p1[i] + p2[i]); } } /** \brief * Multplication of a matrix with a vector. */ void multMatrixVec(WorldMatrix &m, WorldVector &v); }; // =========================================================================== // ===== class WorldMatrix =================================================== // =========================================================================== /** \ingroup Common * \brief * A WorldMatrix is a FixVec with DIM_OF_WORLD WorldVector entries. * So it can be seen as matrix with DIM_OF_WORLD x DIM_OF_WORLD double * entries. * Here it's not necessary to use the VectorOfFixVecs class, because the * FixVec constructor assumes dim = DIM_OF_WORLD, if no dim is spezified, * what is the right assumption in this case. */ template class WorldMatrix : public Matrix { public: /// Calls the corresponding constructor of FixVec WorldMatrix() : Matrix(Global::getGeo(WORLD), Global::getGeo(WORLD)) {} /// Calls the corresponding constructor of FixVec WorldMatrix(InitType initType, T* ini) : Matrix(Global::getGeo(WORLD), Global::getGeo(WORLD)) { TEST_EXIT_DBG(initType == VALUE_LIST)("???\n"); setValues(ini); } /** \brief * Calls the corresponding constructor of FixVec and sets all matrix entries * to ini */ WorldMatrix(InitType initType, const T& ini) : Matrix(Global::getGeo(WORLD), Global::getGeo(WORLD)) { TEST_EXIT_DBG(initType == DEFAULT_VALUE)("wrong initType or wrong initializer\n"); this->set(ini); } /// Returns true if the matrix is a diagonal matrix, returns false otherwise. bool isDiagMatrix() const; /// Returns true if the matrix is symmetric, returns false otherwise. bool isSymmetric() const; /// Sets the diagonal entries to the given value. void setDiag(T value); /** \brief * Creates a matrix from the "multiplication" of two vectors. * * 2d-Example: * * /a\ /c\ /ac ad\ * | | * | | = | | * \b/ \d/ \bc bd/ */ void vecProduct(const WorldVector& v1, const WorldVector& v2); }; // =========================================================================== // ===== global functions ==================================================== // =========================================================================== /// returns the euclidian distance of a and b template double absteukl(const FixVec& a,const FixVec& b); /// FixVec operator for stream output template std::ostream& operator <<(std::ostream& out, const FixVec& fixvec) { for (int i = 0; i < fixvec.getSize()-1; i++) { out << fixvec[i] << " "; } out << fixvec[fixvec.getSize()-1]; return out; } /// creates and inits a VectorOfFixVecs > VectorOfFixVecs > *createAndInit(int dim, int size, ...); /// creates and inits and double array double *createAndInitArray(int size, ...); inline WorldVector operator*(const WorldVector& v, double d) { WorldVector result = v; result *= d; return result; } inline WorldVector operator+(const WorldVector& v1, const WorldVector& v2) { WorldVector result = v1; result += v2; return result; } inline WorldVector operator+(const WorldVector& v1, const WorldVector& v2) { WorldVector result = v1; result += v2; return result; } inline WorldVector operator-(const WorldVector& v1, const WorldVector& v2) { WorldVector result = v1; result -= v2; return result; } inline bool operator<(const WorldVector& v1, const WorldVector& v2) { int dow = Global::getGeo(WORLD); for (int i = 0; i < dow; i++) { if (abs(v1[i] - v2[i]) < DBL_TOL) continue; return v1[i] < v2[i]; } return false; } inline bool operator==(const WorldVector& v1, const WorldVector& v2) { int dow = Global::getGeo(WORLD); for (int i = 0; i < dow; i++) { if (abs(v1[i] - v2[i]) > DBL_TOL) return false; } return true; } template const WorldMatrix& operator*=(WorldMatrix& m, T scal); template const WorldMatrix& operator-=(WorldMatrix& m1, const WorldMatrix& m2); template const WorldMatrix& operator+=(WorldMatrix& m1, const WorldMatrix& m2); } #include "FixVec.hh" #endif // AMDIS_FIXVEC_H