PaStiX Handbook  6.3.2
schur.c File Reference

Schur usage example. More...

Go to the source code of this file.

Detailed Description

Schur usage example.

Version
6.3.2
Author
Pierre Ramet
Mathieu Faverge
Matias Hastaran
Tony Delarue
Alycia Lisito
Date
2023-07-21
/
#include <pastix.h>
#include <spm.h>
#include <lapacke.h>
void
schurFactorize( pastix_coeftype_t flttype,
pastix_factotype_t factotype,
void *S,
int **ipiv )
{
int info = 0;
assert( ipiv != NULL );
if ( factotype == PastixFactGETRF ) {
*ipiv = malloc( N * sizeof(int) );
}
switch (flttype) {
case PastixFloat:
switch (factotype) {
info = LAPACKE_spotrf_work( LAPACK_COL_MAJOR, 'L', N, S, lds );
break;
info = LAPACKE_sgetrf_work( LAPACK_COL_MAJOR, N, N, S, lds, *ipiv );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
break;
case PastixComplex32:
switch (factotype) {
info = LAPACKE_cpotrf_work( LAPACK_COL_MAJOR, 'L', N, S, lds );
break;
info = LAPACKE_cgetrf_work( LAPACK_COL_MAJOR, N, N, S, lds, *ipiv );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
break;
case PastixComplex64:
switch (factotype) {
info = LAPACKE_zpotrf_work( LAPACK_COL_MAJOR, 'L', N, S, lds );
break;
info = LAPACKE_zgetrf_work( LAPACK_COL_MAJOR, N, N, S, lds, *ipiv );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
break;
case PastixDouble:
switch (factotype) {
info = LAPACKE_dpotrf_work( LAPACK_COL_MAJOR, 'L', N, S, lds );
break;
info = LAPACKE_dgetrf_work( LAPACK_COL_MAJOR, N, N, S, lds, *ipiv );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
break;
default:
fprintf(stderr, "Incorrect arithmetic type\n");
}
if (info != 0) {
fprintf(stderr, "Error in schurFactorize with info =%d\n", info );
}
return;
}
void
schurSolve( pastix_coeftype_t flttype,
pastix_factotype_t factotype,
pastix_int_t Nschur,
void *S,
void *bptr,
int **ipiv )
{
int info = 0;
assert(ipiv != NULL);
switch (flttype) {
case PastixFloat:
{
float *b = (float *)bptr;
switch (factotype) {
info = LAPACKE_spotrs_work( LAPACK_COL_MAJOR, 'L', Nschur, NRHS, S, lds, b, ldb );
break;
info = LAPACKE_sgetrs_work( LAPACK_COL_MAJOR, 'N', Nschur, NRHS, S, lds, *ipiv, b, ldb );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
}
break;
case PastixComplex32:
{
switch (factotype) {
info = LAPACKE_cpotrs_work( LAPACK_COL_MAJOR, 'L', Nschur, NRHS, S, lds, b, ldb );
break;
info = LAPACKE_cgetrs_work( LAPACK_COL_MAJOR, 'N', Nschur, NRHS, S, lds, *ipiv, b, ldb );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
}
break;
case PastixComplex64:
{
pastix_complex64_t *b = (pastix_complex64_t *)bptr;
switch (factotype) {
info = LAPACKE_zpotrs_work( LAPACK_COL_MAJOR, 'L', Nschur, NRHS, S, lds, b, ldb );
break;
info = LAPACKE_zgetrs_work( LAPACK_COL_MAJOR, 'N', Nschur, NRHS, S, lds, *ipiv, b, ldb );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
}
break;
case PastixDouble:
{
double *b = (double *)bptr;
switch (factotype) {
info = LAPACKE_dpotrs_work( LAPACK_COL_MAJOR, 'L', Nschur, NRHS, S, lds, b, ldb );
break;
info = LAPACKE_dgetrs_work( LAPACK_COL_MAJOR, 'N', Nschur, NRHS, S, lds, *ipiv, b, ldb );
break;
default:
fprintf(stderr, "Factorization type not handled by Schur example\n");
}
}
break;
default:
fprintf(stderr, "Incorrect arithmetic type\n");
}
if (*ipiv != NULL) {
free( *ipiv );
*ipiv = NULL;
}
if (info != 0) {
fprintf(stderr, "Error in schurSolve with info =%d\n", info );
}
return;
}
int main (int argc, char **argv)
{
pastix_data_t *pastix_data = NULL; /*< Pointer to the storage structure required by pastix */
pastix_int_t iparm[IPARM_SIZE]; /*< Integer in/out parameters for pastix */
double dparm[DPARM_SIZE]; /*< Floating in/out parameters for pastix */
spm_driver_t driver;
char *filename = NULL;
spmatrix_t *spm, spm2;
void *x, *b, *S, *x0 = NULL;
size_t size;
int scatter = 0;
int check = 1;
int nrhs = 1;
int rc = 0;
pastix_int_t nschur, lds, ldb;
int *ipiv = NULL;
/**
* Initialize parameters to default values
*/
pastixInitParam( iparm, dparm );
/**
* Get options from command line
*/
pastixGetOptions( argc, argv,
iparm, dparm,
&check, &scatter, &driver, &filename );
if ( (iparm[IPARM_FACTORIZATION] == PastixFactLDLT) ||
{
fprintf(stderr, "This types of factorization (LDL^t and LDL^h) are not supported by this example.\n");
return EXIT_FAILURE;
}
/**
* Startup PaStiX
*/
pastixInit( &pastix_data, MPI_COMM_WORLD, iparm, dparm );
/**
* Read the sparse matrix with the driver
*/
spm = malloc( sizeof( spmatrix_t ) );
if ( scatter ) {
rc = spmReadDriverDist( driver, filename, spm, MPI_COMM_WORLD );
}
else {
rc = spmReadDriver( driver, filename, spm );
}
free( filename );
if ( rc != SPM_SUCCESS ) {
pastixFinalize( &pastix_data );
return rc;
}
spmPrintInfo( spm, stdout );
rc = spmCheckAndCorrect( spm, &spm2 );
if ( rc != 0 ) {
spmExit( spm );
*spm = spm2;
}
/**
* Generate a Fake values array if needed for the numerical part
*/
if ( spm->flttype == SpmPattern ) {
spmGenFakeValues( spm );
}
/**
* Initialize the schur list with the first third of the unknowns
*/
{
nschur = spm->gN / 3;
/* Set to a maximum to avoid memory problem with the test */
nschur = (nschur > 5000) ? 5000 : nschur;
if ( nschur > 0 ) {
pastix_int_t baseval = spmFindBase(spm);
pastix_int_t *list = (pastix_int_t*)malloc(nschur * sizeof(pastix_int_t));
for (i=0; i<nschur; i++) {
list[i] = i+baseval;
}
pastixSetSchurUnknownList( pastix_data, nschur, list );
free( list );
}
iparm[IPARM_SCHUR_SOLV_MODE] = PastixSolvModeInterface;
}
/**
* Perform ordering, symbolic factorization, and analyze steps
*/
pastix_task_analyze( pastix_data, spm );
/**
* Normalize A matrix (optional, but recommended for low-rank functionality)
*/
double normA = spmNorm( SpmFrobeniusNorm, spm );
spmScal( 1./normA, spm );
/**
* Perform the numerical factorization
*/
pastix_task_numfact( pastix_data, spm );
/**
* Get the Schur complement back
*/
lds = nschur;
S = malloc( pastix_size_of( spm->flttype ) * nschur * lds );
rc = pastixGetSchur( pastix_data, S, lds );
if( rc == -1 ){
spmExit( spm );
free( spm );
free( S );
pastixFinalize( &pastix_data );
exit(0);
}
/**
* Factorize the Schur complement
*/
schurFactorize( spm->flttype, iparm[IPARM_FACTORIZATION],
nschur, S, lds, &ipiv );
/**
* Generates the b and x vector such that A * x = b
* Compute the norms of the initial vectors if checking purpose.
*/
size = pastix_size_of( spm->flttype ) * spm->nexp * nrhs;
x = malloc( size );
b = malloc( size );
ldb = spm->nexp;
if ( check )
{
if ( check > 1 ) {
x0 = malloc( size );
}
spmGenRHS( SpmRhsRndX, nrhs, spm, x0, spm->nexp, b, spm->nexp );
memcpy( x, b, size );
}
else {
spmGenRHS( SpmRhsRndB, nrhs, spm, NULL, spm->nexp, x, spm->nexp );
/* Apply also normalization to b vectors */
spmScalMat( 1./normA, spm, nrhs, b, spm->nexp );
}
/**
* Solve the linear system Ax = (P^tLUP)x = b
*/
/* 1- Apply P to b */
pastixRhsInit( &Xp );
spm->nexp, nrhs, x, ldb, Xp );
/* 2- Forward solve on the non Schur complement part of the system */
diag = PastixNonUnit;
}
else if( iparm[IPARM_FACTORIZATION] == PastixFactGETRF ) {
diag = PastixUnit;
}
/* 3- Solve the Schur complement part */
{
void *schur_x;
size = pastix_size_of( spm->flttype ) * nschur * nrhs;
schur_x = malloc( size );
pastixRhsSchurGet( pastix_data, nschur, nrhs, Xp, schur_x, nschur );
schurSolve( spm->flttype, iparm[IPARM_FACTORIZATION],
nschur, nrhs, S, lds, schur_x, nschur, &ipiv );
pastixRhsSchurSet( pastix_data, nschur, nrhs, schur_x, nschur, Xp );
free( schur_x );
}
/* 4- Backward solve on the non Schur complement part of the system */
pastix_subtask_trsm( pastix_data,
Xp );
}
else if( iparm[IPARM_FACTORIZATION] == PastixFactGETRF ) {
pastix_subtask_trsm( pastix_data,
Xp );
}
/* 5- Apply P^t to x */
spm->nexp, nrhs, x, ldb, Xp );
if ( check )
{
rc = spmCheckAxb( dparm[DPARM_EPSILON_REFINEMENT], nrhs, spm, x0, spm->nexp, b, spm->nexp, x, spm->nexp );
if ( x0 ) {
free( x0 );
}
}
spmExit( spm );
free( spm );
free( S );
free( x );
free( b );
pastixFinalize( &pastix_data );
return rc;
}
/**
*
BEGIN_C_DECLS typedef int pastix_int_t
Definition: datatypes.h:51
float _Complex pastix_complex32_t
Definition: datatypes.h:76
int pastixRhsInit(pastix_rhs_t *rhs)
Initialize an RHS data structure.
Definition: pastix_rhs.c:41
int pastixRhsFinalize(pastix_rhs_t rhs)
Cleanup an RHS data structure.
Definition: pastix_rhs.c:86
spm_coeftype_t pastix_coeftype_t
Arithmetic types.
Definition: api.h:294
void pastixFinalize(pastix_data_t **pastix_data)
Finalize the solver instance.
Definition: api.c:919
enum pastix_diag_e pastix_diag_t
Diagonal.
void pastixInitParam(pastix_int_t *iparm, double *dparm)
Initialize the iparm and dparm arrays to their default values.
Definition: api.c:411
void pastixInit(pastix_data_t **pastix_data, PASTIX_Comm pastix_comm, pastix_int_t *iparm, double *dparm)
Initialize the solver instance.
Definition: api.c:896
enum pastix_factotype_e pastix_factotype_t
Factorization algorithms available for IPARM_FACTORIZATION parameter.
@ PastixDirForward
Definition: api.h:513
@ PastixDirBackward
Definition: api.h:514
@ PastixFactLDLH
Definition: api.h:319
@ PastixFactLDLT
Definition: api.h:316
@ PastixFactPOTRF
Definition: api.h:310
@ PastixFactGETRF
Definition: api.h:312
@ DPARM_EPSILON_REFINEMENT
Definition: api.h:161
@ IPARM_FACTORIZATION
Definition: api.h:99
@ IPARM_SCHUR_SOLV_MODE
Definition: api.h:107
@ PastixUpper
Definition: api.h:466
@ PastixLower
Definition: api.h:467
@ PastixLeft
Definition: api.h:495
@ PastixUnit
Definition: api.h:488
@ PastixNonUnit
Definition: api.h:487
@ PastixConjTrans
Definition: api.h:447
@ PastixNoTrans
Definition: api.h:445
void pastixGetOptions(int argc, char **argv, pastix_int_t *iparm, double *dparm, int *check, int *scatter, spm_driver_t *driver, char **filename)
PaStiX helper function to read command line options in examples.
Definition: get_options.c:149
void pastixSetSchurUnknownList(pastix_data_t *pastix_data, pastix_int_t n, const pastix_int_t *list)
Set the list of unknowns that belongs to the schur complement.
Definition: schur.c:50
int pastixGetSchur(const pastix_data_t *pastix_data, void *S, pastix_int_t lds)
Return the Schur complement.
Definition: schur.c:90
int pastixRhsSchurSet(const pastix_data_t *pastix_data, pastix_int_t m, pastix_int_t n, void *B, pastix_int_t ldb, pastix_rhs_t rhsB)
Set the vector in an RHS data structure.
Definition: schur.c:284
int pastix_subtask_applyorder(pastix_data_t *pastix_data, pastix_dir_t dir, pastix_int_t m, pastix_int_t n, void *B, pastix_int_t ldb, pastix_rhs_t Bp)
Apply a permutation on the right-and-side vector before the solve step.
int pastix_subtask_trsm(pastix_data_t *pastix_data, pastix_side_t side, pastix_uplo_t uplo, pastix_trans_t trans, pastix_diag_t diag, pastix_rhs_t b)
Apply a triangular solve on the right-and-side vectors.
int pastixRhsSchurGet(const pastix_data_t *pastix_data, pastix_int_t m, pastix_int_t n, pastix_rhs_t rhsB, void *B, pastix_int_t ldb)
Get the vector in an RHS data structure.
Definition: schur.c:182
int pastix_task_analyze(pastix_data_t *pastix_data, const spmatrix_t *spm)
Perform all the preprocessing steps: ordering, symbolic factorization, reordering,...
int pastix_task_numfact(pastix_data_t *pastix_data, spmatrix_t *spm)
Perform all the numerical factorization steps: fill the internal block CSC and the solver matrix stru...
Main PaStiX data structure.
Definition: pastixdata.h:67
Main PaStiX RHS structure.
Definition: pastixdata.h:150

Definition in file schur.c.