xref: /petsc/src/ksp/pc/impls/spai/ispai.c (revision b45d2f2cb7e031d9c0de5873eca80614ca7b863b)
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 */
2001a81e61SBarry Smith 
21*b45d2f2cSJed Brown #include <petsc-private/pcimpl.h>        /*I "petscpc.h" I*/
2275031707SSatish Balay #include "petscspai.h"
2301a81e61SBarry Smith 
2401a81e61SBarry Smith /*
2501a81e61SBarry Smith     These are the SPAI include files
2601a81e61SBarry Smith */
2701a81e61SBarry Smith EXTERN_C_BEGIN
28b7f9c950SSatish Balay #define MPI /* required for setting SPAI_Comm correctly in basics.h */
29c6db04a5SJed Brown #include <spai.h>
30c6db04a5SJed Brown #include <matrix.h>
3101a81e61SBarry Smith EXTERN_C_END
3201a81e61SBarry Smith 
3309573ac7SBarry Smith extern PetscErrorCode ConvertMatToMatrix(MPI_Comm,Mat,Mat,matrix**);
3409573ac7SBarry Smith extern PetscErrorCode ConvertMatrixToMat(MPI_Comm,matrix *,Mat *);
3509573ac7SBarry Smith extern PetscErrorCode ConvertVectorToVec(MPI_Comm,vector *v,Vec *Pv);
3609573ac7SBarry Smith extern PetscErrorCode MM_to_PETSC(char *,char *,char *);
3701a81e61SBarry Smith 
3801a81e61SBarry Smith typedef struct {
3901a81e61SBarry Smith 
4001a81e61SBarry Smith   matrix   *B;              /* matrix in SPAI format */
4101a81e61SBarry Smith   matrix   *BT;             /* transpose of matrix in SPAI format */
4201a81e61SBarry Smith   matrix   *M;              /* the approximate inverse in SPAI format */
4301a81e61SBarry Smith 
4401a81e61SBarry Smith   Mat      PM;              /* the approximate inverse PETSc format */
4501a81e61SBarry Smith 
4601a81e61SBarry Smith   double   epsilon;         /* tolerance */
4701a81e61SBarry Smith   int      nbsteps;         /* max number of "improvement" steps per line */
4801a81e61SBarry Smith   int      max;             /* max dimensions of is_I, q, etc. */
4901a81e61SBarry Smith   int      maxnew;          /* max number of new entries per step */
5001a81e61SBarry Smith   int      block_size;      /* constant block size */
5101a81e61SBarry Smith   int      cache_size;      /* one of (1,2,3,4,5,6) indicting size of cache */
5201a81e61SBarry Smith   int      verbose;         /* SPAI prints timing and statistics */
5301a81e61SBarry Smith 
5401a81e61SBarry Smith   int      sp;              /* symmetric nonzero pattern */
5501a81e61SBarry Smith   MPI_Comm comm_spai;     /* communicator to be used with spai */
5601a81e61SBarry Smith } PC_SPAI;
5701a81e61SBarry Smith 
5801a81e61SBarry Smith /**********************************************************************/
5901a81e61SBarry Smith 
6001a81e61SBarry Smith #undef __FUNCT__
6101a81e61SBarry Smith #define __FUNCT__ "PCSetUp_SPAI"
6201a81e61SBarry Smith static PetscErrorCode PCSetUp_SPAI(PC pc)
6301a81e61SBarry Smith {
6401a81e61SBarry Smith   PC_SPAI        *ispai = (PC_SPAI*)pc->data;
6501a81e61SBarry Smith   PetscErrorCode ierr;
6601a81e61SBarry Smith   Mat            AT;
6701a81e61SBarry Smith 
6801a81e61SBarry Smith   PetscFunctionBegin;
6901a81e61SBarry Smith 
7001a81e61SBarry Smith   init_SPAI();
7101a81e61SBarry Smith 
7201a81e61SBarry Smith   if (ispai->sp) {
7301a81e61SBarry Smith     ierr = ConvertMatToMatrix(ispai->comm_spai,pc->pmat,pc->pmat,&ispai->B);CHKERRQ(ierr);
7401a81e61SBarry Smith   } else {
7501a81e61SBarry Smith     /* Use the transpose to get the column nonzero structure. */
76fc4dec0aSBarry Smith     ierr = MatTranspose(pc->pmat,MAT_INITIAL_MATRIX,&AT);CHKERRQ(ierr);
7701a81e61SBarry Smith     ierr = ConvertMatToMatrix(ispai->comm_spai,pc->pmat,AT,&ispai->B);CHKERRQ(ierr);
7869a3b875SJed Brown     ierr = MatDestroy(&AT);CHKERRQ(ierr);
7901a81e61SBarry Smith   }
8001a81e61SBarry Smith 
8101a81e61SBarry Smith   /* Destroy the transpose */
8201a81e61SBarry Smith   /* Don't know how to do it. PETSc developers? */
8301a81e61SBarry Smith 
8401a81e61SBarry Smith   /* construct SPAI preconditioner */
8501a81e61SBarry Smith   /* FILE *messages */     /* file for warning messages */
8601a81e61SBarry Smith   /* double epsilon */     /* tolerance */
8701a81e61SBarry Smith   /* int nbsteps */        /* max number of "improvement" steps per line */
8801a81e61SBarry Smith   /* int max */            /* max dimensions of is_I, q, etc. */
8901a81e61SBarry Smith   /* int maxnew */         /* max number of new entries per step */
9001a81e61SBarry Smith   /* int block_size */     /* block_size == 1 specifies scalar elments
9101a81e61SBarry Smith                               block_size == n specifies nxn constant-block elements
9201a81e61SBarry Smith                               block_size == 0 specifies variable-block elements */
9301a81e61SBarry Smith   /* int cache_size */     /* one of (1,2,3,4,5,6) indicting size of cache */
9401a81e61SBarry Smith                            /* cache_size == 0 indicates no caching */
9501a81e61SBarry Smith   /* int    verbose    */  /* verbose == 0 specifies that SPAI is silent
9601a81e61SBarry Smith                               verbose == 1 prints timing and matrix statistics */
9701a81e61SBarry Smith 
9801a81e61SBarry Smith   ierr = bspai(ispai->B,&ispai->M,
9901a81e61SBarry Smith 		   stdout,
10001a81e61SBarry Smith 		   ispai->epsilon,
10101a81e61SBarry Smith 		   ispai->nbsteps,
10201a81e61SBarry Smith 		   ispai->max,
10301a81e61SBarry Smith 		   ispai->maxnew,
10401a81e61SBarry Smith 		   ispai->block_size,
10501a81e61SBarry Smith 		   ispai->cache_size,
10601a81e61SBarry Smith 	       ispai->verbose);CHKERRQ(ierr);
10701a81e61SBarry Smith 
1087adad957SLisandro Dalcin   ierr = ConvertMatrixToMat(((PetscObject)pc)->comm,ispai->M,&ispai->PM);CHKERRQ(ierr);
10901a81e61SBarry Smith 
11001a81e61SBarry Smith   /* free the SPAI matrices */
11101a81e61SBarry Smith   sp_free_matrix(ispai->B);
11201a81e61SBarry Smith   sp_free_matrix(ispai->M);
11301a81e61SBarry Smith 
11401a81e61SBarry Smith   PetscFunctionReturn(0);
11501a81e61SBarry Smith }
11601a81e61SBarry Smith 
11701a81e61SBarry Smith /**********************************************************************/
11801a81e61SBarry Smith 
11901a81e61SBarry Smith #undef __FUNCT__
12001a81e61SBarry Smith #define __FUNCT__ "PCApply_SPAI"
12101a81e61SBarry Smith static PetscErrorCode PCApply_SPAI(PC pc,Vec xx,Vec y)
12201a81e61SBarry Smith {
12301a81e61SBarry Smith   PC_SPAI        *ispai = (PC_SPAI*)pc->data;
12401a81e61SBarry Smith   PetscErrorCode ierr;
12501a81e61SBarry Smith 
12601a81e61SBarry Smith   PetscFunctionBegin;
12701a81e61SBarry Smith   /* Now using PETSc's multiply */
12801a81e61SBarry Smith   ierr = MatMult(ispai->PM,xx,y);CHKERRQ(ierr);
12901a81e61SBarry Smith   PetscFunctionReturn(0);
13001a81e61SBarry Smith }
13101a81e61SBarry Smith 
13201a81e61SBarry Smith /**********************************************************************/
13301a81e61SBarry Smith 
13401a81e61SBarry Smith #undef __FUNCT__
13501a81e61SBarry Smith #define __FUNCT__ "PCDestroy_SPAI"
13601a81e61SBarry Smith static PetscErrorCode PCDestroy_SPAI(PC pc)
13701a81e61SBarry Smith {
13801a81e61SBarry Smith   PetscErrorCode ierr;
13901a81e61SBarry Smith   PC_SPAI        *ispai = (PC_SPAI*)pc->data;
14001a81e61SBarry Smith 
14101a81e61SBarry Smith   PetscFunctionBegin;
14269a3b875SJed Brown   ierr = MatDestroy(&ispai->PM);CHKERRQ(ierr);
14301a81e61SBarry Smith   ierr = MPI_Comm_free(&(ispai->comm_spai));CHKERRQ(ierr);
144c31cb41cSBarry Smith   ierr = PetscFree(pc->data);CHKERRQ(ierr);
14501a81e61SBarry Smith   PetscFunctionReturn(0);
14601a81e61SBarry Smith }
14701a81e61SBarry Smith 
14801a81e61SBarry Smith /**********************************************************************/
14901a81e61SBarry Smith 
15001a81e61SBarry Smith #undef __FUNCT__
15101a81e61SBarry Smith #define __FUNCT__ "PCView_SPAI"
15201a81e61SBarry Smith static PetscErrorCode PCView_SPAI(PC pc,PetscViewer viewer)
15301a81e61SBarry Smith {
15401a81e61SBarry Smith   PC_SPAI        *ispai = (PC_SPAI*)pc->data;
15501a81e61SBarry Smith   PetscErrorCode ierr;
156ace3abfcSBarry Smith   PetscBool      iascii;
15701a81e61SBarry Smith 
15801a81e61SBarry Smith   PetscFunctionBegin;
1592692d6eeSBarry Smith   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
16001a81e61SBarry Smith   if (iascii) {
16101a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    SPAI preconditioner\n");CHKERRQ(ierr);
162a83599f4SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    epsilon %G\n",   ispai->epsilon);CHKERRQ(ierr);
16301a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    nbsteps %d\n",   ispai->nbsteps);CHKERRQ(ierr);
16401a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    max %d\n",       ispai->max);CHKERRQ(ierr);
16501a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    maxnew %d\n",    ispai->maxnew);CHKERRQ(ierr);
16601a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    block_size %d\n",ispai->block_size);CHKERRQ(ierr);
16701a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    cache_size %d\n",ispai->cache_size);CHKERRQ(ierr);
16801a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    verbose %d\n",   ispai->verbose);CHKERRQ(ierr);
16901a81e61SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"    sp %d\n",        ispai->sp);CHKERRQ(ierr);
17001a81e61SBarry Smith   }
17101a81e61SBarry Smith   PetscFunctionReturn(0);
17201a81e61SBarry Smith }
17301a81e61SBarry Smith 
17401a81e61SBarry Smith EXTERN_C_BEGIN
17501a81e61SBarry Smith #undef __FUNCT__
17601a81e61SBarry Smith #define __FUNCT__ "PCSPAISetEpsilon_SPAI"
1777087cfbeSBarry Smith PetscErrorCode  PCSPAISetEpsilon_SPAI(PC pc,double epsilon1)
17801a81e61SBarry Smith {
17901a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
18001a81e61SBarry Smith   PetscFunctionBegin;
18101a81e61SBarry Smith   ispai->epsilon = epsilon1;
18201a81e61SBarry Smith   PetscFunctionReturn(0);
18301a81e61SBarry Smith }
18401a81e61SBarry Smith EXTERN_C_END
18501a81e61SBarry Smith 
18601a81e61SBarry Smith /**********************************************************************/
18701a81e61SBarry Smith 
18801a81e61SBarry Smith EXTERN_C_BEGIN
18901a81e61SBarry Smith #undef __FUNCT__
19001a81e61SBarry Smith #define __FUNCT__ "PCSPAISetNBSteps_SPAI"
1917087cfbeSBarry Smith PetscErrorCode  PCSPAISetNBSteps_SPAI(PC pc,int nbsteps1)
19201a81e61SBarry Smith {
19301a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
19401a81e61SBarry Smith   PetscFunctionBegin;
19501a81e61SBarry Smith   ispai->nbsteps = nbsteps1;
19601a81e61SBarry Smith   PetscFunctionReturn(0);
19701a81e61SBarry Smith }
19801a81e61SBarry Smith EXTERN_C_END
19901a81e61SBarry Smith 
20001a81e61SBarry Smith /**********************************************************************/
20101a81e61SBarry Smith 
20201a81e61SBarry Smith /* added 1/7/99 g.h. */
20301a81e61SBarry Smith EXTERN_C_BEGIN
20401a81e61SBarry Smith #undef __FUNCT__
20501a81e61SBarry Smith #define __FUNCT__ "PCSPAISetMax_SPAI"
2067087cfbeSBarry Smith PetscErrorCode  PCSPAISetMax_SPAI(PC pc,int max1)
20701a81e61SBarry Smith {
20801a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
20901a81e61SBarry Smith   PetscFunctionBegin;
21001a81e61SBarry Smith   ispai->max = max1;
21101a81e61SBarry Smith   PetscFunctionReturn(0);
21201a81e61SBarry Smith }
21301a81e61SBarry Smith EXTERN_C_END
21401a81e61SBarry Smith 
21501a81e61SBarry Smith /**********************************************************************/
21601a81e61SBarry Smith 
21701a81e61SBarry Smith EXTERN_C_BEGIN
21801a81e61SBarry Smith #undef __FUNCT__
21901a81e61SBarry Smith #define __FUNCT__ "PCSPAISetMaxNew_SPAI"
2207087cfbeSBarry Smith PetscErrorCode  PCSPAISetMaxNew_SPAI(PC pc,int maxnew1)
22101a81e61SBarry Smith {
22201a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
22301a81e61SBarry Smith   PetscFunctionBegin;
22401a81e61SBarry Smith   ispai->maxnew = maxnew1;
22501a81e61SBarry Smith   PetscFunctionReturn(0);
22601a81e61SBarry Smith }
22701a81e61SBarry Smith EXTERN_C_END
22801a81e61SBarry Smith 
22901a81e61SBarry Smith /**********************************************************************/
23001a81e61SBarry Smith 
23101a81e61SBarry Smith EXTERN_C_BEGIN
23201a81e61SBarry Smith #undef __FUNCT__
23301a81e61SBarry Smith #define __FUNCT__ "PCSPAISetBlockSize_SPAI"
2347087cfbeSBarry Smith PetscErrorCode  PCSPAISetBlockSize_SPAI(PC pc,int block_size1)
23501a81e61SBarry Smith {
23601a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
23701a81e61SBarry Smith   PetscFunctionBegin;
23801a81e61SBarry Smith   ispai->block_size = block_size1;
23901a81e61SBarry Smith   PetscFunctionReturn(0);
24001a81e61SBarry Smith }
24101a81e61SBarry Smith EXTERN_C_END
24201a81e61SBarry Smith 
24301a81e61SBarry Smith /**********************************************************************/
24401a81e61SBarry Smith 
24501a81e61SBarry Smith EXTERN_C_BEGIN
24601a81e61SBarry Smith #undef __FUNCT__
24701a81e61SBarry Smith #define __FUNCT__ "PCSPAISetCacheSize_SPAI"
2487087cfbeSBarry Smith PetscErrorCode  PCSPAISetCacheSize_SPAI(PC pc,int cache_size)
24901a81e61SBarry Smith {
25001a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
25101a81e61SBarry Smith   PetscFunctionBegin;
25201a81e61SBarry Smith   ispai->cache_size = cache_size;
25301a81e61SBarry Smith   PetscFunctionReturn(0);
25401a81e61SBarry Smith }
25501a81e61SBarry Smith EXTERN_C_END
25601a81e61SBarry Smith 
25701a81e61SBarry Smith /**********************************************************************/
25801a81e61SBarry Smith 
25901a81e61SBarry Smith EXTERN_C_BEGIN
26001a81e61SBarry Smith #undef __FUNCT__
26101a81e61SBarry Smith #define __FUNCT__ "PCSPAISetVerbose_SPAI"
2627087cfbeSBarry Smith PetscErrorCode  PCSPAISetVerbose_SPAI(PC pc,int verbose)
26301a81e61SBarry Smith {
26401a81e61SBarry Smith   PC_SPAI    *ispai = (PC_SPAI*)pc->data;
26501a81e61SBarry Smith   PetscFunctionBegin;
26601a81e61SBarry Smith   ispai->verbose = verbose;
26701a81e61SBarry Smith   PetscFunctionReturn(0);
26801a81e61SBarry Smith }
26901a81e61SBarry Smith EXTERN_C_END
27001a81e61SBarry Smith 
27101a81e61SBarry Smith /**********************************************************************/
27201a81e61SBarry Smith 
27301a81e61SBarry Smith EXTERN_C_BEGIN
27401a81e61SBarry Smith #undef __FUNCT__
27501a81e61SBarry Smith #define __FUNCT__ "PCSPAISetSp_SPAI"
2767087cfbeSBarry Smith PetscErrorCode  PCSPAISetSp_SPAI(PC pc,int sp)
27701a81e61SBarry Smith {
27801a81e61SBarry Smith   PC_SPAI *ispai = (PC_SPAI*)pc->data;
27901a81e61SBarry Smith   PetscFunctionBegin;
28001a81e61SBarry Smith   ispai->sp = sp;
28101a81e61SBarry Smith   PetscFunctionReturn(0);
28201a81e61SBarry Smith }
28301a81e61SBarry Smith EXTERN_C_END
28401a81e61SBarry Smith 
28501a81e61SBarry Smith /* -------------------------------------------------------------------*/
28601a81e61SBarry Smith 
28701a81e61SBarry Smith #undef __FUNCT__
28801a81e61SBarry Smith #define __FUNCT__ "PCSPAISetEpsilon"
28901a81e61SBarry Smith /*@
29001a81e61SBarry Smith   PCSPAISetEpsilon -- Set the tolerance for the SPAI preconditioner
29101a81e61SBarry Smith 
29201a81e61SBarry Smith   Input Parameters:
29301a81e61SBarry Smith + pc - the preconditioner
29401a81e61SBarry Smith - eps - epsilon (default .4)
29501a81e61SBarry Smith 
29601a81e61SBarry Smith   Notes:  Espilon must be between 0 and 1. It controls the
29701a81e61SBarry Smith                  quality of the approximation of M to the inverse of
29801a81e61SBarry Smith                  A. Higher values of epsilon lead to more work, more
29901a81e61SBarry Smith                  fill, and usually better preconditioners. In many
30001a81e61SBarry Smith                  cases the best choice of epsilon is the one that
30101a81e61SBarry Smith                  divides the total solution time equally between the
30201a81e61SBarry Smith                  preconditioner and the solver.
30301a81e61SBarry Smith 
30401a81e61SBarry Smith   Level: intermediate
30501a81e61SBarry Smith 
30601a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
30701a81e61SBarry Smith   @*/
3087087cfbeSBarry Smith PetscErrorCode  PCSPAISetEpsilon(PC pc,double epsilon1)
30901a81e61SBarry Smith {
3104ac538c5SBarry Smith   PetscErrorCode ierr;
31101a81e61SBarry Smith   PetscFunctionBegin;
3124ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetEpsilon_C",(PC,double),(pc,epsilon1));CHKERRQ(ierr);
31301a81e61SBarry Smith   PetscFunctionReturn(0);
31401a81e61SBarry Smith }
31501a81e61SBarry Smith 
31601a81e61SBarry Smith /**********************************************************************/
31701a81e61SBarry Smith 
31801a81e61SBarry Smith #undef __FUNCT__
31901a81e61SBarry Smith #define __FUNCT__ "PCSPAISetNBSteps"
32001a81e61SBarry Smith /*@
32101a81e61SBarry Smith   PCSPAISetNBSteps - set maximum number of improvement steps per row in
32201a81e61SBarry Smith         the SPAI preconditioner
32301a81e61SBarry Smith 
32401a81e61SBarry Smith   Input Parameters:
32501a81e61SBarry Smith + pc - the preconditioner
32601a81e61SBarry Smith - n - number of steps (default 5)
32701a81e61SBarry Smith 
32801a81e61SBarry Smith   Notes:  SPAI constructs to approximation to every column of
32901a81e61SBarry Smith                  the exact inverse of A in a series of improvement
33001a81e61SBarry Smith                  steps. The quality of the approximation is determined
33101a81e61SBarry Smith                  by epsilon. If an approximation achieving an accuracy
33201a81e61SBarry Smith                  of epsilon is not obtained after ns steps, SPAI simply
33301a81e61SBarry Smith                  uses the best approximation constructed so far.
33401a81e61SBarry Smith 
33501a81e61SBarry Smith   Level: intermediate
33601a81e61SBarry Smith 
33701a81e61SBarry Smith .seealso: PCSPAI, PCSetType(), PCSPAISetMaxNew()
33801a81e61SBarry Smith @*/
3397087cfbeSBarry Smith PetscErrorCode  PCSPAISetNBSteps(PC pc,int nbsteps1)
34001a81e61SBarry Smith {
3414ac538c5SBarry Smith   PetscErrorCode ierr;
34201a81e61SBarry Smith   PetscFunctionBegin;
3434ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetNBSteps_C",(PC,int),(pc,nbsteps1));CHKERRQ(ierr);
34401a81e61SBarry Smith   PetscFunctionReturn(0);
34501a81e61SBarry Smith }
34601a81e61SBarry Smith 
34701a81e61SBarry Smith /**********************************************************************/
34801a81e61SBarry Smith 
34901a81e61SBarry Smith /* added 1/7/99 g.h. */
35001a81e61SBarry Smith #undef __FUNCT__
35101a81e61SBarry Smith #define __FUNCT__ "PCSPAISetMax"
35201a81e61SBarry Smith /*@
35301a81e61SBarry Smith   PCSPAISetMax - set the size of various working buffers in
35401a81e61SBarry Smith         the SPAI preconditioner
35501a81e61SBarry Smith 
35601a81e61SBarry Smith   Input Parameters:
35701a81e61SBarry Smith + pc - the preconditioner
35801a81e61SBarry Smith - n - size (default is 5000)
35901a81e61SBarry Smith 
36001a81e61SBarry Smith   Level: intermediate
36101a81e61SBarry Smith 
36201a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
36301a81e61SBarry Smith @*/
3647087cfbeSBarry Smith PetscErrorCode  PCSPAISetMax(PC pc,int max1)
36501a81e61SBarry Smith {
3664ac538c5SBarry Smith   PetscErrorCode ierr;
36701a81e61SBarry Smith   PetscFunctionBegin;
3684ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetMax_C",(PC,int),(pc,max1));CHKERRQ(ierr);
36901a81e61SBarry Smith   PetscFunctionReturn(0);
37001a81e61SBarry Smith }
37101a81e61SBarry Smith 
37201a81e61SBarry Smith /**********************************************************************/
37301a81e61SBarry Smith 
37401a81e61SBarry Smith #undef __FUNCT__
37501a81e61SBarry Smith #define __FUNCT__ "PCSPAISetMaxNew"
37601a81e61SBarry Smith /*@
37701a81e61SBarry Smith   PCSPAISetMaxNew - set maximum number of new nonzero candidates per step
37801a81e61SBarry Smith    in SPAI preconditioner
37901a81e61SBarry Smith 
38001a81e61SBarry Smith   Input Parameters:
38101a81e61SBarry Smith + pc - the preconditioner
38201a81e61SBarry Smith - n - maximum number (default 5)
38301a81e61SBarry Smith 
38401a81e61SBarry Smith   Level: intermediate
38501a81e61SBarry Smith 
38601a81e61SBarry Smith .seealso: PCSPAI, PCSetType(), PCSPAISetNBSteps()
38701a81e61SBarry Smith @*/
3887087cfbeSBarry Smith PetscErrorCode  PCSPAISetMaxNew(PC pc,int maxnew1)
38901a81e61SBarry Smith {
3904ac538c5SBarry Smith   PetscErrorCode ierr;
39101a81e61SBarry Smith   PetscFunctionBegin;
3924ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetMaxNew_C",(PC,int),(pc,maxnew1));CHKERRQ(ierr);
39301a81e61SBarry Smith   PetscFunctionReturn(0);
39401a81e61SBarry Smith }
39501a81e61SBarry Smith 
39601a81e61SBarry Smith /**********************************************************************/
39701a81e61SBarry Smith 
39801a81e61SBarry Smith #undef __FUNCT__
39901a81e61SBarry Smith #define __FUNCT__ "PCSPAISetBlockSize"
40001a81e61SBarry Smith /*@
40101a81e61SBarry Smith   PCSPAISetBlockSize - set the block size for the SPAI preconditioner
40201a81e61SBarry Smith 
40301a81e61SBarry Smith   Input Parameters:
40401a81e61SBarry Smith + pc - the preconditioner
40501a81e61SBarry Smith - n - block size (default 1)
40601a81e61SBarry Smith 
40701a81e61SBarry Smith   Notes: A block
40801a81e61SBarry Smith                  size of 1 treats A as a matrix of scalar elements. A
40901a81e61SBarry Smith                  block size of s > 1 treats A as a matrix of sxs
41001a81e61SBarry Smith                  blocks. A block size of 0 treats A as a matrix with
41101a81e61SBarry Smith                  variable sized blocks, which are determined by
41201a81e61SBarry Smith                  searching for dense square diagonal blocks in A.
41301a81e61SBarry Smith                  This can be very effective for finite-element
41401a81e61SBarry Smith                  matrices.
41501a81e61SBarry Smith 
41601a81e61SBarry Smith                  SPAI will convert A to block form, use a block
41701a81e61SBarry Smith                  version of the preconditioner algorithm, and then
41801a81e61SBarry Smith                  convert the result back to scalar form.
41901a81e61SBarry Smith 
42001a81e61SBarry Smith                  In many cases the a block-size parameter other than 1
42101a81e61SBarry Smith                  can lead to very significant improvement in
42201a81e61SBarry Smith                  performance.
42301a81e61SBarry Smith 
42401a81e61SBarry Smith 
42501a81e61SBarry Smith   Level: intermediate
42601a81e61SBarry Smith 
42701a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
42801a81e61SBarry Smith @*/
4297087cfbeSBarry Smith PetscErrorCode  PCSPAISetBlockSize(PC pc,int block_size1)
43001a81e61SBarry Smith {
4314ac538c5SBarry Smith   PetscErrorCode ierr;
43201a81e61SBarry Smith   PetscFunctionBegin;
4334ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetBlockSize_C",(PC,int),(pc,block_size1));CHKERRQ(ierr);
43401a81e61SBarry Smith   PetscFunctionReturn(0);
43501a81e61SBarry Smith }
43601a81e61SBarry Smith 
43701a81e61SBarry Smith /**********************************************************************/
43801a81e61SBarry Smith 
43901a81e61SBarry Smith #undef __FUNCT__
44001a81e61SBarry Smith #define __FUNCT__ "PCSPAISetCacheSize"
44101a81e61SBarry Smith /*@
44201a81e61SBarry Smith   PCSPAISetCacheSize - specify cache size in the SPAI preconditioner
44301a81e61SBarry Smith 
44401a81e61SBarry Smith   Input Parameters:
44501a81e61SBarry Smith + pc - the preconditioner
44601a81e61SBarry Smith - n -  cache size {0,1,2,3,4,5} (default 5)
44701a81e61SBarry Smith 
44801a81e61SBarry Smith   Notes:    SPAI uses a hash table to cache messages and avoid
44901a81e61SBarry Smith                  redundant communication. If suggest always using
45001a81e61SBarry Smith                  5. This parameter is irrelevant in the serial
45101a81e61SBarry Smith                  version.
45201a81e61SBarry Smith 
45301a81e61SBarry Smith   Level: intermediate
45401a81e61SBarry Smith 
45501a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
45601a81e61SBarry Smith @*/
4577087cfbeSBarry Smith PetscErrorCode  PCSPAISetCacheSize(PC pc,int cache_size)
45801a81e61SBarry Smith {
4594ac538c5SBarry Smith   PetscErrorCode ierr;
46001a81e61SBarry Smith   PetscFunctionBegin;
4614ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetCacheSize_C",(PC,int),(pc,cache_size));CHKERRQ(ierr);
46201a81e61SBarry Smith   PetscFunctionReturn(0);
46301a81e61SBarry Smith }
46401a81e61SBarry Smith 
46501a81e61SBarry Smith /**********************************************************************/
46601a81e61SBarry Smith 
46701a81e61SBarry Smith #undef __FUNCT__
46801a81e61SBarry Smith #define __FUNCT__ "PCSPAISetVerbose"
46901a81e61SBarry Smith /*@
47001a81e61SBarry Smith   PCSPAISetVerbose - verbosity level for the SPAI preconditioner
47101a81e61SBarry Smith 
47201a81e61SBarry Smith   Input Parameters:
47301a81e61SBarry Smith + pc - the preconditioner
47401a81e61SBarry Smith - n - level (default 1)
47501a81e61SBarry Smith 
47601a81e61SBarry Smith   Notes: print parameters, timings and matrix statistics
47701a81e61SBarry Smith 
47801a81e61SBarry Smith   Level: intermediate
47901a81e61SBarry Smith 
48001a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
48101a81e61SBarry Smith @*/
4827087cfbeSBarry Smith PetscErrorCode  PCSPAISetVerbose(PC pc,int verbose)
48301a81e61SBarry Smith {
4844ac538c5SBarry Smith   PetscErrorCode ierr;
48501a81e61SBarry Smith   PetscFunctionBegin;
4864ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetVerbose_C",(PC,int),(pc,verbose));CHKERRQ(ierr);
48701a81e61SBarry Smith   PetscFunctionReturn(0);
48801a81e61SBarry Smith }
48901a81e61SBarry Smith 
49001a81e61SBarry Smith /**********************************************************************/
49101a81e61SBarry Smith 
49201a81e61SBarry Smith #undef __FUNCT__
49301a81e61SBarry Smith #define __FUNCT__ "PCSPAISetSp"
49401a81e61SBarry Smith /*@
49501a81e61SBarry Smith   PCSPAISetSp - specify a symmetric matrix sparsity pattern in the SPAI preconditioner
49601a81e61SBarry Smith 
49701a81e61SBarry Smith   Input Parameters:
49801a81e61SBarry Smith + pc - the preconditioner
49901a81e61SBarry Smith - n - 0 or 1
50001a81e61SBarry Smith 
50101a81e61SBarry Smith   Notes: If A has a symmetric nonzero pattern use -sp 1 to
50201a81e61SBarry Smith                  improve performance by eliminating some communication
50301a81e61SBarry Smith                  in the parallel version. Even if A does not have a
50401a81e61SBarry Smith                  symmetric nonzero pattern -sp 1 may well lead to good
50501a81e61SBarry Smith                  results, but the code will not follow the published
50601a81e61SBarry Smith                  SPAI algorithm exactly.
50701a81e61SBarry Smith 
50801a81e61SBarry Smith 
50901a81e61SBarry Smith   Level: intermediate
51001a81e61SBarry Smith 
51101a81e61SBarry Smith .seealso: PCSPAI, PCSetType()
51201a81e61SBarry Smith @*/
5137087cfbeSBarry Smith PetscErrorCode  PCSPAISetSp(PC pc,int sp)
51401a81e61SBarry Smith {
5154ac538c5SBarry Smith   PetscErrorCode ierr;
51601a81e61SBarry Smith   PetscFunctionBegin;
5174ac538c5SBarry Smith   ierr = PetscTryMethod(pc,"PCSPAISetSp_C",(PC,int),(pc,sp));CHKERRQ(ierr);
51801a81e61SBarry Smith   PetscFunctionReturn(0);
51901a81e61SBarry Smith }
52001a81e61SBarry Smith 
52101a81e61SBarry Smith /**********************************************************************/
52201a81e61SBarry Smith 
52301a81e61SBarry Smith /**********************************************************************/
52401a81e61SBarry Smith 
52501a81e61SBarry Smith #undef __FUNCT__
52601a81e61SBarry Smith #define __FUNCT__ "PCSetFromOptions_SPAI"
52701a81e61SBarry Smith static PetscErrorCode PCSetFromOptions_SPAI(PC pc)
52801a81e61SBarry Smith {
52901a81e61SBarry Smith   PC_SPAI        *ispai = (PC_SPAI*)pc->data;
53001a81e61SBarry Smith   PetscErrorCode ierr;
53101a81e61SBarry Smith   int            nbsteps1,max1,maxnew1,block_size1,cache_size,verbose,sp;
53201a81e61SBarry Smith   double         epsilon1;
533ace3abfcSBarry Smith   PetscBool      flg;
53401a81e61SBarry Smith 
53501a81e61SBarry Smith   PetscFunctionBegin;
53601a81e61SBarry Smith   ierr = PetscOptionsHead("SPAI options");CHKERRQ(ierr);
53701a81e61SBarry Smith     ierr = PetscOptionsReal("-pc_spai_epsilon","","PCSPAISetEpsilon",ispai->epsilon,&epsilon1,&flg);CHKERRQ(ierr);
53801a81e61SBarry Smith     if (flg) {
53901a81e61SBarry Smith       ierr = PCSPAISetEpsilon(pc,epsilon1);CHKERRQ(ierr);
54001a81e61SBarry Smith     }
54101a81e61SBarry Smith     ierr = PetscOptionsInt("-pc_spai_nbsteps","","PCSPAISetNBSteps",ispai->nbsteps,&nbsteps1,&flg);CHKERRQ(ierr);
54201a81e61SBarry Smith     if (flg) {
54301a81e61SBarry Smith       ierr = PCSPAISetNBSteps(pc,nbsteps1);CHKERRQ(ierr);
54401a81e61SBarry Smith     }
54501a81e61SBarry Smith     /* added 1/7/99 g.h. */
54601a81e61SBarry Smith     ierr = PetscOptionsInt("-pc_spai_max","","PCSPAISetMax",ispai->max,&max1,&flg);CHKERRQ(ierr);
54701a81e61SBarry Smith     if (flg) {
54801a81e61SBarry Smith       ierr = PCSPAISetMax(pc,max1);CHKERRQ(ierr);
54901a81e61SBarry Smith     }
55001a81e61SBarry Smith     ierr = PetscOptionsInt("-pc_spai_maxnew","","PCSPAISetMaxNew",ispai->maxnew,&maxnew1,&flg);CHKERRQ(ierr);
55101a81e61SBarry Smith     if (flg) {
55201a81e61SBarry Smith       ierr = PCSPAISetMaxNew(pc,maxnew1);CHKERRQ(ierr);
55301a81e61SBarry Smith     }
55401a81e61SBarry Smith     ierr = PetscOptionsInt("-pc_spai_block_size","","PCSPAISetBlockSize",ispai->block_size,&block_size1,&flg);CHKERRQ(ierr);
55501a81e61SBarry Smith     if (flg) {
55601a81e61SBarry Smith       ierr = PCSPAISetBlockSize(pc,block_size1);CHKERRQ(ierr);
55701a81e61SBarry Smith     }
55801a81e61SBarry Smith     ierr = PetscOptionsInt("-pc_spai_cache_size","","PCSPAISetCacheSize",ispai->cache_size,&cache_size,&flg);CHKERRQ(ierr);
55901a81e61SBarry Smith     if (flg) {
56001a81e61SBarry Smith       ierr = PCSPAISetCacheSize(pc,cache_size);CHKERRQ(ierr);
56101a81e61SBarry Smith     }
56201a81e61SBarry Smith     ierr = PetscOptionsInt("-pc_spai_verbose","","PCSPAISetVerbose",ispai->verbose,&verbose,&flg);CHKERRQ(ierr);
56301a81e61SBarry Smith     if (flg) {
56401a81e61SBarry Smith       ierr = PCSPAISetVerbose(pc,verbose);CHKERRQ(ierr);
56501a81e61SBarry Smith     }
56601a81e61SBarry Smith     ierr = PetscOptionsInt("-pc_spai_sp","","PCSPAISetSp",ispai->sp,&sp,&flg);CHKERRQ(ierr);
56701a81e61SBarry Smith     if (flg) {
56801a81e61SBarry Smith       ierr = PCSPAISetSp(pc,sp);CHKERRQ(ierr);
56901a81e61SBarry Smith     }
57001a81e61SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
57101a81e61SBarry Smith   PetscFunctionReturn(0);
57201a81e61SBarry Smith }
57301a81e61SBarry Smith 
57401a81e61SBarry Smith /**********************************************************************/
57501a81e61SBarry Smith 
57601a81e61SBarry Smith /*MC
57701a81e61SBarry Smith    PCSPAI - Use the Sparse Approximate Inverse method of Grote and Barnard
57801a81e61SBarry Smith      as a preconditioner (SIAM J. Sci. Comput.; vol 18, nr 3)
57901a81e61SBarry Smith 
58001a81e61SBarry Smith    Options Database Keys:
581c5ae99e3SSatish Balay +  -pc_spai_epsilon <eps> - set tolerance
58201a81e61SBarry Smith .  -pc_spai_nbstep <n> - set nbsteps
58301a81e61SBarry Smith .  -pc_spai_max <m> - set max
58401a81e61SBarry Smith .  -pc_spai_max_new <m> - set maxnew
58501a81e61SBarry Smith .  -pc_spai_block_size <n> - set block size
58601a81e61SBarry Smith .  -pc_spai_cache_size <n> - set cache size
58701a81e61SBarry Smith .  -pc_spai_sp <m> - set sp
58801a81e61SBarry Smith -  -pc_spai_set_verbose <true,false> - verbose output
58901a81e61SBarry Smith 
59001a81e61SBarry Smith    Notes: This only works with AIJ matrices.
59101a81e61SBarry Smith 
59201a81e61SBarry Smith    Level: beginner
59301a81e61SBarry Smith 
59401a81e61SBarry Smith    Concepts: approximate inverse
59501a81e61SBarry Smith 
59601a81e61SBarry Smith .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,
59701a81e61SBarry Smith     PCSPAISetEpsilon(), PCSPAISetMax(), PCSPAISetMaxNew(), PCSPAISetBlockSize(),
59801a81e61SBarry Smith     PCSPAISetVerbose(), PCSPAISetSp()
59901a81e61SBarry Smith M*/
60001a81e61SBarry Smith 
60101a81e61SBarry Smith EXTERN_C_BEGIN
60201a81e61SBarry Smith #undef __FUNCT__
60301a81e61SBarry Smith #define __FUNCT__ "PCCreate_SPAI"
6047087cfbeSBarry Smith PetscErrorCode  PCCreate_SPAI(PC pc)
60501a81e61SBarry Smith {
60601a81e61SBarry Smith   PC_SPAI        *ispai;
60701a81e61SBarry Smith   PetscErrorCode ierr;
60801a81e61SBarry Smith 
60901a81e61SBarry Smith   PetscFunctionBegin;
61038f2d2fdSLisandro Dalcin   ierr               = PetscNewLog(pc,PC_SPAI,&ispai);CHKERRQ(ierr);
6112a4967abSBarry Smith   pc->data           = ispai;
61201a81e61SBarry Smith 
61301a81e61SBarry Smith   pc->ops->destroy         = PCDestroy_SPAI;
61401a81e61SBarry Smith   pc->ops->apply           = PCApply_SPAI;
61501a81e61SBarry Smith   pc->ops->applyrichardson = 0;
61601a81e61SBarry Smith   pc->ops->setup           = PCSetUp_SPAI;
61701a81e61SBarry Smith   pc->ops->view            = PCView_SPAI;
61801a81e61SBarry Smith   pc->ops->setfromoptions  = PCSetFromOptions_SPAI;
61901a81e61SBarry Smith 
62001a81e61SBarry Smith   ispai->epsilon    = .4;
62101a81e61SBarry Smith   ispai->nbsteps    = 5;
62201a81e61SBarry Smith   ispai->max        = 5000;
62301a81e61SBarry Smith   ispai->maxnew     = 5;
62401a81e61SBarry Smith   ispai->block_size = 1;
62501a81e61SBarry Smith   ispai->cache_size = 5;
62601a81e61SBarry Smith   ispai->verbose    = 0;
62701a81e61SBarry Smith 
62801a81e61SBarry Smith   ispai->sp         = 1;
6297adad957SLisandro Dalcin   ierr = MPI_Comm_dup(((PetscObject)pc)->comm,&(ispai->comm_spai));CHKERRQ(ierr);
63001a81e61SBarry Smith 
63101a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetEpsilon_C",
63201a81e61SBarry Smith                     "PCSPAISetEpsilon_SPAI",
63301a81e61SBarry Smith                      PCSPAISetEpsilon_SPAI);CHKERRQ(ierr);
63401a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetNBSteps_C",
63501a81e61SBarry Smith                     "PCSPAISetNBSteps_SPAI",
63601a81e61SBarry Smith                      PCSPAISetNBSteps_SPAI);CHKERRQ(ierr);
63701a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetMax_C",
63801a81e61SBarry Smith                     "PCSPAISetMax_SPAI",
63901a81e61SBarry Smith                      PCSPAISetMax_SPAI);CHKERRQ(ierr);
64001a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetMaxNew_CC",
64101a81e61SBarry Smith                     "PCSPAISetMaxNew_SPAI",
64201a81e61SBarry Smith                      PCSPAISetMaxNew_SPAI);CHKERRQ(ierr);
64301a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetBlockSize_C",
64401a81e61SBarry Smith                     "PCSPAISetBlockSize_SPAI",
64501a81e61SBarry Smith                      PCSPAISetBlockSize_SPAI);CHKERRQ(ierr);
64601a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetCacheSize_C",
64701a81e61SBarry Smith                     "PCSPAISetCacheSize_SPAI",
64801a81e61SBarry Smith                      PCSPAISetCacheSize_SPAI);CHKERRQ(ierr);
64901a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetVerbose_C",
65001a81e61SBarry Smith                     "PCSPAISetVerbose_SPAI",
65101a81e61SBarry Smith                      PCSPAISetVerbose_SPAI);CHKERRQ(ierr);
65201a81e61SBarry Smith   ierr = PetscObjectComposeFunctionDynamic((PetscObject)pc,"PCSPAISetSp_C",
65301a81e61SBarry Smith                     "PCSPAISetSp_SPAI",
65401a81e61SBarry Smith                      PCSPAISetSp_SPAI);CHKERRQ(ierr);
65501a81e61SBarry Smith 
65601a81e61SBarry Smith   PetscFunctionReturn(0);
65701a81e61SBarry Smith }
65801a81e61SBarry Smith EXTERN_C_END
65901a81e61SBarry Smith 
66001a81e61SBarry Smith /**********************************************************************/
66101a81e61SBarry Smith 
66201a81e61SBarry Smith /*
66301a81e61SBarry Smith    Converts from a PETSc matrix to an SPAI matrix
66401a81e61SBarry Smith */
66501a81e61SBarry Smith #undef __FUNCT__
66601a81e61SBarry Smith #define __FUNCT__ "ConvertMatToMatrix"
66701a81e61SBarry Smith PetscErrorCode ConvertMatToMatrix(MPI_Comm comm, Mat A,Mat AT,matrix **B)
66801a81e61SBarry Smith {
66901a81e61SBarry Smith   matrix                  *M;
67001a81e61SBarry Smith   int                     i,j,col;
67101a81e61SBarry Smith   int                     row_indx;
67201a81e61SBarry Smith   int                     len,pe,local_indx,start_indx;
67301a81e61SBarry Smith   int                     *mapping;
67401a81e61SBarry Smith   PetscErrorCode          ierr;
67501a81e61SBarry Smith   const int               *cols;
67601a81e61SBarry Smith   const double            *vals;
6772a4967abSBarry Smith   int                     *num_ptr,n,mnl,nnl,nz,rstart,rend;
6782a4967abSBarry Smith   PetscMPIInt             size,rank;
67901a81e61SBarry Smith   struct compressed_lines *rows;
68001a81e61SBarry Smith 
68101a81e61SBarry Smith   PetscFunctionBegin;
68201a81e61SBarry Smith 
68301a81e61SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
68401a81e61SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
68501a81e61SBarry Smith   ierr = MatGetSize(A,&n,&n);CHKERRQ(ierr);
68601a81e61SBarry Smith   ierr = MatGetLocalSize(A,&mnl,&nnl);CHKERRQ(ierr);
68701a81e61SBarry Smith 
68801a81e61SBarry Smith   /*
68901a81e61SBarry Smith     not sure why a barrier is required. commenting out
69001a81e61SBarry Smith   ierr = MPI_Barrier(comm);CHKERRQ(ierr);
69101a81e61SBarry Smith   */
69201a81e61SBarry Smith 
69329b2f704SSatish Balay   M = new_matrix((SPAI_Comm)comm);
69401a81e61SBarry Smith 
69501a81e61SBarry Smith   M->n = n;
69601a81e61SBarry Smith   M->bs = 1;
69701a81e61SBarry Smith   M->max_block_size = 1;
69801a81e61SBarry Smith 
69901a81e61SBarry Smith   M->mnls          = (int*)malloc(sizeof(int)*size);
70001a81e61SBarry Smith   M->start_indices = (int*)malloc(sizeof(int)*size);
70101a81e61SBarry Smith   M->pe            = (int*)malloc(sizeof(int)*n);
70201a81e61SBarry Smith   M->block_sizes   = (int*)malloc(sizeof(int)*n);
70301a81e61SBarry Smith   for (i=0; i<n; i++) M->block_sizes[i] = 1;
70401a81e61SBarry Smith 
70501a81e61SBarry Smith   ierr = MPI_Allgather(&mnl,1,MPI_INT,M->mnls,1,MPI_INT,comm);CHKERRQ(ierr);
70601a81e61SBarry Smith 
70701a81e61SBarry Smith   M->start_indices[0] = 0;
70801a81e61SBarry Smith   for (i=1; i<size; i++) {
70901a81e61SBarry Smith     M->start_indices[i] = M->start_indices[i-1] + M->mnls[i-1];
71001a81e61SBarry Smith   }
71101a81e61SBarry Smith 
71201a81e61SBarry Smith   M->mnl = M->mnls[M->myid];
71301a81e61SBarry Smith   M->my_start_index = M->start_indices[M->myid];
71401a81e61SBarry Smith 
71501a81e61SBarry Smith   for (i=0; i<size; i++) {
71601a81e61SBarry Smith     start_indx = M->start_indices[i];
71701a81e61SBarry Smith     for (j=0; j<M->mnls[i]; j++)
71801a81e61SBarry Smith       M->pe[start_indx+j] = i;
71901a81e61SBarry Smith   }
72001a81e61SBarry Smith 
72101a81e61SBarry Smith   if (AT) {
72201a81e61SBarry Smith     M->lines = new_compressed_lines(M->mnls[rank],1);CHKERRQ(ierr);
72301a81e61SBarry Smith   } else {
72401a81e61SBarry Smith     M->lines = new_compressed_lines(M->mnls[rank],0);CHKERRQ(ierr);
72501a81e61SBarry Smith   }
72601a81e61SBarry Smith 
72701a81e61SBarry Smith   rows = M->lines;
72801a81e61SBarry Smith 
72901a81e61SBarry Smith   /* Determine the mapping from global indices to pointers */
73001a81e61SBarry Smith   ierr       = PetscMalloc(M->n*sizeof(int),&mapping);CHKERRQ(ierr);
73101a81e61SBarry Smith   pe         = 0;
73201a81e61SBarry Smith   local_indx = 0;
73301a81e61SBarry Smith   for (i=0; i<M->n; i++) {
73401a81e61SBarry Smith     if (local_indx >= M->mnls[pe]) {
73501a81e61SBarry Smith       pe++;
73601a81e61SBarry Smith       local_indx = 0;
73701a81e61SBarry Smith     }
73801a81e61SBarry Smith     mapping[i] = local_indx + M->start_indices[pe];
73901a81e61SBarry Smith     local_indx++;
74001a81e61SBarry Smith   }
74101a81e61SBarry Smith 
74201a81e61SBarry Smith 
74301a81e61SBarry Smith   ierr = PetscMalloc(mnl*sizeof(int),&num_ptr);CHKERRQ(ierr);
74401a81e61SBarry Smith 
74501a81e61SBarry Smith   /*********************************************************/
74601a81e61SBarry Smith   /************** Set up the row structure *****************/
74701a81e61SBarry Smith   /*********************************************************/
74801a81e61SBarry Smith 
74901a81e61SBarry Smith   /* count number of nonzeros in every row */
75001a81e61SBarry Smith   ierr = MatGetOwnershipRange(A,&rstart,&rend);CHKERRQ(ierr);
75101a81e61SBarry Smith   for (i=rstart; i<rend; i++) {
75201a81e61SBarry Smith     ierr = MatGetRow(A,i,&num_ptr[i-rstart],PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
75301a81e61SBarry Smith     ierr = MatRestoreRow(A,i,&num_ptr[i-rstart],PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
75401a81e61SBarry Smith   }
75501a81e61SBarry Smith 
75601a81e61SBarry Smith   /* allocate buffers */
75701a81e61SBarry Smith   len = 0;
75801a81e61SBarry Smith   for (i=0; i<mnl; i++) {
75901a81e61SBarry Smith     if (len < num_ptr[i]) len = num_ptr[i];
76001a81e61SBarry Smith   }
76101a81e61SBarry Smith 
76201a81e61SBarry Smith   for (i=rstart; i<rend; i++) {
76301a81e61SBarry Smith     row_indx             = i-rstart;
76401a81e61SBarry Smith     len                  = num_ptr[row_indx];
76501a81e61SBarry Smith     rows->ptrs[row_indx] = (int*)malloc(len*sizeof(int));
76601a81e61SBarry Smith     rows->A[row_indx]    = (double*)malloc(len*sizeof(double));
76701a81e61SBarry Smith   }
76801a81e61SBarry Smith 
76901a81e61SBarry Smith   /* copy the matrix */
77001a81e61SBarry Smith   for (i=rstart; i<rend; i++) {
77101a81e61SBarry Smith     row_indx = i - rstart;
77201a81e61SBarry Smith     ierr     = MatGetRow(A,i,&nz,&cols,&vals);CHKERRQ(ierr);
77301a81e61SBarry Smith     for (j=0; j<nz; j++) {
77401a81e61SBarry Smith       col = cols[j];
77501a81e61SBarry Smith       len = rows->len[row_indx]++;
77601a81e61SBarry Smith       rows->ptrs[row_indx][len] = mapping[col];
77701a81e61SBarry Smith       rows->A[row_indx][len]    = vals[j];
77801a81e61SBarry Smith     }
77901a81e61SBarry Smith     rows->slen[row_indx] = rows->len[row_indx];
78001a81e61SBarry Smith     ierr = MatRestoreRow(A,i,&nz,&cols,&vals);CHKERRQ(ierr);
78101a81e61SBarry Smith   }
78201a81e61SBarry Smith 
78301a81e61SBarry Smith 
78401a81e61SBarry Smith   /************************************************************/
78501a81e61SBarry Smith   /************** Set up the column structure *****************/
78601a81e61SBarry Smith   /*********************************************************/
78701a81e61SBarry Smith 
78801a81e61SBarry Smith   if (AT) {
78901a81e61SBarry Smith 
79001a81e61SBarry Smith     /* count number of nonzeros in every column */
79101a81e61SBarry Smith     for (i=rstart; i<rend; i++) {
79201a81e61SBarry Smith       ierr = MatGetRow(AT,i,&num_ptr[i-rstart],PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
79301a81e61SBarry Smith       ierr = MatRestoreRow(AT,i,&num_ptr[i-rstart],PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
79401a81e61SBarry Smith     }
79501a81e61SBarry Smith 
79601a81e61SBarry Smith     /* allocate buffers */
79701a81e61SBarry Smith     len = 0;
79801a81e61SBarry Smith     for (i=0; i<mnl; i++) {
79901a81e61SBarry Smith       if (len < num_ptr[i]) len = num_ptr[i];
80001a81e61SBarry Smith     }
80101a81e61SBarry Smith 
80201a81e61SBarry Smith     for (i=rstart; i<rend; i++) {
80301a81e61SBarry Smith       row_indx = i-rstart;
80401a81e61SBarry Smith       len      = num_ptr[row_indx];
80501a81e61SBarry Smith       rows->rptrs[row_indx] = (int*)malloc(len*sizeof(int));
80601a81e61SBarry Smith     }
80701a81e61SBarry Smith 
80801a81e61SBarry Smith     /* copy the matrix (i.e., the structure) */
80901a81e61SBarry Smith     for (i=rstart; i<rend; i++) {
81001a81e61SBarry Smith       row_indx = i - rstart;
81101a81e61SBarry Smith       ierr     = MatGetRow(AT,i,&nz,&cols,&vals);CHKERRQ(ierr);
81201a81e61SBarry Smith       for (j=0; j<nz; j++) {
81301a81e61SBarry Smith 	col = cols[j];
81401a81e61SBarry Smith 	len = rows->rlen[row_indx]++;
81501a81e61SBarry Smith 	rows->rptrs[row_indx][len] = mapping[col];
81601a81e61SBarry Smith       }
81701a81e61SBarry Smith       ierr = MatRestoreRow(AT,i,&nz,&cols,&vals);CHKERRQ(ierr);
81801a81e61SBarry Smith     }
81901a81e61SBarry Smith   }
82001a81e61SBarry Smith 
82101a81e61SBarry Smith   ierr = PetscFree(num_ptr);CHKERRQ(ierr);
82201a81e61SBarry Smith   ierr = PetscFree(mapping);CHKERRQ(ierr);
82301a81e61SBarry Smith 
82401a81e61SBarry Smith   order_pointers(M);
82501a81e61SBarry Smith   M->maxnz = calc_maxnz(M);
82601a81e61SBarry Smith 
82701a81e61SBarry Smith   *B = M;
82801a81e61SBarry Smith 
82901a81e61SBarry Smith   PetscFunctionReturn(0);
83001a81e61SBarry Smith }
83101a81e61SBarry Smith 
83201a81e61SBarry Smith /**********************************************************************/
83301a81e61SBarry Smith 
83401a81e61SBarry Smith /*
83501a81e61SBarry Smith    Converts from an SPAI matrix B  to a PETSc matrix PB.
83601a81e61SBarry Smith    This assumes that the the SPAI matrix B is stored in
83701a81e61SBarry Smith    COMPRESSED-ROW format.
83801a81e61SBarry Smith */
83901a81e61SBarry Smith #undef __FUNCT__
84001a81e61SBarry Smith #define __FUNCT__ "ConvertMatrixToMat"
84101a81e61SBarry Smith PetscErrorCode ConvertMatrixToMat(MPI_Comm comm,matrix *B,Mat *PB)
84201a81e61SBarry Smith {
8434b6b5fe1SBarry Smith   PetscMPIInt    size,rank;
84401a81e61SBarry Smith   PetscErrorCode ierr;
84501a81e61SBarry Smith   int            m,n,M,N;
84601a81e61SBarry Smith   int            d_nz,o_nz;
84701a81e61SBarry Smith   int            *d_nnz,*o_nnz;
84801a81e61SBarry Smith   int            i,k,global_row,global_col,first_diag_col,last_diag_col;
84901a81e61SBarry Smith   PetscScalar    val;
85001a81e61SBarry Smith 
85101a81e61SBarry Smith   PetscFunctionBegin;
85201a81e61SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
85301a81e61SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
85401a81e61SBarry Smith 
85501a81e61SBarry Smith   m = n = B->mnls[rank];
85601a81e61SBarry Smith   d_nz = o_nz = 0;
85701a81e61SBarry Smith 
85801a81e61SBarry Smith   /* Determine preallocation for MatCreateMPIAIJ */
8592a4967abSBarry Smith   ierr = PetscMalloc(m*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
8602a4967abSBarry Smith   ierr = PetscMalloc(m*sizeof(PetscInt),&o_nnz);CHKERRQ(ierr);
86101a81e61SBarry Smith   for (i=0; i<m; i++) d_nnz[i] = o_nnz[i] = 0;
86201a81e61SBarry Smith   first_diag_col = B->start_indices[rank];
86301a81e61SBarry Smith   last_diag_col = first_diag_col + B->mnls[rank];
86401a81e61SBarry Smith   for (i=0; i<B->mnls[rank]; i++) {
86501a81e61SBarry Smith     for (k=0; k<B->lines->len[i]; k++) {
86601a81e61SBarry Smith       global_col = B->lines->ptrs[i][k];
86701a81e61SBarry Smith       if ((global_col >= first_diag_col) && (global_col <= last_diag_col))
86801a81e61SBarry Smith 	d_nnz[i]++;
86901a81e61SBarry Smith       else
87001a81e61SBarry Smith 	o_nnz[i]++;
87101a81e61SBarry Smith     }
87201a81e61SBarry Smith   }
87301a81e61SBarry Smith 
87401a81e61SBarry Smith   M = N = B->n;
87501a81e61SBarry Smith   /* Here we only know how to create AIJ format */
876f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,PB);CHKERRQ(ierr);
877f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*PB,m,n,M,N);CHKERRQ(ierr);
87801a81e61SBarry Smith   ierr = MatSetType(*PB,MATAIJ);CHKERRQ(ierr);
87901a81e61SBarry Smith   ierr = MatSeqAIJSetPreallocation(*PB,d_nz,d_nnz);CHKERRQ(ierr);
88001a81e61SBarry Smith   ierr = MatMPIAIJSetPreallocation(*PB,d_nz,d_nnz,o_nz,o_nnz);CHKERRQ(ierr);
88101a81e61SBarry Smith 
88201a81e61SBarry Smith   for (i=0; i<B->mnls[rank]; i++) {
88301a81e61SBarry Smith     global_row = B->start_indices[rank]+i;
88401a81e61SBarry Smith     for (k=0; k<B->lines->len[i]; k++) {
88501a81e61SBarry Smith       global_col = B->lines->ptrs[i][k];
88601a81e61SBarry Smith       val = B->lines->A[i][k];
88701a81e61SBarry Smith       ierr = MatSetValues(*PB,1,&global_row,1,&global_col,&val,ADD_VALUES);CHKERRQ(ierr);
88801a81e61SBarry Smith     }
88901a81e61SBarry Smith   }
89001a81e61SBarry Smith 
89101a81e61SBarry Smith   ierr = PetscFree(d_nnz);CHKERRQ(ierr);
89201a81e61SBarry Smith   ierr = PetscFree(o_nnz);CHKERRQ(ierr);
89301a81e61SBarry Smith 
89401a81e61SBarry Smith   ierr = MatAssemblyBegin(*PB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
89501a81e61SBarry Smith   ierr = MatAssemblyEnd(*PB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
89601a81e61SBarry Smith 
89701a81e61SBarry Smith   PetscFunctionReturn(0);
89801a81e61SBarry Smith }
89901a81e61SBarry Smith 
90001a81e61SBarry Smith /**********************************************************************/
90101a81e61SBarry Smith 
90201a81e61SBarry Smith /*
90301a81e61SBarry Smith    Converts from an SPAI vector v  to a PETSc vec Pv.
90401a81e61SBarry Smith */
90501a81e61SBarry Smith #undef __FUNCT__
90601a81e61SBarry Smith #define __FUNCT__ "ConvertVectorToVec"
90701a81e61SBarry Smith PetscErrorCode ConvertVectorToVec(MPI_Comm comm,vector *v,Vec *Pv)
90801a81e61SBarry Smith {
90901a81e61SBarry Smith   PetscErrorCode ierr;
9104b6b5fe1SBarry Smith   PetscMPIInt    size,rank;
9114b6b5fe1SBarry Smith   int            m,M,i,*mnls,*start_indices,*global_indices;
91201a81e61SBarry Smith 
91301a81e61SBarry Smith   PetscFunctionBegin;
91401a81e61SBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
91501a81e61SBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
91601a81e61SBarry Smith 
91701a81e61SBarry Smith   m = v->mnl;
91801a81e61SBarry Smith   M = v->n;
91901a81e61SBarry Smith 
92001a81e61SBarry Smith 
92101a81e61SBarry Smith   ierr = VecCreateMPI(comm,m,M,Pv);CHKERRQ(ierr);
92201a81e61SBarry Smith 
92301a81e61SBarry Smith   ierr = PetscMalloc(size*sizeof(int),&mnls);CHKERRQ(ierr);
9242a4967abSBarry Smith   ierr = MPI_Allgather(&v->mnl,1,MPI_INT,mnls,1,MPI_INT,comm);CHKERRQ(ierr);
92501a81e61SBarry Smith 
92601a81e61SBarry Smith   ierr = PetscMalloc(size*sizeof(int),&start_indices);CHKERRQ(ierr);
92701a81e61SBarry Smith   start_indices[0] = 0;
92801a81e61SBarry Smith   for (i=1; i<size; i++)
92901a81e61SBarry Smith     start_indices[i] = start_indices[i-1] +mnls[i-1];
93001a81e61SBarry Smith 
93101a81e61SBarry Smith   ierr = PetscMalloc(v->mnl*sizeof(int),&global_indices);CHKERRQ(ierr);
93201a81e61SBarry Smith   for (i=0; i<v->mnl; i++)
93301a81e61SBarry Smith     global_indices[i] = start_indices[rank] + i;
93401a81e61SBarry Smith 
93501a81e61SBarry Smith   ierr = PetscFree(mnls);CHKERRQ(ierr);
93601a81e61SBarry Smith   ierr = PetscFree(start_indices);CHKERRQ(ierr);
93701a81e61SBarry Smith 
93801a81e61SBarry Smith   ierr = VecSetValues(*Pv,v->mnl,global_indices,v->v,INSERT_VALUES);CHKERRQ(ierr);
93901a81e61SBarry Smith   ierr = VecAssemblyBegin(*Pv);CHKERRQ(ierr);
94001a81e61SBarry Smith   ierr = VecAssemblyEnd(*Pv);CHKERRQ(ierr);
94101a81e61SBarry Smith 
9424b6b5fe1SBarry Smith   ierr = PetscFree(global_indices);CHKERRQ(ierr);
94301a81e61SBarry Smith   PetscFunctionReturn(0);
94401a81e61SBarry Smith }
94501a81e61SBarry Smith 
94601a81e61SBarry Smith 
94701a81e61SBarry Smith 
94801a81e61SBarry Smith 
949