545 lines
17 KiB
C++
545 lines
17 KiB
C++
#ifndef GETMATRIX_FILE
|
|
#define GETMATRIX_FILE
|
|
|
|
#include "geom.h"
|
|
#include <cassert>
|
|
#include <vector>
|
|
// #####################################################################
|
|
/**
|
|
* 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<double> &d) const = 0;
|
|
|
|
/**
|
|
* Extracts the diagonal elements of the matrix.
|
|
*
|
|
* @return d vector of diagonal elements
|
|
*/
|
|
std::vector<double> const &GetDiag() const
|
|
{
|
|
if ( 0 == _dd.size() ) // GH: better? Nrows()>static_cast<int>(_dd.size())
|
|
{
|
|
_dd.resize(Nrows());
|
|
this->GetDiag(_dd);
|
|
}
|
|
assert( Nrows() == static_cast<int>(_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<double> &w, std::vector<double> 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<double> &w,
|
|
std::vector<double> const &f, std::vector<double> 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<double> _dd; //!< diagonal matrix elements
|
|
};
|
|
|
|
// #####################################################################
|
|
class BisectInterpolation; // class forward declaration
|
|
/**
|
|
* Matrix in CRS format (compressed row storage; also named CSR),
|
|
* see an <a href="https://en.wikipedia.org/wiki/Sparse_matrix">introduction</a>.
|
|
*/
|
|
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<double> &d) const override;
|
|
///**
|
|
//* Extracts the diagonal elements of the sparse matrix.
|
|
//*
|
|
//* @return d vector of diagonal elements
|
|
//*/
|
|
//std::vector<double> 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<double> &w, std::vector<double> 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<double> &w,
|
|
std::vector<double> const &f, std::vector<double> 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<double> &fc, std::vector<double> &ff, std::vector<double> &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<int> _id; //!< start indices of matrix rows
|
|
std::vector<int> _ik; //!< column indices
|
|
std::vector<double> _sk; //!< non-zero values
|
|
};
|
|
|
|
|
|
/**
|
|
* FEM Matrix in CRS format (compressed row storage; also named CSR),
|
|
* see an <a href="https://en.wikipedia.org/wiki/Sparse_matrix">introduction</a>.
|
|
*/
|
|
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<double> &f);
|
|
|
|
/**
|
|
* Applies Dirichlet boundary conditions to stiffness matrix and to load vector @p f.
|
|
* The <a href="https://www.jstor.org/stable/2005611?seq=1#metadata_info_tab_contents">penalty method</a>
|
|
* 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<double> const &u, std::vector<double> &f);
|
|
|
|
///**
|
|
//* Extracts the diagonal elements of the sparse matrix.
|
|
//*
|
|
//* @param[in,out] d (prellocated) vector of diagonal elements
|
|
//*/
|
|
//void GetDiag(std::vector<double> &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<double> &f);
|
|
|
|
|
|
private:
|
|
Mesh const &_mesh; //!< reference to discretization
|
|
|
|
};
|
|
|
|
|
|
///**
|
|
//* Prolongation matrix in CRS format (compressed row storage; also named CSR),
|
|
//* see an <a href="https://en.wikipedia.org/wiki/Sparse_matrix">introduction</a>.
|
|
//*
|
|
//* 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<int> 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<double> &d) const override;
|
|
///**
|
|
//* Extracts the diagonal elements of the sparse matrix.
|
|
//*
|
|
//* @return d vector of diagonal elements
|
|
//*/
|
|
//std::vector<double> 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<double> &wf, std::vector<double> 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<double> const &wf, std::vector<double> &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<double> &w,
|
|
std::vector<double> const &f, std::vector<double> 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<double> &fc, std::vector<double> &ff, std::vector<double> &uf);
|
|
|
|
protected:
|
|
std::vector<int> _iv; //!< fathers[nnode][2] of fine grid nodes, double entries denote injection points
|
|
std::vector<double> _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<int> const &fathers, std::vector<int> 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
|