xref: /petsc/src/ksp/pc/impls/spai/ispai.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
101a81e61SBarry Smith 
201a81e61SBarry Smith /*
301a81e61SBarry Smith    3/99 Modified by Stephen Barnard to support SPAI version 3.0
401a81e61SBarry Smith */
501a81e61SBarry Smith 
601a81e61SBarry Smith /*
701a81e61SBarry Smith       Provides an interface to the SPAI Sparse Approximate Inverse Preconditioner
801a81e61SBarry Smith    Code written by Stephen Barnard.
901a81e61SBarry Smith 
1001a81e61SBarry Smith       Note: there is some BAD memory bleeding below!
1101a81e61SBarry Smith 
1201a81e61SBarry Smith       This code needs work
1301a81e61SBarry Smith 
1401a81e61SBarry Smith    1) get rid of all memory bleeding
1501a81e61SBarry Smith    2) fix PETSc/interface so that it gets if the matrix is symmetric from the matrix
1601a81e61SBarry Smith       rather than having the sp flag for PC_SPAI
172a4967abSBarry Smith    3) fix to set the block size based on the matrix block size
1801a81e61SBarry Smith 
1901a81e61SBarry Smith */
20762360ffSBarry Smith #define PETSC_SKIP_COMPLEX /* since spai uses I which conflicts with some complex implementations */
2101a81e61SBarry Smith 
22af0996ceSBarry Smith #include <petsc/private/pcimpl.h>        /*I "petscpc.h" I*/
231c7d2463SJed Brown #include <../src/ksp/pc/impls/spai/petscspai.h>
2401a81e61SBarry Smith 
2501a81e61SBarry Smith /*
2601a81e61SBarry Smith     These are the SPAI include files
2701a81e61SBarry Smith */
2801a81e61SBarry Smith EXTERN_C_BEGIN
29b1bda85cSSatish Balay #define SPAI_USE_MPI /* required for setting SPAI_Comm correctly in basics.h */
30c6db04a5SJed Brown #include <spai.h>
31c6db04a5SJed Brown #include <matrix.h>
3201a81e61SBarry Smith EXTERN_C_END
3301a81e61SBarry Smith 
3409573ac7SBarry Smith extern PetscErrorCode ConvertMatToMatrix(MPI_Comm,Mat,Mat,matrix**);
3509573ac7SBarry Smith extern PetscErrorCode ConvertMatrixToMat(MPI_Comm,matrix*,Mat*);
3609573ac7SBarry Smith extern PetscErrorCode ConvertVectorToVec(MPI_Comm,vector *v,Vec *Pv);
3709573ac7SBarry Smith extern PetscErrorCode MM_to_PETSC(char*,char*,char*);
3801a81e61SBarry Smith 
3901a81e61SBarry Smith typedef struct {
4001a81e61SBarry Smith 
4101a81e61SBarry Smith   matrix *B;                /* matrix in SPAI format */
4201a81e61SBarry Smith   matrix *BT;               /* transpose of matrix in SPAI format */
4301a81e61SBarry Smith   matrix *M;                /* the approximate inverse in SPAI format */
4401a81e61SBarry Smith 
4501a81e61SBarry Smith   Mat PM;                   /* the approximate inverse PETSc format */
4601a81e61SBarry Smith 
4701a81e61SBarry Smith   double epsilon;           /* tolerance */
4801a81e61SBarry Smith   int    nbsteps;           /* max number of "improvement" steps per line */
4901a81e61SBarry Smith   int    max;               /* max dimensions of is_I, q, etc. */
5001a81e61SBarry Smith   int    maxnew;            /* max number of new entries per step */
5101a81e61SBarry Smith   int    block_size;        /* constant block size */
5201a81e61SBarry Smith   int    cache_size;        /* one of (1,2,3,4,5,6) indicting size of cache */
5301a81e61SBarry Smith   int    verbose;           /* SPAI prints timing and statistics */
5401a81e61SBarry Smith 
5501a81e61SBarry Smith   int      sp;              /* symmetric nonzero pattern */
5601a81e61SBarry Smith   MPI_Comm comm_spai;     /* communicator to be used with spai */
5701a81e61SBarry Smith } PC_SPAI;
5801a81e61SBarry Smith 
5901a81e61SBarry Smith /**********************************************************************/
6001a81e61SBarry Smith 
6101a81e61SBarry Smith static PetscErrorCode PCSetUp_SPAI(PC pc)
6201a81e61SBarry Smith {
6301a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
6401a81e61SBarry Smith   Mat      AT;
6501a81e61SBarry Smith 
6601a81e61SBarry Smith   PetscFunctionBegin;
6701a81e61SBarry Smith   init_SPAI();
6801a81e61SBarry Smith 
6901a81e61SBarry Smith   if (ispai->sp) {
70*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ConvertMatToMatrix(ispai->comm_spai,pc->pmat,pc->pmat,&ispai->B));
7101a81e61SBarry Smith   } else {
7201a81e61SBarry Smith     /* Use the transpose to get the column nonzero structure. */
73*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatTranspose(pc->pmat,MAT_INITIAL_MATRIX,&AT));
74*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ConvertMatToMatrix(ispai->comm_spai,pc->pmat,AT,&ispai->B));
75*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&AT));
7601a81e61SBarry Smith   }
7701a81e61SBarry Smith 
7801a81e61SBarry Smith   /* Destroy the transpose */
7901a81e61SBarry Smith   /* Don't know how to do it. PETSc developers? */
8001a81e61SBarry Smith 
8101a81e61SBarry Smith   /* construct SPAI preconditioner */
8201a81e61SBarry Smith   /* FILE *messages */     /* file for warning messages */
8301a81e61SBarry Smith   /* double epsilon */     /* tolerance */
8401a81e61SBarry Smith   /* int nbsteps */        /* max number of "improvement" steps per line */
8501a81e61SBarry Smith   /* int max */            /* max dimensions of is_I, q, etc. */
8601a81e61SBarry Smith   /* int maxnew */         /* max number of new entries per step */
8701a81e61SBarry Smith   /* int block_size */     /* block_size == 1 specifies scalar elments
8801a81e61SBarry Smith                               block_size == n specifies nxn constant-block elements
8901a81e61SBarry Smith                               block_size == 0 specifies variable-block elements */
902fa5cd67SKarl Rupp   /* int cache_size */     /* one of (1,2,3,4,5,6) indicting size of cache. cache_size == 0 indicates no caching */
9101a81e61SBarry Smith   /* int    verbose    */  /* verbose == 0 specifies that SPAI is silent
9201a81e61SBarry Smith                               verbose == 1 prints timing and matrix statistics */
9301a81e61SBarry Smith 
94*5f80ce2aSJacob Faibussowitsch   CHKERRQ(bspai(ispai->B,&ispai->M,
9501a81e61SBarry Smith                 stdout,
9601a81e61SBarry Smith                 ispai->epsilon,
9701a81e61SBarry Smith                 ispai->nbsteps,
9801a81e61SBarry Smith                 ispai->max,
9901a81e61SBarry Smith                 ispai->maxnew,
10001a81e61SBarry Smith                 ispai->block_size,
10101a81e61SBarry Smith                 ispai->cache_size,
102*5f80ce2aSJacob Faibussowitsch                 ispai->verbose));
10301a81e61SBarry Smith 
104*5f80ce2aSJacob Faibussowitsch   CHKERRQ(ConvertMatrixToMat(PetscObjectComm((PetscObject)pc),ispai->M,&ispai->PM));
10501a81e61SBarry Smith 
10601a81e61SBarry Smith   /* free the SPAI matrices */
10701a81e61SBarry Smith   sp_free_matrix(ispai->B);
10801a81e61SBarry Smith   sp_free_matrix(ispai->M);
10901a81e61SBarry Smith   PetscFunctionReturn(0);
11001a81e61SBarry Smith }
11101a81e61SBarry Smith 
11201a81e61SBarry Smith /**********************************************************************/
11301a81e61SBarry Smith 
11401a81e61SBarry Smith static PetscErrorCode PCApply_SPAI(PC pc,Vec xx,Vec y)
11501a81e61SBarry Smith {
11601a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
11701a81e61SBarry Smith 
11801a81e61SBarry Smith   PetscFunctionBegin;
11901a81e61SBarry Smith   /* Now using PETSc's multiply */
120*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMult(ispai->PM,xx,y));
12101a81e61SBarry Smith   PetscFunctionReturn(0);
12201a81e61SBarry Smith }
12301a81e61SBarry Smith 
12448e38a8aSPierre Jolivet static PetscErrorCode PCMatApply_SPAI(PC pc,Mat X,Mat Y)
12548e38a8aSPierre Jolivet {
12648e38a8aSPierre Jolivet   PC_SPAI *ispai = (PC_SPAI*)pc->data;
12748e38a8aSPierre Jolivet 
12848e38a8aSPierre Jolivet   PetscFunctionBegin;
12948e38a8aSPierre Jolivet   /* Now using PETSc's multiply */
130*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMatMult(ispai->PM,X,MAT_REUSE_MATRIX,PETSC_DEFAULT,&Y));
13148e38a8aSPierre Jolivet   PetscFunctionReturn(0);
13248e38a8aSPierre Jolivet }
13348e38a8aSPierre Jolivet 
13401a81e61SBarry Smith /**********************************************************************/
13501a81e61SBarry Smith 
13601a81e61SBarry Smith static PetscErrorCode PCDestroy_SPAI(PC pc)
13701a81e61SBarry Smith {
13801a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
13901a81e61SBarry Smith 
14001a81e61SBarry Smith   PetscFunctionBegin;
141*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&ispai->PM));
142*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_free(&(ispai->comm_spai)));
143*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(pc->data));
14401a81e61SBarry Smith   PetscFunctionReturn(0);
14501a81e61SBarry Smith }
14601a81e61SBarry Smith 
14701a81e61SBarry Smith /**********************************************************************/
14801a81e61SBarry Smith 
14901a81e61SBarry Smith static PetscErrorCode PCView_SPAI(PC pc,PetscViewer viewer)
15001a81e61SBarry Smith {
15101a81e61SBarry Smith   PC_SPAI   *ispai = (PC_SPAI*)pc->data;
152ace3abfcSBarry Smith   PetscBool  iascii;
15301a81e61SBarry Smith 
15401a81e61SBarry Smith   PetscFunctionBegin;
155*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
15601a81e61SBarry Smith   if (iascii) {
157*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    epsilon %g\n",   (double)ispai->epsilon));
158*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    nbsteps %d\n",   ispai->nbsteps));
159*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    max %d\n",       ispai->max));
160*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    maxnew %d\n",    ispai->maxnew));
161*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    block_size %d\n",ispai->block_size));
162*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    cache_size %d\n",ispai->cache_size));
163*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    verbose %d\n",   ispai->verbose));
164*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"    sp %d\n",        ispai->sp));
16501a81e61SBarry Smith   }
16601a81e61SBarry Smith   PetscFunctionReturn(0);
16701a81e61SBarry Smith }
16801a81e61SBarry Smith 
169f7a08781SBarry Smith static PetscErrorCode  PCSPAISetEpsilon_SPAI(PC pc,double epsilon1)
17001a81e61SBarry Smith {
17101a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
1725fd66863SKarl Rupp 
17301a81e61SBarry Smith   PetscFunctionBegin;
17401a81e61SBarry Smith   ispai->epsilon = epsilon1;
17501a81e61SBarry Smith   PetscFunctionReturn(0);
17601a81e61SBarry Smith }
17701a81e61SBarry Smith 
17801a81e61SBarry Smith /**********************************************************************/
17901a81e61SBarry Smith 
180f7a08781SBarry Smith static PetscErrorCode  PCSPAISetNBSteps_SPAI(PC pc,int nbsteps1)
18101a81e61SBarry Smith {
18201a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
1835fd66863SKarl Rupp 
18401a81e61SBarry Smith   PetscFunctionBegin;
18501a81e61SBarry Smith   ispai->nbsteps = nbsteps1;
18601a81e61SBarry Smith   PetscFunctionReturn(0);
18701a81e61SBarry Smith }
18801a81e61SBarry Smith 
18901a81e61SBarry Smith /**********************************************************************/
19001a81e61SBarry Smith 
19101a81e61SBarry Smith /* added 1/7/99 g.h. */
192f7a08781SBarry Smith static PetscErrorCode  PCSPAISetMax_SPAI(PC pc,int max1)
19301a81e61SBarry Smith {
19401a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
1955fd66863SKarl Rupp 
19601a81e61SBarry Smith   PetscFunctionBegin;
19701a81e61SBarry Smith   ispai->max = max1;
19801a81e61SBarry Smith   PetscFunctionReturn(0);
19901a81e61SBarry Smith }
20001a81e61SBarry Smith 
20101a81e61SBarry Smith /**********************************************************************/
20201a81e61SBarry Smith 
203f7a08781SBarry Smith static PetscErrorCode  PCSPAISetMaxNew_SPAI(PC pc,int maxnew1)
20401a81e61SBarry Smith {
20501a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
2065fd66863SKarl Rupp 
20701a81e61SBarry Smith   PetscFunctionBegin;
20801a81e61SBarry Smith   ispai->maxnew = maxnew1;
20901a81e61SBarry Smith   PetscFunctionReturn(0);
21001a81e61SBarry Smith }
21101a81e61SBarry Smith 
21201a81e61SBarry Smith /**********************************************************************/
21301a81e61SBarry Smith 
214f7a08781SBarry Smith static PetscErrorCode  PCSPAISetBlockSize_SPAI(PC pc,int block_size1)
21501a81e61SBarry Smith {
21601a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
2175fd66863SKarl Rupp 
21801a81e61SBarry Smith   PetscFunctionBegin;
21901a81e61SBarry Smith   ispai->block_size = block_size1;
22001a81e61SBarry Smith   PetscFunctionReturn(0);
22101a81e61SBarry Smith }
22201a81e61SBarry Smith 
22301a81e61SBarry Smith /**********************************************************************/
22401a81e61SBarry Smith 
225f7a08781SBarry Smith static PetscErrorCode  PCSPAISetCacheSize_SPAI(PC pc,int cache_size)
22601a81e61SBarry Smith {
22701a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
2285fd66863SKarl Rupp 
22901a81e61SBarry Smith   PetscFunctionBegin;
23001a81e61SBarry Smith   ispai->cache_size = cache_size;
23101a81e61SBarry Smith   PetscFunctionReturn(0);
23201a81e61SBarry Smith }
23301a81e61SBarry Smith 
23401a81e61SBarry Smith /**********************************************************************/
23501a81e61SBarry Smith 
236f7a08781SBarry Smith static PetscErrorCode  PCSPAISetVerbose_SPAI(PC pc,int verbose)
23701a81e61SBarry Smith {
23801a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
2395fd66863SKarl Rupp 
24001a81e61SBarry Smith   PetscFunctionBegin;
24101a81e61SBarry Smith   ispai->verbose = verbose;
24201a81e61SBarry Smith   PetscFunctionReturn(0);
24301a81e61SBarry Smith }
24401a81e61SBarry Smith 
24501a81e61SBarry Smith /**********************************************************************/
24601a81e61SBarry Smith 
247f7a08781SBarry Smith static PetscErrorCode  PCSPAISetSp_SPAI(PC pc,int sp)
24801a81e61SBarry Smith {
24901a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
2505fd66863SKarl Rupp 
25101a81e61SBarry Smith   PetscFunctionBegin;
25201a81e61SBarry Smith   ispai->sp = sp;
25301a81e61SBarry Smith   PetscFunctionReturn(0);
25401a81e61SBarry Smith }
25501a81e61SBarry Smith 
25601a81e61SBarry Smith /* -------------------------------------------------------------------*/
25701a81e61SBarry Smith 
25801a81e61SBarry Smith /*@
25901a81e61SBarry Smith   PCSPAISetEpsilon -- Set the tolerance for the SPAI preconditioner
26001a81e61SBarry Smith 
26101a81e61SBarry Smith   Input Parameters:
26201a81e61SBarry Smith + pc - the preconditioner
26301a81e61SBarry Smith - eps - epsilon (default .4)
26401a81e61SBarry Smith 
26595452b02SPatrick Sanan   Notes:
26695452b02SPatrick Sanan     Espilon must be between 0 and 1. It controls the
26701a81e61SBarry Smith                  quality of the approximation of M to the inverse of
26801a81e61SBarry Smith                  A. Higher values of epsilon lead to more work, more
26901a81e61SBarry Smith                  fill, and usually better preconditioners. In many
27001a81e61SBarry Smith                  cases the best choice of epsilon is the one that
27101a81e61SBarry Smith                  divides the total solution time equally between the
27201a81e61SBarry Smith                  preconditioner and the solver.
27301a81e61SBarry Smith 
27401a81e61SBarry Smith   Level: intermediate
27501a81e61SBarry Smith 
27601a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
27701a81e61SBarry Smith   @*/
2787087cfbeSBarry Smith PetscErrorCode  PCSPAISetEpsilon(PC pc,double epsilon1)
27901a81e61SBarry Smith {
28001a81e61SBarry Smith   PetscFunctionBegin;
281*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetEpsilon_C",(PC,double),(pc,epsilon1)));
28201a81e61SBarry Smith   PetscFunctionReturn(0);
28301a81e61SBarry Smith }
28401a81e61SBarry Smith 
28501a81e61SBarry Smith /**********************************************************************/
28601a81e61SBarry Smith 
28701a81e61SBarry Smith /*@
28801a81e61SBarry Smith   PCSPAISetNBSteps - set maximum number of improvement steps per row in
28901a81e61SBarry Smith         the SPAI preconditioner
29001a81e61SBarry Smith 
29101a81e61SBarry Smith   Input Parameters:
29201a81e61SBarry Smith + pc - the preconditioner
29301a81e61SBarry Smith - n - number of steps (default 5)
29401a81e61SBarry Smith 
29595452b02SPatrick Sanan   Notes:
29695452b02SPatrick Sanan     SPAI constructs to approximation to every column of
29701a81e61SBarry Smith                  the exact inverse of A in a series of improvement
29801a81e61SBarry Smith                  steps. The quality of the approximation is determined
29901a81e61SBarry Smith                  by epsilon. If an approximation achieving an accuracy
30001a81e61SBarry Smith                  of epsilon is not obtained after ns steps, SPAI simply
30101a81e61SBarry Smith                  uses the best approximation constructed so far.
30201a81e61SBarry Smith 
30301a81e61SBarry Smith   Level: intermediate
30401a81e61SBarry Smith 
30501a81e61SBarry Smith .seealso: PCSPAI, PCSetType(), PCSPAISetMaxNew()
30601a81e61SBarry Smith @*/
3077087cfbeSBarry Smith PetscErrorCode  PCSPAISetNBSteps(PC pc,int nbsteps1)
30801a81e61SBarry Smith {
30901a81e61SBarry Smith   PetscFunctionBegin;
310*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetNBSteps_C",(PC,int),(pc,nbsteps1)));
31101a81e61SBarry Smith   PetscFunctionReturn(0);
31201a81e61SBarry Smith }
31301a81e61SBarry Smith 
31401a81e61SBarry Smith /**********************************************************************/
31501a81e61SBarry Smith 
31601a81e61SBarry Smith /* added 1/7/99 g.h. */
31701a81e61SBarry Smith /*@
31801a81e61SBarry Smith   PCSPAISetMax - set the size of various working buffers in
31901a81e61SBarry Smith         the SPAI preconditioner
32001a81e61SBarry Smith 
32101a81e61SBarry Smith   Input Parameters:
32201a81e61SBarry Smith + pc - the preconditioner
32301a81e61SBarry Smith - n - size (default is 5000)
32401a81e61SBarry Smith 
32501a81e61SBarry Smith   Level: intermediate
32601a81e61SBarry Smith 
32701a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
32801a81e61SBarry Smith @*/
3297087cfbeSBarry Smith PetscErrorCode  PCSPAISetMax(PC pc,int max1)
33001a81e61SBarry Smith {
33101a81e61SBarry Smith   PetscFunctionBegin;
332*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetMax_C",(PC,int),(pc,max1)));
33301a81e61SBarry Smith   PetscFunctionReturn(0);
33401a81e61SBarry Smith }
33501a81e61SBarry Smith 
33601a81e61SBarry Smith /**********************************************************************/
33701a81e61SBarry Smith 
33801a81e61SBarry Smith /*@
33901a81e61SBarry Smith   PCSPAISetMaxNew - set maximum number of new nonzero candidates per step
34001a81e61SBarry Smith    in SPAI preconditioner
34101a81e61SBarry Smith 
34201a81e61SBarry Smith   Input Parameters:
34301a81e61SBarry Smith + pc - the preconditioner
34401a81e61SBarry Smith - n - maximum number (default 5)
34501a81e61SBarry Smith 
34601a81e61SBarry Smith   Level: intermediate
34701a81e61SBarry Smith 
34801a81e61SBarry Smith .seealso: PCSPAI, PCSetType(), PCSPAISetNBSteps()
34901a81e61SBarry Smith @*/
3507087cfbeSBarry Smith PetscErrorCode  PCSPAISetMaxNew(PC pc,int maxnew1)
35101a81e61SBarry Smith {
35201a81e61SBarry Smith   PetscFunctionBegin;
353*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetMaxNew_C",(PC,int),(pc,maxnew1)));
35401a81e61SBarry Smith   PetscFunctionReturn(0);
35501a81e61SBarry Smith }
35601a81e61SBarry Smith 
35701a81e61SBarry Smith /**********************************************************************/
35801a81e61SBarry Smith 
35901a81e61SBarry Smith /*@
36001a81e61SBarry Smith   PCSPAISetBlockSize - set the block size for the SPAI preconditioner
36101a81e61SBarry Smith 
36201a81e61SBarry Smith   Input Parameters:
36301a81e61SBarry Smith + pc - the preconditioner
36401a81e61SBarry Smith - n - block size (default 1)
36501a81e61SBarry Smith 
36695452b02SPatrick Sanan   Notes:
36795452b02SPatrick Sanan     A block
36801a81e61SBarry Smith                  size of 1 treats A as a matrix of scalar elements. A
36901a81e61SBarry Smith                  block size of s > 1 treats A as a matrix of sxs
37001a81e61SBarry Smith                  blocks. A block size of 0 treats A as a matrix with
37101a81e61SBarry Smith                  variable sized blocks, which are determined by
37201a81e61SBarry Smith                  searching for dense square diagonal blocks in A.
37301a81e61SBarry Smith                  This can be very effective for finite-element
37401a81e61SBarry Smith                  matrices.
37501a81e61SBarry Smith 
37601a81e61SBarry Smith                  SPAI will convert A to block form, use a block
37701a81e61SBarry Smith                  version of the preconditioner algorithm, and then
37801a81e61SBarry Smith                  convert the result back to scalar form.
37901a81e61SBarry Smith 
38001a81e61SBarry Smith                  In many cases the a block-size parameter other than 1
38101a81e61SBarry Smith                  can lead to very significant improvement in
38201a81e61SBarry Smith                  performance.
38301a81e61SBarry Smith 
38401a81e61SBarry Smith   Level: intermediate
38501a81e61SBarry Smith 
38601a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
38701a81e61SBarry Smith @*/
3887087cfbeSBarry Smith PetscErrorCode  PCSPAISetBlockSize(PC pc,int block_size1)
38901a81e61SBarry Smith {
39001a81e61SBarry Smith   PetscFunctionBegin;
391*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetBlockSize_C",(PC,int),(pc,block_size1)));
39201a81e61SBarry Smith   PetscFunctionReturn(0);
39301a81e61SBarry Smith }
39401a81e61SBarry Smith 
39501a81e61SBarry Smith /**********************************************************************/
39601a81e61SBarry Smith 
39701a81e61SBarry Smith /*@
39801a81e61SBarry Smith   PCSPAISetCacheSize - specify cache size in the SPAI preconditioner
39901a81e61SBarry Smith 
40001a81e61SBarry Smith   Input Parameters:
40101a81e61SBarry Smith + pc - the preconditioner
40201a81e61SBarry Smith - n -  cache size {0,1,2,3,4,5} (default 5)
40301a81e61SBarry Smith 
40495452b02SPatrick Sanan   Notes:
40595452b02SPatrick Sanan     SPAI uses a hash table to cache messages and avoid
40601a81e61SBarry Smith                  redundant communication. If suggest always using
40701a81e61SBarry Smith                  5. This parameter is irrelevant in the serial
40801a81e61SBarry Smith                  version.
40901a81e61SBarry Smith 
41001a81e61SBarry Smith   Level: intermediate
41101a81e61SBarry Smith 
41201a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
41301a81e61SBarry Smith @*/
4147087cfbeSBarry Smith PetscErrorCode  PCSPAISetCacheSize(PC pc,int cache_size)
41501a81e61SBarry Smith {
41601a81e61SBarry Smith   PetscFunctionBegin;
417*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetCacheSize_C",(PC,int),(pc,cache_size)));
41801a81e61SBarry Smith   PetscFunctionReturn(0);
41901a81e61SBarry Smith }
42001a81e61SBarry Smith 
42101a81e61SBarry Smith /**********************************************************************/
42201a81e61SBarry Smith 
42301a81e61SBarry Smith /*@
42401a81e61SBarry Smith   PCSPAISetVerbose - verbosity level for the SPAI preconditioner
42501a81e61SBarry Smith 
42601a81e61SBarry Smith   Input Parameters:
42701a81e61SBarry Smith + pc - the preconditioner
42801a81e61SBarry Smith - n - level (default 1)
42901a81e61SBarry Smith 
43095452b02SPatrick Sanan   Notes:
43195452b02SPatrick Sanan     print parameters, timings and matrix statistics
43201a81e61SBarry Smith 
43301a81e61SBarry Smith   Level: intermediate
43401a81e61SBarry Smith 
43501a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
43601a81e61SBarry Smith @*/
4377087cfbeSBarry Smith PetscErrorCode  PCSPAISetVerbose(PC pc,int verbose)
43801a81e61SBarry Smith {
43901a81e61SBarry Smith   PetscFunctionBegin;
440*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetVerbose_C",(PC,int),(pc,verbose)));
44101a81e61SBarry Smith   PetscFunctionReturn(0);
44201a81e61SBarry Smith }
44301a81e61SBarry Smith 
44401a81e61SBarry Smith /**********************************************************************/
44501a81e61SBarry Smith 
44601a81e61SBarry Smith /*@
44701a81e61SBarry Smith   PCSPAISetSp - specify a symmetric matrix sparsity pattern in the SPAI preconditioner
44801a81e61SBarry Smith 
44901a81e61SBarry Smith   Input Parameters:
45001a81e61SBarry Smith + pc - the preconditioner
45101a81e61SBarry Smith - n - 0 or 1
45201a81e61SBarry Smith 
45395452b02SPatrick Sanan   Notes:
45495452b02SPatrick Sanan     If A has a symmetric nonzero pattern use -sp 1 to
45501a81e61SBarry Smith                  improve performance by eliminating some communication
45601a81e61SBarry Smith                  in the parallel version. Even if A does not have a
45701a81e61SBarry Smith                  symmetric nonzero pattern -sp 1 may well lead to good
45801a81e61SBarry Smith                  results, but the code will not follow the published
45901a81e61SBarry Smith                  SPAI algorithm exactly.
46001a81e61SBarry Smith 
46101a81e61SBarry Smith   Level: intermediate
46201a81e61SBarry Smith 
46301a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
46401a81e61SBarry Smith @*/
4657087cfbeSBarry Smith PetscErrorCode  PCSPAISetSp(PC pc,int sp)
46601a81e61SBarry Smith {
46701a81e61SBarry Smith   PetscFunctionBegin;
468*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(pc,"PCSPAISetSp_C",(PC,int),(pc,sp)));
46901a81e61SBarry Smith   PetscFunctionReturn(0);
47001a81e61SBarry Smith }
47101a81e61SBarry Smith 
47201a81e61SBarry Smith /**********************************************************************/
47301a81e61SBarry Smith 
47401a81e61SBarry Smith /**********************************************************************/
47501a81e61SBarry Smith 
4764416b707SBarry Smith static PetscErrorCode PCSetFromOptions_SPAI(PetscOptionItems *PetscOptionsObject,PC pc)
47701a81e61SBarry Smith {
47801a81e61SBarry Smith   PC_SPAI        *ispai = (PC_SPAI*)pc->data;
47901a81e61SBarry Smith   int            nbsteps1,max1,maxnew1,block_size1,cache_size,verbose,sp;
48001a81e61SBarry Smith   double         epsilon1;
481ace3abfcSBarry Smith   PetscBool      flg;
48201a81e61SBarry Smith 
48301a81e61SBarry Smith   PetscFunctionBegin;
484*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject,"SPAI options"));
485*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsReal("-pc_spai_epsilon","","PCSPAISetEpsilon",ispai->epsilon,&epsilon1,&flg));
48601a81e61SBarry Smith   if (flg) {
487*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetEpsilon(pc,epsilon1));
48801a81e61SBarry Smith   }
489*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_spai_nbsteps","","PCSPAISetNBSteps",ispai->nbsteps,&nbsteps1,&flg));
49001a81e61SBarry Smith   if (flg) {
491*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetNBSteps(pc,nbsteps1));
49201a81e61SBarry Smith   }
49301a81e61SBarry Smith   /* added 1/7/99 g.h. */
494*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_spai_max","","PCSPAISetMax",ispai->max,&max1,&flg));
49501a81e61SBarry Smith   if (flg) {
496*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetMax(pc,max1));
49701a81e61SBarry Smith   }
498*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_spai_maxnew","","PCSPAISetMaxNew",ispai->maxnew,&maxnew1,&flg));
49901a81e61SBarry Smith   if (flg) {
500*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetMaxNew(pc,maxnew1));
50101a81e61SBarry Smith   }
502*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_spai_block_size","","PCSPAISetBlockSize",ispai->block_size,&block_size1,&flg));
50301a81e61SBarry Smith   if (flg) {
504*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetBlockSize(pc,block_size1));
50501a81e61SBarry Smith   }
506*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_spai_cache_size","","PCSPAISetCacheSize",ispai->cache_size,&cache_size,&flg));
50701a81e61SBarry Smith   if (flg) {
508*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetCacheSize(pc,cache_size));
50901a81e61SBarry Smith   }
510*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_spai_verbose","","PCSPAISetVerbose",ispai->verbose,&verbose,&flg));
51101a81e61SBarry Smith   if (flg) {
512*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetVerbose(pc,verbose));
51301a81e61SBarry Smith   }
514*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsInt("-pc_spai_sp","","PCSPAISetSp",ispai->sp,&sp,&flg));
51501a81e61SBarry Smith   if (flg) {
516*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSPAISetSp(pc,sp));
51701a81e61SBarry Smith   }
518*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
51901a81e61SBarry Smith   PetscFunctionReturn(0);
52001a81e61SBarry Smith }
52101a81e61SBarry Smith 
52201a81e61SBarry Smith /**********************************************************************/
52301a81e61SBarry Smith 
52401a81e61SBarry Smith /*MC
52501a81e61SBarry Smith    PCSPAI - Use the Sparse Approximate Inverse method of Grote and Barnard
52601a81e61SBarry Smith      as a preconditioner (SIAM J. Sci. Comput.; vol 18, nr 3)
52701a81e61SBarry Smith 
52801a81e61SBarry Smith    Options Database Keys:
529c5ae99e3SSatish Balay +  -pc_spai_epsilon <eps> - set tolerance
53001a81e61SBarry Smith .  -pc_spai_nbstep <n> - set nbsteps
53101a81e61SBarry Smith .  -pc_spai_max <m> - set max
53201a81e61SBarry Smith .  -pc_spai_max_new <m> - set maxnew
53301a81e61SBarry Smith .  -pc_spai_block_size <n> - set block size
53401a81e61SBarry Smith .  -pc_spai_cache_size <n> - set cache size
53501a81e61SBarry Smith .  -pc_spai_sp <m> - set sp
53601a81e61SBarry Smith -  -pc_spai_set_verbose <true,false> - verbose output
53701a81e61SBarry Smith 
53895452b02SPatrick Sanan    Notes:
53995452b02SPatrick Sanan     This only works with AIJ matrices.
54001a81e61SBarry Smith 
54101a81e61SBarry Smith    Level: beginner
54201a81e61SBarry Smith 
54301a81e61SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
54401a81e61SBarry Smith     PCSPAISetEpsilon(), PCSPAISetMax(), PCSPAISetMaxNew(), PCSPAISetBlockSize(),
54501a81e61SBarry Smith     PCSPAISetVerbose(), PCSPAISetSp()
54601a81e61SBarry Smith M*/
54701a81e61SBarry Smith 
5488cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_SPAI(PC pc)
54901a81e61SBarry Smith {
55001a81e61SBarry Smith   PC_SPAI *ispai;
55101a81e61SBarry Smith 
55201a81e61SBarry Smith   PetscFunctionBegin;
553*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(pc,&ispai));
5542a4967abSBarry Smith   pc->data = ispai;
55501a81e61SBarry Smith 
55601a81e61SBarry Smith   pc->ops->destroy         = PCDestroy_SPAI;
55701a81e61SBarry Smith   pc->ops->apply           = PCApply_SPAI;
55848e38a8aSPierre Jolivet   pc->ops->matapply        = PCMatApply_SPAI;
55901a81e61SBarry Smith   pc->ops->applyrichardson = 0;
56001a81e61SBarry Smith   pc->ops->setup           = PCSetUp_SPAI;
56101a81e61SBarry Smith   pc->ops->view            = PCView_SPAI;
56201a81e61SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_SPAI;
56301a81e61SBarry Smith 
56401a81e61SBarry Smith   ispai->epsilon    = .4;
56501a81e61SBarry Smith   ispai->nbsteps    = 5;
56601a81e61SBarry Smith   ispai->max        = 5000;
56701a81e61SBarry Smith   ispai->maxnew     = 5;
56801a81e61SBarry Smith   ispai->block_size = 1;
56901a81e61SBarry Smith   ispai->cache_size = 5;
57001a81e61SBarry Smith   ispai->verbose    = 0;
57101a81e61SBarry Smith 
57201a81e61SBarry Smith   ispai->sp = 1;
573*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_dup(PetscObjectComm((PetscObject)pc),&(ispai->comm_spai)));
57401a81e61SBarry Smith 
575*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetEpsilon_C",PCSPAISetEpsilon_SPAI));
576*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetNBSteps_C",PCSPAISetNBSteps_SPAI));
577*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetMax_C",PCSPAISetMax_SPAI));
578*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetMaxNew_C",PCSPAISetMaxNew_SPAI));
579*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetBlockSize_C",PCSPAISetBlockSize_SPAI));
580*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetCacheSize_C",PCSPAISetCacheSize_SPAI));
581*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetVerbose_C",PCSPAISetVerbose_SPAI));
582*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)pc,"PCSPAISetSp_C",PCSPAISetSp_SPAI));
58301a81e61SBarry Smith   PetscFunctionReturn(0);
58401a81e61SBarry Smith }
58501a81e61SBarry Smith 
58601a81e61SBarry Smith /**********************************************************************/
58701a81e61SBarry Smith 
58801a81e61SBarry Smith /*
58901a81e61SBarry Smith    Converts from a PETSc matrix to an SPAI matrix
59001a81e61SBarry Smith */
59101a81e61SBarry Smith PetscErrorCode ConvertMatToMatrix(MPI_Comm comm, Mat A,Mat AT,matrix **B)
59201a81e61SBarry Smith {
59301a81e61SBarry Smith   matrix                  *M;
59401a81e61SBarry Smith   int                     i,j,col;
59501a81e61SBarry Smith   int                     row_indx;
59601a81e61SBarry Smith   int                     len,pe,local_indx,start_indx;
59701a81e61SBarry Smith   int                     *mapping;
59801a81e61SBarry Smith   const int               *cols;
59901a81e61SBarry Smith   const double            *vals;
6002122902bSSatish Balay   int                     n,mnl,nnl,nz,rstart,rend;
6012a4967abSBarry Smith   PetscMPIInt             size,rank;
60201a81e61SBarry Smith   struct compressed_lines *rows;
60301a81e61SBarry Smith 
60401a81e61SBarry Smith   PetscFunctionBegin;
605*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
606*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
607*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,&n,&n));
608*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetLocalSize(A,&mnl,&nnl));
60901a81e61SBarry Smith 
61001a81e61SBarry Smith   /*
61101a81e61SBarry Smith     not sure why a barrier is required. commenting out
612*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Barrier(comm));
61301a81e61SBarry Smith   */
61401a81e61SBarry Smith 
61529b2f704SSatish Balay   M = new_matrix((SPAI_Comm)comm);
61601a81e61SBarry Smith 
61701a81e61SBarry Smith   M->n              = n;
61801a81e61SBarry Smith   M->bs             = 1;
61901a81e61SBarry Smith   M->max_block_size = 1;
62001a81e61SBarry Smith 
62101a81e61SBarry Smith   M->mnls          = (int*)malloc(sizeof(int)*size);
62201a81e61SBarry Smith   M->start_indices = (int*)malloc(sizeof(int)*size);
62301a81e61SBarry Smith   M->pe            = (int*)malloc(sizeof(int)*n);
62401a81e61SBarry Smith   M->block_sizes   = (int*)malloc(sizeof(int)*n);
62501a81e61SBarry Smith   for (i=0; i<n; i++) M->block_sizes[i] = 1;
62601a81e61SBarry Smith 
627*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allgather(&mnl,1,MPI_INT,M->mnls,1,MPI_INT,comm));
62801a81e61SBarry Smith 
62901a81e61SBarry Smith   M->start_indices[0] = 0;
6302fa5cd67SKarl Rupp   for (i=1; i<size; i++) M->start_indices[i] = M->start_indices[i-1] + M->mnls[i-1];
63101a81e61SBarry Smith 
63201a81e61SBarry Smith   M->mnl            = M->mnls[M->myid];
63301a81e61SBarry Smith   M->my_start_index = M->start_indices[M->myid];
63401a81e61SBarry Smith 
63501a81e61SBarry Smith   for (i=0; i<size; i++) {
63601a81e61SBarry Smith     start_indx = M->start_indices[i];
6372fa5cd67SKarl Rupp     for (j=0; j<M->mnls[i]; j++) M->pe[start_indx+j] = i;
63801a81e61SBarry Smith   }
63901a81e61SBarry Smith 
64001a81e61SBarry Smith   if (AT) {
6412f613bf5SBarry Smith     M->lines = new_compressed_lines(M->mnls[rank],1);
64201a81e61SBarry Smith   } else {
6432f613bf5SBarry Smith     M->lines = new_compressed_lines(M->mnls[rank],0);
64401a81e61SBarry Smith   }
64501a81e61SBarry Smith 
64601a81e61SBarry Smith   rows = M->lines;
64701a81e61SBarry Smith 
64801a81e61SBarry Smith   /* Determine the mapping from global indices to pointers */
649*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(M->n,&mapping));
65001a81e61SBarry Smith   pe         = 0;
65101a81e61SBarry Smith   local_indx = 0;
65201a81e61SBarry Smith   for (i=0; i<M->n; i++) {
65301a81e61SBarry Smith     if (local_indx >= M->mnls[pe]) {
65401a81e61SBarry Smith       pe++;
65501a81e61SBarry Smith       local_indx = 0;
65601a81e61SBarry Smith     }
65701a81e61SBarry Smith     mapping[i] = local_indx + M->start_indices[pe];
65801a81e61SBarry Smith     local_indx++;
65901a81e61SBarry Smith   }
66001a81e61SBarry Smith 
66101a81e61SBarry Smith   /*********************************************************/
66201a81e61SBarry Smith   /************** Set up the row structure *****************/
66301a81e61SBarry Smith   /*********************************************************/
66401a81e61SBarry Smith 
665*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetOwnershipRange(A,&rstart,&rend));
66601a81e61SBarry Smith   for (i=rstart; i<rend; i++) {
66701a81e61SBarry Smith     row_indx = i - rstart;
668*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetRow(A,i,&nz,&cols,&vals));
6692122902bSSatish Balay     /* allocate buffers */
6702122902bSSatish Balay     rows->ptrs[row_indx] = (int*)malloc(nz*sizeof(int));
6712122902bSSatish Balay     rows->A[row_indx]    = (double*)malloc(nz*sizeof(double));
6722122902bSSatish Balay     /* copy the matrix */
67301a81e61SBarry Smith     for (j=0; j<nz; j++) {
67401a81e61SBarry Smith       col = cols[j];
67501a81e61SBarry Smith       len = rows->len[row_indx]++;
6762fa5cd67SKarl Rupp 
67701a81e61SBarry Smith       rows->ptrs[row_indx][len] = mapping[col];
67801a81e61SBarry Smith       rows->A[row_indx][len]    = vals[j];
67901a81e61SBarry Smith     }
68001a81e61SBarry Smith     rows->slen[row_indx] = rows->len[row_indx];
6812fa5cd67SKarl Rupp 
682*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatRestoreRow(A,i,&nz,&cols,&vals));
68301a81e61SBarry Smith   }
68401a81e61SBarry Smith 
68501a81e61SBarry Smith   /************************************************************/
68601a81e61SBarry Smith   /************** Set up the column structure *****************/
68701a81e61SBarry Smith   /*********************************************************/
68801a81e61SBarry Smith 
68901a81e61SBarry Smith   if (AT) {
69001a81e61SBarry Smith 
69101a81e61SBarry Smith     for (i=rstart; i<rend; i++) {
69201a81e61SBarry Smith       row_indx = i - rstart;
693*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetRow(AT,i,&nz,&cols,&vals));
6942122902bSSatish Balay       /* allocate buffers */
6952122902bSSatish Balay       rows->rptrs[row_indx] = (int*)malloc(nz*sizeof(int));
6962122902bSSatish Balay       /* copy the matrix (i.e., the structure) */
69701a81e61SBarry Smith       for (j=0; j<nz; j++) {
69801a81e61SBarry Smith         col = cols[j];
69901a81e61SBarry Smith         len = rows->rlen[row_indx]++;
7002fa5cd67SKarl Rupp 
70101a81e61SBarry Smith         rows->rptrs[row_indx][len] = mapping[col];
70201a81e61SBarry Smith       }
703*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatRestoreRow(AT,i,&nz,&cols,&vals));
70401a81e61SBarry Smith     }
70501a81e61SBarry Smith   }
70601a81e61SBarry Smith 
707*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mapping));
70801a81e61SBarry Smith 
70901a81e61SBarry Smith   order_pointers(M);
71001a81e61SBarry Smith   M->maxnz = calc_maxnz(M);
71101a81e61SBarry Smith   *B       = M;
71201a81e61SBarry Smith   PetscFunctionReturn(0);
71301a81e61SBarry Smith }
71401a81e61SBarry Smith 
71501a81e61SBarry Smith /**********************************************************************/
71601a81e61SBarry Smith 
71701a81e61SBarry Smith /*
71801a81e61SBarry Smith    Converts from an SPAI matrix B  to a PETSc matrix PB.
719df3898eeSBarry Smith    This assumes that the SPAI matrix B is stored in
72001a81e61SBarry Smith    COMPRESSED-ROW format.
72101a81e61SBarry Smith */
72201a81e61SBarry Smith PetscErrorCode ConvertMatrixToMat(MPI_Comm comm,matrix *B,Mat *PB)
72301a81e61SBarry Smith {
7244b6b5fe1SBarry Smith   PetscMPIInt    size,rank;
72501a81e61SBarry Smith   int            m,n,M,N;
72601a81e61SBarry Smith   int            d_nz,o_nz;
72701a81e61SBarry Smith   int            *d_nnz,*o_nnz;
72801a81e61SBarry Smith   int            i,k,global_row,global_col,first_diag_col,last_diag_col;
72901a81e61SBarry Smith   PetscScalar    val;
73001a81e61SBarry Smith 
73101a81e61SBarry Smith   PetscFunctionBegin;
732*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
733*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
73401a81e61SBarry Smith 
73501a81e61SBarry Smith   m    = n = B->mnls[rank];
73601a81e61SBarry Smith   d_nz = o_nz = 0;
73701a81e61SBarry Smith 
73806946f3aSJose E. Roman   /* Determine preallocation for MatCreateAIJ */
739*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m,&d_nnz));
740*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m,&o_nnz));
74101a81e61SBarry Smith   for (i=0; i<m; i++) d_nnz[i] = o_nnz[i] = 0;
74201a81e61SBarry Smith   first_diag_col = B->start_indices[rank];
74301a81e61SBarry Smith   last_diag_col  = first_diag_col + B->mnls[rank];
74401a81e61SBarry Smith   for (i=0; i<B->mnls[rank]; i++) {
74501a81e61SBarry Smith     for (k=0; k<B->lines->len[i]; k++) {
74601a81e61SBarry Smith       global_col = B->lines->ptrs[i][k];
747db4deed7SKarl Rupp       if ((global_col >= first_diag_col) && (global_col < last_diag_col)) d_nnz[i]++;
748db4deed7SKarl Rupp       else o_nnz[i]++;
74901a81e61SBarry Smith     }
75001a81e61SBarry Smith   }
75101a81e61SBarry Smith 
75201a81e61SBarry Smith   M = N = B->n;
75301a81e61SBarry Smith   /* Here we only know how to create AIJ format */
754*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,PB));
755*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*PB,m,n,M,N));
756*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*PB,MATAIJ));
757*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(*PB,d_nz,d_nnz));
758*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAIJSetPreallocation(*PB,d_nz,d_nnz,o_nz,o_nnz));
75901a81e61SBarry Smith 
76001a81e61SBarry Smith   for (i=0; i<B->mnls[rank]; i++) {
76101a81e61SBarry Smith     global_row = B->start_indices[rank]+i;
76201a81e61SBarry Smith     for (k=0; k<B->lines->len[i]; k++) {
76301a81e61SBarry Smith       global_col = B->lines->ptrs[i][k];
7642fa5cd67SKarl Rupp 
76501a81e61SBarry Smith       val  = B->lines->A[i][k];
766*5f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetValues(*PB,1,&global_row,1,&global_col,&val,ADD_VALUES));
76701a81e61SBarry Smith     }
76801a81e61SBarry Smith   }
76901a81e61SBarry Smith 
770*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d_nnz));
771*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(o_nnz));
77201a81e61SBarry Smith 
773*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(*PB,MAT_FINAL_ASSEMBLY));
774*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(*PB,MAT_FINAL_ASSEMBLY));
77501a81e61SBarry Smith   PetscFunctionReturn(0);
77601a81e61SBarry Smith }
77701a81e61SBarry Smith 
77801a81e61SBarry Smith /**********************************************************************/
77901a81e61SBarry Smith 
78001a81e61SBarry Smith /*
78101a81e61SBarry Smith    Converts from an SPAI vector v  to a PETSc vec Pv.
78201a81e61SBarry Smith */
78301a81e61SBarry Smith PetscErrorCode ConvertVectorToVec(MPI_Comm comm,vector *v,Vec *Pv)
78401a81e61SBarry Smith {
7854b6b5fe1SBarry Smith   PetscMPIInt size,rank;
7864b6b5fe1SBarry Smith   int         m,M,i,*mnls,*start_indices,*global_indices;
78701a81e61SBarry Smith 
78801a81e61SBarry Smith   PetscFunctionBegin;
789*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
790*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
79101a81e61SBarry Smith 
79201a81e61SBarry Smith   m = v->mnl;
79301a81e61SBarry Smith   M = v->n;
79401a81e61SBarry Smith 
795*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateMPI(comm,m,M,Pv));
79601a81e61SBarry Smith 
797*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(size,&mnls));
798*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Allgather(&v->mnl,1,MPI_INT,mnls,1,MPI_INT,comm));
79901a81e61SBarry Smith 
800*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(size,&start_indices));
8012fa5cd67SKarl Rupp 
80201a81e61SBarry Smith   start_indices[0] = 0;
8032fa5cd67SKarl Rupp   for (i=1; i<size; i++) start_indices[i] = start_indices[i-1] +mnls[i-1];
80401a81e61SBarry Smith 
805*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(v->mnl,&global_indices));
8062fa5cd67SKarl Rupp   for (i=0; i<v->mnl; i++) global_indices[i] = start_indices[rank] + i;
80701a81e61SBarry Smith 
808*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mnls));
809*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(start_indices));
81001a81e61SBarry Smith 
811*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetValues(*Pv,v->mnl,global_indices,v->v,INSERT_VALUES));
812*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyBegin(*Pv));
813*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAssemblyEnd(*Pv));
81401a81e61SBarry Smith 
815*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(global_indices));
81601a81e61SBarry Smith   PetscFunctionReturn(0);
81701a81e61SBarry Smith }
818