SpM Handbook 1.3.0
Loading...
Searching...
No Matches
example_lap1.c File Reference

Go to the source code of this file.

Detailed Description

Example to show how to use the SPM library with an spm matrix allocated through the library but initialized by the user.

Version
1.3.0
Author
Mathieu Faverge
Tony Delarue
Date
2024-07-09
/
#include <spm.h>
/**
* @brief Create an IJV symmetric laplacian matrix for a regular cube of
* dimensions (dim1 x dim2 x dim3) and with 1-based values as in Fortran arrays.
*/
static inline void
spm_example_fill_ijv_spm( spm_int_t *colptr,
spm_int_t *rowptr,
double *values,
spm_int_t dim1,
spm_int_t dim2,
spm_int_t dim3 )
{
spm_int_t l, i, j, k;
spm_int_t mdim1, mdim2, mdim3;
double alpha = 8.;
double beta = 0.5;
mdim1 = dim1 - 1;
mdim2 = dim2 - 1;
mdim3 = dim3 - 1;
l = 0;
for( i = 0; i < dim1; i++ )
{
for( j = 0; j < dim2; j++ )
{
for( k = 0; k < dim3; k++ )
{
/*
* Start with the diagonal element connected with its two
* neigbours in the three directions
*/
rowptr[l] = i + dim1 * j + dim1 * dim2 * k + 1;
colptr[l] = i + dim1 * j + dim1 * dim2 * k + 1;
values[l] = 6.;
/*
* Handle limit cases
*/
if ( i == 0 ) { values[l] -= 1.; }
if ( i == mdim1 ) { values[l] -= 1.; }
if ( j == 0 ) { values[l] -= 1.; }
if ( j == mdim2 ) { values[l] -= 1.; }
if ( k == 0 ) { values[l] -= 1.; }
if ( k == mdim3 ) { values[l] -= 1.; }
/* Scale by alpha */
values[l] *= alpha;
l++;
/* Add connexions */
if ( i < mdim1 ) {
rowptr[l] = (i+1) + dim1 * j + dim1 * dim2 * k + 1;
colptr[l] = i + dim1 * j + dim1 * dim2 * k + 1;
values[l] = - beta;
l++;
}
if ( j < mdim2 ) {
rowptr[l] = i + dim1 * (j+1) + dim1 * dim2 * k + 1;
colptr[l] = i + dim1 * j + dim1 * dim2 * k + 1;
values[l] = - beta;
l++;
}
if ( k < mdim3 ) {
rowptr[l] = i + dim1 * j + dim1 * dim2 * (k+1) + 1;
colptr[l] = i + dim1 * j + dim1 * dim2 * k + 1;
values[l] = - beta;
l++;
}
}
}
}
assert( l == ((2*(dim1)-1) * dim2 * dim3 + (dim2-1)*dim1*dim3 + dim2*dim1*(dim3-1)) );
}
/**
* @brief Create a laplacian manually
*/
void
spm_example_create_laplacian( spmatrix_t *spm )
{
spm_int_t dim1, dim2, dim3;
spm_int_t n, nnz;
dim1 = 10;
dim2 = 10;
dim3 = 10;
n = dim1 * dim2 * dim3;
nnz = (2*(dim1)-1) * dim2 * dim3 + (dim2-1)*dim1*dim3 + dim2*dim1*(dim3-1);
/*
* Initialize all non computed fields.
*/
spmInit( spm );
/*
* Set the fields according to what we want to generate.
* All non computed fields must be set.
*/
spm->baseval = 1;
spm->fmttype = SpmIJV;
spm->n = n;
spm->nnz = nnz;
spm->dof = 1;
/* The full matrix is replicated on all nodes */
spm->replicated = 1;
/*
* Update the computed fields.
* If dof < 0, please see example_user2.c
*/
/*
* Allocate the arrays of the spm.
*/
spmAlloc( spm );
/*
* Fill the arrays with the generator.
*/
spm_example_fill_ijv_spm( spm->colptr,
spm->rowptr,
spm->values,
dim1, dim2, dim3 );
}
int main( int argc, char **argv )
{
spm_int_t nrhs = 10;
double alpha = 2.;
spm_int_t size, ldb, ldx;
double epsilon, norm;
void *x, *b;
int rc = 0;
/*
* MPI need to be initialize before any call to spm library if it has been
* compiled wth MPI support.
*/
#if defined(SPM_WITH_MPI)
MPI_Init( &argc, &argv );
#endif
/*
* Create a user made sparse matrix.
*/
spm_example_create_laplacian( &spm );
/*
* Print basic information about the sparse matrix
*/
spmPrintInfo( &spm, stdout );
/*
* Possibly convert the SPM into another format (CSC may be needed for a few routines)
*/
spmConvert( SpmCSC, &spm );
/*
* Compute the frobenius norm of the spm
*/
norm = spmNorm( SpmFrobeniusNorm, &spm );
fprintf( stdout, " || A ||_f: %e\n", norm );
/*
* Scale the sparse matrix.
*/
if ( norm > 0. ) {
spmScal( 1. / norm, &spm );
}
/*
* Create a random matrix x to test products (multiple right hand side).
* Note that you can get the size to allocate with spm_size_of() that
* returns the size of each value.
*/
ldb = spm.nexp > 1 ? spm.nexp : 1;
ldx = spm.nexp > 1 ? spm.nexp : 1;
size = spm_size_of( spm.flttype ) * spm.n * nrhs;
x = malloc( size );
rc = spmGenMat( SpmRhsRndX, nrhs, &spm, &alpha, 24356, x, ldx );
if ( rc != SPM_SUCCESS ) {
free( x );
spmExit( &spm );
return rc;
}
/*
* Compute b = A * x
*/
b = malloc( size );
spmMatMat( SpmNoTrans, nrhs, 1., &spm, x, ldx, 0., b, ldb );
/*
* The following routines helps to check results obtained out of solvers by
* computing b = b - A * x with a given precision.
*/
if ( (spm.flttype == SpmDouble ) ||
(spm.flttype == SpmComplex64) )
{
epsilon = 1e-15;
}
else {
epsilon = 1e-7;
}
epsilon = epsilon * spm.nnzexp / spm.gN;
rc = spmCheckAxb( epsilon, nrhs, &spm, NULL, 1, b, ldb, x, ldx );
free( x );
free( b );
spmExit( &spm );
#if defined(SPM_WITH_MPI)
MPI_Finalize();
#endif
(void)argc;
(void)argv;
return rc;
}
/**
*
static size_t spm_size_of(spm_coeftype_t type)
Double datatype that is not converted through precision generator functions.
Definition datatypes.h:209
@ SPM_SUCCESS
Definition const.h:82
@ SpmNoTrans
Definition const.h:155
@ SpmComplex64
Definition const.h:66
@ SpmDouble
Definition const.h:64
@ SpmSymmetric
Definition const.h:166
@ SpmCSC
Definition const.h:73
@ SpmIJV
Definition const.h:75
@ SpmFrobeniusNorm
Definition const.h:200
spm_coeftype_t flttype
Definition spm.h:68
spm_int_t nexp
Definition spm.h:79
void * values
Definition spm.h:93
spm_int_t nnz
Definition spm.h:76
spm_int_t nnzexp
Definition spm.h:81
spm_int_t * rowptr
Definition spm.h:91
spm_fmttype_t fmttype
Definition spm.h:70
spm_int_t dof
Definition spm.h:83
spm_int_t n
Definition spm.h:74
spm_mtxtype_t mtxtype
Definition spm.h:66
spm_int_t baseval
Definition spm.h:72
spm_int_t * colptr
Definition spm.h:90
spm_int_t gN
Definition spm.h:73
int replicated
Definition spm.h:99
void spmAlloc(spmatrix_t *spm)
Allocate the arrays of an spm structure.
Definition spm.c:179
void spmExit(spmatrix_t *spm)
Cleanup the spm structure but do not free the spm pointer.
Definition spm.c:234
void spmUpdateComputedFields(spmatrix_t *spm)
Update all the computed fields based on the static values stored.
struct spmatrix_s spmatrix_t
The sparse matrix data structure.
int spmCheckAxb(double eps, spm_int_t nrhs, const spmatrix_t *spm, void *opt_X0, spm_int_t opt_ldx0, void *B, spm_int_t ldb, const void *X, spm_int_t ldx)
Check the backward error, and the forward error if x0 is provided.
Definition spm.c:1434
int spmConvert(int ofmttype, spmatrix_t *ospm)
Convert the storage format of the spm.
Definition spm.c:429
int spmMatMat(spm_trans_t trans, spm_int_t n, double alpha, const spmatrix_t *A, const void *B, spm_int_t ldb, double beta, void *C, spm_int_t ldc)
Compute a matrix-matrix product.
Definition spm.c:1338
void spmScal(double alpha, spmatrix_t *spm)
Scale the spm.
Definition spm.c:1492
double spmNorm(spm_normtype_t ntype, const spmatrix_t *spm)
Compute the norm of the spm.
Definition spm.c:525
void spmInit(spmatrix_t *spm)
Init the spm structure.
Definition spm.c:156
int spm_int_t
The main integer datatype used in spm arrays.
Definition datatypes.h:70
int spmGenMat(spm_rhstype_t type, spm_int_t nrhs, const spmatrix_t *spm, void *alpha, unsigned long long int seed, void *A, spm_int_t lda)
Generate a set of vectors associated to a given matrix.
Definition spm.c:1743
void spmPrintInfo(const spmatrix_t *spm, FILE *f)
Print basic informations about the spm matrix into a given stream.
Definition spm.c:1037

Definition in file example_lap1.c.