xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 41f5e1b12945b656a8400dc9a13b2f7fba7b2c0b)
1d5d45c9bSBarry Smith /*
23369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
3d5d45c9bSBarry Smith   matrix storage format.
4d5d45c9bSBarry Smith */
53369ce9aSBarry Smith 
67c4f633dSBarry Smith 
7c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
8c6db04a5SJed Brown #include <petscblaslapack.h>
9c6db04a5SJed Brown #include <petscbt.h>
10af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
110716a85fSBarry Smith 
124099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
134099cc6bSBarry Smith {
144099cc6bSBarry Smith   PetscErrorCode       ierr;
154099cc6bSBarry Smith   PetscBool            flg;
164099cc6bSBarry Smith   char                 type[256];
174099cc6bSBarry Smith 
184099cc6bSBarry Smith   PetscFunctionBegin;
194099cc6bSBarry Smith   ierr = PetscObjectOptionsBegin((PetscObject)A);
204099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
214099cc6bSBarry Smith   if (flg) {
224099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
234099cc6bSBarry Smith   }
244099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
254099cc6bSBarry Smith   PetscFunctionReturn(0);
264099cc6bSBarry Smith }
274099cc6bSBarry Smith 
280716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
290716a85fSBarry Smith {
300716a85fSBarry Smith   PetscErrorCode ierr;
310716a85fSBarry Smith   PetscInt       i,m,n;
320716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
330716a85fSBarry Smith 
340716a85fSBarry Smith   PetscFunctionBegin;
350716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
36580bdb30SBarry Smith   ierr = PetscArrayzero(norms,n);CHKERRQ(ierr);
370716a85fSBarry Smith   if (type == NORM_2) {
380716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
390716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
400716a85fSBarry Smith     }
410716a85fSBarry Smith   } else if (type == NORM_1) {
420716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
430716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
440716a85fSBarry Smith     }
450716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
460716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
470716a85fSBarry Smith       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
480716a85fSBarry Smith     }
490716a85fSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");
500716a85fSBarry Smith 
510716a85fSBarry Smith   if (type == NORM_2) {
528f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
530716a85fSBarry Smith   }
540716a85fSBarry Smith   PetscFunctionReturn(0);
550716a85fSBarry Smith }
560716a85fSBarry Smith 
573a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
583a062f41SBarry Smith {
593a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
603a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
613a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
623a062f41SBarry Smith   PetscInt        *rows;
633a062f41SBarry Smith   PetscErrorCode  ierr;
643a062f41SBarry Smith 
653a062f41SBarry Smith   PetscFunctionBegin;
663a062f41SBarry Smith   for (i=0; i<m; i++) {
673a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
683a062f41SBarry Smith       cnt++;
693a062f41SBarry Smith     }
703a062f41SBarry Smith   }
713a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
723a062f41SBarry Smith   cnt  = 0;
733a062f41SBarry Smith   for (i=0; i<m; i++) {
743a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
753a062f41SBarry Smith       rows[cnt] = i;
763a062f41SBarry Smith       cnt++;
773a062f41SBarry Smith     }
783a062f41SBarry Smith   }
793a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
803a062f41SBarry Smith   PetscFunctionReturn(0);
813a062f41SBarry Smith }
823a062f41SBarry Smith 
83f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
846ce1633cSBarry Smith {
856ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
866ce1633cSBarry Smith   const MatScalar *aa = a->a;
876ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
88b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
896ce1633cSBarry Smith   PetscInt        *rows;
906ce1633cSBarry Smith   PetscErrorCode  ierr;
916ce1633cSBarry Smith 
926ce1633cSBarry Smith   PetscFunctionBegin;
936ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
946ce1633cSBarry Smith   diag = a->diag;
956ce1633cSBarry Smith   for (i=0; i<m; i++) {
96b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
976ce1633cSBarry Smith       cnt++;
986ce1633cSBarry Smith     }
996ce1633cSBarry Smith   }
100785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1016ce1633cSBarry Smith   cnt  = 0;
1026ce1633cSBarry Smith   for (i=0; i<m; i++) {
103b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1046ce1633cSBarry Smith       rows[cnt++] = i;
1056ce1633cSBarry Smith     }
1066ce1633cSBarry Smith   }
107f1f41ecbSJed Brown   *nrows = cnt;
108f1f41ecbSJed Brown   *zrows = rows;
109f1f41ecbSJed Brown   PetscFunctionReturn(0);
110f1f41ecbSJed Brown }
111f1f41ecbSJed Brown 
112f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
113f1f41ecbSJed Brown {
114f1f41ecbSJed Brown   PetscInt       nrows,*rows;
115f1f41ecbSJed Brown   PetscErrorCode ierr;
116f1f41ecbSJed Brown 
117f1f41ecbSJed Brown   PetscFunctionBegin;
1180298fd71SBarry Smith   *zrows = NULL;
119f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
120ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1216ce1633cSBarry Smith   PetscFunctionReturn(0);
1226ce1633cSBarry Smith }
1236ce1633cSBarry Smith 
124b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
125b3a44c85SBarry Smith {
126b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
127b3a44c85SBarry Smith   const MatScalar *aa;
128b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
129b3a44c85SBarry Smith   const PetscInt  *ii;
130b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
131b3a44c85SBarry Smith   PetscErrorCode  ierr;
132b3a44c85SBarry Smith 
133b3a44c85SBarry Smith   PetscFunctionBegin;
1342e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
135f4259b30SLisandro Dalcin   *keptrows = NULL;
136b3a44c85SBarry Smith   ii        = a->i;
137b3a44c85SBarry Smith   for (i=0; i<m; i++) {
138b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
139b3a44c85SBarry Smith     if (!n) {
140b3a44c85SBarry Smith       cnt++;
141b3a44c85SBarry Smith       goto ok1;
142b3a44c85SBarry Smith     }
1432e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
144b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
145b3a44c85SBarry Smith     }
146b3a44c85SBarry Smith     cnt++;
147b3a44c85SBarry Smith ok1:;
148b3a44c85SBarry Smith   }
1492e5835c6SStefano Zampini   if (!cnt) {
1502e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1512e5835c6SStefano Zampini     PetscFunctionReturn(0);
1522e5835c6SStefano Zampini   }
153854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
154b3a44c85SBarry Smith   cnt  = 0;
155b3a44c85SBarry Smith   for (i=0; i<m; i++) {
156b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
157b3a44c85SBarry Smith     if (!n) continue;
1582e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
159b3a44c85SBarry Smith       if (aa[j] != 0.0) {
160b3a44c85SBarry Smith         rows[cnt++] = i;
161b3a44c85SBarry Smith         break;
162b3a44c85SBarry Smith       }
163b3a44c85SBarry Smith     }
164b3a44c85SBarry Smith   }
1652e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
166b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
167b3a44c85SBarry Smith   PetscFunctionReturn(0);
168b3a44c85SBarry Smith }
169b3a44c85SBarry Smith 
1707087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
17179299369SBarry Smith {
17279299369SBarry Smith   PetscErrorCode    ierr;
17379299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17499e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17599e65526SBarry Smith   const PetscInt    *diag;
1762e5835c6SStefano Zampini   MatScalar         *aa;
17799e65526SBarry Smith   const PetscScalar *v;
178ace3abfcSBarry Smith   PetscBool         missing;
1798c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
180837a59e1SRichard Tran Mills   PetscBool         inserted = PETSC_FALSE;
181837a59e1SRichard Tran Mills #endif
18279299369SBarry Smith 
18379299369SBarry Smith   PetscFunctionBegin;
18409f38230SBarry Smith   if (Y->assembled) {
1850298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
18609f38230SBarry Smith     if (!missing) {
18779299369SBarry Smith       diag = aij->diag;
18899e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
1892e5835c6SStefano Zampini       ierr = MatSeqAIJGetArray(Y,&aa);CHKERRQ(ierr);
19079299369SBarry Smith       if (is == INSERT_VALUES) {
1918c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
192837a59e1SRichard Tran Mills         inserted = PETSC_TRUE;
193837a59e1SRichard Tran Mills #endif
19479299369SBarry Smith         for (i=0; i<m; i++) {
19579299369SBarry Smith           aa[diag[i]] = v[i];
19679299369SBarry Smith         }
19779299369SBarry Smith       } else {
19879299369SBarry Smith         for (i=0; i<m; i++) {
1998c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
200837a59e1SRichard Tran Mills           if (v[i] != 0.0) inserted = PETSC_TRUE;
201837a59e1SRichard Tran Mills #endif
20279299369SBarry Smith           aa[diag[i]] += v[i];
20379299369SBarry Smith         }
20479299369SBarry Smith       }
2052e5835c6SStefano Zampini       ierr = MatSeqAIJRestoreArray(Y,&aa);CHKERRQ(ierr);
2068c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
207837a59e1SRichard Tran Mills       if (inserted) Y->offloadmask = PETSC_OFFLOAD_CPU;
208837a59e1SRichard Tran Mills #endif
20999e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
21079299369SBarry Smith       PetscFunctionReturn(0);
21179299369SBarry Smith     }
212acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
21309f38230SBarry Smith   }
21409f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
21509f38230SBarry Smith   PetscFunctionReturn(0);
21609f38230SBarry Smith }
21779299369SBarry Smith 
2181a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21917ab2063SBarry Smith {
220416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
221dfbe8321SBarry Smith   PetscErrorCode ierr;
22297f1f81fSBarry Smith   PetscInt       i,ishift;
22317ab2063SBarry Smith 
2243a40ed3dSBarry Smith   PetscFunctionBegin;
225d0f46423SBarry Smith   *m = A->rmap->n;
2263a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
227bfeeae90SHong Zhang   ishift = 0;
22853e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2292462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
230bfeeae90SHong Zhang   } else if (oshift == 1) {
2311a83f524SJed Brown     PetscInt *tia;
232d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2333b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
234854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2351a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2361a83f524SJed Brown     *ia = tia;
237ecc77c7aSBarry Smith     if (ja) {
2381a83f524SJed Brown       PetscInt *tja;
239854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2401a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2411a83f524SJed Brown       *ja = tja;
242ecc77c7aSBarry Smith     }
2436945ee14SBarry Smith   } else {
244ecc77c7aSBarry Smith     *ia = a->i;
245ecc77c7aSBarry Smith     if (ja) *ja = a->j;
246a2ce50c7SBarry Smith   }
2473a40ed3dSBarry Smith   PetscFunctionReturn(0);
248a2744918SBarry Smith }
249a2744918SBarry Smith 
2501a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2516945ee14SBarry Smith {
252dfbe8321SBarry Smith   PetscErrorCode ierr;
2536945ee14SBarry Smith 
2543a40ed3dSBarry Smith   PetscFunctionBegin;
2553a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
256bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
257606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
258ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
259bcd2baecSBarry Smith   }
2603a40ed3dSBarry Smith   PetscFunctionReturn(0);
26117ab2063SBarry Smith }
26217ab2063SBarry Smith 
2631a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2643b2fbd54SBarry Smith {
2653b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
266dfbe8321SBarry Smith   PetscErrorCode ierr;
267d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
26897f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2693b2fbd54SBarry Smith 
2703a40ed3dSBarry Smith   PetscFunctionBegin;
271899cda47SBarry Smith   *nn = n;
2723a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2733b2fbd54SBarry Smith   if (symmetric) {
2742462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2753b2fbd54SBarry Smith   } else {
276b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
277854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
278b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2793b2fbd54SBarry Smith     jj   = a->j;
2803b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
281bfeeae90SHong Zhang       collengths[jj[i]]++;
2823b2fbd54SBarry Smith     }
2833b2fbd54SBarry Smith     cia[0] = oshift;
2843b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2853b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2863b2fbd54SBarry Smith     }
287580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2883b2fbd54SBarry Smith     jj   = a->j;
289a93ec695SBarry Smith     for (row=0; row<m; row++) {
290a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
291a93ec695SBarry Smith       for (i=0; i<mr; i++) {
292bfeeae90SHong Zhang         col = *jj++;
2932205254eSKarl Rupp 
2943b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2953b2fbd54SBarry Smith       }
2963b2fbd54SBarry Smith     }
297606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2983b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2993b2fbd54SBarry Smith   }
3003a40ed3dSBarry Smith   PetscFunctionReturn(0);
3013b2fbd54SBarry Smith }
3023b2fbd54SBarry Smith 
3031a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
3043b2fbd54SBarry Smith {
305dfbe8321SBarry Smith   PetscErrorCode ierr;
306606d414cSSatish Balay 
3073a40ed3dSBarry Smith   PetscFunctionBegin;
3083a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3093b2fbd54SBarry Smith 
310606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
311606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3123a40ed3dSBarry Smith   PetscFunctionReturn(0);
3133b2fbd54SBarry Smith }
3143b2fbd54SBarry Smith 
3157cee066cSHong Zhang /*
3167cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3177cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
318040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3197cee066cSHong Zhang */
3207cee066cSHong Zhang PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3217cee066cSHong Zhang {
3227cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3237cee066cSHong Zhang   PetscErrorCode ierr;
3247cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
325071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3267cee066cSHong Zhang   PetscInt       *cspidx;
327071fcb05SBarry Smith   const PetscInt *jj;
3287cee066cSHong Zhang 
3297cee066cSHong Zhang   PetscFunctionBegin;
3307cee066cSHong Zhang   *nn = n;
3317cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
332625f6d37SHong Zhang 
333b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
334854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
335b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
336b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3377cee066cSHong Zhang   jj   = a->j;
3387cee066cSHong Zhang   for (i=0; i<nz; i++) {
3397cee066cSHong Zhang     collengths[jj[i]]++;
3407cee066cSHong Zhang   }
3417cee066cSHong Zhang   cia[0] = oshift;
3427cee066cSHong Zhang   for (i=0; i<n; i++) {
3437cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3447cee066cSHong Zhang   }
345580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3467cee066cSHong Zhang   jj   = a->j;
3477cee066cSHong Zhang   for (row=0; row<m; row++) {
3487cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3497cee066cSHong Zhang     for (i=0; i<mr; i++) {
3507cee066cSHong Zhang       col         = *jj++;
351071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
352071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
353071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3547cee066cSHong Zhang     }
3557cee066cSHong Zhang   }
3567cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
357071fcb05SBarry Smith   *ia    = cia;
358071fcb05SBarry Smith   *ja    = cja;
3597cee066cSHong Zhang   *spidx = cspidx;
3607cee066cSHong Zhang   PetscFunctionReturn(0);
3617cee066cSHong Zhang }
3627cee066cSHong Zhang 
3637cee066cSHong Zhang PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3647cee066cSHong Zhang {
3657cee066cSHong Zhang   PetscErrorCode ierr;
3667cee066cSHong Zhang 
3677cee066cSHong Zhang   PetscFunctionBegin;
3685243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3697cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3707cee066cSHong Zhang   PetscFunctionReturn(0);
3717cee066cSHong Zhang }
3727cee066cSHong Zhang 
37387d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
37487d4246cSBarry Smith {
37587d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
37687d4246cSBarry Smith   PetscInt       *ai = a->i;
37787d4246cSBarry Smith   PetscErrorCode ierr;
37887d4246cSBarry Smith 
37987d4246cSBarry Smith   PetscFunctionBegin;
380580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
3818c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
382c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
383e2cf4d64SStefano Zampini #endif
38487d4246cSBarry Smith   PetscFunctionReturn(0);
38587d4246cSBarry Smith }
38687d4246cSBarry Smith 
387bd04181cSBarry Smith /*
388bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
389bd04181cSBarry Smith 
390bd04181cSBarry Smith       -   a single row of values is set with each call
391bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
392bd04181cSBarry Smith       -   the values are always added to the matrix, not set
393bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
394bd04181cSBarry Smith 
3951f763a69SBarry Smith      This does NOT assume the global column indices are sorted
396bd04181cSBarry Smith 
3971f763a69SBarry Smith */
398bd04181cSBarry Smith 
399af0996ceSBarry Smith #include <petsc/private/isimpl.h>
400189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
401189e4007SBarry Smith {
402189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4031f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
4041f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4051f763a69SBarry Smith   PetscInt       lastcol = -1;
406189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
407189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
408189e4007SBarry Smith 
409f38dd0b8SBarry Smith   row  = ridx[im[0]];
4101f763a69SBarry Smith   rp   = aj + ai[row];
4111f763a69SBarry Smith   ap   = aa + ai[row];
4121f763a69SBarry Smith   nrow = ailen[row];
413189e4007SBarry Smith   low  = 0;
414189e4007SBarry Smith   high = nrow;
415189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
416189e4007SBarry Smith     col = cidx[in[l]];
417f38dd0b8SBarry Smith     value = v[l];
418189e4007SBarry Smith 
419189e4007SBarry Smith     if (col <= lastcol) low = 0;
420189e4007SBarry Smith     else high = nrow;
421189e4007SBarry Smith     lastcol = col;
422189e4007SBarry Smith     while (high-low > 5) {
423189e4007SBarry Smith       t = (low+high)/2;
424189e4007SBarry Smith       if (rp[t] > col) high = t;
425189e4007SBarry Smith       else low = t;
426189e4007SBarry Smith     }
427189e4007SBarry Smith     for (i=low; i<high; i++) {
428189e4007SBarry Smith       if (rp[i] == col) {
4291f763a69SBarry Smith         ap[i] += value;
430189e4007SBarry Smith         low = i + 1;
4311f763a69SBarry Smith         break;
432189e4007SBarry Smith       }
433189e4007SBarry Smith     }
434189e4007SBarry Smith   }
4358c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
436c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
437e2cf4d64SStefano Zampini #endif
438f38dd0b8SBarry Smith   return 0;
439189e4007SBarry Smith }
440189e4007SBarry Smith 
44197f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
44217ab2063SBarry Smith {
443416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
444e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
44597f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4466849ba73SBarry Smith   PetscErrorCode ierr;
447e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
448d8cdefa3SHong Zhang   MatScalar      *ap=NULL,value=0.0,*aa = a->a;
449ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
450ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
4518c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
452e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
453e2cf4d64SStefano Zampini #endif
45417ab2063SBarry Smith 
4553a40ed3dSBarry Smith   PetscFunctionBegin;
45617ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
457416022c9SBarry Smith     row = im[k];
4585ef9f2a5SBarry Smith     if (row < 0) continue;
459cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
460720833daSHong Zhang     rp   = aj + ai[row];
461876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
46217ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
463416022c9SBarry Smith     low  = 0;
464c71e6ed7SBarry Smith     high = nrow;
46517ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4665ef9f2a5SBarry Smith       if (in[l] < 0) continue;
467cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
468bfeeae90SHong Zhang       col = in[l];
469071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
470071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
47136db0b34SBarry Smith 
4722205254eSKarl Rupp       if (col <= lastcol) low = 0;
4732205254eSKarl Rupp       else high = nrow;
474e2ee6c50SBarry Smith       lastcol = col;
475416022c9SBarry Smith       while (high-low > 5) {
476416022c9SBarry Smith         t = (low+high)/2;
477416022c9SBarry Smith         if (rp[t] > col) high = t;
478416022c9SBarry Smith         else low = t;
47917ab2063SBarry Smith       }
480416022c9SBarry Smith       for (i=low; i<high; i++) {
48117ab2063SBarry Smith         if (rp[i] > col) break;
48217ab2063SBarry Smith         if (rp[i] == col) {
483876c6284SHong Zhang           if (!A->structure_only) {
4840c0d7e18SFande Kong             if (is == ADD_VALUES) {
4850c0d7e18SFande Kong               ap[i] += value;
4860c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4870c0d7e18SFande Kong             }
48817ab2063SBarry Smith             else ap[i] = value;
4898c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
490e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
491e2cf4d64SStefano Zampini #endif
492720833daSHong Zhang           }
493e44c0bd4SBarry Smith           low = i + 1;
49417ab2063SBarry Smith           goto noinsert;
49517ab2063SBarry Smith         }
49617ab2063SBarry Smith       }
497dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
498c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
499e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
500720833daSHong Zhang       if (A->structure_only) {
501876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
502720833daSHong Zhang       } else {
503fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
504720833daSHong Zhang       }
505c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
506416022c9SBarry Smith       /* shift up all the later entries in this row */
507580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
50817ab2063SBarry Smith       rp[i] = col;
509580bdb30SBarry Smith       if (!A->structure_only){
510580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
511580bdb30SBarry Smith         ap[i] = value;
512580bdb30SBarry Smith       }
513416022c9SBarry Smith       low = i + 1;
514e56f5c9eSBarry Smith       A->nonzerostate++;
5158c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
516e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
517e2cf4d64SStefano Zampini #endif
518e44c0bd4SBarry Smith noinsert:;
51917ab2063SBarry Smith     }
52017ab2063SBarry Smith     ailen[row] = nrow;
52117ab2063SBarry Smith   }
5228c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
523c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
524e2cf4d64SStefano Zampini #endif
5253a40ed3dSBarry Smith   PetscFunctionReturn(0);
52617ab2063SBarry Smith }
52717ab2063SBarry Smith 
52819b08ed1SBarry Smith 
52919b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
53019b08ed1SBarry Smith {
53119b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
53219b08ed1SBarry Smith   PetscInt       *rp,k,row;
53319b08ed1SBarry Smith   PetscInt       *ai = a->i;
53419b08ed1SBarry Smith   PetscErrorCode ierr;
53519b08ed1SBarry Smith   PetscInt       *aj = a->j;
53619b08ed1SBarry Smith   MatScalar      *aa = a->a,*ap;
53719b08ed1SBarry Smith 
53819b08ed1SBarry Smith   PetscFunctionBegin;
53919b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
54019b08ed1SBarry Smith   if (m*n+a->nz > a->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of entries in matrix will be larger than maximum nonzeros allocated for %D in MatSeqAIJSetTotalPreallocation()",a->maxnz);
54119b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
54219b08ed1SBarry Smith     row  = im[k];
54319b08ed1SBarry Smith     rp   = aj + ai[row];
54419b08ed1SBarry Smith     ap   = aa + ai[row];
54519b08ed1SBarry Smith 
54619b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
54719b08ed1SBarry Smith     if (!A->structure_only) {
54819b08ed1SBarry Smith       if (v) {
54919b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
55019b08ed1SBarry Smith         v   += n;
55119b08ed1SBarry Smith       } else {
55219b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
55319b08ed1SBarry Smith       }
55419b08ed1SBarry Smith     }
55519b08ed1SBarry Smith     a->ilen[row] = n;
55619b08ed1SBarry Smith     a->imax[row] = n;
55719b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
55819b08ed1SBarry Smith     a->nz       += n;
55919b08ed1SBarry Smith   }
5608c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
56119b08ed1SBarry Smith   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
56219b08ed1SBarry Smith #endif
56319b08ed1SBarry Smith   PetscFunctionReturn(0);
56419b08ed1SBarry Smith }
56519b08ed1SBarry Smith 
56619b08ed1SBarry Smith /*@
56719b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
56819b08ed1SBarry Smith 
56919b08ed1SBarry Smith   Input Parameters:
57019b08ed1SBarry Smith +  A - the SeqAIJ matrix
57119b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
57219b08ed1SBarry Smith 
57319b08ed1SBarry Smith   Level: advanced
57419b08ed1SBarry Smith 
57519b08ed1SBarry Smith   Notes:
57619b08ed1SBarry Smith     This can be called if you will be provided the matrix row by row (from row zero) with sorted column indices for each row.
57719b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
57819b08ed1SBarry Smith     as always with multiple matrix assemblies.
57919b08ed1SBarry Smith 
58019b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
58119b08ed1SBarry Smith @*/
58219b08ed1SBarry Smith 
58319b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
58419b08ed1SBarry Smith {
58519b08ed1SBarry Smith   PetscErrorCode ierr;
58619b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
58719b08ed1SBarry Smith 
58819b08ed1SBarry Smith   PetscFunctionBegin;
58919b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
59019b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
59119b08ed1SBarry Smith   a->maxnz  = nztotal;
59219b08ed1SBarry Smith   if (!a->imax) {
59319b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
59419b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59519b08ed1SBarry Smith   }
59619b08ed1SBarry Smith   if (!a->ilen) {
59719b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
59819b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59919b08ed1SBarry Smith   } else {
60019b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60119b08ed1SBarry Smith   }
60219b08ed1SBarry Smith 
60319b08ed1SBarry Smith   /* allocate the matrix space */
60419b08ed1SBarry Smith   if (A->structure_only) {
60519b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
60619b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
60719b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
60819b08ed1SBarry Smith   } else {
60919b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
61019b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
61119b08ed1SBarry Smith   }
61219b08ed1SBarry Smith   a->i[0] = 0;
61319b08ed1SBarry Smith   if (A->structure_only) {
61419b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
61519b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
61619b08ed1SBarry Smith   } else {
61719b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
61819b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
61919b08ed1SBarry Smith   }
62019b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
62119b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
62219b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
62319b08ed1SBarry Smith   PetscFunctionReturn(0);
62419b08ed1SBarry Smith }
62519b08ed1SBarry Smith 
626071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
627071fcb05SBarry Smith {
628071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
629071fcb05SBarry Smith   PetscInt       *rp,k,row;
630071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
631071fcb05SBarry Smith   PetscErrorCode ierr;
632071fcb05SBarry Smith   PetscInt       *aj = a->j;
633071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
634071fcb05SBarry Smith 
635071fcb05SBarry Smith   PetscFunctionBegin;
636071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
637071fcb05SBarry Smith     row  = im[k];
63819b08ed1SBarry Smith     if (PetscUnlikelyDebug(n > a->imax[row])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Preallocation for row %D does not match number of columns provided",n);
639071fcb05SBarry Smith     rp   = aj + ai[row];
640071fcb05SBarry Smith     ap   = aa + ai[row];
641071fcb05SBarry Smith     if (!A->was_assembled) {
642071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
643071fcb05SBarry Smith     }
644071fcb05SBarry Smith     if (!A->structure_only) {
645071fcb05SBarry Smith       if (v) {
646071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
647071fcb05SBarry Smith         v   += n;
648071fcb05SBarry Smith       } else {
649071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
650071fcb05SBarry Smith       }
651071fcb05SBarry Smith     }
652071fcb05SBarry Smith     ailen[row] = n;
653071fcb05SBarry Smith     a->nz      += n;
654071fcb05SBarry Smith   }
6558c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
656c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
657e2cf4d64SStefano Zampini #endif
658071fcb05SBarry Smith   PetscFunctionReturn(0);
659071fcb05SBarry Smith }
660071fcb05SBarry Smith 
66181824310SBarry Smith 
662a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6637eb43aa7SLois Curfman McInnes {
6647eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
66597f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
66697f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
66754f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
6687eb43aa7SLois Curfman McInnes 
6693a40ed3dSBarry Smith   PetscFunctionBegin;
6707eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6717eb43aa7SLois Curfman McInnes     row = im[k];
672e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
673e32f2f54SBarry Smith     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
674bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6757eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6767eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
677e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
678e32f2f54SBarry Smith       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
679bfeeae90SHong Zhang       col  = in[l];
6807eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6817eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6827eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6837eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6847eb43aa7SLois Curfman McInnes         else low = t;
6857eb43aa7SLois Curfman McInnes       }
6867eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6877eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6887eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
689b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6907eb43aa7SLois Curfman McInnes           goto finished;
6917eb43aa7SLois Curfman McInnes         }
6927eb43aa7SLois Curfman McInnes       }
69397e567efSBarry Smith       *v++ = 0.0;
6947eb43aa7SLois Curfman McInnes finished:;
6957eb43aa7SLois Curfman McInnes     }
6967eb43aa7SLois Curfman McInnes   }
6973a40ed3dSBarry Smith   PetscFunctionReturn(0);
6987eb43aa7SLois Curfman McInnes }
6997eb43aa7SLois Curfman McInnes 
7003ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
70117ab2063SBarry Smith {
7023ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
703c898d852SStefano Zampini   const PetscScalar *av;
7043ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
7053ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
7066849ba73SBarry Smith   PetscErrorCode    ierr;
70717ab2063SBarry Smith 
7083a40ed3dSBarry Smith   PetscFunctionBegin;
7093ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7102205254eSKarl Rupp 
7113ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7123ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7133ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7143ea6fe3dSLisandro Dalcin   nz = A->nz;
715416022c9SBarry Smith 
7163ea6fe3dSLisandro Dalcin   /* write matrix header */
7173ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7183ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7193ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
720416022c9SBarry Smith 
7213ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7223ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7233ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7243ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7253ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7263ea6fe3dSLisandro Dalcin   /* store column indices */
7273ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
728416022c9SBarry Smith   /* store nonzero values */
729c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
730c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
731c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
732b37d52dbSMark F. Adams 
7333ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7343ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7353a40ed3dSBarry Smith   PetscFunctionReturn(0);
73617ab2063SBarry Smith }
737416022c9SBarry Smith 
7387dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7397dc0baabSHong Zhang {
7407dc0baabSHong Zhang   PetscErrorCode ierr;
7417dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7427dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7437dc0baabSHong Zhang 
7447dc0baabSHong Zhang   PetscFunctionBegin;
7457dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7467dc0baabSHong Zhang   for (i=0; i<m; i++) {
7477dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7487dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7497dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7507dc0baabSHong Zhang     }
7517dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7527dc0baabSHong Zhang   }
7537dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7547dc0baabSHong Zhang   PetscFunctionReturn(0);
7557dc0baabSHong Zhang }
7567dc0baabSHong Zhang 
75709573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
758cd155464SBarry Smith 
759dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
760416022c9SBarry Smith {
761416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
762c898d852SStefano Zampini   const PetscScalar *av;
763dfbe8321SBarry Smith   PetscErrorCode    ierr;
76460e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
765e060cb09SBarry Smith   const char        *name;
766f3ef73ceSBarry Smith   PetscViewerFormat format;
76717ab2063SBarry Smith 
7683a40ed3dSBarry Smith   PetscFunctionBegin;
7697dc0baabSHong Zhang   if (A->structure_only) {
7707dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7717dc0baabSHong Zhang     PetscFunctionReturn(0);
7727dc0baabSHong Zhang   }
77343e49210SHong Zhang 
774b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
7752e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7762e5835c6SStefano Zampini 
777c898d852SStefano Zampini   /* trigger copy to CPU if needed */
778c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
779c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
78071c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
78197f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
78260e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
783c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
784d00d2cf4SBarry Smith       nofinalvalue = 1;
785d00d2cf4SBarry Smith     }
786d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
787d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
78877431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
789fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
790fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
791fbfe6fa7SJed Brown #else
79277431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
793fbfe6fa7SJed Brown #endif
794b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
79517ab2063SBarry Smith 
79617ab2063SBarry Smith     for (i=0; i<m; i++) {
79760e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
798aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
799a9bf72d8SJed Brown         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",i+1,a->j[j]+1,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
80017ab2063SBarry Smith #else
80160e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
80217ab2063SBarry Smith #endif
80317ab2063SBarry Smith       }
80417ab2063SBarry Smith     }
805d00d2cf4SBarry Smith     if (nofinalvalue) {
806c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
807c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
808c337ccceSJed Brown #else
809d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
810c337ccceSJed Brown #endif
811d00d2cf4SBarry Smith     }
812317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
813fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
814d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
815fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
816d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
81744cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
81877431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
81960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
820aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
82136db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
82260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
82336db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
82460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
82536db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
82660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8276831982aSBarry Smith         }
82844cd7ae7SLois Curfman McInnes #else
82960e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
83044cd7ae7SLois Curfman McInnes #endif
83144cd7ae7SLois Curfman McInnes       }
832b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
83344cd7ae7SLois Curfman McInnes     }
834d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
835fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
83697f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
837d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
838854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
839496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
840496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
84160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
842496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
843aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
84436db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
845496be53dSLois Curfman McInnes #else
846496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
847496be53dSLois Curfman McInnes #endif
848496be53dSLois Curfman McInnes         }
849496be53dSLois Curfman McInnes       }
850496be53dSLois Curfman McInnes     }
8512e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
85277431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8532e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8542205254eSKarl Rupp       if (i+4<m) {
8552205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);CHKERRQ(ierr);
8562205254eSKarl Rupp       } else if (i+3<m) {
8572205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);CHKERRQ(ierr);
8582205254eSKarl Rupp       } else if (i+2<m) {
8592205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8602205254eSKarl Rupp       } else if (i+1<m) {
8612205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8622205254eSKarl Rupp       } else if (i<m) {
8632205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8642205254eSKarl Rupp       } else {
8652205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8662205254eSKarl Rupp       }
867496be53dSLois Curfman McInnes     }
868b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
869606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
870496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
87160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
87277431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
873496be53dSLois Curfman McInnes       }
874b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
875496be53dSLois Curfman McInnes     }
876b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
877496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
87860e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
879496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
880aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
88136db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
88260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8836831982aSBarry Smith           }
884496be53dSLois Curfman McInnes #else
88560e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
886496be53dSLois Curfman McInnes #endif
887496be53dSLois Curfman McInnes         }
888496be53dSLois Curfman McInnes       }
889b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
890496be53dSLois Curfman McInnes     }
891d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
892fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
89397f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
89487828ca2SBarry Smith     PetscScalar value;
89568f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
89668f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
89768f1ed48SBarry Smith 
89868f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
89968f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
90068f1ed48SBarry Smith         realonly = PETSC_FALSE;
90168f1ed48SBarry Smith         break;
90268f1ed48SBarry Smith       }
90368f1ed48SBarry Smith     }
90468f1ed48SBarry Smith #endif
90502594712SBarry Smith 
906d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
90702594712SBarry Smith     for (i=0; i<m; i++) {
90802594712SBarry Smith       jcnt = 0;
909d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
910e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
91102594712SBarry Smith           value = a->a[cnt++];
912e24b481bSBarry Smith           jcnt++;
91302594712SBarry Smith         } else {
91402594712SBarry Smith           value = 0.0;
91502594712SBarry Smith         }
916aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
91768f1ed48SBarry Smith         if (realonly) {
91860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
91968f1ed48SBarry Smith         } else {
92060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
92168f1ed48SBarry Smith         }
92202594712SBarry Smith #else
92360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
92402594712SBarry Smith #endif
92502594712SBarry Smith       }
926b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
92702594712SBarry Smith     }
928d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9293c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
930150b93efSMatthew G. Knepley     PetscInt fshift=1;
931d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9323c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
93319303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9343c215bfdSMatthew Knepley #else
93519303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9363c215bfdSMatthew Knepley #endif
937d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9383c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
93960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9403c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
941a9a0e077SKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g %g\n", i+fshift,a->j[j]+fshift,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9423c215bfdSMatthew Knepley #else
943150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9443c215bfdSMatthew Knepley #endif
9453c215bfdSMatthew Knepley       }
9463c215bfdSMatthew Knepley     }
947d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9483a40ed3dSBarry Smith   } else {
949d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
950d5f3da31SBarry Smith     if (A->factortype) {
95116cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
95216cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
95316cd7e1dSShri Abhyankar         /* L part */
95460e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
95516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
95616cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
95760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
95816cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9596712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
96016cd7e1dSShri Abhyankar           } else {
96160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
96216cd7e1dSShri Abhyankar           }
96316cd7e1dSShri Abhyankar #else
96460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
96516cd7e1dSShri Abhyankar #endif
96616cd7e1dSShri Abhyankar         }
96716cd7e1dSShri Abhyankar         /* diagonal */
96816cd7e1dSShri Abhyankar         j = a->diag[i];
96916cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97016cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
97160e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j]));CHKERRQ(ierr);
97216cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9736712e2f1SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j])));CHKERRQ(ierr);
97416cd7e1dSShri Abhyankar         } else {
97560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
97616cd7e1dSShri Abhyankar         }
97716cd7e1dSShri Abhyankar #else
97860e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
97916cd7e1dSShri Abhyankar #endif
98016cd7e1dSShri Abhyankar 
98116cd7e1dSShri Abhyankar         /* U part */
98260e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
98316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
98416cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
98560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
98616cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
98722ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
98816cd7e1dSShri Abhyankar           } else {
98960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
99016cd7e1dSShri Abhyankar           }
99116cd7e1dSShri Abhyankar #else
99260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
99316cd7e1dSShri Abhyankar #endif
99416cd7e1dSShri Abhyankar         }
99516cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
99616cd7e1dSShri Abhyankar       }
99716cd7e1dSShri Abhyankar     } else {
99817ab2063SBarry Smith       for (i=0; i<m; i++) {
99977431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
100060e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
1001aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
100236db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
100360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
100436db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
100560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
10063a40ed3dSBarry Smith           } else {
100760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
100817ab2063SBarry Smith           }
100917ab2063SBarry Smith #else
101060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
101117ab2063SBarry Smith #endif
101217ab2063SBarry Smith         }
1013b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
101417ab2063SBarry Smith       }
101516cd7e1dSShri Abhyankar     }
1016d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
101717ab2063SBarry Smith   }
1018b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10193a40ed3dSBarry Smith   PetscFunctionReturn(0);
1020416022c9SBarry Smith }
1021416022c9SBarry Smith 
10229804daf3SBarry Smith #include <petscdraw.h>
1023dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1024416022c9SBarry Smith {
1025480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1026416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1027dfbe8321SBarry Smith   PetscErrorCode    ierr;
1028383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1029383922c3SLisandro Dalcin   int               color;
1030b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1031b0a32e0cSBarry Smith   PetscViewer       viewer;
1032f3ef73ceSBarry Smith   PetscViewerFormat format;
1033cddf8d76SBarry Smith 
10343a40ed3dSBarry Smith   PetscFunctionBegin;
1035480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1036b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1037b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1038383922c3SLisandro Dalcin 
1039416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10400513a670SBarry Smith 
1041fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1042383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10430513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1044b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1045416022c9SBarry Smith     for (i=0; i<m; i++) {
1046cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1047bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1048bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
104936db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
1050b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1051cddf8d76SBarry Smith       }
1052cddf8d76SBarry Smith     }
1053b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1054cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1055cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1056bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1057bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1058cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
1059b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1060cddf8d76SBarry Smith       }
1061cddf8d76SBarry Smith     }
1062b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1063cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1064cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1065bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1066bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
106736db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
1068b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1069416022c9SBarry Smith       }
1070416022c9SBarry Smith     }
1071383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10720513a670SBarry Smith   } else {
10730513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10740513a670SBarry Smith     /* first determine max of all nonzero values */
1075b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1076383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1077b0a32e0cSBarry Smith     PetscDraw popup;
10780513a670SBarry Smith 
10790513a670SBarry Smith     for (i=0; i<nz; i++) {
10800513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
10810513a670SBarry Smith     }
1082383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1083b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
108445f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1085383922c3SLisandro Dalcin 
1086383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10870513a670SBarry Smith     for (i=0; i<m; i++) {
1088383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1089383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1090bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1091383922c3SLisandro Dalcin         x_l = a->j[j];
1092383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1093b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
1094b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
10950513a670SBarry Smith         count++;
10960513a670SBarry Smith       }
10970513a670SBarry Smith     }
1098383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10990513a670SBarry Smith   }
1100480ef9eaSBarry Smith   PetscFunctionReturn(0);
1101480ef9eaSBarry Smith }
1102cddf8d76SBarry Smith 
11039804daf3SBarry Smith #include <petscdraw.h>
1104dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1105480ef9eaSBarry Smith {
1106dfbe8321SBarry Smith   PetscErrorCode ierr;
1107b0a32e0cSBarry Smith   PetscDraw      draw;
110836db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1109ace3abfcSBarry Smith   PetscBool      isnull;
1110480ef9eaSBarry Smith 
1111480ef9eaSBarry Smith   PetscFunctionBegin;
1112b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1113b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1114480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1115480ef9eaSBarry Smith 
1116d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1117480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1118b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1119832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1120b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11210298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1122832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11233a40ed3dSBarry Smith   PetscFunctionReturn(0);
1124416022c9SBarry Smith }
1125416022c9SBarry Smith 
1126dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1127416022c9SBarry Smith {
1128dfbe8321SBarry Smith   PetscErrorCode ierr;
1129ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1130416022c9SBarry Smith 
11313a40ed3dSBarry Smith   PetscFunctionBegin;
1132251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1133251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1134251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1135c45a1595SBarry Smith   if (iascii) {
11363a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11370f5bd95cSBarry Smith   } else if (isbinary) {
11383a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11390f5bd95cSBarry Smith   } else if (isdraw) {
11403a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
114111aeaf0aSBarry Smith   }
11424108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11433a40ed3dSBarry Smith   PetscFunctionReturn(0);
114417ab2063SBarry Smith }
114519bcc07fSBarry Smith 
1146dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
114717ab2063SBarry Smith {
1148416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11496849ba73SBarry Smith   PetscErrorCode ierr;
1150580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1151d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
115254f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11533447b6efSHong Zhang   PetscReal      ratio  = 0.6;
115417ab2063SBarry Smith 
11553a40ed3dSBarry Smith   PetscFunctionBegin;
11563a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1157071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1158b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1159b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1160b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1161b215bc84SStefano Zampini     PetscFunctionReturn(0);
1162b215bc84SStefano Zampini   }
116317ab2063SBarry Smith 
116443ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
116517ab2063SBarry Smith   for (i=1; i<m; i++) {
1166416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
116717ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
116894a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
116917ab2063SBarry Smith     if (fshift) {
1170bfeeae90SHong Zhang       ip = aj + ai[i];
1171bfeeae90SHong Zhang       ap = aa + ai[i];
117217ab2063SBarry Smith       N  = ailen[i];
1173580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1174580bdb30SBarry Smith       if (!A->structure_only) {
1175580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
117617ab2063SBarry Smith       }
117717ab2063SBarry Smith     }
117817ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
117917ab2063SBarry Smith   }
118017ab2063SBarry Smith   if (m) {
118117ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
118217ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
118317ab2063SBarry Smith   }
11847b083b7cSBarry Smith 
118517ab2063SBarry Smith   /* reset ilen and imax for each row */
11867b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1187396832f4SHong Zhang   if (A->structure_only) {
1188071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1189071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1190396832f4SHong Zhang   } else { /* !A->structure_only */
119117ab2063SBarry Smith     for (i=0; i<m; i++) {
119217ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11937b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
119417ab2063SBarry Smith     }
1195396832f4SHong Zhang   }
1196bfeeae90SHong Zhang   a->nz = ai[m];
119765e19b50SBarry Smith   if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift);
119817ab2063SBarry Smith 
119909f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1200d0f46423SBarry Smith   ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr);
1201ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1202ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
12032205254eSKarl Rupp 
12048e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1205dd5f02e7SSatish Balay   a->reallocs         = 0;
12066712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
120736db0b34SBarry Smith   a->rmax             = rmax;
12084e220ebcSLois Curfman McInnes 
1209396832f4SHong Zhang   if (!A->structure_only) {
121011e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1211396832f4SHong Zhang   }
12124108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12133a40ed3dSBarry Smith   PetscFunctionReturn(0);
121417ab2063SBarry Smith }
121517ab2063SBarry Smith 
121699cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
121799cafbc1SBarry Smith {
121899cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
121999cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12202e5835c6SStefano Zampini   MatScalar      *aa;
1221acf2f550SJed Brown   PetscErrorCode ierr;
122299cafbc1SBarry Smith 
122399cafbc1SBarry Smith   PetscFunctionBegin;
12242e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
122599cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
12262e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1227acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12288c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1229c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1230e2cf4d64SStefano Zampini #endif
123199cafbc1SBarry Smith   PetscFunctionReturn(0);
123299cafbc1SBarry Smith }
123399cafbc1SBarry Smith 
123499cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
123599cafbc1SBarry Smith {
123699cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
123799cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12382e5835c6SStefano Zampini   MatScalar      *aa;
1239acf2f550SJed Brown   PetscErrorCode ierr;
124099cafbc1SBarry Smith 
124199cafbc1SBarry Smith   PetscFunctionBegin;
12422e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
124399cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12442e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1245acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12468c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1247c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1248e2cf4d64SStefano Zampini #endif
124999cafbc1SBarry Smith   PetscFunctionReturn(0);
125099cafbc1SBarry Smith }
125199cafbc1SBarry Smith 
1252dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
125317ab2063SBarry Smith {
1254416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1255dfbe8321SBarry Smith   PetscErrorCode ierr;
12563a40ed3dSBarry Smith 
12573a40ed3dSBarry Smith   PetscFunctionBegin;
1258580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1259acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12608c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1261c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1262e2cf4d64SStefano Zampini #endif
12633a40ed3dSBarry Smith   PetscFunctionReturn(0);
126417ab2063SBarry Smith }
1265416022c9SBarry Smith 
1266dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
126717ab2063SBarry Smith {
1268416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1269dfbe8321SBarry Smith   PetscErrorCode ierr;
1270d5d45c9bSBarry Smith 
12713a40ed3dSBarry Smith   PetscFunctionBegin;
1272aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1273d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
127417ab2063SBarry Smith #endif
1275e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12766bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12776bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
127805b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1279d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1280071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1281071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1282846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
128371f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
128405b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12856bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
128605b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1287cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1288a30b2313SHong Zhang 
12894108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1290bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1291901853e0SKris Buschelman 
12926718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12936718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12946718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12956718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12966718818eSStefano Zampini      due to different matrix sizes */
12976718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
12986718818eSStefano Zampini 
1299f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1300bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1301bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1302bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1303bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1304bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1305bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
13064222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
13074222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1308e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1309fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
13104222ddf1SHong Zhang #endif
13113d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
13123d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13133d0639e7SStefano Zampini #endif
13144222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1315af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1316af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1317af8000cdSHong Zhang #endif
1318d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1319d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1320d24d4204SJose E. Roman #endif
132163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
132263c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13234222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
132463c07aadSStefano Zampini #endif
1325b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1326c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1327c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1328bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1329bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1330846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1331bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1332bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13334222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13344222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13354222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
13363a40ed3dSBarry Smith   PetscFunctionReturn(0);
133717ab2063SBarry Smith }
133817ab2063SBarry Smith 
1339ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
134017ab2063SBarry Smith {
1341416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13424846f1f5SKris Buschelman   PetscErrorCode ierr;
13433a40ed3dSBarry Smith 
13443a40ed3dSBarry Smith   PetscFunctionBegin;
1345a65d3064SKris Buschelman   switch (op) {
1346a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13474e0d8c25SBarry Smith     a->roworiented = flg;
1348a65d3064SKris Buschelman     break;
1349a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1350a9817697SBarry Smith     a->keepnonzeropattern = flg;
1351a65d3064SKris Buschelman     break;
1352512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1353512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1354a65d3064SKris Buschelman     break;
1355a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13564e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1357a65d3064SKris Buschelman     break;
1358a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13594e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1360a65d3064SKris Buschelman     break;
136128b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
136228b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
136328b2fa4aSMatthew Knepley     break;
1364a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13654e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13660df259c2SBarry Smith     break;
13673d472b54SHong Zhang   case MAT_SPD:
1368b1646e73SJed Brown   case MAT_SYMMETRIC:
1369b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1370b1646e73SJed Brown   case MAT_HERMITIAN:
1371b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1372957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13735021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13745021d80fSJed Brown     break;
13758c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1376a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1377a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1378290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1379a65d3064SKris Buschelman     break;
1380b87ac2d8SJed Brown   case MAT_USE_INODES:
1381b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1382b87ac2d8SJed Brown     break;
1383c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1384c10200c1SHong Zhang     A->submat_singleis = flg;
1385c10200c1SHong Zhang     break;
1386071fcb05SBarry Smith   case MAT_SORTED_FULL:
1387071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1388071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1389071fcb05SBarry Smith     break;
1390a65d3064SKris Buschelman   default:
1391e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1392a65d3064SKris Buschelman   }
13933a40ed3dSBarry Smith   PetscFunctionReturn(0);
139417ab2063SBarry Smith }
139517ab2063SBarry Smith 
1396dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
139717ab2063SBarry Smith {
1398416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
13996849ba73SBarry Smith   PetscErrorCode    ierr;
1400fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1401c898d852SStefano Zampini   PetscScalar       *x;
1402c898d852SStefano Zampini   const PetscScalar *aa;
140317ab2063SBarry Smith 
14043a40ed3dSBarry Smith   PetscFunctionBegin;
1405d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1406e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1407c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1408d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1409d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1410fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14112c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1412fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1413c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
141435e7444dSHong Zhang     PetscFunctionReturn(0);
141535e7444dSHong Zhang   }
141635e7444dSHong Zhang 
1417fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
141835e7444dSHong Zhang   for (i=0; i<n; i++) {
1419fdc842d1SBarry Smith     x[i] = 0.0;
142035e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
142135e7444dSHong Zhang       if (aj[j] == i) {
142235e7444dSHong Zhang         x[i] = aa[j];
142317ab2063SBarry Smith         break;
142417ab2063SBarry Smith       }
142517ab2063SBarry Smith     }
142617ab2063SBarry Smith   }
1427fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1428c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14293a40ed3dSBarry Smith   PetscFunctionReturn(0);
143017ab2063SBarry Smith }
143117ab2063SBarry Smith 
1432c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1433dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
143417ab2063SBarry Smith {
1435416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1436d9ca1df4SBarry Smith   PetscScalar       *y;
1437d9ca1df4SBarry Smith   const PetscScalar *x;
1438dfbe8321SBarry Smith   PetscErrorCode    ierr;
1439d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14405c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1441d9ca1df4SBarry Smith   const MatScalar   *v;
1442a77337e4SBarry Smith   PetscScalar       alpha;
1443d9ca1df4SBarry Smith   PetscInt          n,i,j;
1444d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14453447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1446ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14475c897100SBarry Smith #endif
144817ab2063SBarry Smith 
14493a40ed3dSBarry Smith   PetscFunctionBegin;
14502e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1451d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14521ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14535c897100SBarry Smith 
14545c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1455bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14565c897100SBarry Smith #else
14573447b6efSHong Zhang   if (usecprow) {
14583447b6efSHong Zhang     m    = cprow.nrows;
14593447b6efSHong Zhang     ii   = cprow.i;
14607b2bb3b9SHong Zhang     ridx = cprow.rindex;
14613447b6efSHong Zhang   } else {
14623447b6efSHong Zhang     ii = a->i;
14633447b6efSHong Zhang   }
146417ab2063SBarry Smith   for (i=0; i<m; i++) {
14653447b6efSHong Zhang     idx = a->j + ii[i];
14663447b6efSHong Zhang     v   = a->a + ii[i];
14673447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14683447b6efSHong Zhang     if (usecprow) {
14697b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14703447b6efSHong Zhang     } else {
147117ab2063SBarry Smith       alpha = x[i];
14723447b6efSHong Zhang     }
147304fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
147417ab2063SBarry Smith   }
14755c897100SBarry Smith #endif
1476dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1477d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14781ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14793a40ed3dSBarry Smith   PetscFunctionReturn(0);
148017ab2063SBarry Smith }
148117ab2063SBarry Smith 
1482dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14835c897100SBarry Smith {
1484dfbe8321SBarry Smith   PetscErrorCode ierr;
14855c897100SBarry Smith 
14865c897100SBarry Smith   PetscFunctionBegin;
1487170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14885c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14895c897100SBarry Smith   PetscFunctionReturn(0);
14905c897100SBarry Smith }
14915c897100SBarry Smith 
1492c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
149378b84d54SShri Abhyankar 
1494dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
149517ab2063SBarry Smith {
1496416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1497d9fead3dSBarry Smith   PetscScalar       *y;
149854f21887SBarry Smith   const PetscScalar *x;
149954f21887SBarry Smith   const MatScalar   *aa;
1500dfbe8321SBarry Smith   PetscErrorCode    ierr;
1501003131ecSBarry Smith   PetscInt          m=A->rmap->n;
15020298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
15037b083b7cSBarry Smith   PetscInt          n,i;
1504362ced78SSatish Balay   PetscScalar       sum;
1505ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
150617ab2063SBarry Smith 
1507b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
150897952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1509fee21e36SBarry Smith #endif
1510fee21e36SBarry Smith 
15113a40ed3dSBarry Smith   PetscFunctionBegin;
1512b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1513b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1514b215bc84SStefano Zampini     PetscFunctionReturn(0);
1515b215bc84SStefano Zampini   }
15163649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15171ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1518416022c9SBarry Smith   ii   = a->i;
15194eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1520580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
152197952fefSHong Zhang     m    = a->compressedrow.nrows;
152297952fefSHong Zhang     ii   = a->compressedrow.i;
152397952fefSHong Zhang     ridx = a->compressedrow.rindex;
152497952fefSHong Zhang     for (i=0; i<m; i++) {
152597952fefSHong Zhang       n           = ii[i+1] - ii[i];
152697952fefSHong Zhang       aj          = a->j + ii[i];
152797952fefSHong Zhang       aa          = a->a + ii[i];
152897952fefSHong Zhang       sum         = 0.0;
1529003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1530003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
153197952fefSHong Zhang       y[*ridx++] = sum;
153297952fefSHong Zhang     }
153397952fefSHong Zhang   } else { /* do not use compressed row format */
1534b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15353d3eaba7SBarry Smith     aj   = a->j;
15363d3eaba7SBarry Smith     aa   = a->a;
1537b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1538b05257ddSBarry Smith #else
153917ab2063SBarry Smith     for (i=0; i<m; i++) {
1540003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1541003131ecSBarry Smith       aj          = a->j + ii[i];
1542003131ecSBarry Smith       aa          = a->a + ii[i];
154317ab2063SBarry Smith       sum         = 0.0;
1544003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
154517ab2063SBarry Smith       y[i] = sum;
154617ab2063SBarry Smith     }
15478d195f9aSBarry Smith #endif
1548b05257ddSBarry Smith   }
15497b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15503649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15511ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15523a40ed3dSBarry Smith   PetscFunctionReturn(0);
155317ab2063SBarry Smith }
155417ab2063SBarry Smith 
1555b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1556b434eb95SMatthew G. Knepley {
1557b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1558b434eb95SMatthew G. Knepley   PetscScalar       *y;
1559b434eb95SMatthew G. Knepley   const PetscScalar *x;
1560b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1561b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1562b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1563b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1564b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1565b434eb95SMatthew G. Knepley   PetscScalar       sum;
1566b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1567b434eb95SMatthew G. Knepley 
1568b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1569b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1570b434eb95SMatthew G. Knepley #endif
1571b434eb95SMatthew G. Knepley 
1572b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1573b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1574b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1575b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1576b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1577b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1578b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1579b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1580b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1581b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1582b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1583b434eb95SMatthew G. Knepley       sum         = 0.0;
1584b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1585b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1586b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1587b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1588b434eb95SMatthew G. Knepley     }
1589b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15903d3eaba7SBarry Smith     ii = a->i;
1591b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1592b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1593b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1594b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1595b434eb95SMatthew G. Knepley       sum         = 0.0;
1596b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1597b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1598b434eb95SMatthew G. Knepley       y[i] = sum;
1599b434eb95SMatthew G. Knepley     }
1600b434eb95SMatthew G. Knepley   }
1601b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1602b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1603b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1604b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1605b434eb95SMatthew G. Knepley }
1606b434eb95SMatthew G. Knepley 
1607b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1608b434eb95SMatthew G. Knepley {
1609b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1610b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1611b434eb95SMatthew G. Knepley   const PetscScalar *x;
1612b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1613b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1614b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1615b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1616b434eb95SMatthew G. Knepley   PetscScalar       sum;
1617b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1618b434eb95SMatthew G. Knepley 
1619b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1620b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1621d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1622b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1623b434eb95SMatthew G. Knepley     if (zz != yy) {
1624580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1625b434eb95SMatthew G. Knepley     }
1626b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1627b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1628b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1629b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1630b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1631b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1632b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1633b434eb95SMatthew G. Knepley       sum = y[*ridx];
1634b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1635b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1636b434eb95SMatthew G. Knepley     }
1637b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16383d3eaba7SBarry Smith     ii = a->i;
1639b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1640b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1641b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1642b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1643b434eb95SMatthew G. Knepley       sum = y[i];
1644b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1645b434eb95SMatthew G. Knepley       z[i] = sum;
1646b434eb95SMatthew G. Knepley     }
1647b434eb95SMatthew G. Knepley   }
1648b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1649b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1650d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1651b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1652b434eb95SMatthew G. Knepley }
1653b434eb95SMatthew G. Knepley 
1654c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1655dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
165617ab2063SBarry Smith {
1657416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1658f15663dcSBarry Smith   PetscScalar       *y,*z;
1659f15663dcSBarry Smith   const PetscScalar *x;
166054f21887SBarry Smith   const MatScalar   *aa;
1661dfbe8321SBarry Smith   PetscErrorCode    ierr;
1662d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1663d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1664362ced78SSatish Balay   PetscScalar       sum;
1665ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16669ea0dfa2SSatish Balay 
16673a40ed3dSBarry Smith   PetscFunctionBegin;
1668b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1669b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1670b215bc84SStefano Zampini     PetscFunctionReturn(0);
1671b215bc84SStefano Zampini   }
1672f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1673d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16744eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16754eb6d288SHong Zhang     if (zz != yy) {
1676580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16774eb6d288SHong Zhang     }
167897952fefSHong Zhang     m    = a->compressedrow.nrows;
167997952fefSHong Zhang     ii   = a->compressedrow.i;
168097952fefSHong Zhang     ridx = a->compressedrow.rindex;
168197952fefSHong Zhang     for (i=0; i<m; i++) {
168297952fefSHong Zhang       n   = ii[i+1] - ii[i];
168397952fefSHong Zhang       aj  = a->j + ii[i];
168497952fefSHong Zhang       aa  = a->a + ii[i];
168597952fefSHong Zhang       sum = y[*ridx];
1686f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
168797952fefSHong Zhang       z[*ridx++] = sum;
168897952fefSHong Zhang     }
168997952fefSHong Zhang   } else { /* do not use compressed row format */
16903d3eaba7SBarry Smith     ii = a->i;
1691f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16923d3eaba7SBarry Smith     aj = a->j;
16933d3eaba7SBarry Smith     aa = a->a;
1694f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1695f15663dcSBarry Smith #else
169617ab2063SBarry Smith     for (i=0; i<m; i++) {
1697f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1698f15663dcSBarry Smith       aj  = a->j + ii[i];
1699f15663dcSBarry Smith       aa  = a->a + ii[i];
170017ab2063SBarry Smith       sum = y[i];
1701f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
170217ab2063SBarry Smith       z[i] = sum;
170317ab2063SBarry Smith     }
170402ab625aSSatish Balay #endif
1705f15663dcSBarry Smith   }
1706dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1707f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1708d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
17093a40ed3dSBarry Smith   PetscFunctionReturn(0);
171017ab2063SBarry Smith }
171117ab2063SBarry Smith 
171217ab2063SBarry Smith /*
171317ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
171417ab2063SBarry Smith */
1715dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
171617ab2063SBarry Smith {
1717416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17186849ba73SBarry Smith   PetscErrorCode ierr;
1719d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
172017ab2063SBarry Smith 
17213a40ed3dSBarry Smith   PetscFunctionBegin;
172209f38230SBarry Smith   if (!a->diag) {
1723785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17243bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
172509f38230SBarry Smith   }
1726d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
172709f38230SBarry Smith     a->diag[i] = a->i[i+1];
1728bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1729bfeeae90SHong Zhang       if (a->j[j] == i) {
173009f38230SBarry Smith         a->diag[i] = j;
173117ab2063SBarry Smith         break;
173217ab2063SBarry Smith       }
173317ab2063SBarry Smith     }
173417ab2063SBarry Smith   }
17353a40ed3dSBarry Smith   PetscFunctionReturn(0);
173617ab2063SBarry Smith }
173717ab2063SBarry Smith 
173861ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
173961ecd0c6SBarry Smith {
174061ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
174161ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
174261ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
174361ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
174461ecd0c6SBarry Smith   PetscErrorCode    ierr;
174561ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
174661ecd0c6SBarry Smith 
174761ecd0c6SBarry Smith   PetscFunctionBegin;
174861ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
174961ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
175061ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
175161ecd0c6SBarry Smith     PetscFunctionReturn(0);
175261ecd0c6SBarry Smith   }
175361ecd0c6SBarry Smith 
175461ecd0c6SBarry Smith   if (a->diagonaldense) {
175561ecd0c6SBarry Smith     cnt = 0;
175661ecd0c6SBarry Smith   } else {
175761ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
175861ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
175961ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
176061ecd0c6SBarry Smith         cnt++;
176161ecd0c6SBarry Smith         mdiag[i] = 1;
176261ecd0c6SBarry Smith       }
176361ecd0c6SBarry Smith     }
176461ecd0c6SBarry Smith   }
176561ecd0c6SBarry Smith   if (!cnt) {
176661ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
176761ecd0c6SBarry Smith   } else {
1768b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1769b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
177061ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
177161ecd0c6SBarry Smith 
177261ecd0c6SBarry Smith     a->a = NULL;
177361ecd0c6SBarry Smith     a->j = NULL;
177461ecd0c6SBarry Smith     a->i = NULL;
177561ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
177661ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
177761ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1778447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
177961ecd0c6SBarry Smith     }
178061ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
178161ecd0c6SBarry Smith 
178261ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
178361ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
178461ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1785447d62f5SStefano Zampini       if (i < A->cmap->n) {
178661ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
178761ecd0c6SBarry Smith       }
1788447d62f5SStefano Zampini     }
178961ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179061ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179161ecd0c6SBarry Smith     if (singlemalloc) {
179261ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
179361ecd0c6SBarry Smith     } else {
179461ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
179561ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
179661ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
179761ecd0c6SBarry Smith     }
179861ecd0c6SBarry Smith   }
179961ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
180061ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
180161ecd0c6SBarry Smith   PetscFunctionReturn(0);
180261ecd0c6SBarry Smith }
180361ecd0c6SBarry Smith 
1804be5855fcSBarry Smith /*
1805be5855fcSBarry Smith      Checks for missing diagonals
1806be5855fcSBarry Smith */
1807ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1808be5855fcSBarry Smith {
1809be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18107734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1811994fe344SLisandro Dalcin   PetscErrorCode ierr;
1812be5855fcSBarry Smith 
1813be5855fcSBarry Smith   PetscFunctionBegin;
181409f38230SBarry Smith   *missing = PETSC_FALSE;
18157734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
181609f38230SBarry Smith     *missing = PETSC_TRUE;
181709f38230SBarry Smith     if (d) *d = 0;
1818994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
181909f38230SBarry Smith   } else {
182001445905SHong Zhang     PetscInt n;
182101445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1822f1e2ffcdSBarry Smith     diag = a->diag;
182301445905SHong Zhang     for (i=0; i<n; i++) {
18247734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
182509f38230SBarry Smith         *missing = PETSC_TRUE;
182609f38230SBarry Smith         if (d) *d = i;
1827994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1828358d2f5dSShri Abhyankar         break;
182909f38230SBarry Smith       }
1830be5855fcSBarry Smith     }
1831be5855fcSBarry Smith   }
1832be5855fcSBarry Smith   PetscFunctionReturn(0);
1833be5855fcSBarry Smith }
1834be5855fcSBarry Smith 
18350da83c2eSBarry Smith #include <petscblaslapack.h>
18360da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18370da83c2eSBarry Smith 
18380da83c2eSBarry Smith /*
18390da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18400da83c2eSBarry Smith */
18410da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18420da83c2eSBarry Smith {
18430da83c2eSBarry Smith   PetscErrorCode  ierr;
18440da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18450da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18460da83c2eSBarry Smith   const PetscReal shift = 0.0;
18470da83c2eSBarry Smith   PetscInt        ipvt[5];
18480da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18490da83c2eSBarry Smith 
18500da83c2eSBarry Smith   PetscFunctionBegin;
18510da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18520da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18530da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18540da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18550da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18560da83c2eSBarry Smith   }
18570da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18580da83c2eSBarry Smith   if (bsizemax > 7) {
18590da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18600da83c2eSBarry Smith   }
18610da83c2eSBarry Smith   ncnt = 0;
18620da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18630da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18640da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18650da83c2eSBarry Smith     switch (bsizes[i]) {
18660da83c2eSBarry Smith     case 1:
18670da83c2eSBarry Smith       *diag = 1.0/(*diag);
18680da83c2eSBarry Smith       break;
18690da83c2eSBarry Smith     case 2:
18700da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18710da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18720da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18730da83c2eSBarry Smith       break;
18740da83c2eSBarry Smith     case 3:
18750da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18760da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18770da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18780da83c2eSBarry Smith       break;
18790da83c2eSBarry Smith     case 4:
18800da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18810da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18820da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18830da83c2eSBarry Smith       break;
18840da83c2eSBarry Smith     case 5:
18850da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18860da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18870da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18880da83c2eSBarry Smith       break;
18890da83c2eSBarry Smith     case 6:
18900da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18910da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18920da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
18930da83c2eSBarry Smith       break;
18940da83c2eSBarry Smith     case 7:
18950da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18960da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18970da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
18980da83c2eSBarry Smith       break;
18990da83c2eSBarry Smith     default:
19000da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19010da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19020da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19030da83c2eSBarry Smith     }
19040da83c2eSBarry Smith     ncnt   += bsizes[i];
19050da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19060da83c2eSBarry Smith   }
19070da83c2eSBarry Smith   if (bsizemax > 7) {
19080da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19090da83c2eSBarry Smith   }
19100da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19110da83c2eSBarry Smith   PetscFunctionReturn(0);
19120da83c2eSBarry Smith }
19130da83c2eSBarry Smith 
1914422a814eSBarry Smith /*
1915422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1916422a814eSBarry Smith */
19177087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
191871f1c65dSBarry Smith {
191971f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
192071f1c65dSBarry Smith   PetscErrorCode  ierr;
1921d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19222e5835c6SStefano Zampini   const MatScalar *v;
192354f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
192471f1c65dSBarry Smith 
192571f1c65dSBarry Smith   PetscFunctionBegin;
192671f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
192771f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
192871f1c65dSBarry Smith   diag = a->diag;
192971f1c65dSBarry Smith   if (!a->idiag) {
1930dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19313bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
193271f1c65dSBarry Smith   }
19332e5835c6SStefano Zampini 
193471f1c65dSBarry Smith   mdiag = a->mdiag;
193571f1c65dSBarry Smith   idiag = a->idiag;
19362e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1937422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
193871f1c65dSBarry Smith     for (i=0; i<m; i++) {
193971f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1940899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1941899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1942899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19437b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19447b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19457b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1946a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1947899639b0SHong Zhang       }
194871f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
194971f1c65dSBarry Smith     }
195071f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
195171f1c65dSBarry Smith   } else {
195271f1c65dSBarry Smith     for (i=0; i<m; i++) {
195371f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
195471f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
195571f1c65dSBarry Smith     }
1956dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
195771f1c65dSBarry Smith   }
195871f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19592e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
196071f1c65dSBarry Smith   PetscFunctionReturn(0);
196171f1c65dSBarry Smith }
196271f1c65dSBarry Smith 
1963c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
196441f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
196517ab2063SBarry Smith {
1966416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1967e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19682e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
196954f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1970dfbe8321SBarry Smith   PetscErrorCode    ierr;
19713d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
197297f1f81fSBarry Smith   const PetscInt    *idx,*diag;
197317ab2063SBarry Smith 
19743a40ed3dSBarry Smith   PetscFunctionBegin;
1975b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1976b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1977b215bc84SStefano Zampini     PetscFunctionReturn(0);
1978b215bc84SStefano Zampini   }
1979b965ef7fSBarry Smith   its = its*lits;
198091723122SBarry Smith 
198171f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
198271f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
198371f1c65dSBarry Smith   a->fshift = fshift;
198471f1c65dSBarry Smith   a->omega  = omega;
1985ed480e8bSBarry Smith 
198671f1c65dSBarry Smith   diag  = a->diag;
198771f1c65dSBarry Smith   t     = a->ssor_work;
1988ed480e8bSBarry Smith   idiag = a->idiag;
198971f1c65dSBarry Smith   mdiag = a->mdiag;
1990ed480e8bSBarry Smith 
19912e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
19921ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
19933649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1994ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
199517ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
199617ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1997ed480e8bSBarry Smith     bs = b;
199817ab2063SBarry Smith     for (i=0; i<m; i++) {
199971f1c65dSBarry Smith       d   = fshift + mdiag[i];
2000416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2001ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20022e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
200317ab2063SBarry Smith       sum = b[i]*d/omega;
2004003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
200517ab2063SBarry Smith       x[i] = sum;
200617ab2063SBarry Smith     }
20071ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20083649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20092e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2010efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20113a40ed3dSBarry Smith     PetscFunctionReturn(0);
201217ab2063SBarry Smith   }
2013c783ea89SBarry Smith 
20142205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20152205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20164c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2017887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
201817ab2063SBarry Smith 
201917ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
202017ab2063SBarry Smith 
2021887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
202217ab2063SBarry Smith     */
202317ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
202417ab2063SBarry Smith 
202517ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
202617ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2027416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2028ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20292e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
203017ab2063SBarry Smith       sum = b[i];
2031e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2032ed480e8bSBarry Smith       x[i] = sum*idiag[i];
203317ab2063SBarry Smith     }
203417ab2063SBarry Smith 
203517ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20362e5835c6SStefano Zampini     v = aa;
20372205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
203817ab2063SBarry Smith 
203917ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2040ed480e8bSBarry Smith     ts   = t;
2041416022c9SBarry Smith     diag = a->diag;
204217ab2063SBarry Smith     for (i=0; i<m; i++) {
2043416022c9SBarry Smith       n   = diag[i] - a->i[i];
2044ed480e8bSBarry Smith       idx = a->j + a->i[i];
20452e5835c6SStefano Zampini       v   = aa + a->i[i];
204617ab2063SBarry Smith       sum = t[i];
2047003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2048ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2049733d66baSBarry Smith       /*  x = x + t */
2050733d66baSBarry Smith       x[i] += t[i];
205117ab2063SBarry Smith     }
205217ab2063SBarry Smith 
2053dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20541ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20553649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20563a40ed3dSBarry Smith     PetscFunctionReturn(0);
205717ab2063SBarry Smith   }
205817ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
205917ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
206017ab2063SBarry Smith       for (i=0; i<m; i++) {
2061416022c9SBarry Smith         n   = diag[i] - a->i[i];
2062ed480e8bSBarry Smith         idx = a->j + a->i[i];
20632e5835c6SStefano Zampini         v   = aa + a->i[i];
206417ab2063SBarry Smith         sum = b[i];
2065e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20665c99c7daSBarry Smith         t[i] = sum;
2067ed480e8bSBarry Smith         x[i] = sum*idiag[i];
206817ab2063SBarry Smith       }
20695c99c7daSBarry Smith       xb   = t;
2070efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20713a40ed3dSBarry Smith     } else xb = b;
207217ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
207317ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2074416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2075ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20762e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
207717ab2063SBarry Smith         sum = xb[i];
2078e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20795c99c7daSBarry Smith         if (xb == b) {
2080ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20815c99c7daSBarry Smith         } else {
2082b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
208317ab2063SBarry Smith         }
20845c99c7daSBarry Smith       }
2085b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
208617ab2063SBarry Smith     }
208717ab2063SBarry Smith     its--;
208817ab2063SBarry Smith   }
208917ab2063SBarry Smith   while (its--) {
209017ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
209117ab2063SBarry Smith       for (i=0; i<m; i++) {
2092b19a5dc2SMark Adams         /* lower */
2093b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2094ed480e8bSBarry Smith         idx = a->j + a->i[i];
20952e5835c6SStefano Zampini         v   = aa + a->i[i];
209617ab2063SBarry Smith         sum = b[i];
2097e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2098b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2099b19a5dc2SMark Adams         /* upper */
2100b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2101b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21022e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2103b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2104b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
210517ab2063SBarry Smith       }
2106b19a5dc2SMark Adams       xb   = t;
21079f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2108b19a5dc2SMark Adams     } else xb = b;
210917ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
211017ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2111b19a5dc2SMark Adams         sum = xb[i];
2112b19a5dc2SMark Adams         if (xb == b) {
2113b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2114416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2115ed480e8bSBarry Smith           idx = a->j + a->i[i];
21162e5835c6SStefano Zampini           v   = aa + a->i[i];
2117e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2118ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2119b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2120b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2121b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21222e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2123b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2124b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
212517ab2063SBarry Smith         }
2126b19a5dc2SMark Adams       }
2127b19a5dc2SMark Adams       if (xb == b) {
21289f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2129b19a5dc2SMark Adams       } else {
2130b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2131b19a5dc2SMark Adams       }
213217ab2063SBarry Smith     }
213317ab2063SBarry Smith   }
21342e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21351ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21363649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2137365a8a9eSBarry Smith   PetscFunctionReturn(0);
213817ab2063SBarry Smith }
213917ab2063SBarry Smith 
21402af78befSBarry Smith 
2141dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
214217ab2063SBarry Smith {
2143416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21444e220ebcSLois Curfman McInnes 
21453a40ed3dSBarry Smith   PetscFunctionBegin;
21464e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21473966268fSBarry Smith   info->nz_allocated = a->maxnz;
21483966268fSBarry Smith   info->nz_used      = a->nz;
21493966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21503966268fSBarry Smith   info->assemblies   = A->num_ass;
21513966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21527adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2153d5f3da31SBarry Smith   if (A->factortype) {
21544e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21554e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21564e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21574e220ebcSLois Curfman McInnes   } else {
21584e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21594e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21604e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21614e220ebcSLois Curfman McInnes   }
21623a40ed3dSBarry Smith   PetscFunctionReturn(0);
216317ab2063SBarry Smith }
216417ab2063SBarry Smith 
21652b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
216617ab2063SBarry Smith {
2167416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2168c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21696849ba73SBarry Smith   PetscErrorCode    ierr;
217097b48c8fSBarry Smith   const PetscScalar *xx;
21712e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2172c7da8527SEric Chamberland   PetscInt          d = 0;
217317ab2063SBarry Smith 
21743a40ed3dSBarry Smith   PetscFunctionBegin;
217597b48c8fSBarry Smith   if (x && b) {
217697b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
217797b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
217897b48c8fSBarry Smith     for (i=0; i<N; i++) {
217997b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2180447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
218197b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
218297b48c8fSBarry Smith     }
218397b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
218497b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
218597b48c8fSBarry Smith   }
218697b48c8fSBarry Smith 
21872e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
2188a9817697SBarry Smith   if (a->keepnonzeropattern) {
2189f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2190e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
21912e5835c6SStefano Zampini       ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2192f1e2ffcdSBarry Smith     }
2193f4df32b1SMatthew Knepley     if (diag != 0.0) {
2194c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2195c7da8527SEric Chamberland         d = rows[i];
2196447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2197c7da8527SEric Chamberland         if (a->diag[d] >= a->i[d+1]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in the zeroed row %D",d);
2198c7da8527SEric Chamberland       }
2199f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2200447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22012e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2202f1e2ffcdSBarry Smith       }
2203f1e2ffcdSBarry Smith     }
2204f1e2ffcdSBarry Smith   } else {
2205f4df32b1SMatthew Knepley     if (diag != 0.0) {
220617ab2063SBarry Smith       for (i=0; i<N; i++) {
2207e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22087ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2209447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2210447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2211447d62f5SStefano Zampini           } else {
2212416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
22132e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2214bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2215447d62f5SStefano Zampini           }
2216447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2217f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
221817ab2063SBarry Smith         }
221917ab2063SBarry Smith       }
22203a40ed3dSBarry Smith     } else {
222117ab2063SBarry Smith       for (i=0; i<N; i++) {
2222e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2223416022c9SBarry Smith         a->ilen[rows[i]] = 0;
222417ab2063SBarry Smith       }
222517ab2063SBarry Smith     }
2226e56f5c9eSBarry Smith     A->nonzerostate++;
2227f1e2ffcdSBarry Smith   }
22282e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22298c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2230c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2231e2cf4d64SStefano Zampini #endif
22324099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22333a40ed3dSBarry Smith   PetscFunctionReturn(0);
223417ab2063SBarry Smith }
223517ab2063SBarry Smith 
22366e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22376e169961SBarry Smith {
22386e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22396e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22406e169961SBarry Smith   PetscErrorCode    ierr;
22412b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22426e169961SBarry Smith   const PetscScalar *xx;
22432e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22446e169961SBarry Smith 
22456e169961SBarry Smith   PetscFunctionBegin;
22462e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22472e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
22486e169961SBarry Smith   if (x && b) {
22496e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22506e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22512b40b63fSBarry Smith     vecs = PETSC_TRUE;
22526e169961SBarry Smith   }
22531795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22546e169961SBarry Smith   for (i=0; i<N; i++) {
22556e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22562e5835c6SStefano Zampini     ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22572205254eSKarl Rupp 
22586e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22596e169961SBarry Smith   }
22606e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22616e169961SBarry Smith     if (!zeroed[i]) {
22626e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22634cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22642e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22652e5835c6SStefano Zampini           aa[j] = 0.0;
22666e169961SBarry Smith         }
22676e169961SBarry Smith       }
22684cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22696e169961SBarry Smith   }
22706e169961SBarry Smith   if (x && b) {
22716e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22726e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22736e169961SBarry Smith   }
22746e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22756e169961SBarry Smith   if (diag != 0.0) {
22766e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22771d5a398dSstefano_zampini     if (missing) {
22781d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22794cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22804cf107fdSStefano Zampini         if (a->nonew && rows[i] >= d) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D (%D)",d,rows[i]);
22811d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22821d5a398dSstefano_zampini       }
22831d5a398dSstefano_zampini     } else {
22846e169961SBarry Smith       for (i=0; i<N; i++) {
22852e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
22866e169961SBarry Smith       }
22876e169961SBarry Smith     }
22881d5a398dSstefano_zampini   }
22892e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22908c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2291c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2292e2cf4d64SStefano Zampini #endif
22934099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22946e169961SBarry Smith   PetscFunctionReturn(0);
22956e169961SBarry Smith }
22966e169961SBarry Smith 
2297a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
229817ab2063SBarry Smith {
2299416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
23002e5835c6SStefano Zampini   const PetscScalar *aa = a->a;
230197f1f81fSBarry Smith   PetscInt          *itmp;
23022e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23032e5835c6SStefano Zampini   PetscErrorCode    ierr;
23042e5835c6SStefano Zampini   PetscBool         rest = PETSC_FALSE;
23052e5835c6SStefano Zampini #endif
230617ab2063SBarry Smith 
23073a40ed3dSBarry Smith   PetscFunctionBegin;
23082e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23092e5835c6SStefano Zampini   if (v && A->offloadmask == PETSC_OFFLOAD_GPU) {
23102e5835c6SStefano Zampini     /* triggers copy to CPU */
23112e5835c6SStefano Zampini     rest = PETSC_TRUE;
23122e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
23132e5835c6SStefano Zampini   } else aa = a->a;
23142e5835c6SStefano Zampini #endif
2315416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
23162e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
231717ab2063SBarry Smith   if (idx) {
2318bfeeae90SHong Zhang     itmp = a->j + a->i[row];
231926fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2320f4259b30SLisandro Dalcin     else *idx = NULL;
232117ab2063SBarry Smith   }
23222e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23232e5835c6SStefano Zampini   if (rest) {
23242e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
23252e5835c6SStefano Zampini   }
23262e5835c6SStefano Zampini #endif
23273a40ed3dSBarry Smith   PetscFunctionReturn(0);
232817ab2063SBarry Smith }
232917ab2063SBarry Smith 
2330a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
233117ab2063SBarry Smith {
23323a40ed3dSBarry Smith   PetscFunctionBegin;
23332e5835c6SStefano Zampini   *nz = 0;
23342e5835c6SStefano Zampini   if (idx) *idx = NULL;
23352e5835c6SStefano Zampini   if (v) *v = NULL;
23363a40ed3dSBarry Smith   PetscFunctionReturn(0);
233717ab2063SBarry Smith }
233817ab2063SBarry Smith 
2339dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
234017ab2063SBarry Smith {
2341416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
23422e5835c6SStefano Zampini   const MatScalar *v;
234336db0b34SBarry Smith   PetscReal       sum = 0.0;
23446849ba73SBarry Smith   PetscErrorCode  ierr;
234597f1f81fSBarry Smith   PetscInt        i,j;
234617ab2063SBarry Smith 
23473a40ed3dSBarry Smith   PetscFunctionBegin;
23482e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
234917ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2350570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2351570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
235273cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2353570b7f6dSBarry Smith #else
2354416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
235536db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
235617ab2063SBarry Smith     }
23578f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2358570b7f6dSBarry Smith #endif
2359ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23603a40ed3dSBarry Smith   } else if (type == NORM_1) {
236136db0b34SBarry Smith     PetscReal *tmp;
236297f1f81fSBarry Smith     PetscInt  *jj = a->j;
23631795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2364064f8208SBarry Smith     *nrm = 0.0;
2365416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2366bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
236717ab2063SBarry Smith     }
2368d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2369064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
237017ab2063SBarry Smith     }
2371606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
237251f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23733a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2374064f8208SBarry Smith     *nrm = 0.0;
2375d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23762e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
237717ab2063SBarry Smith       sum = 0.0;
2378416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23792e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
238017ab2063SBarry Smith       }
2381064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
238217ab2063SBarry Smith     }
238351f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2384f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23852e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
23863a40ed3dSBarry Smith   PetscFunctionReturn(0);
238717ab2063SBarry Smith }
238817ab2063SBarry Smith 
23894e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23904e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23914e938277SHong Zhang {
23924e938277SHong Zhang   PetscErrorCode ierr;
23934e938277SHong Zhang   PetscInt       i,j,anzj;
23944e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23954e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23964e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23974e938277SHong Zhang 
23984e938277SHong Zhang   PetscFunctionBegin;
23994e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2400854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2401785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2402785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
24034e938277SHong Zhang 
24044e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
24054e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
240626fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
24074e938277SHong Zhang   /* Form ati for csr format of A^T. */
240826fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
24094e938277SHong Zhang 
24104e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2411580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
24124e938277SHong Zhang 
24134e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
24144e938277SHong Zhang   for (i=0;i<am;i++) {
24154e938277SHong Zhang     anzj = ai[i+1] - ai[i];
24164e938277SHong Zhang     for (j=0;j<anzj;j++) {
24174e938277SHong Zhang       atj[atfill[*aj]] = i;
24184e938277SHong Zhang       atfill[*aj++]   += 1;
24194e938277SHong Zhang     }
24204e938277SHong Zhang   }
24214e938277SHong Zhang 
24224e938277SHong Zhang   /* Clean up temporary space and complete requests. */
24234e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2424ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
242533d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2426b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2427a2f3521dSMark F. Adams 
24284e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
24294e938277SHong Zhang   b->free_a  = PETSC_FALSE;
24304e938277SHong Zhang   b->free_ij = PETSC_TRUE;
24314e938277SHong Zhang   b->nonew   = 0;
24324e938277SHong Zhang   PetscFunctionReturn(0);
24334e938277SHong Zhang }
24344e938277SHong Zhang 
24357087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2436cd0d46ebSvictorle {
24373d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
243854f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
24392e5835c6SStefano Zampini   const MatScalar *va,*vb;
24406849ba73SBarry Smith   PetscErrorCode  ierr;
244197f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2442cd0d46ebSvictorle 
2443cd0d46ebSvictorle   PetscFunctionBegin;
2444cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2445cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24465485867bSBarry Smith   if (ma!=nb || na!=mb) {
24475485867bSBarry Smith     *f = PETSC_FALSE;
24485485867bSBarry Smith     PetscFunctionReturn(0);
24495485867bSBarry Smith   }
24502e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr);
24512e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr);
2452cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2453cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2454785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2455785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2456cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2457cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2458cd0d46ebSvictorle 
2459cd0d46ebSvictorle   *f = PETSC_TRUE;
2460cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2461cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
246297f1f81fSBarry Smith       PetscInt    idc,idr;
24635485867bSBarry Smith       PetscScalar vc,vr;
2464cd0d46ebSvictorle       /* column/row index/value */
24655485867bSBarry Smith       idc = adx[aptr[i]];
24665485867bSBarry Smith       idr = bdx[bptr[idc]];
24675485867bSBarry Smith       vc  = va[aptr[i]];
24685485867bSBarry Smith       vr  = vb[bptr[idc]];
24695485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24705485867bSBarry Smith         *f = PETSC_FALSE;
24715485867bSBarry Smith         goto done;
2472cd0d46ebSvictorle       } else {
24735485867bSBarry Smith         aptr[i]++;
24745485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2475cd0d46ebSvictorle       }
2476cd0d46ebSvictorle     }
2477cd0d46ebSvictorle   }
2478cd0d46ebSvictorle done:
2479cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24803aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
24812e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr);
24822e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr);
2483cd0d46ebSvictorle   PetscFunctionReturn(0);
2484cd0d46ebSvictorle }
2485cd0d46ebSvictorle 
24867087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24871cbb95d3SBarry Smith {
24883d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
248954f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
249054f21887SBarry Smith   MatScalar      *va,*vb;
24911cbb95d3SBarry Smith   PetscErrorCode ierr;
24921cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24931cbb95d3SBarry Smith 
24941cbb95d3SBarry Smith   PetscFunctionBegin;
24951cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
24961cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24971cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24981cbb95d3SBarry Smith     *f = PETSC_FALSE;
24991cbb95d3SBarry Smith     PetscFunctionReturn(0);
25001cbb95d3SBarry Smith   }
25011cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
25021cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
25031cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2504785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2505785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
25061cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
25071cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
25081cbb95d3SBarry Smith 
25091cbb95d3SBarry Smith   *f = PETSC_TRUE;
25101cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
25111cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
25121cbb95d3SBarry Smith       PetscInt    idc,idr;
25131cbb95d3SBarry Smith       PetscScalar vc,vr;
25141cbb95d3SBarry Smith       /* column/row index/value */
25151cbb95d3SBarry Smith       idc = adx[aptr[i]];
25161cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
25171cbb95d3SBarry Smith       vc  = va[aptr[i]];
25181cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
25191cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
25201cbb95d3SBarry Smith         *f = PETSC_FALSE;
25211cbb95d3SBarry Smith         goto done;
25221cbb95d3SBarry Smith       } else {
25231cbb95d3SBarry Smith         aptr[i]++;
25241cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
25251cbb95d3SBarry Smith       }
25261cbb95d3SBarry Smith     }
25271cbb95d3SBarry Smith   }
25281cbb95d3SBarry Smith done:
25291cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
25301cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
25311cbb95d3SBarry Smith   PetscFunctionReturn(0);
25321cbb95d3SBarry Smith }
25331cbb95d3SBarry Smith 
2534ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25359e29f15eSvictorle {
2536dfbe8321SBarry Smith   PetscErrorCode ierr;
25376e111a19SKarl Rupp 
25389e29f15eSvictorle   PetscFunctionBegin;
25395485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25409e29f15eSvictorle   PetscFunctionReturn(0);
25419e29f15eSvictorle }
25429e29f15eSvictorle 
2543ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25441cbb95d3SBarry Smith {
25451cbb95d3SBarry Smith   PetscErrorCode ierr;
25466e111a19SKarl Rupp 
25471cbb95d3SBarry Smith   PetscFunctionBegin;
25481cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25491cbb95d3SBarry Smith   PetscFunctionReturn(0);
25501cbb95d3SBarry Smith }
25511cbb95d3SBarry Smith 
2552dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
255317ab2063SBarry Smith {
2554416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2555fff8e43fSBarry Smith   const PetscScalar *l,*r;
2556fff8e43fSBarry Smith   PetscScalar       x;
255754f21887SBarry Smith   MatScalar         *v;
2558dfbe8321SBarry Smith   PetscErrorCode    ierr;
2559fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2560fff8e43fSBarry Smith   const PetscInt    *jj;
256117ab2063SBarry Smith 
25623a40ed3dSBarry Smith   PetscFunctionBegin;
256317ab2063SBarry Smith   if (ll) {
25643ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25653ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2566e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2567e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2568fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
25692e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
257017ab2063SBarry Smith     for (i=0; i<m; i++) {
257117ab2063SBarry Smith       x = l[i];
2572416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25732205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
257417ab2063SBarry Smith     }
2575fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2576efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
25772e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
257817ab2063SBarry Smith   }
257917ab2063SBarry Smith   if (rr) {
2580e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2581e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2582fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
25832e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
25842e5835c6SStefano Zampini     jj = a->j;
25852205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
25862e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
2587fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2588efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
258917ab2063SBarry Smith   }
2590acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
25918c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2592c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2593e2cf4d64SStefano Zampini #endif
25943a40ed3dSBarry Smith   PetscFunctionReturn(0);
259517ab2063SBarry Smith }
259617ab2063SBarry Smith 
25977dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
259817ab2063SBarry Smith {
2599db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
26006849ba73SBarry Smith   PetscErrorCode    ierr;
2601d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
260297f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
26035d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
26042e5835c6SStefano Zampini   const PetscScalar *aa;
26055d0c19d7SBarry Smith   PetscInt          nrows,ncols;
260697f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
260754f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2608416022c9SBarry Smith   Mat               C;
2609cdc6f3adSToby Isaac   PetscBool         stride;
261017ab2063SBarry Smith 
26113a40ed3dSBarry Smith   PetscFunctionBegin;
261217ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2613b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2614b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
261517ab2063SBarry Smith 
2616251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2617ff718158SBarry Smith   if (stride) {
2618ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2619ff718158SBarry Smith   } else {
2620ff718158SBarry Smith     first = 0;
2621ff718158SBarry Smith     step  = 0;
2622ff718158SBarry Smith   }
2623fee21e36SBarry Smith   if (stride && step == 1) {
262402834360SBarry Smith     /* special case of contiguous rows */
2625dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
262602834360SBarry Smith     /* loop over new rows determining lens and starting points */
262702834360SBarry Smith     for (i=0; i<nrows; i++) {
2628bfeeae90SHong Zhang       kstart = ai[irow[i]];
2629a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2630a91a9bebSLisandro Dalcin       starts[i] = kstart;
263102834360SBarry Smith       for (k=kstart; k<kend; k++) {
2632bfeeae90SHong Zhang         if (aj[k] >= first) {
263302834360SBarry Smith           starts[i] = k;
263402834360SBarry Smith           break;
263502834360SBarry Smith         }
263602834360SBarry Smith       }
2637a2744918SBarry Smith       sum = 0;
263802834360SBarry Smith       while (k < kend) {
2639bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2640a2744918SBarry Smith         sum++;
264102834360SBarry Smith       }
2642a2744918SBarry Smith       lens[i] = sum;
264302834360SBarry Smith     }
264402834360SBarry Smith     /* create submatrix */
2645cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
264697f1f81fSBarry Smith       PetscInt n_cols,n_rows;
264708480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2648e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2649d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
265008480c60SBarry Smith       C    = *B;
26513a40ed3dSBarry Smith     } else {
26523bef6203SJed Brown       PetscInt rbs,cbs;
2653ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2654f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26553bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26563bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26573bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26587adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2659ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
266008480c60SBarry Smith     }
2661db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2662db02288aSLois Curfman McInnes 
266302834360SBarry Smith     /* loop over rows inserting into submatrix */
2664db02288aSLois Curfman McInnes     a_new = c->a;
2665db02288aSLois Curfman McInnes     j_new = c->j;
2666db02288aSLois Curfman McInnes     i_new = c->i;
26672e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
266802834360SBarry Smith     for (i=0; i<nrows; i++) {
2669a2744918SBarry Smith       ii    = starts[i];
2670a2744918SBarry Smith       lensi = lens[i];
2671a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2672a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
267302834360SBarry Smith       }
26742e5835c6SStefano Zampini       ierr       = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr);
2675a2744918SBarry Smith       a_new     += lensi;
2676a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2677a2744918SBarry Smith       c->ilen[i] = lensi;
267802834360SBarry Smith     }
26792e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
26800e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26813a40ed3dSBarry Smith   } else {
268202834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26831795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2684854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26854dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2686d9ef940eSSatish Balay       if (PetscUnlikelyDebug(icol[i] >= oldcols)) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%D] %D >= A->cmap->n %D",i,icol[i],oldcols);
26874dcab191SBarry Smith       smap[icol[i]] = i+1;
26884dcab191SBarry Smith     }
26894dcab191SBarry Smith 
269002834360SBarry Smith     /* determine lens of each row */
269102834360SBarry Smith     for (i=0; i<nrows; i++) {
2692bfeeae90SHong Zhang       kstart  = ai[irow[i]];
269302834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
269402834360SBarry Smith       lens[i] = 0;
269502834360SBarry Smith       for (k=kstart; k<kend; k++) {
2696bfeeae90SHong Zhang         if (smap[aj[k]]) {
269702834360SBarry Smith           lens[i]++;
269802834360SBarry Smith         }
269902834360SBarry Smith       }
270002834360SBarry Smith     }
270117ab2063SBarry Smith     /* Create and fill new matrix */
2702a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2703ace3abfcSBarry Smith       PetscBool equal;
27040f5bd95cSBarry Smith 
270599141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2706e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2707580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2708f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2709580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
271008480c60SBarry Smith       C    = *B;
27113a40ed3dSBarry Smith     } else {
27123bef6203SJed Brown       PetscInt rbs,cbs;
2713ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2714f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
27153bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
27163bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
27173bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
27187adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2719ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
272008480c60SBarry Smith     }
27212e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
272299141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
272317ab2063SBarry Smith     for (i=0; i<nrows; i++) {
272499141d43SSatish Balay       row      = irow[i];
2725bfeeae90SHong Zhang       kstart   = ai[row];
272699141d43SSatish Balay       kend     = kstart + a->ilen[row];
2727bfeeae90SHong Zhang       mat_i    = c->i[i];
272899141d43SSatish Balay       mat_j    = c->j + mat_i;
272999141d43SSatish Balay       mat_a    = c->a + mat_i;
273099141d43SSatish Balay       mat_ilen = c->ilen + i;
273117ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2732bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2733ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
27342e5835c6SStefano Zampini           *mat_a++ = aa[k];
273599141d43SSatish Balay           (*mat_ilen)++;
273699141d43SSatish Balay 
273717ab2063SBarry Smith         }
273817ab2063SBarry Smith       }
273917ab2063SBarry Smith     }
27402e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
274102834360SBarry Smith     /* Free work space */
274202834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2743606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2744606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2745cdc6f3adSToby Isaac     /* sort */
2746cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2747cdc6f3adSToby Isaac       PetscInt ilen;
2748cdc6f3adSToby Isaac 
2749cdc6f3adSToby Isaac       mat_i = c->i[i];
2750cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2751cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2752cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2753390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2754cdc6f3adSToby Isaac     }
275502834360SBarry Smith   }
27568c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2757b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2758305c6ccfSStefano Zampini #endif
27596d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27606d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
276117ab2063SBarry Smith 
276217ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2763416022c9SBarry Smith   *B   = C;
27643a40ed3dSBarry Smith   PetscFunctionReturn(0);
276517ab2063SBarry Smith }
276617ab2063SBarry Smith 
2767fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
276882d44351SHong Zhang {
276982d44351SHong Zhang   PetscErrorCode ierr;
277082d44351SHong Zhang   Mat            B;
277182d44351SHong Zhang 
277282d44351SHong Zhang   PetscFunctionBegin;
2773c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
277482d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
277582d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
277633d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
277782d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
277882d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
277982d44351SHong Zhang     *subMat = B;
2780c2d650bdSHong Zhang   } else {
2781c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2782c2d650bdSHong Zhang   }
278382d44351SHong Zhang   PetscFunctionReturn(0);
278482d44351SHong Zhang }
278582d44351SHong Zhang 
27869a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2787a871dcd8SBarry Smith {
278863b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2789dfbe8321SBarry Smith   PetscErrorCode ierr;
279063b91edcSBarry Smith   Mat            outA;
2791ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
279263b91edcSBarry Smith 
27933a40ed3dSBarry Smith   PetscFunctionBegin;
2794e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27951df811f5SHong Zhang 
2796b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2797b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2798a871dcd8SBarry Smith 
279963b91edcSBarry Smith   outA             = inA;
2800d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2801f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2802f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
28032205254eSKarl Rupp 
2804c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
28056bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
28062205254eSKarl Rupp 
2807c3122656SLisandro Dalcin   a->row = row;
28082205254eSKarl Rupp 
2809c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
28106bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
28112205254eSKarl Rupp 
2812c3122656SLisandro Dalcin   a->col = col;
281363b91edcSBarry Smith 
281436db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
28156bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
28164c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
28173bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2818f0ec6fceSSatish Balay 
281994a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2820854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
28213bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
282294a9d846SBarry Smith   }
282363b91edcSBarry Smith 
2824f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2825137fb511SHong Zhang   if (row_identity && col_identity) {
2826ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2827137fb511SHong Zhang   } else {
2828719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2829137fb511SHong Zhang   }
28303a40ed3dSBarry Smith   PetscFunctionReturn(0);
2831a871dcd8SBarry Smith }
2832a871dcd8SBarry Smith 
2833f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2834f0b747eeSBarry Smith {
2835f0b747eeSBarry Smith   Mat_SeqAIJ     *a     = (Mat_SeqAIJ*)inA->data;
2836f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
2837efee365bSSatish Balay   PetscErrorCode ierr;
2838c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
28393a40ed3dSBarry Smith 
28403a40ed3dSBarry Smith   PetscFunctionBegin;
2841c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
28428b83055fSJed Brown   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one));
2843efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2844acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
28458c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2846c70f7ee4SJunchao Zhang   if (inA->offloadmask != PETSC_OFFLOAD_UNALLOCATED) inA->offloadmask = PETSC_OFFLOAD_CPU;
2847e2cf4d64SStefano Zampini #endif
28483a40ed3dSBarry Smith   PetscFunctionReturn(0);
2849f0b747eeSBarry Smith }
2850f0b747eeSBarry Smith 
2851f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
285216b64355SHong Zhang {
285316b64355SHong Zhang   PetscErrorCode ierr;
285416b64355SHong Zhang   PetscInt       i;
285516b64355SHong Zhang 
285616b64355SHong Zhang   PetscFunctionBegin;
285716b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
285816b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
285916b64355SHong Zhang 
286016b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
286116b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
286216b64355SHong Zhang     }
286316b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
286416b64355SHong Zhang 
286516b64355SHong Zhang     if (submatj->rbuf1) {
286616b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
286716b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
286816b64355SHong Zhang     }
286916b64355SHong Zhang 
287016b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
287116b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
287216b64355SHong Zhang     }
287316b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
287416b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
287516b64355SHong Zhang   }
287616b64355SHong Zhang 
287716b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
287816b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
287916b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
288016b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
288116b64355SHong Zhang #else
288216b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
288316b64355SHong Zhang #endif
288416b64355SHong Zhang 
288516b64355SHong Zhang   if (!submatj->allcolumns) {
288616b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
288716b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
288816b64355SHong Zhang #else
288916b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
289016b64355SHong Zhang #endif
289116b64355SHong Zhang   }
289216b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
289316b64355SHong Zhang 
289416b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
289516b64355SHong Zhang   PetscFunctionReturn(0);
289616b64355SHong Zhang }
289716b64355SHong Zhang 
28980fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
289916b64355SHong Zhang {
290016b64355SHong Zhang   PetscErrorCode ierr;
290116b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
29025c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
290316b64355SHong Zhang 
290416b64355SHong Zhang   PetscFunctionBegin;
290534136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2906f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
290716b64355SHong Zhang   PetscFunctionReturn(0);
290816b64355SHong Zhang }
290916b64355SHong Zhang 
29102d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
29112d033e1fSHong Zhang {
29122d033e1fSHong Zhang   PetscErrorCode ierr;
29132d033e1fSHong Zhang   PetscInt       i;
29140fb991dcSHong Zhang   Mat            C;
29150fb991dcSHong Zhang   Mat_SeqAIJ     *c;
29160fb991dcSHong Zhang   Mat_SubSppt    *submatj;
29172d033e1fSHong Zhang 
29182d033e1fSHong Zhang   PetscFunctionBegin;
29192d033e1fSHong Zhang   for (i=0; i<n; i++) {
29200fb991dcSHong Zhang     C       = (*mat)[i];
29210fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
29220fb991dcSHong Zhang     submatj = c->submatis1;
29232d033e1fSHong Zhang     if (submatj) {
2924682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
292534136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2926f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
292734136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
29282d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
29292d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
29302d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2931682e4c99SStefano Zampini       }
29322d033e1fSHong Zhang     } else {
29332d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
29342d033e1fSHong Zhang     }
29352d033e1fSHong Zhang   }
293686e85357SHong Zhang 
293763a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
293863a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
293963a75b2aSHong Zhang 
29402d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
29412d033e1fSHong Zhang   PetscFunctionReturn(0);
29422d033e1fSHong Zhang }
29432d033e1fSHong Zhang 
29447dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2945cddf8d76SBarry Smith {
2946dfbe8321SBarry Smith   PetscErrorCode ierr;
294797f1f81fSBarry Smith   PetscInt       i;
2948cddf8d76SBarry Smith 
29493a40ed3dSBarry Smith   PetscFunctionBegin;
2950cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2951df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2952cddf8d76SBarry Smith   }
2953cddf8d76SBarry Smith 
2954cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29557dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2956cddf8d76SBarry Smith   }
29573a40ed3dSBarry Smith   PetscFunctionReturn(0);
2958cddf8d76SBarry Smith }
2959cddf8d76SBarry Smith 
296097f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29614dcbc457SBarry Smith {
2962e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29636849ba73SBarry Smith   PetscErrorCode ierr;
29645d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29655d0c19d7SBarry Smith   const PetscInt *idx;
296697f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2967f1af5d2fSBarry Smith   PetscBT        table;
2968bbd702dbSSatish Balay 
29693a40ed3dSBarry Smith   PetscFunctionBegin;
2970d0f46423SBarry Smith   m  = A->rmap->n;
2971e4d965acSSatish Balay   ai = a->i;
2972bfeeae90SHong Zhang   aj = a->j;
29738a047759SSatish Balay 
2974e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
297506763907SSatish Balay 
2976854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
297753b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
297806763907SSatish Balay 
2979e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2980b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2981e4d965acSSatish Balay     isz  = 0;
29826831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2983e4d965acSSatish Balay 
2984e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29854dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2986b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2987e4d965acSSatish Balay 
2988dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2989e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29902205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29914dcbc457SBarry Smith     }
299206763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
29936bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2994e4d965acSSatish Balay 
299504a348a9SBarry Smith     k = 0;
299604a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
299704a348a9SBarry Smith       n = isz;
299806763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2999e4d965acSSatish Balay         row   = nidx[k];
3000e4d965acSSatish Balay         start = ai[row];
3001e4d965acSSatish Balay         end   = ai[row+1];
300204a348a9SBarry Smith         for (l = start; l<end; l++) {
3003efb16452SHong Zhang           val = aj[l];
30042205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
3005e4d965acSSatish Balay         }
3006e4d965acSSatish Balay       }
3007e4d965acSSatish Balay     }
300870b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
3009e4d965acSSatish Balay   }
301094bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
3011606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
30123a40ed3dSBarry Smith   PetscFunctionReturn(0);
30134dcbc457SBarry Smith }
301417ab2063SBarry Smith 
30150513a670SBarry Smith /* -------------------------------------------------------------- */
3016dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
30170513a670SBarry Smith {
30180513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
30196849ba73SBarry Smith   PetscErrorCode ierr;
30203b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
30215d0c19d7SBarry Smith   const PetscInt *row,*col;
30225d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
302356cd22aeSBarry Smith   IS             icolp,irowp;
30240298fd71SBarry Smith   PetscInt       *cwork = NULL;
30250298fd71SBarry Smith   PetscScalar    *vwork = NULL;
30260513a670SBarry Smith 
30273a40ed3dSBarry Smith   PetscFunctionBegin;
30284c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
302956cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
30304c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
303156cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
30320513a670SBarry Smith 
30330513a670SBarry Smith   /* determine lengths of permuted rows */
3034854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
30352205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
3036ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
3037f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
303833d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
30397adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
3040ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
3041606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
30420513a670SBarry Smith 
3043785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
30440513a670SBarry Smith   for (i=0; i<m; i++) {
304532ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30462205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3047cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
304832ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30490513a670SBarry Smith   }
3050606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30512205254eSKarl Rupp 
30523c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30532205254eSKarl Rupp 
30548c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3055b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30569fe5e383SStefano Zampini #endif
30570513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30580513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
305956cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
306056cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30616bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30626bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30636768869dSprj-   if (rowp == colp) {
30646768869dSprj-     if (A->symmetric) {
30656768869dSprj-       ierr = MatSetOption(*B,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
30666768869dSprj-     }
30676768869dSprj-     if (A->hermitian) {
30686768869dSprj-       ierr = MatSetOption(*B,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
30696768869dSprj-     }
30706768869dSprj-   }
30713a40ed3dSBarry Smith   PetscFunctionReturn(0);
30720513a670SBarry Smith }
30730513a670SBarry Smith 
3074dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3075cb5b572fSBarry Smith {
3076dfbe8321SBarry Smith   PetscErrorCode ierr;
3077cb5b572fSBarry Smith 
3078cb5b572fSBarry Smith   PetscFunctionBegin;
307933f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
308033f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3081be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3082be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30832e5835c6SStefano Zampini     const PetscScalar *aa;
3084be6bf707SBarry Smith 
30852e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30864d805d7cSStefano Zampini     if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different %D != %D",a->i[A->rmap->n],b->i[B->rmap->n]);
30872e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3088cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
30892e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3090cb5b572fSBarry Smith   } else {
3091cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3092cb5b572fSBarry Smith   }
3093cb5b572fSBarry Smith   PetscFunctionReturn(0);
3094cb5b572fSBarry Smith }
3095cb5b572fSBarry Smith 
30964994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3097273d9f13SBarry Smith {
3098dfbe8321SBarry Smith   PetscErrorCode ierr;
3099273d9f13SBarry Smith 
3100273d9f13SBarry Smith   PetscFunctionBegin;
3101f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3102273d9f13SBarry Smith   PetscFunctionReturn(0);
3103273d9f13SBarry Smith }
3104273d9f13SBarry Smith 
3105f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
31066c0721eeSBarry Smith {
31076c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
31086e111a19SKarl Rupp 
31096c0721eeSBarry Smith   PetscFunctionBegin;
31106c0721eeSBarry Smith   *array = a->a;
31116c0721eeSBarry Smith   PetscFunctionReturn(0);
31126c0721eeSBarry Smith }
31136c0721eeSBarry Smith 
3114f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
31156c0721eeSBarry Smith {
31166c0721eeSBarry Smith   PetscFunctionBegin;
3117f38c1e66SStefano Zampini   *array = NULL;
31186c0721eeSBarry Smith   PetscFunctionReturn(0);
31196c0721eeSBarry Smith }
3120273d9f13SBarry Smith 
31218229c054SShri Abhyankar /*
31228229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
31238229c054SShri Abhyankar    have different nonzero structure.
31248229c054SShri Abhyankar */
3125b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3126ec7775f6SShri Abhyankar {
3127b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3128ec7775f6SShri Abhyankar 
3129ec7775f6SShri Abhyankar   PetscFunctionBegin;
3130ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3131ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3132b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3133b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3134b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31358af7cee1SJed Brown     nnz[i] = 0;
31368af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3137b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3138b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31398af7cee1SJed Brown       nnz[i]++;
31408af7cee1SJed Brown     }
31418af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3142ec7775f6SShri Abhyankar   }
3143ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3144ec7775f6SShri Abhyankar }
3145ec7775f6SShri Abhyankar 
3146b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3147b264fe52SHong Zhang {
3148b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3149b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3150b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3151b264fe52SHong Zhang   PetscErrorCode ierr;
3152b264fe52SHong Zhang 
3153b264fe52SHong Zhang   PetscFunctionBegin;
3154b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3155b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3156b264fe52SHong Zhang   PetscFunctionReturn(0);
3157b264fe52SHong Zhang }
3158b264fe52SHong Zhang 
3159f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3160ac90fabeSBarry Smith {
3161dfbe8321SBarry Smith   PetscErrorCode ierr;
3162ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3163ac90fabeSBarry Smith 
3164ac90fabeSBarry Smith   PetscFunctionBegin;
3165*41f5e1b1SStefano Zampini   if (str == UNKNOWN_NONZERO_PATTERN && x->nz == y->nz) {
316681fa06acSBarry Smith     PetscBool e;
316781fa06acSBarry Smith     ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
316881fa06acSBarry Smith     if (e) {
316981fa06acSBarry Smith       ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
317081fa06acSBarry Smith       if (e) {
317181fa06acSBarry Smith         str = SAME_NONZERO_PATTERN;
317281fa06acSBarry Smith       }
317381fa06acSBarry Smith     }
317481fa06acSBarry Smith   }
3175ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31762e5835c6SStefano Zampini     const PetscScalar *xa;
31772e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
317881fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
317981fa06acSBarry Smith 
318081fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31812e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31822e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31832e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31842e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31852e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
3186*41f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3187acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3188a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
318981fa06acSBarry Smith     /* the MatAXPY_Basic* subroutines calls MatAssembly, so the matrix on the GPU will be updated */
31908c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3191*41f5e1b1SStefano Zampini     if (Y->offloadmask != PETSC_OFFLOAD_UNALLOCATED) Y->offloadmask = PETSC_OFFLOAD_CPU;
3192e2cf4d64SStefano Zampini #endif
3193ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3194ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3195ac90fabeSBarry Smith   } else {
31968229c054SShri Abhyankar     Mat      B;
31978229c054SShri Abhyankar     PetscInt *nnz;
3198785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3199ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3200bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
320181fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
32022e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
32038229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3204ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3205ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
320628be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
32078229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3208ac90fabeSBarry Smith   }
3209ac90fabeSBarry Smith   PetscFunctionReturn(0);
3210ac90fabeSBarry Smith }
3211ac90fabeSBarry Smith 
32127087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
3213354c94deSBarry Smith {
3214354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3215354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3216354c94deSBarry Smith   PetscInt    i,nz;
3217354c94deSBarry Smith   PetscScalar *a;
3218354c94deSBarry Smith 
3219354c94deSBarry Smith   PetscFunctionBegin;
3220354c94deSBarry Smith   nz = aij->nz;
3221354c94deSBarry Smith   a  = aij->a;
32222205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
32238c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3224c70f7ee4SJunchao Zhang   if (mat->offloadmask != PETSC_OFFLOAD_UNALLOCATED) mat->offloadmask = PETSC_OFFLOAD_CPU;
3225e2cf4d64SStefano Zampini #endif
3226354c94deSBarry Smith #else
3227354c94deSBarry Smith   PetscFunctionBegin;
3228354c94deSBarry Smith #endif
3229354c94deSBarry Smith   PetscFunctionReturn(0);
3230354c94deSBarry Smith }
3231354c94deSBarry Smith 
3232985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3233e34fafa9SBarry Smith {
3234e34fafa9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3235e34fafa9SBarry Smith   PetscErrorCode ierr;
3236d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3237e34fafa9SBarry Smith   PetscReal      atmp;
3238985db425SBarry Smith   PetscScalar    *x;
3239e34fafa9SBarry Smith   MatScalar      *aa;
3240e34fafa9SBarry Smith 
3241e34fafa9SBarry Smith   PetscFunctionBegin;
3242e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3243e34fafa9SBarry Smith   aa = a->a;
3244e34fafa9SBarry Smith   ai = a->i;
3245e34fafa9SBarry Smith   aj = a->j;
3246e34fafa9SBarry Smith 
3247985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3248475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3249e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3250e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3251e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3252e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3253e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3254985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3255985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3256985db425SBarry Smith       aa++; aj++;
3257985db425SBarry Smith     }
3258985db425SBarry Smith   }
3259475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3260985db425SBarry Smith   PetscFunctionReturn(0);
3261985db425SBarry Smith }
3262985db425SBarry Smith 
3263985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3264985db425SBarry Smith {
3265985db425SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3266985db425SBarry Smith   PetscErrorCode ierr;
3267d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3268985db425SBarry Smith   PetscScalar    *x;
3269985db425SBarry Smith   MatScalar      *aa;
3270985db425SBarry Smith 
3271985db425SBarry Smith   PetscFunctionBegin;
3272e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3273985db425SBarry Smith   aa = a->a;
3274985db425SBarry Smith   ai = a->i;
3275985db425SBarry Smith   aj = a->j;
3276985db425SBarry Smith 
3277985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3278fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3279985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3280e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3281985db425SBarry Smith   for (i=0; i<m; i++) {
3282985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3283d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3284985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3285985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3286985db425SBarry Smith       x[i] = 0.0;
3287985db425SBarry Smith       if (idx) {
3288985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3289985db425SBarry Smith           if (aj[j] > j) {
3290985db425SBarry Smith             idx[i] = j;
3291985db425SBarry Smith             break;
3292985db425SBarry Smith           }
3293985db425SBarry Smith         }
32941a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32951a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3296985db425SBarry Smith       }
3297985db425SBarry Smith     }
3298985db425SBarry Smith     for (j=0; j<ncols; j++) {
3299985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3300985db425SBarry Smith       aa++; aj++;
3301985db425SBarry Smith     }
3302985db425SBarry Smith   }
3303fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3304985db425SBarry Smith   PetscFunctionReturn(0);
3305985db425SBarry Smith }
3306985db425SBarry Smith 
3307c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3308c87e5d42SMatthew Knepley {
3309c87e5d42SMatthew Knepley   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3310c87e5d42SMatthew Knepley   PetscErrorCode ierr;
3311c87e5d42SMatthew Knepley   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
33124e879edeSHong Zhang   PetscScalar    *x,*aa;
3313c87e5d42SMatthew Knepley 
3314c87e5d42SMatthew Knepley   PetscFunctionBegin;
3315c87e5d42SMatthew Knepley   aa = a->a;
3316c87e5d42SMatthew Knepley   ai = a->i;
3317c87e5d42SMatthew Knepley   aj = a->j;
3318c87e5d42SMatthew Knepley 
3319c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3320f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3321c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3322f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3323c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3324c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3325f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3326f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3327f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3328f07e67edSHong Zhang       x[i] = 0.0;
3329f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3330289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3331f07e67edSHong Zhang           if (aj[j] > j) {
3332f07e67edSHong Zhang             idx[i] = j;
33332205254eSKarl Rupp             break;
33342205254eSKarl Rupp           }
3335289a08f5SMatthew Knepley         }
3336f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3337f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3338f07e67edSHong Zhang       }
3339289a08f5SMatthew Knepley     }
3340c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3341f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3342c87e5d42SMatthew Knepley       aa++; aj++;
3343c87e5d42SMatthew Knepley     }
3344c87e5d42SMatthew Knepley   }
3345f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3346c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3347c87e5d42SMatthew Knepley }
3348c87e5d42SMatthew Knepley 
3349985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3350985db425SBarry Smith {
3351985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3352985db425SBarry Smith   PetscErrorCode  ierr;
3353d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3354d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3355985db425SBarry Smith   PetscScalar     *x;
3356d9ca1df4SBarry Smith   const MatScalar *aa;
3357985db425SBarry Smith 
3358985db425SBarry Smith   PetscFunctionBegin;
3359e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3360985db425SBarry Smith   aa = a->a;
3361985db425SBarry Smith   ai = a->i;
3362985db425SBarry Smith   aj = a->j;
3363985db425SBarry Smith 
3364985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3365fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3366985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3367f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3368985db425SBarry Smith   for (i=0; i<m; i++) {
3369985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3370d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3371985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3372985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3373985db425SBarry Smith       x[i] = 0.0;
3374985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3375985db425SBarry Smith         for (j=0; j<ncols; j++) {
3376985db425SBarry Smith           if (aj[j] > j) {
3377985db425SBarry Smith             idx[i] = j;
3378985db425SBarry Smith             break;
3379985db425SBarry Smith           }
3380985db425SBarry Smith         }
3381fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3382fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3383985db425SBarry Smith       }
3384985db425SBarry Smith     }
3385985db425SBarry Smith     for (j=0; j<ncols; j++) {
3386985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3387985db425SBarry Smith       aa++; aj++;
3388e34fafa9SBarry Smith     }
3389e34fafa9SBarry Smith   }
3390fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3391e34fafa9SBarry Smith   PetscFunctionReturn(0);
3392e34fafa9SBarry Smith }
3393bbead8a2SBarry Smith 
3394713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3395bbead8a2SBarry Smith {
3396bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3397bbead8a2SBarry Smith   PetscErrorCode  ierr;
339833d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3399bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
34000da83c2eSBarry Smith   const PetscReal shift = 0.0;
34011a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3402bbead8a2SBarry Smith 
3403bbead8a2SBarry Smith   PetscFunctionBegin;
3404a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
34054a0d0026SBarry Smith   if (a->ibdiagvalid) {
34064a0d0026SBarry Smith     if (values) *values = a->ibdiag;
34074a0d0026SBarry Smith     PetscFunctionReturn(0);
34084a0d0026SBarry Smith   }
3409bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3410bbead8a2SBarry Smith   if (!a->ibdiag) {
3411785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
34123bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3413bbead8a2SBarry Smith   }
3414bbead8a2SBarry Smith   diag = a->ibdiag;
3415bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3416bbead8a2SBarry Smith   /* factor and invert each block */
3417bbead8a2SBarry Smith   switch (bs) {
3418bbead8a2SBarry Smith   case 1:
3419bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3420bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3421ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3422ec1892c8SHong Zhang         if (allowzeropivot) {
34237b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34247b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34257b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34267b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
34277b6c816cSBarry Smith         } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot, row %D pivot %g tolerance %g",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);
3428ec1892c8SHong Zhang       }
3429bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3430bbead8a2SBarry Smith     }
3431bbead8a2SBarry Smith     break;
3432bbead8a2SBarry Smith   case 2:
3433bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3434bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3435bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3436a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34377b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
343896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3439bbead8a2SBarry Smith       diag += 4;
3440bbead8a2SBarry Smith     }
3441bbead8a2SBarry Smith     break;
3442bbead8a2SBarry Smith   case 3:
3443bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3444bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3445bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3446a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34477b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
344896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3449bbead8a2SBarry Smith       diag += 9;
3450bbead8a2SBarry Smith     }
3451bbead8a2SBarry Smith     break;
3452bbead8a2SBarry Smith   case 4:
3453bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3454bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3455bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3456a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34577b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3459bbead8a2SBarry Smith       diag += 16;
3460bbead8a2SBarry Smith     }
3461bbead8a2SBarry Smith     break;
3462bbead8a2SBarry Smith   case 5:
3463bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3464bbead8a2SBarry Smith       ij[0] = 5*i; ij[1] = 5*i + 1; ij[2] = 5*i + 2; ij[3] = 5*i + 3; ij[4] = 5*i + 4;
3465bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3466a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34677b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3469bbead8a2SBarry Smith       diag += 25;
3470bbead8a2SBarry Smith     }
3471bbead8a2SBarry Smith     break;
3472bbead8a2SBarry Smith   case 6:
3473bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3474bbead8a2SBarry Smith       ij[0] = 6*i; ij[1] = 6*i + 1; ij[2] = 6*i + 2; ij[3] = 6*i + 3; ij[4] = 6*i + 4; ij[5] = 6*i + 5;
3475bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3476a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34777b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
347896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3479bbead8a2SBarry Smith       diag += 36;
3480bbead8a2SBarry Smith     }
3481bbead8a2SBarry Smith     break;
3482bbead8a2SBarry Smith   case 7:
3483bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3484bbead8a2SBarry Smith       ij[0] = 7*i; ij[1] = 7*i + 1; ij[2] = 7*i + 2; ij[3] = 7*i + 3; ij[4] = 7*i + 4; ij[5] = 7*i + 5; ij[5] = 7*i + 6;
3485bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3486a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34877b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
348896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3489bbead8a2SBarry Smith       diag += 49;
3490bbead8a2SBarry Smith     }
3491bbead8a2SBarry Smith     break;
3492bbead8a2SBarry Smith   default:
3493dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3494bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3495bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3496bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3497bbead8a2SBarry Smith       }
3498bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
34995f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
35007b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
350196b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3502bbead8a2SBarry Smith       diag += bs2;
3503bbead8a2SBarry Smith     }
3504bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3505bbead8a2SBarry Smith   }
3506bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3507bbead8a2SBarry Smith   PetscFunctionReturn(0);
3508bbead8a2SBarry Smith }
3509bbead8a2SBarry Smith 
351073a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
351173a71a0fSBarry Smith {
351273a71a0fSBarry Smith   PetscErrorCode ierr;
351373a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
351473a71a0fSBarry Smith   PetscScalar    a;
351573a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
351673a71a0fSBarry Smith 
351773a71a0fSBarry Smith   PetscFunctionBegin;
351873a71a0fSBarry Smith   if (!x->assembled) {
351973a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
352073a71a0fSBarry Smith     for (i=0; i<m; i++) {
352173a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
352273a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
352373a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
352473a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
352573a71a0fSBarry Smith       }
352673a71a0fSBarry Smith     }
3527e2ce353bSJunchao Zhang   } else {
3528e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3529e2ce353bSJunchao Zhang   }
353073a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
353173a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
353273a71a0fSBarry Smith   PetscFunctionReturn(0);
353373a71a0fSBarry Smith }
353473a71a0fSBarry Smith 
3535679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3536679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3537679944adSJunchao Zhang {
3538679944adSJunchao Zhang   PetscErrorCode ierr;
3539679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3540679944adSJunchao Zhang   PetscScalar    a;
3541679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3542679944adSJunchao Zhang 
3543679944adSJunchao Zhang   PetscFunctionBegin;
3544679944adSJunchao Zhang   nskip = high - low;
3545679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3546679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3547679944adSJunchao Zhang   for (i=0; i<m; i++) {
3548679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3549679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3550679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3551679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3552679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3553679944adSJunchao Zhang     }
3554e2ce353bSJunchao Zhang   }
3555679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3556679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3557679944adSJunchao Zhang   PetscFunctionReturn(0);
3558679944adSJunchao Zhang }
3559679944adSJunchao Zhang 
3560679944adSJunchao Zhang 
3561682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35620a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3563cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3564cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3565cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
356697304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35677c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35687c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3569f4259b30SLisandro Dalcin                                         NULL,
3570f4259b30SLisandro Dalcin                                         NULL,
3571f4259b30SLisandro Dalcin                                         NULL,
3572f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3573cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3574f4259b30SLisandro Dalcin                                         NULL,
357541f059aeSBarry Smith                                         MatSOR_SeqAIJ,
357691e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
357797304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3578cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3579cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3580cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3581cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3582f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3583cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3584cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3585cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3586d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3587f4259b30SLisandro Dalcin                                         NULL,
3588f4259b30SLisandro Dalcin                                         NULL,
3589f4259b30SLisandro Dalcin                                         NULL,
3590f4259b30SLisandro Dalcin                                         NULL,
35914994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3592f4259b30SLisandro Dalcin                                         NULL,
3593f4259b30SLisandro Dalcin                                         NULL,
3594f4259b30SLisandro Dalcin                                         NULL,
3595f4259b30SLisandro Dalcin                                         NULL,
3596d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3597f4259b30SLisandro Dalcin                                         NULL,
3598f4259b30SLisandro Dalcin                                         NULL,
3599cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3600f4259b30SLisandro Dalcin                                         NULL,
3601d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
36027dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3603cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3604cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3605cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3606d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3607cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
36087d68702bSBarry Smith                                         MatShift_SeqAIJ,
360979299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
36106e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
361173a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
36123b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
36133b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
36143b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3615a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
361693dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3617f4259b30SLisandro Dalcin                                         NULL,
3618f4259b30SLisandro Dalcin                                         NULL,
3619cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3620f4259b30SLisandro Dalcin                                         NULL,
3621f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3622b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3623b9b97703SBarry Smith                                         MatView_SeqAIJ,
3624f4259b30SLisandro Dalcin                                         NULL,
3625f4259b30SLisandro Dalcin                                         NULL,
3626f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3627321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3628f4259b30SLisandro Dalcin                                         NULL,
3629f4259b30SLisandro Dalcin                                         NULL,
3630f4259b30SLisandro Dalcin                                         NULL,
3631d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3632c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3633f4259b30SLisandro Dalcin                                         NULL,
3634f4259b30SLisandro Dalcin                                         NULL,
3635f4259b30SLisandro Dalcin                                         NULL,
3636f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36373acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3638f4259b30SLisandro Dalcin                                         NULL,
3639f4259b30SLisandro Dalcin                                         NULL,
3640f4259b30SLisandro Dalcin                                         NULL,
36416ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3642f4259b30SLisandro Dalcin                                         NULL,
3643f4259b30SLisandro Dalcin                                         NULL,
3644f4259b30SLisandro Dalcin                                         NULL,
3645bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3646d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36471cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3648f4259b30SLisandro Dalcin                                         NULL,
3649f4259b30SLisandro Dalcin                                         NULL,
3650f4259b30SLisandro Dalcin                                         NULL,
3651f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3652f4259b30SLisandro Dalcin                                         NULL,
365326be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3654f4259b30SLisandro Dalcin                                         NULL,
3655f4259b30SLisandro Dalcin                                         NULL,
36568fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3657f4259b30SLisandro Dalcin                                         NULL,
3658f4259b30SLisandro Dalcin                                         NULL,
36596fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3660f4259b30SLisandro Dalcin                                         NULL,
36614222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3662f4259b30SLisandro Dalcin                                         NULL,
3663f4259b30SLisandro Dalcin                                         NULL,
366487d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3665f4259b30SLisandro Dalcin                                         NULL,
3666d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
366799cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3668f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3669f4259b30SLisandro Dalcin                                         NULL,
3670f4259b30SLisandro Dalcin                                         NULL,
3671cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3672f4259b30SLisandro Dalcin                                         NULL,
36732af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3674f4259b30SLisandro Dalcin                                         NULL,
3675599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3676f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3677f4259b30SLisandro Dalcin                                         NULL,
3678f4259b30SLisandro Dalcin                                         NULL,
3679f4259b30SLisandro Dalcin                                         NULL,
3680f4259b30SLisandro Dalcin                                         NULL,
3681f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3682f4259b30SLisandro Dalcin                                         NULL,
3683f4259b30SLisandro Dalcin                                         NULL,
3684f4259b30SLisandro Dalcin                                         NULL,
3685b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36860716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3687bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
368837868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36890da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3690f4259b30SLisandro Dalcin                                         NULL,
3691f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3692f4259b30SLisandro Dalcin                                         NULL,
3693f4259b30SLisandro Dalcin                                         NULL,
369475648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3695b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3696b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36972b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3698f4259b30SLisandro Dalcin                                         NULL,
3699f4259b30SLisandro Dalcin                                         NULL,
37003964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3701f4259b30SLisandro Dalcin                                  /*139*/NULL,
3702f4259b30SLisandro Dalcin                                         NULL,
3703f4259b30SLisandro Dalcin                                         NULL,
37043a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
37059c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
37064222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
37074222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3708f4259b30SLisandro Dalcin                                         NULL,
3709f4259b30SLisandro Dalcin                                         NULL
37109e29f15eSvictorle };
371117ab2063SBarry Smith 
37127087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3713bef8e0ddSBarry Smith {
3714bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
371597f1f81fSBarry Smith   PetscInt   i,nz,n;
3716bef8e0ddSBarry Smith 
3717bef8e0ddSBarry Smith   PetscFunctionBegin;
3718bef8e0ddSBarry Smith   nz = aij->maxnz;
3719d0f46423SBarry Smith   n  = mat->rmap->n;
3720bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3721bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3722bef8e0ddSBarry Smith   }
3723bef8e0ddSBarry Smith   aij->nz = nz;
3724bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3725bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3726bef8e0ddSBarry Smith   }
3727bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3728bef8e0ddSBarry Smith }
3729bef8e0ddSBarry Smith 
3730a3bb6f32SFande Kong /*
3731e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3732a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3733a3bb6f32SFande Kong  * */
3734a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3735a3bb6f32SFande Kong {
3736a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3737a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3738a3bb6f32SFande Kong   PetscTablePosition tpos;
373925b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
374025b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3741a3bb6f32SFande Kong   PetscErrorCode     ierr;
3742a3bb6f32SFande Kong 
3743a3bb6f32SFande Kong   PetscFunctionBegin;
3744a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3745a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3746a3bb6f32SFande Kong   /* use a table */
3747a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3748a3bb6f32SFande Kong   ec = 0;
374925b670f0SStefano Zampini   for (i=0; i<nz; i++) {
375025b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3751a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3752a3bb6f32SFande Kong     if (!data) {
3753a3bb6f32SFande Kong       /* one based table */
3754a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3755a3bb6f32SFande Kong     }
3756a3bb6f32SFande Kong   }
3757a3bb6f32SFande Kong   /* form array of columns we need */
3758a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3759a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3760a3bb6f32SFande Kong   while (tpos) {
3761a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3762a3bb6f32SFande Kong     gid--;
3763a3bb6f32SFande Kong     lid--;
3764a3bb6f32SFande Kong     garray[lid] = gid;
3765a3bb6f32SFande Kong   }
3766a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3767a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3768a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3769a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3770a3bb6f32SFande Kong   }
3771a3bb6f32SFande Kong   /* compact out the extra columns in B */
377225b670f0SStefano Zampini   for (i=0; i<nz; i++) {
377325b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3774a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3775a3bb6f32SFande Kong     lid--;
377625b670f0SStefano Zampini     jj[i] = lid;
3777a3bb6f32SFande Kong   }
3778ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3779a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
378025b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3781a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3782a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3783a3bb6f32SFande Kong   PetscFunctionReturn(0);
3784a3bb6f32SFande Kong }
3785a3bb6f32SFande Kong 
3786bef8e0ddSBarry Smith /*@
3787bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3788bef8e0ddSBarry Smith        in the matrix.
3789bef8e0ddSBarry Smith 
3790bef8e0ddSBarry Smith   Input Parameters:
3791bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3792bef8e0ddSBarry Smith -  indices - the column indices
3793bef8e0ddSBarry Smith 
379415091d37SBarry Smith   Level: advanced
379515091d37SBarry Smith 
3796bef8e0ddSBarry Smith   Notes:
3797bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3798bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3799bef8e0ddSBarry Smith   of the MatSetValues() operation.
3800bef8e0ddSBarry Smith 
3801bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3802d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3803bef8e0ddSBarry Smith 
3804bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3805bef8e0ddSBarry Smith 
3806b9617806SBarry Smith     The indices should start with zero, not one.
3807b9617806SBarry Smith 
3808bef8e0ddSBarry Smith @*/
38097087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3810bef8e0ddSBarry Smith {
38114ac538c5SBarry Smith   PetscErrorCode ierr;
3812bef8e0ddSBarry Smith 
3813bef8e0ddSBarry Smith   PetscFunctionBegin;
38140700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38154482741eSBarry Smith   PetscValidPointer(indices,2);
38164ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3817bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3818bef8e0ddSBarry Smith }
3819bef8e0ddSBarry Smith 
3820be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3821be6bf707SBarry Smith 
38227087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3823be6bf707SBarry Smith {
3824be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38256849ba73SBarry Smith   PetscErrorCode ierr;
3826d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3827be6bf707SBarry Smith 
3828be6bf707SBarry Smith   PetscFunctionBegin;
3829169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3830be6bf707SBarry Smith 
3831be6bf707SBarry Smith   /* allocate space for values if not already there */
3832be6bf707SBarry Smith   if (!aij->saved_values) {
3833854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38343bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3835be6bf707SBarry Smith   }
3836be6bf707SBarry Smith 
3837be6bf707SBarry Smith   /* copy values over */
3838580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3839be6bf707SBarry Smith   PetscFunctionReturn(0);
3840be6bf707SBarry Smith }
3841be6bf707SBarry Smith 
3842be6bf707SBarry Smith /*@
3843be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3844be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3845be6bf707SBarry Smith        nonlinear portion.
3846be6bf707SBarry Smith 
3847be6bf707SBarry Smith    Collect on Mat
3848be6bf707SBarry Smith 
3849be6bf707SBarry Smith   Input Parameters:
38500e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3851be6bf707SBarry Smith 
385215091d37SBarry Smith   Level: advanced
385315091d37SBarry Smith 
3854be6bf707SBarry Smith   Common Usage, with SNESSolve():
3855be6bf707SBarry Smith $    Create Jacobian matrix
3856be6bf707SBarry Smith $    Set linear terms into matrix
3857be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3858be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3859be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3860512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3861be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3862be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3863be6bf707SBarry Smith $    In your Jacobian routine
3864be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3865be6bf707SBarry Smith $      Set nonlinear terms in matrix
3866be6bf707SBarry Smith 
3867be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3868be6bf707SBarry Smith $    // build linear portion of Jacobian
3869512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3870be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3871be6bf707SBarry Smith $    loop over nonlinear iterations
3872be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3873be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3874be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3875be6bf707SBarry Smith $       Solve linear system with Jacobian
3876be6bf707SBarry Smith $    endloop
3877be6bf707SBarry Smith 
3878be6bf707SBarry Smith   Notes:
3879be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3880512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3881be6bf707SBarry Smith     calling this routine.
3882be6bf707SBarry Smith 
38830c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38840c468ba9SBarry Smith     and does not allocated additional space.
38850c468ba9SBarry Smith 
3886be6bf707SBarry Smith .seealso: MatRetrieveValues()
3887be6bf707SBarry Smith 
3888be6bf707SBarry Smith @*/
38897087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3890be6bf707SBarry Smith {
38914ac538c5SBarry Smith   PetscErrorCode ierr;
3892be6bf707SBarry Smith 
3893be6bf707SBarry Smith   PetscFunctionBegin;
38940700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3895e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3896e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38974ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3898be6bf707SBarry Smith   PetscFunctionReturn(0);
3899be6bf707SBarry Smith }
3900be6bf707SBarry Smith 
39017087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3902be6bf707SBarry Smith {
3903be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
39046849ba73SBarry Smith   PetscErrorCode ierr;
3905d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3906be6bf707SBarry Smith 
3907be6bf707SBarry Smith   PetscFunctionBegin;
3908169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3909f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3910be6bf707SBarry Smith   /* copy values over */
3911580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3912be6bf707SBarry Smith   PetscFunctionReturn(0);
3913be6bf707SBarry Smith }
3914be6bf707SBarry Smith 
3915be6bf707SBarry Smith /*@
3916be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3917be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3918be6bf707SBarry Smith        nonlinear portion.
3919be6bf707SBarry Smith 
3920be6bf707SBarry Smith    Collect on Mat
3921be6bf707SBarry Smith 
3922be6bf707SBarry Smith   Input Parameters:
3923386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3924be6bf707SBarry Smith 
392515091d37SBarry Smith   Level: advanced
392615091d37SBarry Smith 
3927be6bf707SBarry Smith .seealso: MatStoreValues()
3928be6bf707SBarry Smith 
3929be6bf707SBarry Smith @*/
39307087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3931be6bf707SBarry Smith {
39324ac538c5SBarry Smith   PetscErrorCode ierr;
3933be6bf707SBarry Smith 
3934be6bf707SBarry Smith   PetscFunctionBegin;
39350700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3936e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3937e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39384ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3939be6bf707SBarry Smith   PetscFunctionReturn(0);
3940be6bf707SBarry Smith }
3941be6bf707SBarry Smith 
3942f83d6046SBarry Smith 
3943be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
394417ab2063SBarry Smith /*@C
3945682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39460d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39476e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
394851c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39492bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
395017ab2063SBarry Smith 
3951d083f849SBarry Smith    Collective
3952db81eaa0SLois Curfman McInnes 
395317ab2063SBarry Smith    Input Parameters:
3954db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
395517ab2063SBarry Smith .  m - number of rows
395617ab2063SBarry Smith .  n - number of columns
395717ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
395851c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39590298fd71SBarry Smith          (possibly different for each row) or NULL
396017ab2063SBarry Smith 
396117ab2063SBarry Smith    Output Parameter:
3962416022c9SBarry Smith .  A - the matrix
396317ab2063SBarry Smith 
3964175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3965f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3966175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3967175b88e8SBarry Smith 
3968b259b22eSLois Curfman McInnes    Notes:
396949a6f317SBarry Smith    If nnz is given then nz is ignored
397049a6f317SBarry Smith 
397117ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
397217ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39730002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
397444cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
397517ab2063SBarry Smith 
397617ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39770298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39783d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39796da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
398017ab2063SBarry Smith 
3981682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39824fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3983682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39846c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39856c7ebb05SLois Curfman McInnes 
39866c7ebb05SLois Curfman McInnes    Options Database Keys:
3987698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39889db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
398917ab2063SBarry Smith 
3990027ccd11SLois Curfman McInnes    Level: intermediate
3991027ccd11SLois Curfman McInnes 
399269b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
399336db0b34SBarry Smith 
399417ab2063SBarry Smith @*/
39957087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
399617ab2063SBarry Smith {
3997dfbe8321SBarry Smith   PetscErrorCode ierr;
39986945ee14SBarry Smith 
39993a40ed3dSBarry Smith   PetscFunctionBegin;
4000f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
4001117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
4002c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
4003d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
4004273d9f13SBarry Smith   PetscFunctionReturn(0);
4005273d9f13SBarry Smith }
4006273d9f13SBarry Smith 
4007273d9f13SBarry Smith /*@C
4008273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
4009273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
4010273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
4011273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
4012273d9f13SBarry Smith 
4013d083f849SBarry Smith    Collective
4014273d9f13SBarry Smith 
4015273d9f13SBarry Smith    Input Parameters:
40161c4f3114SJed Brown +  B - The matrix
4017273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
4018273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
40190298fd71SBarry Smith          (possibly different for each row) or NULL
4020273d9f13SBarry Smith 
4021273d9f13SBarry Smith    Notes:
402249a6f317SBarry Smith      If nnz is given then nz is ignored
402349a6f317SBarry Smith 
4024273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4025273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4026273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4027273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4028273d9f13SBarry Smith 
4029273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40300298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4031273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4032273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4033273d9f13SBarry Smith 
4034aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4035aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4036aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4037aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4038aa95bbe8SBarry Smith 
4039a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4040a96a251dSBarry Smith    entries or columns indices
4041a96a251dSBarry Smith 
4042273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4043273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4044273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4045273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4046273d9f13SBarry Smith 
4047273d9f13SBarry Smith    Options Database Keys:
4048698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
404947b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4050273d9f13SBarry Smith 
4051273d9f13SBarry Smith    Level: intermediate
4052273d9f13SBarry Smith 
405319b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
405419b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4055273d9f13SBarry Smith 
4056273d9f13SBarry Smith @*/
40577087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4058273d9f13SBarry Smith {
40594ac538c5SBarry Smith   PetscErrorCode ierr;
4060a23d5eceSKris Buschelman 
4061a23d5eceSKris Buschelman   PetscFunctionBegin;
40626ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40636ba663aaSJed Brown   PetscValidType(B,1);
40644ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4065a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4066a23d5eceSKris Buschelman }
4067a23d5eceSKris Buschelman 
40687087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4069a23d5eceSKris Buschelman {
4070273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40712576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40726849ba73SBarry Smith   PetscErrorCode ierr;
407397f1f81fSBarry Smith   PetscInt       i;
4074273d9f13SBarry Smith 
4075273d9f13SBarry Smith   PetscFunctionBegin;
40762576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4077a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4078c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4079c461c341SBarry Smith     nz             = 0;
4080c461c341SBarry Smith   }
408126283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
408226283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4083899cda47SBarry Smith 
4084435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
408560e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4086cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4087d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
408860e0710aSBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]);
408960e0710aSBarry Smith       if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %D value %d rowlength %D",i,nnz[i],B->cmap->n);
4090b73539f3SBarry Smith     }
4091b73539f3SBarry Smith   }
4092b73539f3SBarry Smith 
4093273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
40942205254eSKarl Rupp 
4095273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4096273d9f13SBarry Smith 
4097ab93d7beSBarry Smith   if (!skipallocation) {
40982ee49352SLisandro Dalcin     if (!b->imax) {
4099071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4100071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4101071fcb05SBarry Smith     }
4102071fcb05SBarry Smith     if (!b->ilen) {
4103071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4104071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4105071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4106071fcb05SBarry Smith     } else {
4107071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
41082ee49352SLisandro Dalcin     }
4109846b4da1SFande Kong     if (!b->ipre) {
4110846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4111846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4112846b4da1SFande Kong     }
4113273d9f13SBarry Smith     if (!nnz) {
4114435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4115c62bd62aSJed Brown       else if (nz < 0) nz = 1;
41165d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4117d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4118d0f46423SBarry Smith       nz = nz*B->rmap->n;
4119273d9f13SBarry Smith     } else {
4120c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4121c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4122c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4123273d9f13SBarry Smith     }
4124ab93d7beSBarry Smith 
4125273d9f13SBarry Smith     /* allocate the matrix space */
412653dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41272ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4128396832f4SHong Zhang     if (B->structure_only) {
41295848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41305848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4131396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4132396832f4SHong Zhang     } else {
4133dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41343bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4135396832f4SHong Zhang     }
4136bfeeae90SHong Zhang     b->i[0] = 0;
4137d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41385da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41395da197adSKris Buschelman     }
4140396832f4SHong Zhang     if (B->structure_only) {
4141396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4142396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4143396832f4SHong Zhang     } else {
4144273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4145e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4146396832f4SHong Zhang     }
4147e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4148c461c341SBarry Smith   } else {
4149e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4150e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4151c461c341SBarry Smith   }
4152273d9f13SBarry Smith 
4153846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4154846b4da1SFande Kong     /* reserve user-requested sparsity */
4155580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4156846b4da1SFande Kong   }
4157846b4da1SFande Kong 
4158846b4da1SFande Kong 
4159273d9f13SBarry Smith   b->nz               = 0;
4160273d9f13SBarry Smith   b->maxnz            = nz;
4161273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41622205254eSKarl Rupp   if (realalloc) {
41632205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41642205254eSKarl Rupp   }
4165cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4166cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4167273d9f13SBarry Smith   PetscFunctionReturn(0);
4168273d9f13SBarry Smith }
4169273d9f13SBarry Smith 
4170846b4da1SFande Kong 
4171846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4172846b4da1SFande Kong {
4173846b4da1SFande Kong   Mat_SeqAIJ     *a;
4174a5bbaf83SFande Kong   PetscInt       i;
4175846b4da1SFande Kong   PetscErrorCode ierr;
4176846b4da1SFande Kong 
4177846b4da1SFande Kong   PetscFunctionBegin;
4178846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
417914d0e64fSAlex Lindsay 
418014d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
418114d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
418214d0e64fSAlex Lindsay 
4183846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41842c814fdeSFande Kong   /* if no saved info, we error out */
4185fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
41862c814fdeSFande Kong 
4187fb4dc15dSAlex Lindsay   if (!a->i || !a->j || !a->a || !a->imax || !a->ilen) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation \n");
41882c814fdeSFande Kong 
4189580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4190580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4191846b4da1SFande Kong   a->i[0] = 0;
4192846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4193846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4194846b4da1SFande Kong   }
4195846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4196846b4da1SFande Kong   a->nz               = 0;
4197846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4198846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4199846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4200846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4201846b4da1SFande Kong   PetscFunctionReturn(0);
4202846b4da1SFande Kong }
4203846b4da1SFande Kong 
420458d36128SBarry Smith /*@
4205a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4206a1661176SMatthew Knepley 
4207a1661176SMatthew Knepley    Input Parameters:
4208a1661176SMatthew Knepley +  B - the matrix
4209a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4210a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4211a1661176SMatthew Knepley -  v - optional values in the matrix
4212a1661176SMatthew Knepley 
4213a1661176SMatthew Knepley    Level: developer
4214a1661176SMatthew Knepley 
42156a9b8d82SBarry Smith    Notes:
421658d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
421758d36128SBarry Smith 
42186a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
42196a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
42206a9b8d82SBarry Smith 
42216a9b8d82SBarry Smith     Developer Notes:
42226a9b8d82SBarry Smith       An optimization could be added to the implementation where it checks if the i, and j are identical to the current i and j and
42236a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
42246a9b8d82SBarry Smith 
42256a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
42266a9b8d82SBarry Smith 
42276a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4228a1661176SMatthew Knepley @*/
4229a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4230a1661176SMatthew Knepley {
4231a1661176SMatthew Knepley   PetscErrorCode ierr;
4232a1661176SMatthew Knepley 
4233a1661176SMatthew Knepley   PetscFunctionBegin;
42340700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42356ba663aaSJed Brown   PetscValidType(B,1);
42364ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4237a1661176SMatthew Knepley   PetscFunctionReturn(0);
4238a1661176SMatthew Knepley }
4239a1661176SMatthew Knepley 
42407087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4241a1661176SMatthew Knepley {
4242a1661176SMatthew Knepley   PetscInt       i;
4243a1661176SMatthew Knepley   PetscInt       m,n;
4244a1661176SMatthew Knepley   PetscInt       nz;
42456a9b8d82SBarry Smith   PetscInt       *nnz;
4246a1661176SMatthew Knepley   PetscErrorCode ierr;
4247a1661176SMatthew Knepley 
4248a1661176SMatthew Knepley   PetscFunctionBegin;
424965e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4250779a8d59SSatish Balay 
4251779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4252779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4253779a8d59SSatish Balay 
4254779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4255854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4256a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4257b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
425865e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4259a1661176SMatthew Knepley     nnz[i] = nz;
4260a1661176SMatthew Knepley   }
4261a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4262a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4263a1661176SMatthew Knepley 
4264a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4265071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4266a1661176SMatthew Knepley   }
4267a1661176SMatthew Knepley 
4268a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4269a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4270a1661176SMatthew Knepley 
42717827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4272a1661176SMatthew Knepley   PetscFunctionReturn(0);
4273a1661176SMatthew Knepley }
4274a1661176SMatthew Knepley 
4275c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4276af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4277170fe5c8SBarry Smith 
4278170fe5c8SBarry Smith /*
4279170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4280170fe5c8SBarry Smith 
4281170fe5c8SBarry Smith                n                       p                          p
42822da392ccSBarry Smith         [             ]       [             ]         [                 ]
42832da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
42842da392ccSBarry Smith         [             ]       [             ]         [                 ]
4285170fe5c8SBarry Smith 
4286170fe5c8SBarry Smith */
4287170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4288170fe5c8SBarry Smith {
4289170fe5c8SBarry Smith   PetscErrorCode    ierr;
4290170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4291170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4292170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
429386214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4294170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4295170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4296170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
429786214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
429886214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4299170fe5c8SBarry Smith 
4300170fe5c8SBarry Smith   PetscFunctionBegin;
4301d0f46423SBarry Smith   m    = A->rmap->n;
4302d0f46423SBarry Smith   n    = A->cmap->n;
4303d0f46423SBarry Smith   p    = B->cmap->n;
4304170fe5c8SBarry Smith   a    = sub_a->v;
4305170fe5c8SBarry Smith   b    = sub_b->a;
4306170fe5c8SBarry Smith   c    = sub_c->v;
430786214ceeSStefano Zampini   if (clda == m) {
4308580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
430986214ceeSStefano Zampini   } else {
431086214ceeSStefano Zampini     for (j=0;j<p;j++)
431186214ceeSStefano Zampini       for (i=0;i<m;i++)
431286214ceeSStefano Zampini         c[j*clda + i] = 0.0;
431386214ceeSStefano Zampini   }
4314170fe5c8SBarry Smith   ii  = sub_b->i;
4315170fe5c8SBarry Smith   idx = sub_b->j;
4316170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4317170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4318170fe5c8SBarry Smith     while (q-->0) {
431986214ceeSStefano Zampini       c_q = c + clda*(*idx);
432086214ceeSStefano Zampini       a_q = a + alda*i;
4321854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4322170fe5c8SBarry Smith       idx++;
4323170fe5c8SBarry Smith       b++;
4324170fe5c8SBarry Smith     }
4325170fe5c8SBarry Smith   }
4326170fe5c8SBarry Smith   PetscFunctionReturn(0);
4327170fe5c8SBarry Smith }
4328170fe5c8SBarry Smith 
43294222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4330170fe5c8SBarry Smith {
4331170fe5c8SBarry Smith   PetscErrorCode ierr;
4332d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
433386214ceeSStefano Zampini   PetscBool      cisdense;
4334170fe5c8SBarry Smith 
4335170fe5c8SBarry Smith   PetscFunctionBegin;
433660e0710aSBarry Smith   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %D != B->rmap->n %D\n",A->cmap->n,B->rmap->n);
43374222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
43384222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
433986214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
434086214ceeSStefano Zampini   if (!cisdense) {
434186214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
434286214ceeSStefano Zampini   }
434386214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4344d73949e8SHong Zhang 
43454222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4346170fe5c8SBarry Smith   PetscFunctionReturn(0);
4347170fe5c8SBarry Smith }
4348170fe5c8SBarry Smith 
4349170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
43500bad9183SKris Buschelman /*MC
4351fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
43520bad9183SKris Buschelman    based on compressed sparse row format.
43530bad9183SKris Buschelman 
43540bad9183SKris Buschelman    Options Database Keys:
43550bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
43560bad9183SKris Buschelman 
43570bad9183SKris Buschelman    Level: beginner
43580bad9183SKris Buschelman 
43590cd7f59aSBarry Smith    Notes:
43600cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
43610cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
43620cd7f59aSBarry Smith     in the matrix
43630cd7f59aSBarry Smith 
43640cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
43650cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
43660cd7f59aSBarry Smith 
43670cd7f59aSBarry Smith   Developer Notes:
43680cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
43690cd7f59aSBarry Smith 
4370f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
43710bad9183SKris Buschelman M*/
43720bad9183SKris Buschelman 
4373ccd284c7SBarry Smith /*MC
4374ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4375ccd284c7SBarry Smith 
4376ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4377ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
43780cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4379ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4380ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4381ccd284c7SBarry Smith 
4382ccd284c7SBarry Smith    Options Database Keys:
4383ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4384ccd284c7SBarry Smith 
438595452b02SPatrick Sanan   Developer Notes:
4386ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4387ccd284c7SBarry Smith    enough exist.
4388ccd284c7SBarry Smith 
4389ccd284c7SBarry Smith   Level: beginner
4390ccd284c7SBarry Smith 
4391ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4392ccd284c7SBarry Smith M*/
4393ccd284c7SBarry Smith 
4394ccd284c7SBarry Smith /*MC
4395ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4396ccd284c7SBarry Smith 
4397ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4398ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4399ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4400ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4401ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4402ccd284c7SBarry Smith 
4403ccd284c7SBarry Smith    Options Database Keys:
4404ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4405ccd284c7SBarry Smith 
4406ccd284c7SBarry Smith   Level: beginner
4407ccd284c7SBarry Smith 
4408ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4409ccd284c7SBarry Smith M*/
4410ccd284c7SBarry Smith 
44117906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
44127906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
44137906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
44147906f579SHong Zhang #endif
4415d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4416d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4417d24d4204SJose E. Roman #endif
44187906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
44197906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
44207906f579SHong Zhang #endif
44217906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
44227906f579SHong Zhang 
4423d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4424c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
44254222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
44267906f579SHong Zhang 
44278c778c55SBarry Smith /*@C
44288f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
44298c778c55SBarry Smith 
44308c778c55SBarry Smith    Not Collective
44318c778c55SBarry Smith 
44328c778c55SBarry Smith    Input Parameter:
4433579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
44348c778c55SBarry Smith 
44358c778c55SBarry Smith    Output Parameter:
44368c778c55SBarry Smith .   array - pointer to the data
44378c778c55SBarry Smith 
44388c778c55SBarry Smith    Level: intermediate
44398c778c55SBarry Smith 
4440774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
44418c778c55SBarry Smith @*/
44428c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
44438c778c55SBarry Smith {
44448c778c55SBarry Smith   PetscErrorCode ierr;
44458c778c55SBarry Smith 
44468c778c55SBarry Smith   PetscFunctionBegin;
44478c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
44482e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
44492e5835c6SStefano Zampini   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
44502e5835c6SStefano Zampini #endif
44518c778c55SBarry Smith   PetscFunctionReturn(0);
44528c778c55SBarry Smith }
44538c778c55SBarry Smith 
445421e72a00SBarry Smith /*@C
44558f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
44568f1ea47aSStefano Zampini 
44578f1ea47aSStefano Zampini    Not Collective
44588f1ea47aSStefano Zampini 
44598f1ea47aSStefano Zampini    Input Parameter:
44608f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44618f1ea47aSStefano Zampini 
44628f1ea47aSStefano Zampini    Output Parameter:
44638f1ea47aSStefano Zampini .   array - pointer to the data
44648f1ea47aSStefano Zampini 
44658f1ea47aSStefano Zampini    Level: intermediate
44668f1ea47aSStefano Zampini 
44678f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
44688f1ea47aSStefano Zampini @*/
44698f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
44708f1ea47aSStefano Zampini {
44718c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4472c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44738f1ea47aSStefano Zampini #endif
44748f1ea47aSStefano Zampini   PetscErrorCode ierr;
44758f1ea47aSStefano Zampini 
44768f1ea47aSStefano Zampini   PetscFunctionBegin;
44778c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4478c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44798f1ea47aSStefano Zampini #endif
44808f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44818c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4482c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
44838f1ea47aSStefano Zampini #endif
44848f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44858f1ea47aSStefano Zampini }
44868f1ea47aSStefano Zampini 
44878f1ea47aSStefano Zampini /*@C
44888f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
44898f1ea47aSStefano Zampini 
44908f1ea47aSStefano Zampini    Not Collective
44918f1ea47aSStefano Zampini 
44928f1ea47aSStefano Zampini    Input Parameter:
44938f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44948f1ea47aSStefano Zampini 
44958f1ea47aSStefano Zampini    Output Parameter:
44968f1ea47aSStefano Zampini .   array - pointer to the data
44978f1ea47aSStefano Zampini 
44988f1ea47aSStefano Zampini    Level: intermediate
44998f1ea47aSStefano Zampini 
45008f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
45018f1ea47aSStefano Zampini @*/
45028f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
45038f1ea47aSStefano Zampini {
45048c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4505c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
45068f1ea47aSStefano Zampini #endif
45078f1ea47aSStefano Zampini   PetscErrorCode ierr;
45088f1ea47aSStefano Zampini 
45098f1ea47aSStefano Zampini   PetscFunctionBegin;
45108c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4511c70f7ee4SJunchao Zhang   oval = A->offloadmask;
45128f1ea47aSStefano Zampini #endif
45138f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
45148c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4515c70f7ee4SJunchao Zhang   A->offloadmask = oval;
45168f1ea47aSStefano Zampini #endif
45178f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45188f1ea47aSStefano Zampini }
45198f1ea47aSStefano Zampini 
45208f1ea47aSStefano Zampini /*@C
452121e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
452221e72a00SBarry Smith 
452321e72a00SBarry Smith    Not Collective
452421e72a00SBarry Smith 
452521e72a00SBarry Smith    Input Parameter:
4526579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
452721e72a00SBarry Smith 
452821e72a00SBarry Smith    Output Parameter:
452921e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
453021e72a00SBarry Smith 
453121e72a00SBarry Smith    Level: intermediate
453221e72a00SBarry Smith 
453321e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
453421e72a00SBarry Smith @*/
453521e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
453621e72a00SBarry Smith {
453721e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
453821e72a00SBarry Smith 
453921e72a00SBarry Smith   PetscFunctionBegin;
454021e72a00SBarry Smith   *nz = aij->rmax;
454121e72a00SBarry Smith   PetscFunctionReturn(0);
454221e72a00SBarry Smith }
454321e72a00SBarry Smith 
45448c778c55SBarry Smith /*@C
4545579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
45468c778c55SBarry Smith 
45478c778c55SBarry Smith    Not Collective
45488c778c55SBarry Smith 
45498c778c55SBarry Smith    Input Parameters:
4550a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4551a2b725a8SWilliam Gropp -  array - pointer to the data
45528c778c55SBarry Smith 
45538c778c55SBarry Smith    Level: intermediate
45548c778c55SBarry Smith 
4555774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
45568c778c55SBarry Smith @*/
45578c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
45588c778c55SBarry Smith {
45598c778c55SBarry Smith   PetscErrorCode ierr;
45608c778c55SBarry Smith 
45618c778c55SBarry Smith   PetscFunctionBegin;
45628c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
45638c778c55SBarry Smith   PetscFunctionReturn(0);
45648c778c55SBarry Smith }
45658c778c55SBarry Smith 
456634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
45670ce8acdeSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
456802fe1965SBarry Smith #endif
45693d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
45703d0639e7SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat);
45713d0639e7SStefano Zampini #endif
457202fe1965SBarry Smith 
45738cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4574273d9f13SBarry Smith {
4575273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4576dfbe8321SBarry Smith   PetscErrorCode ierr;
457738baddfdSBarry Smith   PetscMPIInt    size;
4578273d9f13SBarry Smith 
4579273d9f13SBarry Smith   PetscFunctionBegin;
4580ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
4581e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4582273d9f13SBarry Smith 
4583b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
45842205254eSKarl Rupp 
4585b0a32e0cSBarry Smith   B->data = (void*)b;
45862205254eSKarl Rupp 
4587549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4588071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
45892205254eSKarl Rupp 
4590f4259b30SLisandro Dalcin   b->row                = NULL;
4591f4259b30SLisandro Dalcin   b->col                = NULL;
4592f4259b30SLisandro Dalcin   b->icol               = NULL;
4593b810aeb4SBarry Smith   b->reallocs           = 0;
459436db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4595f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4596416022c9SBarry Smith   b->nonew              = 0;
4597f4259b30SLisandro Dalcin   b->diag               = NULL;
4598f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4599f4259b30SLisandro Dalcin   B->spptr              = NULL;
4600f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4601f4259b30SLisandro Dalcin   b->idiag              = NULL;
4602f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4603f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
460471f1c65dSBarry Smith   b->omega              = 1.0;
460571f1c65dSBarry Smith   b->fshift             = 0.0;
460671f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4607bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4608a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
460917ab2063SBarry Smith 
461035d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4611bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4612bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
46138c778c55SBarry Smith 
4614b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4615bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4616bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4617b3866ffcSBarry Smith #endif
461817f1a0eaSHong Zhang 
4619bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4620bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4621bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4622bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4623bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4624bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
46254dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
46269779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
46274a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4628191b95cbSRichard Tran Mills #endif
462934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
463002fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
46314222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4632fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
463302fe1965SBarry Smith #endif
46343d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
46353d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
46363d0639e7SStefano Zampini #endif
4637bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4638af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4639af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4640af8000cdSHong Zhang #endif
4641d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4642d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4643d24d4204SJose E. Roman #endif
464463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
464563c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
46464222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
464763c07aadSStefano Zampini #endif
4648b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4649d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4650c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4651bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4652bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4653bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4654846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4655bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4656bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
46574222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
46584222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
46594222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
46604108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
466117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
46624099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
46633a40ed3dSBarry Smith   PetscFunctionReturn(0);
466417ab2063SBarry Smith }
466517ab2063SBarry Smith 
4666b24902e0SBarry Smith /*
4667b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4668b24902e0SBarry Smith */
4669ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
467017ab2063SBarry Smith {
46712a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
46726849ba73SBarry Smith   PetscErrorCode ierr;
4673071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
467417ab2063SBarry Smith 
46753a40ed3dSBarry Smith   PetscFunctionBegin;
4676ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4677273d9f13SBarry Smith 
4678d5f3da31SBarry Smith   C->factortype = A->factortype;
4679f4259b30SLisandro Dalcin   c->row        = NULL;
4680f4259b30SLisandro Dalcin   c->col        = NULL;
4681f4259b30SLisandro Dalcin   c->icol       = NULL;
46826ad4291fSHong Zhang   c->reallocs   = 0;
468317ab2063SBarry Smith 
46846ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
468517ab2063SBarry Smith 
4686aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4687aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4688eec197d1SBarry Smith 
4689071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4690071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4691071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4692071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
46933bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
469417ab2063SBarry Smith 
469517ab2063SBarry Smith   /* allocate the matrix space */
4696f77e22a1SHong Zhang   if (mallocmatspace) {
4697dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
46983bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
46992205254eSKarl Rupp 
4700f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
47012205254eSKarl Rupp 
4702580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
470317ab2063SBarry Smith     if (m > 0) {
4704580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4705be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
47062e5835c6SStefano Zampini         const PetscScalar *aa;
47072e5835c6SStefano Zampini 
47082e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
47092e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
47102e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4711be6bf707SBarry Smith       } else {
4712580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
471317ab2063SBarry Smith       }
471408480c60SBarry Smith     }
4715f77e22a1SHong Zhang   }
471617ab2063SBarry Smith 
47176ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4718416022c9SBarry Smith   c->roworiented       = a->roworiented;
4719416022c9SBarry Smith   c->nonew             = a->nonew;
4720416022c9SBarry Smith   if (a->diag) {
4721854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4722071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
47233bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4724071fcb05SBarry Smith   } else c->diag = NULL;
47252205254eSKarl Rupp 
4726f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4727f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4728f4259b30SLisandro Dalcin   c->idiag              = NULL;
4729f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4730a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4731e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4732e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
47336ad4291fSHong Zhang 
4734893ad86cSHong Zhang   c->rmax         = a->rmax;
4735416022c9SBarry Smith   c->nz           = a->nz;
47368ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4737273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4738754ec7b1SSatish Balay 
47396ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
47406ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4741cd6b891eSBarry Smith   if (a->compressedrow.use) {
47426ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4743dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4744580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4745580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
474627ea64f8SHong Zhang   } else {
474727ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
47480298fd71SBarry Smith     c->compressedrow.i      = NULL;
47490298fd71SBarry Smith     c->compressedrow.rindex = NULL;
47506ad4291fSHong Zhang   }
4751ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4752e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
47534846f1f5SKris Buschelman 
47542205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4755140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
47563a40ed3dSBarry Smith   PetscFunctionReturn(0);
475717ab2063SBarry Smith }
475817ab2063SBarry Smith 
4759b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4760b24902e0SBarry Smith {
4761b24902e0SBarry Smith   PetscErrorCode ierr;
4762b24902e0SBarry Smith 
4763b24902e0SBarry Smith   PetscFunctionBegin;
4764ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
47654b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4766cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
476733d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4768cfd3f464SBarry Smith   }
4769a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4770f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4771b24902e0SBarry Smith   PetscFunctionReturn(0);
4772b24902e0SBarry Smith }
4773b24902e0SBarry Smith 
4774112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4775fbdbba38SShri Abhyankar {
477652f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
477752f91c60SVaclav Hapla   PetscErrorCode ierr;
477852f91c60SVaclav Hapla 
477952f91c60SVaclav Hapla   PetscFunctionBegin;
478052f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
478152f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4782c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4783c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
478452f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
478552f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
478652f91c60SVaclav Hapla   if (isbinary) {
478752f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
478852f91c60SVaclav Hapla   } else if (ishdf5) {
478952f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
479052f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
479152f91c60SVaclav Hapla #else
479252f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
479352f91c60SVaclav Hapla #endif
479452f91c60SVaclav Hapla   } else {
479552f91c60SVaclav Hapla     SETERRQ2(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name);
479652f91c60SVaclav Hapla   }
479752f91c60SVaclav Hapla   PetscFunctionReturn(0);
479852f91c60SVaclav Hapla }
479952f91c60SVaclav Hapla 
48003ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
480152f91c60SVaclav Hapla {
48023ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4803fbdbba38SShri Abhyankar   PetscErrorCode ierr;
48043ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4805fbdbba38SShri Abhyankar 
4806fbdbba38SShri Abhyankar   PetscFunctionBegin;
48073ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4808bbead8a2SBarry Smith 
48093ea6fe3dSLisandro Dalcin   /* read in matrix header */
48103ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
48113ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4812fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
48133ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
48143ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4815bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4816fbdbba38SShri Abhyankar 
48173ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
48183ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
48193ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
48203ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
48213ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
48223ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
48233ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
48243ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
48253ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
48263ea6fe3dSLisandro Dalcin 
48273ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
48283ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
48293ea6fe3dSLisandro Dalcin   if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%D, %D) than the input matrix (%D, %D)",M,N,rows,cols);
48303ea6fe3dSLisandro Dalcin 
4831fbdbba38SShri Abhyankar   /* read in row lengths */
48323ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
48333ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
48343ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
48353ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
48363ea6fe3dSLisandro Dalcin   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent matrix data in file: nonzeros = %D, sum-row-lengths = %D\n",nz,sum);
48373ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
48383ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
48393ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
484060e0710aSBarry Smith   if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%D, %D) than the input matrix (%D, %D)",M,N,rows,cols);
48413ea6fe3dSLisandro Dalcin   /* store row lengths */
48423ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
48433ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4844fbdbba38SShri Abhyankar 
48453ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
48463ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
48473ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
48483ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
48493ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
48503ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4851fbdbba38SShri Abhyankar 
48523ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
48533ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4854fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4855fbdbba38SShri Abhyankar }
4856fbdbba38SShri Abhyankar 
4857ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
48587264ac53SSatish Balay {
48597264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4860dfbe8321SBarry Smith   PetscErrorCode ierr;
4861eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4862eeffb40dSHong Zhang   PetscInt k;
4863eeffb40dSHong Zhang #endif
48647264ac53SSatish Balay 
48653a40ed3dSBarry Smith   PetscFunctionBegin;
4866bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4867d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4868ca44d042SBarry Smith     *flg = PETSC_FALSE;
4869ca44d042SBarry Smith     PetscFunctionReturn(0);
4870bcd2baecSBarry Smith   }
48717264ac53SSatish Balay 
48727264ac53SSatish Balay   /* if the a->i are the same */
4873580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4874abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
48757264ac53SSatish Balay 
48767264ac53SSatish Balay   /* if a->j are the same */
4877580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4878abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4879bcd2baecSBarry Smith 
4880bcd2baecSBarry Smith   /* if a->a are the same */
4881eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4882eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4883eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4884eeffb40dSHong Zhang       *flg = PETSC_FALSE;
48853a40ed3dSBarry Smith       PetscFunctionReturn(0);
4886eeffb40dSHong Zhang     }
4887eeffb40dSHong Zhang   }
4888eeffb40dSHong Zhang #else
4889580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4890eeffb40dSHong Zhang #endif
4891eeffb40dSHong Zhang   PetscFunctionReturn(0);
48927264ac53SSatish Balay }
489336db0b34SBarry Smith 
489405869f15SSatish Balay /*@
489536db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
489636db0b34SBarry Smith               provided by the user.
489736db0b34SBarry Smith 
4898d083f849SBarry Smith       Collective
489936db0b34SBarry Smith 
490036db0b34SBarry Smith    Input Parameters:
490136db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
490236db0b34SBarry Smith .   m - number of rows
490336db0b34SBarry Smith .   n - number of columns
4904483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
490536db0b34SBarry Smith .   j - column indices
490636db0b34SBarry Smith -   a - matrix values
490736db0b34SBarry Smith 
490836db0b34SBarry Smith    Output Parameter:
490936db0b34SBarry Smith .   mat - the matrix
491036db0b34SBarry Smith 
491136db0b34SBarry Smith    Level: intermediate
491236db0b34SBarry Smith 
491336db0b34SBarry Smith    Notes:
49140551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4915292fb18eSBarry Smith     once the matrix is destroyed and not before
491636db0b34SBarry Smith 
491736db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
491836db0b34SBarry Smith 
4919bfeeae90SHong Zhang        The i and j indices are 0 based
492036db0b34SBarry Smith 
4921a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4922a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
49238eef79e4SBarry Smith     as shown
4924a4552177SSatish Balay 
49258eef79e4SBarry Smith $        1 0 0
49268eef79e4SBarry Smith $        2 0 3
49278eef79e4SBarry Smith $        4 5 6
49288eef79e4SBarry Smith $
49298eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
49308eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
49318eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4932a4552177SSatish Balay 
49339985e31cSBarry Smith 
493469b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
493536db0b34SBarry Smith 
493636db0b34SBarry Smith @*/
4937c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
493836db0b34SBarry Smith {
4939dfbe8321SBarry Smith   PetscErrorCode ierr;
4940cbcfb4deSHong Zhang   PetscInt       ii;
494136db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4942cbcfb4deSHong Zhang   PetscInt jj;
494336db0b34SBarry Smith 
494436db0b34SBarry Smith   PetscFunctionBegin;
494541096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4946f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4947f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4948a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4949ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4950f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
4951ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4952071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4953071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4954ab93d7beSBarry Smith 
495536db0b34SBarry Smith   aij->i            = i;
495636db0b34SBarry Smith   aij->j            = j;
495736db0b34SBarry Smith   aij->a            = a;
495836db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
495936db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4960e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4961e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
496236db0b34SBarry Smith 
496336db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
496436db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
496576bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
496660e0710aSBarry Smith       if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %D length = %D",ii,i[ii+1] - i[ii]);
49679985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4968a061629eSStefano Zampini         if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is not sorted",jj-i[ii],j[jj],ii);
4969a061629eSStefano Zampini         if (j[jj] == j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii);
49709985e31cSBarry Smith       }
497136db0b34SBarry Smith     }
497276bd3646SJed Brown   }
497376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
497436db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
497560e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
497660e0710aSBarry Smith       if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %D index = %D",ii,j[ii]);
497736db0b34SBarry Smith     }
497876bd3646SJed Brown   }
497936db0b34SBarry Smith 
4980b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4981b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
498236db0b34SBarry Smith   PetscFunctionReturn(0);
498336db0b34SBarry Smith }
498480ef6e79SMatthew G Knepley /*@C
4985d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
49868a0b0e6bSVictor Minden               provided by the user.
49878a0b0e6bSVictor Minden 
4988d083f849SBarry Smith       Collective
49898a0b0e6bSVictor Minden 
49908a0b0e6bSVictor Minden    Input Parameters:
49918a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
49928a0b0e6bSVictor Minden .   m   - number of rows
49938a0b0e6bSVictor Minden .   n   - number of columns
49948a0b0e6bSVictor Minden .   i   - row indices
49958a0b0e6bSVictor Minden .   j   - column indices
49961230e6d1SVictor Minden .   a   - matrix values
49971230e6d1SVictor Minden .   nz  - number of nonzeros
49981230e6d1SVictor Minden -   idx - 0 or 1 based
49998a0b0e6bSVictor Minden 
50008a0b0e6bSVictor Minden    Output Parameter:
50018a0b0e6bSVictor Minden .   mat - the matrix
50028a0b0e6bSVictor Minden 
50038a0b0e6bSVictor Minden    Level: intermediate
50048a0b0e6bSVictor Minden 
50058a0b0e6bSVictor Minden    Notes:
50068a0b0e6bSVictor Minden        The i and j indices are 0 based
50078a0b0e6bSVictor Minden 
50088a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
50098a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
50108a0b0e6bSVictor Minden     as shown:
50118a0b0e6bSVictor Minden 
50128a0b0e6bSVictor Minden         1 0 0
50138a0b0e6bSVictor Minden         2 0 3
50148a0b0e6bSVictor Minden         4 5 6
50158a0b0e6bSVictor Minden 
50168a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
50178a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
50188a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
50198a0b0e6bSVictor Minden 
50208a0b0e6bSVictor Minden 
502169b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
50228a0b0e6bSVictor Minden 
50238a0b0e6bSVictor Minden @*/
5024c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
50258a0b0e6bSVictor Minden {
50268a0b0e6bSVictor Minden   PetscErrorCode ierr;
5027d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
50288a0b0e6bSVictor Minden 
50298a0b0e6bSVictor Minden 
50308a0b0e6bSVictor Minden   PetscFunctionBegin;
50311795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
50321230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5033c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
50341230e6d1SVictor Minden   }
50358a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
50368a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
50378a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
50381230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
50391230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
50401230e6d1SVictor Minden     if (idx) {
50411230e6d1SVictor Minden       row = i[ii] - 1;
50421230e6d1SVictor Minden       col = j[ii] - 1;
50431230e6d1SVictor Minden     } else {
50441230e6d1SVictor Minden       row = i[ii];
50451230e6d1SVictor Minden       col = j[ii];
50468a0b0e6bSVictor Minden     }
50471230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
50488a0b0e6bSVictor Minden   }
50498a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
50508a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5051d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
50528a0b0e6bSVictor Minden   PetscFunctionReturn(0);
50538a0b0e6bSVictor Minden }
505436db0b34SBarry Smith 
5055acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5056acf2f550SJed Brown {
5057acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5058acf2f550SJed Brown   PetscErrorCode ierr;
5059acf2f550SJed Brown 
5060acf2f550SJed Brown   PetscFunctionBegin;
5061acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5062acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
50632205254eSKarl Rupp 
5064acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5065acf2f550SJed Brown   PetscFunctionReturn(0);
5066acf2f550SJed Brown }
5067acf2f550SJed Brown 
50689c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
50699c8f2541SHong Zhang {
50709c8f2541SHong Zhang   PetscErrorCode ierr;
50718761c3d6SHong Zhang   PetscMPIInt    size;
50729c8f2541SHong Zhang 
50739c8f2541SHong Zhang   PetscFunctionBegin;
5074ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
50757bbdc51dSHong Zhang   if (size == 1) {
50767bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
50777bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
50787bbdc51dSHong Zhang     } else {
50798761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
50807bbdc51dSHong Zhang     }
50818761c3d6SHong Zhang   } else {
50829c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
50838761c3d6SHong Zhang   }
50849c8f2541SHong Zhang   PetscFunctionReturn(0);
50859c8f2541SHong Zhang }
50869c8f2541SHong Zhang 
508781824310SBarry Smith /*
508853dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
508953dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
509053dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
509153dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
509253dd7562SDmitry Karpeev  */
509353dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
509453dd7562SDmitry Karpeev {
509553dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
509653dd7562SDmitry Karpeev   PetscErrorCode ierr;
509753dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
509853dd7562SDmitry Karpeev   PetscBool      seqaij;
509953dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
510053dd7562SDmitry Karpeev   PetscScalar    v;
510153dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
510253dd7562SDmitry Karpeev 
510353dd7562SDmitry Karpeev   PetscFunctionBegin;
510453dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
510553dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
51064099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
510753dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
510853dd7562SDmitry Karpeev   if (rowemb) {
510953dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
511053dd7562SDmitry Karpeev     if (m != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row IS of size %D is incompatible with matrix row size %D",m,B->rmap->n);
511153dd7562SDmitry Karpeev   } else {
51126c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
511353dd7562SDmitry Karpeev   }
511453dd7562SDmitry Karpeev   if (colemb) {
511553dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
511653dd7562SDmitry Karpeev     if (n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Diag col IS of size %D is incompatible with input matrix col size %D",n,B->cmap->n);
511753dd7562SDmitry Karpeev   } else {
511853dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
511953dd7562SDmitry Karpeev   }
512053dd7562SDmitry Karpeev 
512153dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
512253dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
512353dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
512453dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
512553dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
512653dd7562SDmitry Karpeev     }
512753dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
512853dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
512953dd7562SDmitry Karpeev   }
513053dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
513153dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
513253dd7562SDmitry Karpeev   }
513353dd7562SDmitry Karpeev   count = 0;
513453dd7562SDmitry Karpeev   rowindices = NULL;
513553dd7562SDmitry Karpeev   colindices = NULL;
513653dd7562SDmitry Karpeev   if (rowemb) {
513753dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
513853dd7562SDmitry Karpeev   }
513953dd7562SDmitry Karpeev   if (colemb) {
514053dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
514153dd7562SDmitry Karpeev   }
514253dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
514353dd7562SDmitry Karpeev     PetscInt row;
514453dd7562SDmitry Karpeev     row = i;
514553dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
514653dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
514753dd7562SDmitry Karpeev       PetscInt col;
514853dd7562SDmitry Karpeev       col  = Baij->j[count];
514953dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
515053dd7562SDmitry Karpeev       v    = Baij->a[count];
515153dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
515253dd7562SDmitry Karpeev       ++count;
515353dd7562SDmitry Karpeev     }
515453dd7562SDmitry Karpeev   }
515553dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
515653dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
515753dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
515853dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
515953dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
516053dd7562SDmitry Karpeev   PetscFunctionReturn(0);
516153dd7562SDmitry Karpeev }
516253dd7562SDmitry Karpeev 
51634099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
51644099cc6bSBarry Smith 
51654099cc6bSBarry Smith /*@C
51664099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
51674099cc6bSBarry Smith 
51684099cc6bSBarry Smith    Collective on Mat
51694099cc6bSBarry Smith 
51704099cc6bSBarry Smith    Input Parameters:
51714099cc6bSBarry Smith +  mat      - the matrix object
51724099cc6bSBarry Smith -  matype   - matrix type
51734099cc6bSBarry Smith 
51744099cc6bSBarry Smith    Options Database Key:
51754099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
51764099cc6bSBarry Smith 
51774099cc6bSBarry Smith 
51784099cc6bSBarry Smith   Level: intermediate
51794099cc6bSBarry Smith 
51804099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
51814099cc6bSBarry Smith @*/
51824099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
51834099cc6bSBarry Smith {
5184fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
51854099cc6bSBarry Smith   PetscBool      sametype;
51864099cc6bSBarry Smith 
51874099cc6bSBarry Smith   PetscFunctionBegin;
51884099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
51894099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
51904099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
51914099cc6bSBarry Smith 
51924099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
51934099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
51944099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
51954099cc6bSBarry Smith   PetscFunctionReturn(0);
51964099cc6bSBarry Smith }
51974099cc6bSBarry Smith 
51984099cc6bSBarry Smith 
51994099cc6bSBarry Smith /*@C
52004099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
52014099cc6bSBarry Smith 
52024099cc6bSBarry Smith    Not Collective
52034099cc6bSBarry Smith 
52044099cc6bSBarry Smith    Input Parameters:
52054099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
52064099cc6bSBarry Smith -  function - routine to convert to subtype
52074099cc6bSBarry Smith 
52084099cc6bSBarry Smith    Notes:
52094099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
52104099cc6bSBarry Smith 
52114099cc6bSBarry Smith 
52124099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
52134099cc6bSBarry Smith $     -mat_seqaij_type my_mat
52144099cc6bSBarry Smith 
52154099cc6bSBarry Smith    Level: advanced
52164099cc6bSBarry Smith 
52174099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
52184099cc6bSBarry Smith 
52194099cc6bSBarry Smith 
52204099cc6bSBarry Smith   Level: advanced
52214099cc6bSBarry Smith @*/
5222388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
52234099cc6bSBarry Smith {
52244099cc6bSBarry Smith   PetscErrorCode ierr;
52254099cc6bSBarry Smith 
52264099cc6bSBarry Smith   PetscFunctionBegin;
52279cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
52284099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
52294099cc6bSBarry Smith   PetscFunctionReturn(0);
52304099cc6bSBarry Smith }
52314099cc6bSBarry Smith 
52324099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
52334099cc6bSBarry Smith 
52344099cc6bSBarry Smith /*@C
52354099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
52364099cc6bSBarry Smith 
52374099cc6bSBarry Smith   Not Collective
52384099cc6bSBarry Smith 
52394099cc6bSBarry Smith   Level: advanced
52404099cc6bSBarry Smith 
5241f719121fSJed Brown   Developers Note: CUSPARSE does not yet support the MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
52424099cc6bSBarry Smith 
52434099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
52444099cc6bSBarry Smith @*/
52454099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
52464099cc6bSBarry Smith {
52474099cc6bSBarry Smith   PetscErrorCode ierr;
52484099cc6bSBarry Smith 
52494099cc6bSBarry Smith   PetscFunctionBegin;
52504099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
52514099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
52524099cc6bSBarry Smith 
52534099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
52544099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
52554dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
52569779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
52576b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5258485f9817SRichard Tran Mills #endif
52594099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
52604099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
52614099cc6bSBarry Smith #endif
52624099cc6bSBarry Smith   PetscFunctionReturn(0);
52634099cc6bSBarry Smith }
526453dd7562SDmitry Karpeev 
526553dd7562SDmitry Karpeev /*
526681824310SBarry Smith     Special version for direct calls from Fortran
526781824310SBarry Smith */
5268af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
526981824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
527081824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
527181824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
527281824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
527381824310SBarry Smith #endif
527481824310SBarry Smith 
527581824310SBarry Smith /* Change these macros so can be used in void function */
527681824310SBarry Smith #undef CHKERRQ
5277ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
527881824310SBarry Smith #undef SETERRQ2
5279e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
52804994cf47SJed Brown #undef SETERRQ3
52814994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
528281824310SBarry Smith 
528319caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
528481824310SBarry Smith {
528581824310SBarry Smith   Mat            A  = *AA;
528681824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
528781824310SBarry Smith   InsertMode     is = *isis;
528881824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
528981824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
529081824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
529181824310SBarry Smith   PetscErrorCode ierr;
529281824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
529354f21887SBarry Smith   MatScalar      *ap,value,*aa;
5294ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5295ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
529681824310SBarry Smith 
529781824310SBarry Smith   PetscFunctionBegin;
52984994cf47SJed Brown   MatCheckPreallocated(A,1);
529981824310SBarry Smith   imax  = a->imax;
530081824310SBarry Smith   ai    = a->i;
530181824310SBarry Smith   ailen = a->ilen;
530281824310SBarry Smith   aj    = a->j;
530381824310SBarry Smith   aa    = a->a;
530481824310SBarry Smith 
530581824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
530681824310SBarry Smith     row = im[k];
530781824310SBarry Smith     if (row < 0) continue;
5308cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
530981824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
531081824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
531181824310SBarry Smith     low  = 0;
531281824310SBarry Smith     high = nrow;
531381824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
531481824310SBarry Smith       if (in[l] < 0) continue;
5315cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
531681824310SBarry Smith       col = in[l];
53172205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
53182205254eSKarl Rupp       else value = v[k + l*m];
53192205254eSKarl Rupp 
532081824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
532181824310SBarry Smith 
53222205254eSKarl Rupp       if (col <= lastcol) low = 0;
53232205254eSKarl Rupp       else high = nrow;
532481824310SBarry Smith       lastcol = col;
532581824310SBarry Smith       while (high-low > 5) {
532681824310SBarry Smith         t = (low+high)/2;
532781824310SBarry Smith         if (rp[t] > col) high = t;
532881824310SBarry Smith         else             low  = t;
532981824310SBarry Smith       }
533081824310SBarry Smith       for (i=low; i<high; i++) {
533181824310SBarry Smith         if (rp[i] > col) break;
533281824310SBarry Smith         if (rp[i] == col) {
533381824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
533481824310SBarry Smith           else                  ap[i] = value;
533581824310SBarry Smith           goto noinsert;
533681824310SBarry Smith         }
533781824310SBarry Smith       }
533881824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
533981824310SBarry Smith       if (nonew == 1) goto noinsert;
5340ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5341fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
534281824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
534381824310SBarry Smith       /* shift up all the later entries in this row */
534481824310SBarry Smith       for (ii=N; ii>=i; ii--) {
534581824310SBarry Smith         rp[ii+1] = rp[ii];
534681824310SBarry Smith         ap[ii+1] = ap[ii];
534781824310SBarry Smith       }
534881824310SBarry Smith       rp[i] = col;
534981824310SBarry Smith       ap[i] = value;
5350e56f5c9eSBarry Smith       A->nonzerostate++;
535181824310SBarry Smith noinsert:;
535281824310SBarry Smith       low = i + 1;
535381824310SBarry Smith     }
535481824310SBarry Smith     ailen[row] = nrow;
535581824310SBarry Smith   }
535681824310SBarry Smith   PetscFunctionReturnVoid();
535781824310SBarry Smith }
5358