#ifndef GETMATRIX_FILE #define GETMATRIX_FILE #include "geom.h" #include #include // ##################################################################### /** * Abstract matrix class. */ class Matrix { public: /** * Constructor for abstract matrix class. * * No memory is allocated. * * @param[in] nrows number of matrix rows. * @param[in] ncols number of matrix columns. */ Matrix(int nrows, int ncols); //Matrix(); Matrix(Matrix const &) = default; /** * Destructor. * * No memory is allocated. */ virtual ~Matrix(); /** * Checks whether the matrix is a square matrix. * * @return True iff square matrix. */ bool isSquare() const { return _nrows == _ncols; } /** * Number of rows in matrix. * @return number of rows. */ int Nrows() const { return _nrows; } /** * Number of columns in matrix. * @return number of columns. */ int Ncols() const { return _ncols; } /** * Show the matrix entries. */ virtual void Debug() const = 0; /** * Extracts the diagonal elements of an inherited matrix. * * @param[in,out] d (prellocated) vector of diagonal elements */ virtual void GetDiag(std::vector &d) const = 0; /** * Extracts the diagonal elements of the matrix. * * @return d vector of diagonal elements */ std::vector const &GetDiag() const { if ( 0 == _dd.size() ) // GH: better? Nrows()>static_cast(_dd.size()) { _dd.resize(Nrows()); this->GetDiag(_dd); } assert( Nrows() == static_cast(_dd.size()) ); return _dd; } /** * Performs the matrix-vector product w := K*u. * * @param[in,out] w resulting vector (preallocated) * @param[in] u vector */ virtual void Mult(std::vector &w, std::vector const &u) const = 0; /** * Calculates the defect/residuum w := f - K*u. * * @param[in,out] w resulting vector (preallocated) * @param[in] f load vector * @param[in] u vector */ virtual void Defect( std::vector &w, std::vector const &f, std::vector const &u) const = 0; /** * Finds in a CRS matrix the access index for an entry at row @p row and column @p col. * * @param[in] row row index * @param[in] col column index * @return index for element (@p row, @p col). If no appropriate entry exists then -1 will be returned. * * @warning assert() stops the function in case that matrix element (@p row, @p col) doesn't exist. */ virtual int fetch(int row, int col) const = 0; protected: int _nrows; //!< number of rows in matrix int _ncols; //!< number of columns in matrix mutable std::vector _dd; //!< diagonal matrix elements }; // ##################################################################### class BisectInterpolation; // class forward declaration /** * Matrix in CRS format (compressed row storage; also named CSR), * see an introduction. */ class CRS_Matrix: public Matrix { public: /** * Constructor * */ CRS_Matrix(); CRS_Matrix(CRS_Matrix const &) = default; /** * Destructor. */ virtual ~CRS_Matrix() override; /** * Extracts the diagonal elements of the sparse matrix. * * @param[in,out] d (prellocated) vector of diagonal elements */ void GetDiag(std::vector &d) const override; ///** //* Extracts the diagonal elements of the sparse matrix. //* //* @return d vector of diagonal elements //*/ //std::vector const & GetDiag() const override; /** * Performs the matrix-vector product w := K*u. * * @param[in,out] w resulting vector (preallocated) * @param[in] u vector */ void Mult(std::vector &w, std::vector const &u) const override; /** * Calculates the defect/residuum w := f - K*u. * * @param[in,out] w resulting vector (preallocated) * @param[in] f load vector * @param[in] u vector */ void Defect(std::vector &w, std::vector const &f, std::vector const &u) const override; /** * Show the matrix entries. */ void Debug() const override; /** * Finds in a CRS matrix the access index for an entry at row @p row and column @p col. * * @param[in] row row index * @param[in] col column index * @return index for element (@p row, @p col). If no appropriate entry exists then -1 will be returned. * * @warning assert() stops the function in case that matrix element (@p row, @p col) doesn't exist. */ int fetch(int row, int col) const override; /** * Compare @p this CRS matrix with an external CRS matrix stored in C-Style. * * The method prints statements on differences found. * * @param[in] nnode row number of external matrix * @param[in] id start indices of matrix rows of external matrix * @param[in] ik column indices of external matrix * @param[in] sk non-zero values of external matrix * * @return true iff all data are identical. */ bool Compare2Old(int nnode, int const id[], int const ik[], double const sk[]) const; /** * Calculates the defect and projects it to the next coarser level @f$ f_C := P^T \cdot (f_F - SK\cdot u_F) @f$. * * @param[in] SK matrix on fine mesh * @param[in] P prolongation operator * @param[in,out] fc resulting coarse mesh vector (preallocated) * @param[in] ff r.h.s. on fine mesh * @param[in] uf status vector on fine mesh * */ friend void DefectRestrict(CRS_Matrix const &SK, BisectInterpolation const &P, std::vector &fc, std::vector &ff, std::vector &uf); protected: //int _nrows; //!< number of rows in matrix //int _ncols; //!< number of columns in matrix int _nnz; //!< number of non-zero entries std::vector _id; //!< start indices of matrix rows std::vector _ik; //!< column indices std::vector _sk; //!< non-zero values }; /** * FEM Matrix in CRS format (compressed row storage; also named CSR), * see an introduction. */ class FEM_Matrix: public CRS_Matrix { public: /** * Initializes the CRS matrix structure from the given discretization in @p mesh. * * The sparse matrix pattern is generated but the values are 0. * * @param[in] mesh given discretization * * @warning A reference to the discretization @p mesh is stored inside this class. * Therefore, changing @p mesh outside requires also * to call method @p Derive_Matrix_Pattern explicitly. * * @see Derive_Matrix_Pattern */ explicit FEM_Matrix(Mesh const &mesh); FEM_Matrix(FEM_Matrix const &) = default; /** * Destructor. */ ~FEM_Matrix() override; /** * Generates the sparse matrix pattern and overwrites the existing pattern. * * The sparse matrix pattern is generated but the values are 0. */ void Derive_Matrix_Pattern() { //Derive_Matrix_Pattern_slow(); Derive_Matrix_Pattern_fast(); } void Derive_Matrix_Pattern_fast(); void Derive_Matrix_Pattern_slow(); /** * Calculates the entries of f.e. stiffness matrix and load/rhs vector @p f for the Laplace operator in 2D. * No memory is allocated. * * @param[in,out] f (preallocated) rhs/load vector */ void CalculateLaplace(std::vector &f); /** * Applies Dirichlet boundary conditions to stiffness matrix and to load vector @p f. * The penalty method * is used for incorporating the given values @p u. * * @param[in] u (global) vector with Dirichlet data * @param[in,out] f load vector */ void ApplyDirichletBC(std::vector const &u, std::vector &f); ///** //* Extracts the diagonal elements of the sparse matrix. //* //* @param[in,out] d (prellocated) vector of diagonal elements //*/ //void GetDiag(std::vector &d) const; // override in MPI parallel /** * Adds the element stiffness matrix @p ske and the element load vector @p fe * of one triangular element with linear shape functions to the appropriate positions in * the stiffness matrix, stored as CSR matrix K(@p sk,@p id, @p ik). * * @param[in] ial node indices of the three element vertices * @param[in] ske element stiffness matrix * @param[in] fe element load vector * @param[in,out] f distributed local vector storing the right hand side * * @warning Algorithm assumes linear triangular elements (ndof_e==3). */ void AddElem_3(int const ial[3], double const ske[3][3], double const fe[3], std::vector &f); private: Mesh const &_mesh; //!< reference to discretization }; ///** //* Prolongation matrix in CRS format (compressed row storage; also named CSR), //* see an introduction. //* //* The prolongation is applied for each node from the coarse mesh to the fine mesh and //* is derived only geometrically (no operator weighted prolongation). //*/ //class Prolongation: public CRS_Matrix //{ //public: ///** //* Intializes the CRS matrix structure from the given discetization in @p mesh. //* //* The sparse matrix pattern is generated but the values are 0. //* //* @param[in] cmesh coarse mesh //* @param[in] fmesh fine mesh //* //* @warning A reference to the discretizations @p fmesh @p cmesh are stored inside this class. //* Therefore, changing these meshes outside requires also //* to call method @p Derive_Matrix_Pattern explicitely. //* //* @see Derive_Matrix_Pattern //*/ //Prolongation(Mesh const & cmesh, Mesh const & fmesh); ///** //* Destructor. //*/ //~Prolongation() override //{} ///** //* Generates the sparse matrix pattern and overwrites the existing pattern. //* //* The sparse matrix pattern is generated but the values are 0. //*/ //void Derive_Matrix_Pattern() override; //private: //Mesh const & _cmesh; //!< reference to coarse discretization //Mesh const & _fmesh; //!< reference to fine discretization //}; // ********************************************************************* /** * Interpolation matrix for prolongation coarse mesh (C) to a fine mesh (F) * generated by bisecting edges. * * All interpolation weights are 0.5 (injection points contribute twice). */ class BisectInterpolation: public Matrix { public: /** * Generates the interpolation matrix for prolongation coarse mesh to a fine mesh * generated by bisecting edges. * The interpolation weights are all 0.5. * * @param[in] fathers vector[nnodes][2] containing * the two coarse grid fathers of a fine grid vertex * */ explicit BisectInterpolation(std::vector const &fathers); BisectInterpolation(); BisectInterpolation(BisectInterpolation const &) = default; /** * Destructor. */ ~BisectInterpolation() override; /** * Extracts the diagonal elements of the matrix. * * @param[in,out] d (prellocated) vector of diagonal elements */ void GetDiag(std::vector &d) const override; ///** //* Extracts the diagonal elements of the sparse matrix. //* //* @return d vector of diagonal elements //*/ //std::vector const & GetDiag() const override; /** * Performs the prolongation @f$ w_F := P*u_C @f$. * * @param[in,out] wf resulting fine vector (preallocated) * @param[in] uc coarse vector */ void Mult(std::vector &wf, std::vector const &uc) const override; /** * Performs the restriction @f$ u_C := P^T*w_F @f$. * * @param[in] wf fine vector * @param[in,out] uc resulting coarse vector (preallocated) */ void MultT(std::vector const &wf, std::vector &uc) const; /** * Calculates the defect/residuum w := f - P*u. * * @param[in,out] w resulting vector (preallocated) * @param[in] f load vector * @param[in] u coarse vector */ void Defect(std::vector &w, std::vector const &f, std::vector const &u) const override; /** * Show the matrix entries. */ void Debug() const override; /** * Finds in this matrix the access index for an entry at row @p row and column @p col. * * @param[in] row row index * @param[in] col column index * @return index for element (@p row, @p col). If no appropriate entry exists then -1 will be returned. * * @warning assert() stops the function in case that matrix element (@p row, @p col) doesn't exist. */ int fetch(int row, int col) const override; /** * Calculates the defect and projects it to the next coarser level @f$ f_C := P^T \cdot (f_F - SK\cdot u_F) @f$. * * @param[in] SK matrix on fine mesh * @param[in] P prolongation operator * @param[in,out] fc resulting coarse mesh vector (preallocated) * @param[in] ff r.h.s. on fine mesh * @param[in] uf status vector on fine mesh * */ friend void DefectRestrict(CRS_Matrix const &SK, BisectInterpolation const &P, std::vector &fc, std::vector &ff, std::vector &uf); protected: std::vector _iv; //!< fathers[nnode][2] of fine grid nodes, double entries denote injection points std::vector _vv; //!< weights[nnode][2] of fathers for grid nodes }; /** * Interpolation matrix for prolongation from coarse mesh (C)) to a fine mesh (F) * generated by bisecting edges. * * We take into account that values at Dirichlet nodes have to be preserved, i.e., * @f$ w_F = P \cdot I_D \cdot w_C @f$ and @f$ d_C = I_D \cdot P^T \cdot d_F@f$ * with @f$ I_D @f$ as @f$ n_C \times n_C @f$ diagonal matrix and entries * @f$ I_{D(j,j)} := \left\{{\begin{array}{l@{\qquad}l} 0 & x_{j}\;\; \textrm{is Dirichlet node} \\ 1 & \textrm{else} \end{array}}\right. @f$ * * Interpolation weights are eighter 0.5 or 0.0 in case of coarse Dirichlet nodes * (injection points contribute twice), * Sets weight to zero iff (at least) one father nodes is a Dirichlet node. */ class BisectIntDirichlet: public BisectInterpolation { public: /** * Default constructor. */ BisectIntDirichlet() : BisectInterpolation() {} /** * Constructs interpolation from father-@p row and column @p col. * * @param[in] fathers two father nodes from each fine node [nnode_f*2]. * @param[in] idxc_dir vector containing the indices of coarse mesh Dirichlet nodes. * */ BisectIntDirichlet(std::vector const &fathers, std::vector const &idxc_dir); BisectIntDirichlet(BisectIntDirichlet const &) = default; /** * Destructor. */ ~BisectIntDirichlet() override; }; // ********************************************************************* /** * Calculates the element stiffness matrix @p ske and the element load vector @p fe * of one triangular element with linear shape functions. * @param[in] ial node indices of the three element vertices * @param[in] xc vector of node coordinates with x(2*k,2*k+1) as coordinates of node k * @param[out] ske element stiffness matrix * @param[out] fe element load vector */ void CalcElem(int const ial[3], double const xc[], double ske[3][3], double fe[3]); /** * Adds the element stiffness matrix @p ske and the element load vector @p fe * of one triangular element with linear shape functions to the appropriate positions in * the symmetric stiffness matrix, stored as CSR matrix K(@p sk,@p id, @p ik) * * @param[in] ial node indices of the three element vertices * @param[in] ske element stiffness matrix * @param[in] fe element load vector * @param[out] sk vector non-zero entries of CSR matrix * @param[in] id index vector containing the first entry in a CSR row * @param[in] ik column index vector of CSR matrix * @param[out] f distributed local vector storing the right hand side * * @warning Algorithm requires indices in connectivity @p ial in ascending order. * Currently deprecated. */ void AddElem(int const ial[3], double const ske[3][3], double const fe[3], int const id[], int const ik[], double sk[], double f[]); #endif