GemaCoreLib
The GeMA Core library
Public Types | Public Member Functions | List of all members
GmSolverMatrix Class Referenceabstract

Base interface class for Solver Matrix objects. More...

#include <gmSolverMatrix.h>

Inheritance diagram for GmSolverMatrix:
Inheritance graph
[legend]

Public Types

enum  ParallelAddMode { NO_SUPPORT, THREAD_SAFE_SUPPORT, REENTRANT_SUPPORT }
 Supported modes for calling add from multiple threads in parallel. More...
 

Public Member Functions

virtual ~GmSolverMatrix ()
 Virtual destructor.
 
virtual bool supportsBatchInsert () const =0
 Does this matrix supports batch inserts? See comments on the class documentation.
 
virtual bool supportsSparseLayouts () const =0
 Does this matrix supports sparse layouts? See comments on the class documentation.
 
virtual bool supportsRandomSet () const =0
 Does this matrix supports setting a value on a random position outside the matrix initialization process (either by a batch insert or a layout builder)?
 
virtual ParallelAddMode supportedParallelAddMode () const =0
 Returns the supported mode for calling add.
 
virtual bool beginBatchInsert (size_t expectedEntries=0)=0
 Begins a batch insert process. Important: see comments on the class documentation. More...
 
virtual bool endBatchInsert (bool discardData=false)=0
 Ends a batch insert process. Important: see comments on the class documentation. More...
 
virtual GmSparseMatrixLayoutBuilderlayoutBuilder () const =0
 If the matrix supports sparse layouts, returns a builder object that can be used to initialize the matrix layout. Otherwise returns NULL. If the layout is being shared by several matrices, only the main matrix, owning the layout should return it.
 
virtual bool emptyLayout () const =0
 If the matrix supports sparse layouts and the layout is currently empty, returns true. Otherwise, returns false.
 
virtual bool symmetric () const =0
 Returns true if the matrix was marked as symmetric by setSymmetric() (it does not check for matrix symmetry itself) More...
 
virtual void setSymmetric (bool sym)=0
 Marks the matrix as symmetric or not. More...
 
virtual int nlin () const =0
 Returns the number of lines in the matrix. IMPORTANT: This function implementation MUST be thread safe.
 
virtual int ncol () const =0
 Returns the number of columns in the matrix. IMPORTANT: This function implementation MUST be thread safe.
 
virtual int layoutSize () const =0
 Returns the size of the sparse matrix layout. More...
 
virtual double at (int lin, int col) const =0
 Returns the value in the position Mat[lin][col].
 
double operator() (int lin, int col) const
 Returns the value in the position Mat[lin][col]. More...
 
virtual bool inLayout (int lin, int col) const =0
 Returns true if the given position belongs to the matrix sparse layout. More...
 
virtual void set (int lin, int col, double value)=0
 Sets the value in the position Mat[lin][col] to the specified value. More...
 
virtual void add (int lin, int col, double value)=0
 Adds the given value to the value in the position Mat[lin][col]. More...
 
virtual void set (GmSolverMatrix *A, GmSolverMatrix *B, double c, bool sameStructure)=0
 Sets the values of the whole matrix to the result of the expresion A + c * B, where A and B are matrices with the same size as this one and c is a constant. More...
 
virtual void clear (bool keepSparseLayout)=0
 Clears the matrix, filling it with zeros. The keepSparseLayout flag is a hint that the matrix layout (non zero positions) will remain the same when the matrix is re-filled with data, and so, if the matrix supports sparse layouts, they should not be removed. This function marks the matrix as unsymmetric.
 
virtual void clearLineAndColumnSet (const QList< int > &indexList, bool setDiagonal, bool keepSparseLayout)=0
 Clears a set of lines and columns from the matrix, filling them with zeroes, optionally puting a 1.0 at the diagonal. More...
 
virtual void ensureDiagonal ()=0
 Updates any zero diagonal value to 1.0. If diagonal values do not belong to the layout, the matrix must NOT be shared!
 
virtual void matAdd (const GmVector &a, const GmVector &b, double zeroTol=0.0)=0
 Adds to the current matrix ('X') the (dense) matrix resulting from multiplying the column vector 'a' by the transpose of the column vector 'b' (X = X + a * b.t()). More...
 
virtual void mul (const GmVector &a, GmVector &b) const =0
 Multiplies the matrix ('X') by a vector 'a' storing the result in 'b' (b = X * a). More...
 
virtual void mulAdd (const GmVector &a, GmVector &b) const =0
 Multiplies the matrix ('X') by a vector 'a' adding the result to 'b' (b = b + X * a). More...
 
virtual void mulSub (const GmVector &a, GmVector &b) const =0
 Multiplies the matrix ('X') by a vector 'a' subtracting the result from 'b' (b = b - X * a). More...
 
virtual void columnMulAdd (int col, GmVector &f, double v, const bool *skipRows=NULL) const =0
 Updates the given vector adding to it a matrix column multiplied by a scalar value. More...
 
virtual size_t usedMemory () const =0
 Returns an estimative of the memory used by the matrix in bytes. More...
 
bool isSymmetric (double relTol=GM_DOUBLECMP_RELTOL, double absTol=GM_DOUBLECMP_ABSTOL) const
 Returns true if the matrix is symmetric, false otherwise. More...
 
void print (const GmLogCategory &logger, GmLogLevel level, int fieldWidth=0, char format='g', int precision=-1)
 Prints the matrix using the specified logger, level and precision fields.
 

Detailed Description

Base interface class for Solver Matrix objects.

Solver matrices are set appart from standard matrices used for day to day operations done by element calculation routines since they are bigger and generally very sparse.

Derived implementations are allowed to use the storage strategy that they seem fit.

This strategy allows, for example, a numerical solver to use the specific sparse matrix implementation that better suits its needs.

Matrices are of static size, defined when the matrix is created. When created a matrix starts initialized with zeros and marked as NOT symmetric.

As a general rule, several sparse matrix formats can not support efficiently an iterative process for creating the matrix with "set" operations, so the matrix layout (the set of non-zero positions) must be created first and later operations can only change values attached to those layout positions (including setting those values to zero without realy removing that zero from the matrix layout).

The solver matrix interface supports two different interfaces for preparing the matrix: batch inserting and layout initialization. Each solver matrix should define its supported strategy. This concepts are orthogonal, so the matrix should support one or the other.

If batch insertion is supported, the matrix is built by calling beginBatchInsert(), followed by calls to add(i, j, value) and a final call to endBatchInsert(). No other functions that change or query matrix values can be called in between. Also, this functions should be called only over clean matrices (recently constructed or after a call to clear()). This mode of operation allows the matrix implementation to store values in a temporary format, such as a triplet list, and fill the real matrix only when endBatchInsert() is called.

The second strategy is to initialize the matrix with its final layout in a first step and later fill values on positions in the layout. Sparse layouts store the fill structure (the set of non zero positions) for a sparse matrix. The matrix data itself is not stored, so the layout can be shared among matrices. When working with sparse layouts, the layout should be filled before matrix data change operations through the use of a layoutBuilder.

The implementation can also support creating an internal layout that is initialized in batch mode. If the layout doesn't changes (clear() is called with a flag to keep the layout), the implementation can reuse the layout in further calls to begin and end batch insert for that matrix. Even though, layout sharing between multiple matrices when operating in batch mode is in general not possible since it would require that the master matrix begins and ends its batch block before the other matrices sharing them (and this is not the current way used by the FEM assembler, for example).

Setting a value on a random position after the matrix has been initialized, which implies in a possible change on the matrix layout (a zero element turns into a non-zero value) through a call to set(i, j, value) is possible only if supportsRandomSet() returns true. This restriction does not apply to operations affecting the whole matrix.

Building the matrix in parallel should respect the advertised locking requirements from supportedParallelAddMode(). Assuming that filling the matrix will be done by calls to add(), it can state that add() can be freely called by the matrix building code from multiple threads (it does the necessary locking internally) or that the caller should manage its own locks to ensure that parallel calls are not referencing the same matrix entry at the same time.

IMPORTANT: If the matrix was marked as symmetric by calling setSymmetric(true), it is the user responsability to ensure that the matrix remains symmetric after matrix operations like add(i, j, v) or set(i, j, v). This can be checked by calling isSymmetric().

IMPORTANT2: add(), symmetric(), nlin(), ncol() and setSymmetric() are the ONLY functions from the solver matrix that can always be called from a worker thread. All other functions should be called from the main thread only.

Member Enumeration Documentation

◆ ParallelAddMode

Supported modes for calling add from multiple threads in parallel.

Assumes that add is being called in parallel inside a beginBatchInsert() / endBatchInsert() block or while filling the matrix with a pre-built layout. Assumes that only call to add() will be done from multiple threads.

Member Function Documentation

◆ add()

virtual void GmSolverMatrix::add ( int  lin,
int  col,
double  value 
)
pure virtual

Adds the given value to the value in the position Mat[lin][col].

In general this function can be used only to change values over positions that belong to the matrix sparse layout (its set of non zero positions) or inside a beginBatchInsert() / endBatchInsert() region. It can only be used to set values on random positions if supportsRandomSet() returns true.

See the class description for comments about calling this function from multiple threads in parallel.

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ beginBatchInsert()

virtual bool GmSolverMatrix::beginBatchInsert ( size_t  expectedEntries = 0)
pure virtual

Begins a batch insert process. Important: see comments on the class documentation.

The expectedEntries parameters is an estimative of the number of times that add() will be called for this beginBatchInsert() / endBatchInsert() block.

Uses a 64 bits value for the size since this list can grow quite quickly and a 32 bits limit can be achieved. An hex27 element with 5 dofs per node generates a 135 x 135 local matrix, translating into 135 * 135 = 18.225 calls to append() per mesh element. That will overflow a standard int with less than 120.000 elements.

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ clearLineAndColumnSet()

virtual void GmSolverMatrix::clearLineAndColumnSet ( const QList< int > &  indexList,
bool  setDiagonal,
bool  keepSparseLayout 
)
pure virtual

Clears a set of lines and columns from the matrix, filling them with zeroes, optionally puting a 1.0 at the diagonal.

This function is semantically equivalent to the code below, but potentially quicker for sparse matrices. It should be used only for square matrices.

foreach(int i, indexList)
{
clearLine(i);
clearColumn(i)
if(setDiagonal)
set(i, i, 1.0);
}

If keepSparseLayout is set to true, matrix values will be changed without updating the internal matrix sparse layout. This can be important for performance if the matrix is later reused to host another set of values with the same layout as the one before removing the set of lines and columns.

IMPORTANT: When enabling both keepSparseLayout and setDiagonal, it is NECESSARY that the diagonal items of the selected rows belong to the current sparse layout. In most cases this is true anyway. Failing to do so will result in undefined behaviour.

If keepSpraseLayout is set to false, the matrix layout can NOT be shared with other matrices since this operation would change the layout.

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ columnMulAdd()

virtual void GmSolverMatrix::columnMulAdd ( int  col,
GmVector f,
double  v,
const bool *  skipRows = NULL 
) const
pure virtual

Updates the given vector adding to it a matrix column multiplied by a scalar value.

Given the matrix column 'col', for each row 'i' in the matrix makes f[i] += Mat[i][col] * v. If the boolean vector skipRows is not NULL, the above operation will be executed only if skipRows[i] is not true.

This function is semantically equivalent to the code below, but potentially quicker for sparse matrices.

foreach row i in the matrix
{
if(skipRows && skipRows[i])
continue;
f[i] += Mat(i, col) * v;
}

Implemented in GmArmadilloSparseSolverMatrix, GmArmadilloSolverMatrixBase< T >, GmArmadilloSolverMatrixBase< arma::sp_mat >, and GmSparseMatrix< IndexType, T >.

◆ endBatchInsert()

virtual bool GmSolverMatrix::endBatchInsert ( bool  discardData = false)
pure virtual

Ends a batch insert process. Important: see comments on the class documentation.

The discardData parameter is a flag that when set to true informs that the matrix building process was interrupted and so the current matrix data is invalid and should be discarded.

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ inLayout()

virtual bool GmSolverMatrix::inLayout ( int  lin,
int  col 
) const
pure virtual

Returns true if the given position belongs to the matrix sparse layout.

This is different from testing if the value is zero since it is possible for a zero value to belong to the layout in antecipation of a future set opertaion. If the matrix does not support the layout concept, it should just test that the value is non zero.

Implemented in GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ isSymmetric()

bool GmSolverMatrix::isSymmetric ( double  relTol = GM_DOUBLECMP_RELTOL,
double  absTol = GM_DOUBLECMP_ABSTOL 
) const

Returns true if the matrix is symmetric, false otherwise.

IMPORTANT: This function does NOT uses the flag setted by setSymmetric(). It traverses the whole matrix checking its symmetry using GmDoubleCmp::equal() with the given tolerance values for the comparisson. If you want to just check the flag, use symmetric() instead.

◆ layoutSize()

virtual int GmSolverMatrix::layoutSize ( ) const
pure virtual

Returns the size of the sparse matrix layout.

The returned size is aproximatelly equal to the number of nonzero entries in the matrix. It will be different if the layout includes places for zero values that might change in the future. If the matriz does not have that information, returns -1.

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ matAdd()

virtual void GmSolverMatrix::matAdd ( const GmVector a,
const GmVector b,
double  zeroTol = 0.0 
)
pure virtual

Adds to the current matrix ('X') the (dense) matrix resulting from multiplying the column vector 'a' by the transpose of the column vector 'b' (X = X + a * b.t()).

In order to keep some kind of sparsisity of the matrix, if the resulting values is smaller than the given tolerance, it will not be stored (set to zero).

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ mul()

virtual void GmSolverMatrix::mul ( const GmVector a,
GmVector b 
) const
pure virtual

Multiplies the matrix ('X') by a vector 'a' storing the result in 'b' (b = X * a).

If X is a matrix with size equal to M x N, a should have size N and b will have size M.

Implemented in GmArmadilloSolverMatrixBase< T >, GmArmadilloSolverMatrixBase< arma::sp_mat >, and GmSparseMatrix< IndexType, T >.

◆ mulAdd()

virtual void GmSolverMatrix::mulAdd ( const GmVector a,
GmVector b 
) const
pure virtual

Multiplies the matrix ('X') by a vector 'a' adding the result to 'b' (b = b + X * a).

If X is a matrix with size equal to M x N, a should have size N and b will have size M.

Implemented in GmArmadilloSolverMatrixBase< T >, GmArmadilloSolverMatrixBase< arma::sp_mat >, and GmSparseMatrix< IndexType, T >.

◆ mulSub()

virtual void GmSolverMatrix::mulSub ( const GmVector a,
GmVector b 
) const
pure virtual

Multiplies the matrix ('X') by a vector 'a' subtracting the result from 'b' (b = b - X * a).

If X is a matrix with size equal to M x N, a should have size N and b will have size M.

Implemented in GmArmadilloSolverMatrixBase< T >, GmArmadilloSolverMatrixBase< arma::sp_mat >, and GmSparseMatrix< IndexType, T >.

◆ operator()()

double GmSolverMatrix::operator() ( int  lin,
int  col 
) const
inline

Returns the value in the position Mat[lin][col].

This function presents the same functionality as the at() method in a 'prettier' way, allowing the user to write x = mat(i,j) instead of x = mat.at(i,j).

The complementary function double& operator(), which could allow us to write mat(i,j) = x instead of mat->set(i,j,x), cannot be defined for sparse matrices since by definition there is no writable position that could be returned in the case of accessing a zero value (a proxy could be returned but that can't be converted to a double&)

◆ set() [1/2]

virtual void GmSolverMatrix::set ( int  lin,
int  col,
double  value 
)
pure virtual

Sets the value in the position Mat[lin][col] to the specified value.

In general this function can be used only to set values over positions that belong to the matrix sparse layout (its set of non zero positions). It can only be used to set values on random positions if supportsRandomSet() returns true. (For performance reasons, no exception is made, even when setting a value of 0.0 over an already 0.0 value since that would probably add an if to the critical path).

This function can not be called at all while inside a beginBatchInsert() / endBatchInsert() region.

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ set() [2/2]

virtual void GmSolverMatrix::set ( GmSolverMatrix A,
GmSolverMatrix B,
double  c,
bool  sameStructure 
)
pure virtual

Sets the values of the whole matrix to the result of the expresion A + c * B, where A and B are matrices with the same size as this one and c is a constant.

Conceptually this operation is equivalent to calling set(i, j, A(i, j) + c * B(i, j)) for every line & column of the matrices, but when working with sparse matrices doing it in a batch can be much faster.

If sameStructure is set to true, this functions assumes that A, B and the current matrix object have all the SAME layout (same non-zero structure). When set to false, the matrix layout can not be shared with other matrices since it would change the layout.

Keep in mind that matrix A or matrix B CAN be equal to the current matrix (this).

If the current matrix is marked as symmetric and either A or B is not marked as symmetric, the current matrix will be marked as unsymmetric.

Implemented in GmArmadilloSparseSolverMatrix, GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ setSymmetric()

virtual void GmSolverMatrix::setSymmetric ( bool  sym)
pure virtual

Marks the matrix as symmetric or not.

Marking a symmetric matrix as such might help the numeric solver. When constructed, the matrix is marked as NOT symmetric

Bear in mind that this method DOES NOT CHECK weather the matrix is really symmetric or not. You can do that by calling isSymmetric().

It is also a user responsability to call setSymmetric() again if a matrix operation turns the matrix as unsymmetric.

IMPORTANT: This function implementation MUST be thread safe

Implemented in GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ symmetric()

virtual bool GmSolverMatrix::symmetric ( ) const
pure virtual

Returns true if the matrix was marked as symmetric by setSymmetric() (it does not check for matrix symmetry itself)

IMPORTANT: This function implementation MUST be thread safe

Implemented in GmSparseMatrix< IndexType, T >, GmArmadilloSolverMatrixBase< T >, and GmArmadilloSolverMatrixBase< arma::sp_mat >.

◆ usedMemory()

virtual size_t GmSolverMatrix::usedMemory ( ) const
pure virtual

Returns an estimative of the memory used by the matrix in bytes.

It returns in general the variable memory that depends on the number of set entries but does not include constant overheads used by the class for control

In particular, this method might return different values before and after a call to endBatchInsert(). If the matrix shares a layout with another matrix, only the layout owner will account for its size.

Implemented in GmArmadilloSparseSolverMatrix, GmArmadilloSolverMatrixBase< T >, GmArmadilloSolverMatrixBase< arma::sp_mat >, and GmSparseMatrix< IndexType, T >.


The documentation for this class was generated from the following files: