xref: /petsc/src/mat/impls/aij/seq/aij.c (revision ce496241a0151439d41b4a288e03a96724a7a6ae)
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;
448*ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
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;
456*ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
457*ce496241SStefano Zampini   if (A->offloadmask == PETSC_OFFLOAD_GPU) {
458*ce496241SStefano Zampini     const PetscScalar *dummy;
459*ce496241SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&dummy);CHKERRQ(ierr);
460*ce496241SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&dummy);CHKERRQ(ierr);
461*ce496241SStefano Zampini   }
462*ce496241SStefano Zampini #endif
463*ce496241SStefano Zampini   aa = a->a;
46417ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
465416022c9SBarry Smith     row = im[k];
4665ef9f2a5SBarry Smith     if (row < 0) continue;
467cf9c20a2SJed 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);
468720833daSHong Zhang     rp   = aj + ai[row];
469876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
47017ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
471416022c9SBarry Smith     low  = 0;
472c71e6ed7SBarry Smith     high = nrow;
47317ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4745ef9f2a5SBarry Smith       if (in[l] < 0) continue;
475cf9c20a2SJed 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);
476bfeeae90SHong Zhang       col = in[l];
477071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
478071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
47936db0b34SBarry Smith 
4802205254eSKarl Rupp       if (col <= lastcol) low = 0;
4812205254eSKarl Rupp       else high = nrow;
482e2ee6c50SBarry Smith       lastcol = col;
483416022c9SBarry Smith       while (high-low > 5) {
484416022c9SBarry Smith         t = (low+high)/2;
485416022c9SBarry Smith         if (rp[t] > col) high = t;
486416022c9SBarry Smith         else low = t;
48717ab2063SBarry Smith       }
488416022c9SBarry Smith       for (i=low; i<high; i++) {
48917ab2063SBarry Smith         if (rp[i] > col) break;
49017ab2063SBarry Smith         if (rp[i] == col) {
491876c6284SHong Zhang           if (!A->structure_only) {
4920c0d7e18SFande Kong             if (is == ADD_VALUES) {
4930c0d7e18SFande Kong               ap[i] += value;
4940c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4950c0d7e18SFande Kong             }
49617ab2063SBarry Smith             else ap[i] = value;
4978c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
498e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
499e2cf4d64SStefano Zampini #endif
500720833daSHong Zhang           }
501e44c0bd4SBarry Smith           low = i + 1;
50217ab2063SBarry Smith           goto noinsert;
50317ab2063SBarry Smith         }
50417ab2063SBarry Smith       }
505dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
506c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
507e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
508720833daSHong Zhang       if (A->structure_only) {
509876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
510720833daSHong Zhang       } else {
511fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
512720833daSHong Zhang       }
513c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
514416022c9SBarry Smith       /* shift up all the later entries in this row */
515580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
51617ab2063SBarry Smith       rp[i] = col;
517580bdb30SBarry Smith       if (!A->structure_only){
518580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
519580bdb30SBarry Smith         ap[i] = value;
520580bdb30SBarry Smith       }
521416022c9SBarry Smith       low = i + 1;
522e56f5c9eSBarry Smith       A->nonzerostate++;
5238c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
524e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
525e2cf4d64SStefano Zampini #endif
526e44c0bd4SBarry Smith noinsert:;
52717ab2063SBarry Smith     }
52817ab2063SBarry Smith     ailen[row] = nrow;
52917ab2063SBarry Smith   }
5308c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
531c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
532e2cf4d64SStefano Zampini #endif
5333a40ed3dSBarry Smith   PetscFunctionReturn(0);
53417ab2063SBarry Smith }
53517ab2063SBarry Smith 
53619b08ed1SBarry Smith 
53719b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
53819b08ed1SBarry Smith {
53919b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
54019b08ed1SBarry Smith   PetscInt       *rp,k,row;
54119b08ed1SBarry Smith   PetscInt       *ai = a->i;
54219b08ed1SBarry Smith   PetscErrorCode ierr;
54319b08ed1SBarry Smith   PetscInt       *aj = a->j;
54419b08ed1SBarry Smith   MatScalar      *aa = a->a,*ap;
54519b08ed1SBarry Smith 
54619b08ed1SBarry Smith   PetscFunctionBegin;
54719b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
54819b08ed1SBarry 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);
54919b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
55019b08ed1SBarry Smith     row  = im[k];
55119b08ed1SBarry Smith     rp   = aj + ai[row];
55219b08ed1SBarry Smith     ap   = aa + ai[row];
55319b08ed1SBarry Smith 
55419b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
55519b08ed1SBarry Smith     if (!A->structure_only) {
55619b08ed1SBarry Smith       if (v) {
55719b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
55819b08ed1SBarry Smith         v   += n;
55919b08ed1SBarry Smith       } else {
56019b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
56119b08ed1SBarry Smith       }
56219b08ed1SBarry Smith     }
56319b08ed1SBarry Smith     a->ilen[row] = n;
56419b08ed1SBarry Smith     a->imax[row] = n;
56519b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
56619b08ed1SBarry Smith     a->nz       += n;
56719b08ed1SBarry Smith   }
5688c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
56919b08ed1SBarry Smith   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
57019b08ed1SBarry Smith #endif
57119b08ed1SBarry Smith   PetscFunctionReturn(0);
57219b08ed1SBarry Smith }
57319b08ed1SBarry Smith 
57419b08ed1SBarry Smith /*@
57519b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
57619b08ed1SBarry Smith 
57719b08ed1SBarry Smith   Input Parameters:
57819b08ed1SBarry Smith +  A - the SeqAIJ matrix
57919b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
58019b08ed1SBarry Smith 
58119b08ed1SBarry Smith   Level: advanced
58219b08ed1SBarry Smith 
58319b08ed1SBarry Smith   Notes:
58419b08ed1SBarry 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.
58519b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
58619b08ed1SBarry Smith     as always with multiple matrix assemblies.
58719b08ed1SBarry Smith 
58819b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
58919b08ed1SBarry Smith @*/
59019b08ed1SBarry Smith 
59119b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
59219b08ed1SBarry Smith {
59319b08ed1SBarry Smith   PetscErrorCode ierr;
59419b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
59519b08ed1SBarry Smith 
59619b08ed1SBarry Smith   PetscFunctionBegin;
59719b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
59819b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
59919b08ed1SBarry Smith   a->maxnz  = nztotal;
60019b08ed1SBarry Smith   if (!a->imax) {
60119b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
60219b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60319b08ed1SBarry Smith   }
60419b08ed1SBarry Smith   if (!a->ilen) {
60519b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
60619b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60719b08ed1SBarry Smith   } else {
60819b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60919b08ed1SBarry Smith   }
61019b08ed1SBarry Smith 
61119b08ed1SBarry Smith   /* allocate the matrix space */
61219b08ed1SBarry Smith   if (A->structure_only) {
61319b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
61419b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
61519b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
61619b08ed1SBarry Smith   } else {
61719b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
61819b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
61919b08ed1SBarry Smith   }
62019b08ed1SBarry Smith   a->i[0] = 0;
62119b08ed1SBarry Smith   if (A->structure_only) {
62219b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
62319b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
62419b08ed1SBarry Smith   } else {
62519b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
62619b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
62719b08ed1SBarry Smith   }
62819b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
62919b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
63019b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
63119b08ed1SBarry Smith   PetscFunctionReturn(0);
63219b08ed1SBarry Smith }
63319b08ed1SBarry Smith 
634071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
635071fcb05SBarry Smith {
636071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
637071fcb05SBarry Smith   PetscInt       *rp,k,row;
638071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
639071fcb05SBarry Smith   PetscErrorCode ierr;
640071fcb05SBarry Smith   PetscInt       *aj = a->j;
641071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
642071fcb05SBarry Smith 
643071fcb05SBarry Smith   PetscFunctionBegin;
644071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
645071fcb05SBarry Smith     row  = im[k];
64619b08ed1SBarry 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);
647071fcb05SBarry Smith     rp   = aj + ai[row];
648071fcb05SBarry Smith     ap   = aa + ai[row];
649071fcb05SBarry Smith     if (!A->was_assembled) {
650071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
651071fcb05SBarry Smith     }
652071fcb05SBarry Smith     if (!A->structure_only) {
653071fcb05SBarry Smith       if (v) {
654071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
655071fcb05SBarry Smith         v   += n;
656071fcb05SBarry Smith       } else {
657071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
658071fcb05SBarry Smith       }
659071fcb05SBarry Smith     }
660071fcb05SBarry Smith     ailen[row] = n;
661071fcb05SBarry Smith     a->nz      += n;
662071fcb05SBarry Smith   }
6638c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
664c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
665e2cf4d64SStefano Zampini #endif
666071fcb05SBarry Smith   PetscFunctionReturn(0);
667071fcb05SBarry Smith }
668071fcb05SBarry Smith 
66981824310SBarry Smith 
670a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6717eb43aa7SLois Curfman McInnes {
6727eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
67397f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
67497f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
67554f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
6767eb43aa7SLois Curfman McInnes 
6773a40ed3dSBarry Smith   PetscFunctionBegin;
6787eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6797eb43aa7SLois Curfman McInnes     row = im[k];
680e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
681e32f2f54SBarry 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);
682bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6837eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6847eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
685e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
686e32f2f54SBarry 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);
687bfeeae90SHong Zhang       col  = in[l];
6887eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6897eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6907eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6917eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6927eb43aa7SLois Curfman McInnes         else low = t;
6937eb43aa7SLois Curfman McInnes       }
6947eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6957eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6967eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
697b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6987eb43aa7SLois Curfman McInnes           goto finished;
6997eb43aa7SLois Curfman McInnes         }
7007eb43aa7SLois Curfman McInnes       }
70197e567efSBarry Smith       *v++ = 0.0;
7027eb43aa7SLois Curfman McInnes finished:;
7037eb43aa7SLois Curfman McInnes     }
7047eb43aa7SLois Curfman McInnes   }
7053a40ed3dSBarry Smith   PetscFunctionReturn(0);
7067eb43aa7SLois Curfman McInnes }
7077eb43aa7SLois Curfman McInnes 
7083ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
70917ab2063SBarry Smith {
7103ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
711c898d852SStefano Zampini   const PetscScalar *av;
7123ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
7133ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
7146849ba73SBarry Smith   PetscErrorCode    ierr;
71517ab2063SBarry Smith 
7163a40ed3dSBarry Smith   PetscFunctionBegin;
7173ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7182205254eSKarl Rupp 
7193ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7203ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7213ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7223ea6fe3dSLisandro Dalcin   nz = A->nz;
723416022c9SBarry Smith 
7243ea6fe3dSLisandro Dalcin   /* write matrix header */
7253ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7263ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7273ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
728416022c9SBarry Smith 
7293ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7303ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7313ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7323ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7333ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7343ea6fe3dSLisandro Dalcin   /* store column indices */
7353ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
736416022c9SBarry Smith   /* store nonzero values */
737c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
738c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
739c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
740b37d52dbSMark F. Adams 
7413ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7423ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7433a40ed3dSBarry Smith   PetscFunctionReturn(0);
74417ab2063SBarry Smith }
745416022c9SBarry Smith 
7467dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7477dc0baabSHong Zhang {
7487dc0baabSHong Zhang   PetscErrorCode ierr;
7497dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7507dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7517dc0baabSHong Zhang 
7527dc0baabSHong Zhang   PetscFunctionBegin;
7537dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7547dc0baabSHong Zhang   for (i=0; i<m; i++) {
7557dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7567dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7577dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7587dc0baabSHong Zhang     }
7597dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7607dc0baabSHong Zhang   }
7617dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7627dc0baabSHong Zhang   PetscFunctionReturn(0);
7637dc0baabSHong Zhang }
7647dc0baabSHong Zhang 
76509573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
766cd155464SBarry Smith 
767dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
768416022c9SBarry Smith {
769416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
770c898d852SStefano Zampini   const PetscScalar *av;
771dfbe8321SBarry Smith   PetscErrorCode    ierr;
77260e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
773e060cb09SBarry Smith   const char        *name;
774f3ef73ceSBarry Smith   PetscViewerFormat format;
77517ab2063SBarry Smith 
7763a40ed3dSBarry Smith   PetscFunctionBegin;
7777dc0baabSHong Zhang   if (A->structure_only) {
7787dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7797dc0baabSHong Zhang     PetscFunctionReturn(0);
7807dc0baabSHong Zhang   }
78143e49210SHong Zhang 
782b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
7832e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7842e5835c6SStefano Zampini 
785c898d852SStefano Zampini   /* trigger copy to CPU if needed */
786c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
787c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
78871c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
78997f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
79060e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
791c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
792d00d2cf4SBarry Smith       nofinalvalue = 1;
793d00d2cf4SBarry Smith     }
794d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
795d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
79677431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
797fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
798fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
799fbfe6fa7SJed Brown #else
80077431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
801fbfe6fa7SJed Brown #endif
802b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
80317ab2063SBarry Smith 
80417ab2063SBarry Smith     for (i=0; i<m; i++) {
80560e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
806aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
807a9bf72d8SJed 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);
80817ab2063SBarry Smith #else
80960e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
81017ab2063SBarry Smith #endif
81117ab2063SBarry Smith       }
81217ab2063SBarry Smith     }
813d00d2cf4SBarry Smith     if (nofinalvalue) {
814c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
815c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
816c337ccceSJed Brown #else
817d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
818c337ccceSJed Brown #endif
819d00d2cf4SBarry Smith     }
820317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
821fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
822d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
823fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
824d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
82544cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
82677431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
82760e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
828aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
82936db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
83060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
83136db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
83260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
83336db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
83460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8356831982aSBarry Smith         }
83644cd7ae7SLois Curfman McInnes #else
83760e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
83844cd7ae7SLois Curfman McInnes #endif
83944cd7ae7SLois Curfman McInnes       }
840b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
84144cd7ae7SLois Curfman McInnes     }
842d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
843fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
84497f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
845d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
846854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
847496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
848496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
84960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
850496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
851aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
85236db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
853496be53dSLois Curfman McInnes #else
854496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
855496be53dSLois Curfman McInnes #endif
856496be53dSLois Curfman McInnes         }
857496be53dSLois Curfman McInnes       }
858496be53dSLois Curfman McInnes     }
8592e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
86077431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8612e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8622205254eSKarl Rupp       if (i+4<m) {
8632205254eSKarl 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);
8642205254eSKarl Rupp       } else if (i+3<m) {
8652205254eSKarl 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);
8662205254eSKarl Rupp       } else if (i+2<m) {
8672205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8682205254eSKarl Rupp       } else if (i+1<m) {
8692205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8702205254eSKarl Rupp       } else if (i<m) {
8712205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8722205254eSKarl Rupp       } else {
8732205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8742205254eSKarl Rupp       }
875496be53dSLois Curfman McInnes     }
876b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
877606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
878496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
87960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
88077431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
881496be53dSLois Curfman McInnes       }
882b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
883496be53dSLois Curfman McInnes     }
884b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
885496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
88660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
887496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
888aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
88936db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
89060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8916831982aSBarry Smith           }
892496be53dSLois Curfman McInnes #else
89360e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
894496be53dSLois Curfman McInnes #endif
895496be53dSLois Curfman McInnes         }
896496be53dSLois Curfman McInnes       }
897b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
898496be53dSLois Curfman McInnes     }
899d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
900fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
90197f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
90287828ca2SBarry Smith     PetscScalar value;
90368f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
90468f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
90568f1ed48SBarry Smith 
90668f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
90768f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
90868f1ed48SBarry Smith         realonly = PETSC_FALSE;
90968f1ed48SBarry Smith         break;
91068f1ed48SBarry Smith       }
91168f1ed48SBarry Smith     }
91268f1ed48SBarry Smith #endif
91302594712SBarry Smith 
914d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
91502594712SBarry Smith     for (i=0; i<m; i++) {
91602594712SBarry Smith       jcnt = 0;
917d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
918e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
91902594712SBarry Smith           value = a->a[cnt++];
920e24b481bSBarry Smith           jcnt++;
92102594712SBarry Smith         } else {
92202594712SBarry Smith           value = 0.0;
92302594712SBarry Smith         }
924aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
92568f1ed48SBarry Smith         if (realonly) {
92660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
92768f1ed48SBarry Smith         } else {
92860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
92968f1ed48SBarry Smith         }
93002594712SBarry Smith #else
93160e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
93202594712SBarry Smith #endif
93302594712SBarry Smith       }
934b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
93502594712SBarry Smith     }
936d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9373c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
938150b93efSMatthew G. Knepley     PetscInt fshift=1;
939d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9403c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
94119303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9423c215bfdSMatthew Knepley #else
94319303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9443c215bfdSMatthew Knepley #endif
945d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9463c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
94760e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9483c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
949a9a0e077SKarl 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);
9503c215bfdSMatthew Knepley #else
951150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9523c215bfdSMatthew Knepley #endif
9533c215bfdSMatthew Knepley       }
9543c215bfdSMatthew Knepley     }
955d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9563a40ed3dSBarry Smith   } else {
957d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
958d5f3da31SBarry Smith     if (A->factortype) {
95916cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
96016cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
96116cd7e1dSShri Abhyankar         /* L part */
96260e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
96316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
96416cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
96560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
96616cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9676712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
96816cd7e1dSShri Abhyankar           } else {
96960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
97016cd7e1dSShri Abhyankar           }
97116cd7e1dSShri Abhyankar #else
97260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
97316cd7e1dSShri Abhyankar #endif
97416cd7e1dSShri Abhyankar         }
97516cd7e1dSShri Abhyankar         /* diagonal */
97616cd7e1dSShri Abhyankar         j = a->diag[i];
97716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97816cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
97960e0710aSBarry 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);
98016cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9816712e2f1SBarry 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);
98216cd7e1dSShri Abhyankar         } else {
98360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
98416cd7e1dSShri Abhyankar         }
98516cd7e1dSShri Abhyankar #else
98660e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
98716cd7e1dSShri Abhyankar #endif
98816cd7e1dSShri Abhyankar 
98916cd7e1dSShri Abhyankar         /* U part */
99060e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
99116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
99216cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
99360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
99416cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
99522ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
99616cd7e1dSShri Abhyankar           } else {
99760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
99816cd7e1dSShri Abhyankar           }
99916cd7e1dSShri Abhyankar #else
100060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
100116cd7e1dSShri Abhyankar #endif
100216cd7e1dSShri Abhyankar         }
100316cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
100416cd7e1dSShri Abhyankar       }
100516cd7e1dSShri Abhyankar     } else {
100617ab2063SBarry Smith       for (i=0; i<m; i++) {
100777431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
100860e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
1009aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
101036db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
101160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
101236db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
101360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
10143a40ed3dSBarry Smith           } else {
101560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
101617ab2063SBarry Smith           }
101717ab2063SBarry Smith #else
101860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
101917ab2063SBarry Smith #endif
102017ab2063SBarry Smith         }
1021b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
102217ab2063SBarry Smith       }
102316cd7e1dSShri Abhyankar     }
1024d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
102517ab2063SBarry Smith   }
1026b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10273a40ed3dSBarry Smith   PetscFunctionReturn(0);
1028416022c9SBarry Smith }
1029416022c9SBarry Smith 
10309804daf3SBarry Smith #include <petscdraw.h>
1031dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1032416022c9SBarry Smith {
1033480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1034416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1035dfbe8321SBarry Smith   PetscErrorCode    ierr;
1036383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1037383922c3SLisandro Dalcin   int               color;
1038b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1039b0a32e0cSBarry Smith   PetscViewer       viewer;
1040f3ef73ceSBarry Smith   PetscViewerFormat format;
1041cddf8d76SBarry Smith 
10423a40ed3dSBarry Smith   PetscFunctionBegin;
1043480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1044b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1045b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1046383922c3SLisandro Dalcin 
1047416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10480513a670SBarry Smith 
1049fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1050383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10510513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1052b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1053416022c9SBarry Smith     for (i=0; i<m; i++) {
1054cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1055bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1056bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
105736db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
1058b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1059cddf8d76SBarry Smith       }
1060cddf8d76SBarry Smith     }
1061b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1062cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1063cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1064bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1065bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1066cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
1067b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1068cddf8d76SBarry Smith       }
1069cddf8d76SBarry Smith     }
1070b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1071cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1072cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1073bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1074bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
107536db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
1076b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1077416022c9SBarry Smith       }
1078416022c9SBarry Smith     }
1079383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10800513a670SBarry Smith   } else {
10810513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10820513a670SBarry Smith     /* first determine max of all nonzero values */
1083b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1084383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1085b0a32e0cSBarry Smith     PetscDraw popup;
10860513a670SBarry Smith 
10870513a670SBarry Smith     for (i=0; i<nz; i++) {
10880513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
10890513a670SBarry Smith     }
1090383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1091b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
109245f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1093383922c3SLisandro Dalcin 
1094383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10950513a670SBarry Smith     for (i=0; i<m; i++) {
1096383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1097383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1098bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1099383922c3SLisandro Dalcin         x_l = a->j[j];
1100383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1101b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
1102b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
11030513a670SBarry Smith         count++;
11040513a670SBarry Smith       }
11050513a670SBarry Smith     }
1106383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
11070513a670SBarry Smith   }
1108480ef9eaSBarry Smith   PetscFunctionReturn(0);
1109480ef9eaSBarry Smith }
1110cddf8d76SBarry Smith 
11119804daf3SBarry Smith #include <petscdraw.h>
1112dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1113480ef9eaSBarry Smith {
1114dfbe8321SBarry Smith   PetscErrorCode ierr;
1115b0a32e0cSBarry Smith   PetscDraw      draw;
111636db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1117ace3abfcSBarry Smith   PetscBool      isnull;
1118480ef9eaSBarry Smith 
1119480ef9eaSBarry Smith   PetscFunctionBegin;
1120b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1121b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1122480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1123480ef9eaSBarry Smith 
1124d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1125480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1126b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1127832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1128b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11290298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1130832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11313a40ed3dSBarry Smith   PetscFunctionReturn(0);
1132416022c9SBarry Smith }
1133416022c9SBarry Smith 
1134dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1135416022c9SBarry Smith {
1136dfbe8321SBarry Smith   PetscErrorCode ierr;
1137ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1138416022c9SBarry Smith 
11393a40ed3dSBarry Smith   PetscFunctionBegin;
1140251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1141251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1142251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1143c45a1595SBarry Smith   if (iascii) {
11443a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11450f5bd95cSBarry Smith   } else if (isbinary) {
11463a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11470f5bd95cSBarry Smith   } else if (isdraw) {
11483a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
114911aeaf0aSBarry Smith   }
11504108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11513a40ed3dSBarry Smith   PetscFunctionReturn(0);
115217ab2063SBarry Smith }
115319bcc07fSBarry Smith 
1154dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
115517ab2063SBarry Smith {
1156416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11576849ba73SBarry Smith   PetscErrorCode ierr;
1158580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1159d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
116054f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11613447b6efSHong Zhang   PetscReal      ratio  = 0.6;
116217ab2063SBarry Smith 
11633a40ed3dSBarry Smith   PetscFunctionBegin;
11643a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1165071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1166b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1167b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1168b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1169b215bc84SStefano Zampini     PetscFunctionReturn(0);
1170b215bc84SStefano Zampini   }
117117ab2063SBarry Smith 
117243ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
117317ab2063SBarry Smith   for (i=1; i<m; i++) {
1174416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
117517ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
117694a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
117717ab2063SBarry Smith     if (fshift) {
1178bfeeae90SHong Zhang       ip = aj + ai[i];
1179bfeeae90SHong Zhang       ap = aa + ai[i];
118017ab2063SBarry Smith       N  = ailen[i];
1181580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1182580bdb30SBarry Smith       if (!A->structure_only) {
1183580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
118417ab2063SBarry Smith       }
118517ab2063SBarry Smith     }
118617ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
118717ab2063SBarry Smith   }
118817ab2063SBarry Smith   if (m) {
118917ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
119017ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
119117ab2063SBarry Smith   }
11927b083b7cSBarry Smith 
119317ab2063SBarry Smith   /* reset ilen and imax for each row */
11947b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1195396832f4SHong Zhang   if (A->structure_only) {
1196071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1197071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1198396832f4SHong Zhang   } else { /* !A->structure_only */
119917ab2063SBarry Smith     for (i=0; i<m; i++) {
120017ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
12017b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
120217ab2063SBarry Smith     }
1203396832f4SHong Zhang   }
1204bfeeae90SHong Zhang   a->nz = ai[m];
120565e19b50SBarry 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);
120617ab2063SBarry Smith 
120709f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1208d0f46423SBarry 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);
1209ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1210ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
12112205254eSKarl Rupp 
12128e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1213dd5f02e7SSatish Balay   a->reallocs         = 0;
12146712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
121536db0b34SBarry Smith   a->rmax             = rmax;
12164e220ebcSLois Curfman McInnes 
1217396832f4SHong Zhang   if (!A->structure_only) {
121811e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1219396832f4SHong Zhang   }
12204108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12213a40ed3dSBarry Smith   PetscFunctionReturn(0);
122217ab2063SBarry Smith }
122317ab2063SBarry Smith 
122499cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
122599cafbc1SBarry Smith {
122699cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
122799cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12282e5835c6SStefano Zampini   MatScalar      *aa;
1229acf2f550SJed Brown   PetscErrorCode ierr;
123099cafbc1SBarry Smith 
123199cafbc1SBarry Smith   PetscFunctionBegin;
12322e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
123399cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
12342e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1235acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12368c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1237c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1238e2cf4d64SStefano Zampini #endif
123999cafbc1SBarry Smith   PetscFunctionReturn(0);
124099cafbc1SBarry Smith }
124199cafbc1SBarry Smith 
124299cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
124399cafbc1SBarry Smith {
124499cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
124599cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12462e5835c6SStefano Zampini   MatScalar      *aa;
1247acf2f550SJed Brown   PetscErrorCode ierr;
124899cafbc1SBarry Smith 
124999cafbc1SBarry Smith   PetscFunctionBegin;
12502e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
125199cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12522e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1253acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12548c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1255c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1256e2cf4d64SStefano Zampini #endif
125799cafbc1SBarry Smith   PetscFunctionReturn(0);
125899cafbc1SBarry Smith }
125999cafbc1SBarry Smith 
1260dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
126117ab2063SBarry Smith {
1262416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1263dfbe8321SBarry Smith   PetscErrorCode ierr;
12643a40ed3dSBarry Smith 
12653a40ed3dSBarry Smith   PetscFunctionBegin;
1266580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1267acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12688c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1269c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1270e2cf4d64SStefano Zampini #endif
12713a40ed3dSBarry Smith   PetscFunctionReturn(0);
127217ab2063SBarry Smith }
1273416022c9SBarry Smith 
1274dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
127517ab2063SBarry Smith {
1276416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1277dfbe8321SBarry Smith   PetscErrorCode ierr;
1278d5d45c9bSBarry Smith 
12793a40ed3dSBarry Smith   PetscFunctionBegin;
1280aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1281d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
128217ab2063SBarry Smith #endif
1283e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12846bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12856bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
128605b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1287d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1288071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1289071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1290846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
129171f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
129205b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12936bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
129405b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1295cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1296a30b2313SHong Zhang 
12974108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1298bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1299901853e0SKris Buschelman 
13006718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
13016718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
13026718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
13036718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
13046718818eSStefano Zampini      due to different matrix sizes */
13056718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
13066718818eSStefano Zampini 
1307f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1308bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1309bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1310bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1311bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1312bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1313bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
13144222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
13154222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1316e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1317fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
13184222ddf1SHong Zhang #endif
13193d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
13203d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13213d0639e7SStefano Zampini #endif
13224222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1323af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1324af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1325af8000cdSHong Zhang #endif
1326d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1327d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1328d24d4204SJose E. Roman #endif
132963c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
133063c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13314222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
133263c07aadSStefano Zampini #endif
1333b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1334c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1335c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1336bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1337bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1338846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1339bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1340bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13414222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13424222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13434222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
13443a40ed3dSBarry Smith   PetscFunctionReturn(0);
134517ab2063SBarry Smith }
134617ab2063SBarry Smith 
1347ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
134817ab2063SBarry Smith {
1349416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13504846f1f5SKris Buschelman   PetscErrorCode ierr;
13513a40ed3dSBarry Smith 
13523a40ed3dSBarry Smith   PetscFunctionBegin;
1353a65d3064SKris Buschelman   switch (op) {
1354a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13554e0d8c25SBarry Smith     a->roworiented = flg;
1356a65d3064SKris Buschelman     break;
1357a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1358a9817697SBarry Smith     a->keepnonzeropattern = flg;
1359a65d3064SKris Buschelman     break;
1360512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1361512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1362a65d3064SKris Buschelman     break;
1363a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13644e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1365a65d3064SKris Buschelman     break;
1366a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13674e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1368a65d3064SKris Buschelman     break;
136928b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
137028b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
137128b2fa4aSMatthew Knepley     break;
1372a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13734e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13740df259c2SBarry Smith     break;
13753d472b54SHong Zhang   case MAT_SPD:
1376b1646e73SJed Brown   case MAT_SYMMETRIC:
1377b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1378b1646e73SJed Brown   case MAT_HERMITIAN:
1379b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1380957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13815021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13825021d80fSJed Brown     break;
13838c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1384a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1385a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1386290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1387a65d3064SKris Buschelman     break;
1388b87ac2d8SJed Brown   case MAT_USE_INODES:
1389b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1390b87ac2d8SJed Brown     break;
1391c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1392c10200c1SHong Zhang     A->submat_singleis = flg;
1393c10200c1SHong Zhang     break;
1394071fcb05SBarry Smith   case MAT_SORTED_FULL:
1395071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1396071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1397071fcb05SBarry Smith     break;
1398a65d3064SKris Buschelman   default:
1399e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1400a65d3064SKris Buschelman   }
14013a40ed3dSBarry Smith   PetscFunctionReturn(0);
140217ab2063SBarry Smith }
140317ab2063SBarry Smith 
1404dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
140517ab2063SBarry Smith {
1406416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14076849ba73SBarry Smith   PetscErrorCode    ierr;
1408fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1409c898d852SStefano Zampini   PetscScalar       *x;
1410c898d852SStefano Zampini   const PetscScalar *aa;
141117ab2063SBarry Smith 
14123a40ed3dSBarry Smith   PetscFunctionBegin;
1413d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1414e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1415c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1416d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1417d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1418fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14192c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1420fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1421c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
142235e7444dSHong Zhang     PetscFunctionReturn(0);
142335e7444dSHong Zhang   }
142435e7444dSHong Zhang 
1425fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
142635e7444dSHong Zhang   for (i=0; i<n; i++) {
1427fdc842d1SBarry Smith     x[i] = 0.0;
142835e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
142935e7444dSHong Zhang       if (aj[j] == i) {
143035e7444dSHong Zhang         x[i] = aa[j];
143117ab2063SBarry Smith         break;
143217ab2063SBarry Smith       }
143317ab2063SBarry Smith     }
143417ab2063SBarry Smith   }
1435fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1436c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14373a40ed3dSBarry Smith   PetscFunctionReturn(0);
143817ab2063SBarry Smith }
143917ab2063SBarry Smith 
1440c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1441dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
144217ab2063SBarry Smith {
1443416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1444d9ca1df4SBarry Smith   PetscScalar       *y;
1445d9ca1df4SBarry Smith   const PetscScalar *x;
1446dfbe8321SBarry Smith   PetscErrorCode    ierr;
1447d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14485c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1449d9ca1df4SBarry Smith   const MatScalar   *v;
1450a77337e4SBarry Smith   PetscScalar       alpha;
1451d9ca1df4SBarry Smith   PetscInt          n,i,j;
1452d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14533447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1454ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14555c897100SBarry Smith #endif
145617ab2063SBarry Smith 
14573a40ed3dSBarry Smith   PetscFunctionBegin;
14582e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1459d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14601ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14615c897100SBarry Smith 
14625c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1463bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14645c897100SBarry Smith #else
14653447b6efSHong Zhang   if (usecprow) {
14663447b6efSHong Zhang     m    = cprow.nrows;
14673447b6efSHong Zhang     ii   = cprow.i;
14687b2bb3b9SHong Zhang     ridx = cprow.rindex;
14693447b6efSHong Zhang   } else {
14703447b6efSHong Zhang     ii = a->i;
14713447b6efSHong Zhang   }
147217ab2063SBarry Smith   for (i=0; i<m; i++) {
14733447b6efSHong Zhang     idx = a->j + ii[i];
14743447b6efSHong Zhang     v   = a->a + ii[i];
14753447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14763447b6efSHong Zhang     if (usecprow) {
14777b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14783447b6efSHong Zhang     } else {
147917ab2063SBarry Smith       alpha = x[i];
14803447b6efSHong Zhang     }
148104fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
148217ab2063SBarry Smith   }
14835c897100SBarry Smith #endif
1484dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1485d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14861ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14873a40ed3dSBarry Smith   PetscFunctionReturn(0);
148817ab2063SBarry Smith }
148917ab2063SBarry Smith 
1490dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14915c897100SBarry Smith {
1492dfbe8321SBarry Smith   PetscErrorCode ierr;
14935c897100SBarry Smith 
14945c897100SBarry Smith   PetscFunctionBegin;
1495170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14965c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14975c897100SBarry Smith   PetscFunctionReturn(0);
14985c897100SBarry Smith }
14995c897100SBarry Smith 
1500c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
150178b84d54SShri Abhyankar 
1502dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
150317ab2063SBarry Smith {
1504416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1505d9fead3dSBarry Smith   PetscScalar       *y;
150654f21887SBarry Smith   const PetscScalar *x;
150754f21887SBarry Smith   const MatScalar   *aa;
1508dfbe8321SBarry Smith   PetscErrorCode    ierr;
1509003131ecSBarry Smith   PetscInt          m=A->rmap->n;
15100298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
15117b083b7cSBarry Smith   PetscInt          n,i;
1512362ced78SSatish Balay   PetscScalar       sum;
1513ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
151417ab2063SBarry Smith 
1515b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
151697952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1517fee21e36SBarry Smith #endif
1518fee21e36SBarry Smith 
15193a40ed3dSBarry Smith   PetscFunctionBegin;
1520b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1521b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1522b215bc84SStefano Zampini     PetscFunctionReturn(0);
1523b215bc84SStefano Zampini   }
15243649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15251ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1526416022c9SBarry Smith   ii   = a->i;
15274eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1528580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
152997952fefSHong Zhang     m    = a->compressedrow.nrows;
153097952fefSHong Zhang     ii   = a->compressedrow.i;
153197952fefSHong Zhang     ridx = a->compressedrow.rindex;
153297952fefSHong Zhang     for (i=0; i<m; i++) {
153397952fefSHong Zhang       n           = ii[i+1] - ii[i];
153497952fefSHong Zhang       aj          = a->j + ii[i];
153597952fefSHong Zhang       aa          = a->a + ii[i];
153697952fefSHong Zhang       sum         = 0.0;
1537003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1538003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
153997952fefSHong Zhang       y[*ridx++] = sum;
154097952fefSHong Zhang     }
154197952fefSHong Zhang   } else { /* do not use compressed row format */
1542b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15433d3eaba7SBarry Smith     aj   = a->j;
15443d3eaba7SBarry Smith     aa   = a->a;
1545b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1546b05257ddSBarry Smith #else
154717ab2063SBarry Smith     for (i=0; i<m; i++) {
1548003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1549003131ecSBarry Smith       aj          = a->j + ii[i];
1550003131ecSBarry Smith       aa          = a->a + ii[i];
155117ab2063SBarry Smith       sum         = 0.0;
1552003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
155317ab2063SBarry Smith       y[i] = sum;
155417ab2063SBarry Smith     }
15558d195f9aSBarry Smith #endif
1556b05257ddSBarry Smith   }
15577b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15583649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15591ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15603a40ed3dSBarry Smith   PetscFunctionReturn(0);
156117ab2063SBarry Smith }
156217ab2063SBarry Smith 
1563b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1564b434eb95SMatthew G. Knepley {
1565b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1566b434eb95SMatthew G. Knepley   PetscScalar       *y;
1567b434eb95SMatthew G. Knepley   const PetscScalar *x;
1568b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1569b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1570b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1571b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1572b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1573b434eb95SMatthew G. Knepley   PetscScalar       sum;
1574b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1575b434eb95SMatthew G. Knepley 
1576b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1577b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1578b434eb95SMatthew G. Knepley #endif
1579b434eb95SMatthew G. Knepley 
1580b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1581b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1582b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1583b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1584b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1585b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1586b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1587b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1588b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1589b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1590b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1591b434eb95SMatthew G. Knepley       sum         = 0.0;
1592b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1593b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1594b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1595b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1596b434eb95SMatthew G. Knepley     }
1597b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15983d3eaba7SBarry Smith     ii = a->i;
1599b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1600b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1601b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1602b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1603b434eb95SMatthew G. Knepley       sum         = 0.0;
1604b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1605b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1606b434eb95SMatthew G. Knepley       y[i] = sum;
1607b434eb95SMatthew G. Knepley     }
1608b434eb95SMatthew G. Knepley   }
1609b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1610b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1611b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1612b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1613b434eb95SMatthew G. Knepley }
1614b434eb95SMatthew G. Knepley 
1615b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1616b434eb95SMatthew G. Knepley {
1617b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1618b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1619b434eb95SMatthew G. Knepley   const PetscScalar *x;
1620b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1621b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1622b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1623b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1624b434eb95SMatthew G. Knepley   PetscScalar       sum;
1625b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1626b434eb95SMatthew G. Knepley 
1627b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1628b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1629d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1630b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1631b434eb95SMatthew G. Knepley     if (zz != yy) {
1632580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1633b434eb95SMatthew G. Knepley     }
1634b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1635b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1636b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1637b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1638b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1639b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1640b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1641b434eb95SMatthew G. Knepley       sum = y[*ridx];
1642b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1643b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1644b434eb95SMatthew G. Knepley     }
1645b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16463d3eaba7SBarry Smith     ii = a->i;
1647b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1648b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1649b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1650b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1651b434eb95SMatthew G. Knepley       sum = y[i];
1652b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1653b434eb95SMatthew G. Knepley       z[i] = sum;
1654b434eb95SMatthew G. Knepley     }
1655b434eb95SMatthew G. Knepley   }
1656b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1657b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1658d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1659b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1660b434eb95SMatthew G. Knepley }
1661b434eb95SMatthew G. Knepley 
1662c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1663dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
166417ab2063SBarry Smith {
1665416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1666f15663dcSBarry Smith   PetscScalar       *y,*z;
1667f15663dcSBarry Smith   const PetscScalar *x;
166854f21887SBarry Smith   const MatScalar   *aa;
1669dfbe8321SBarry Smith   PetscErrorCode    ierr;
1670d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1671d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1672362ced78SSatish Balay   PetscScalar       sum;
1673ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16749ea0dfa2SSatish Balay 
16753a40ed3dSBarry Smith   PetscFunctionBegin;
1676b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1677b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1678b215bc84SStefano Zampini     PetscFunctionReturn(0);
1679b215bc84SStefano Zampini   }
1680f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1681d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16824eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16834eb6d288SHong Zhang     if (zz != yy) {
1684580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16854eb6d288SHong Zhang     }
168697952fefSHong Zhang     m    = a->compressedrow.nrows;
168797952fefSHong Zhang     ii   = a->compressedrow.i;
168897952fefSHong Zhang     ridx = a->compressedrow.rindex;
168997952fefSHong Zhang     for (i=0; i<m; i++) {
169097952fefSHong Zhang       n   = ii[i+1] - ii[i];
169197952fefSHong Zhang       aj  = a->j + ii[i];
169297952fefSHong Zhang       aa  = a->a + ii[i];
169397952fefSHong Zhang       sum = y[*ridx];
1694f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
169597952fefSHong Zhang       z[*ridx++] = sum;
169697952fefSHong Zhang     }
169797952fefSHong Zhang   } else { /* do not use compressed row format */
16983d3eaba7SBarry Smith     ii = a->i;
1699f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
17003d3eaba7SBarry Smith     aj = a->j;
17013d3eaba7SBarry Smith     aa = a->a;
1702f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1703f15663dcSBarry Smith #else
170417ab2063SBarry Smith     for (i=0; i<m; i++) {
1705f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1706f15663dcSBarry Smith       aj  = a->j + ii[i];
1707f15663dcSBarry Smith       aa  = a->a + ii[i];
170817ab2063SBarry Smith       sum = y[i];
1709f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
171017ab2063SBarry Smith       z[i] = sum;
171117ab2063SBarry Smith     }
171202ab625aSSatish Balay #endif
1713f15663dcSBarry Smith   }
1714dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1715f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1716d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
17173a40ed3dSBarry Smith   PetscFunctionReturn(0);
171817ab2063SBarry Smith }
171917ab2063SBarry Smith 
172017ab2063SBarry Smith /*
172117ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
172217ab2063SBarry Smith */
1723dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
172417ab2063SBarry Smith {
1725416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17266849ba73SBarry Smith   PetscErrorCode ierr;
1727d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
172817ab2063SBarry Smith 
17293a40ed3dSBarry Smith   PetscFunctionBegin;
173009f38230SBarry Smith   if (!a->diag) {
1731785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17323bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
173309f38230SBarry Smith   }
1734d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
173509f38230SBarry Smith     a->diag[i] = a->i[i+1];
1736bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1737bfeeae90SHong Zhang       if (a->j[j] == i) {
173809f38230SBarry Smith         a->diag[i] = j;
173917ab2063SBarry Smith         break;
174017ab2063SBarry Smith       }
174117ab2063SBarry Smith     }
174217ab2063SBarry Smith   }
17433a40ed3dSBarry Smith   PetscFunctionReturn(0);
174417ab2063SBarry Smith }
174517ab2063SBarry Smith 
174661ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
174761ecd0c6SBarry Smith {
174861ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
174961ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
175061ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
175161ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
175261ecd0c6SBarry Smith   PetscErrorCode    ierr;
175361ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
175461ecd0c6SBarry Smith 
175561ecd0c6SBarry Smith   PetscFunctionBegin;
175661ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
175761ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
175861ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
175961ecd0c6SBarry Smith     PetscFunctionReturn(0);
176061ecd0c6SBarry Smith   }
176161ecd0c6SBarry Smith 
176261ecd0c6SBarry Smith   if (a->diagonaldense) {
176361ecd0c6SBarry Smith     cnt = 0;
176461ecd0c6SBarry Smith   } else {
176561ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
176661ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
176761ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
176861ecd0c6SBarry Smith         cnt++;
176961ecd0c6SBarry Smith         mdiag[i] = 1;
177061ecd0c6SBarry Smith       }
177161ecd0c6SBarry Smith     }
177261ecd0c6SBarry Smith   }
177361ecd0c6SBarry Smith   if (!cnt) {
177461ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
177561ecd0c6SBarry Smith   } else {
1776b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1777b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
177861ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
177961ecd0c6SBarry Smith 
178061ecd0c6SBarry Smith     a->a = NULL;
178161ecd0c6SBarry Smith     a->j = NULL;
178261ecd0c6SBarry Smith     a->i = NULL;
178361ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
178461ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
178561ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1786447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
178761ecd0c6SBarry Smith     }
178861ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
178961ecd0c6SBarry Smith 
179061ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
179161ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
179261ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1793447d62f5SStefano Zampini       if (i < A->cmap->n) {
179461ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
179561ecd0c6SBarry Smith       }
1796447d62f5SStefano Zampini     }
179761ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179861ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179961ecd0c6SBarry Smith     if (singlemalloc) {
180061ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
180161ecd0c6SBarry Smith     } else {
180261ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
180361ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
180461ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
180561ecd0c6SBarry Smith     }
180661ecd0c6SBarry Smith   }
180761ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
180861ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
180961ecd0c6SBarry Smith   PetscFunctionReturn(0);
181061ecd0c6SBarry Smith }
181161ecd0c6SBarry Smith 
1812be5855fcSBarry Smith /*
1813be5855fcSBarry Smith      Checks for missing diagonals
1814be5855fcSBarry Smith */
1815ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1816be5855fcSBarry Smith {
1817be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18187734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1819994fe344SLisandro Dalcin   PetscErrorCode ierr;
1820be5855fcSBarry Smith 
1821be5855fcSBarry Smith   PetscFunctionBegin;
182209f38230SBarry Smith   *missing = PETSC_FALSE;
18237734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
182409f38230SBarry Smith     *missing = PETSC_TRUE;
182509f38230SBarry Smith     if (d) *d = 0;
1826994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
182709f38230SBarry Smith   } else {
182801445905SHong Zhang     PetscInt n;
182901445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1830f1e2ffcdSBarry Smith     diag = a->diag;
183101445905SHong Zhang     for (i=0; i<n; i++) {
18327734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
183309f38230SBarry Smith         *missing = PETSC_TRUE;
183409f38230SBarry Smith         if (d) *d = i;
1835994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1836358d2f5dSShri Abhyankar         break;
183709f38230SBarry Smith       }
1838be5855fcSBarry Smith     }
1839be5855fcSBarry Smith   }
1840be5855fcSBarry Smith   PetscFunctionReturn(0);
1841be5855fcSBarry Smith }
1842be5855fcSBarry Smith 
18430da83c2eSBarry Smith #include <petscblaslapack.h>
18440da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18450da83c2eSBarry Smith 
18460da83c2eSBarry Smith /*
18470da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18480da83c2eSBarry Smith */
18490da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18500da83c2eSBarry Smith {
18510da83c2eSBarry Smith   PetscErrorCode  ierr;
18520da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18530da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18540da83c2eSBarry Smith   const PetscReal shift = 0.0;
18550da83c2eSBarry Smith   PetscInt        ipvt[5];
18560da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18570da83c2eSBarry Smith 
18580da83c2eSBarry Smith   PetscFunctionBegin;
18590da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18600da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18610da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18620da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18630da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18640da83c2eSBarry Smith   }
18650da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18660da83c2eSBarry Smith   if (bsizemax > 7) {
18670da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18680da83c2eSBarry Smith   }
18690da83c2eSBarry Smith   ncnt = 0;
18700da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18710da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18720da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18730da83c2eSBarry Smith     switch (bsizes[i]) {
18740da83c2eSBarry Smith     case 1:
18750da83c2eSBarry Smith       *diag = 1.0/(*diag);
18760da83c2eSBarry Smith       break;
18770da83c2eSBarry Smith     case 2:
18780da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18790da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18800da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18810da83c2eSBarry Smith       break;
18820da83c2eSBarry Smith     case 3:
18830da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18840da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18850da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18860da83c2eSBarry Smith       break;
18870da83c2eSBarry Smith     case 4:
18880da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18890da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18900da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18910da83c2eSBarry Smith       break;
18920da83c2eSBarry Smith     case 5:
18930da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18940da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18950da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18960da83c2eSBarry Smith       break;
18970da83c2eSBarry Smith     case 6:
18980da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18990da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19000da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
19010da83c2eSBarry Smith       break;
19020da83c2eSBarry Smith     case 7:
19030da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19040da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19050da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
19060da83c2eSBarry Smith       break;
19070da83c2eSBarry Smith     default:
19080da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19090da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19100da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19110da83c2eSBarry Smith     }
19120da83c2eSBarry Smith     ncnt   += bsizes[i];
19130da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19140da83c2eSBarry Smith   }
19150da83c2eSBarry Smith   if (bsizemax > 7) {
19160da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19170da83c2eSBarry Smith   }
19180da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19190da83c2eSBarry Smith   PetscFunctionReturn(0);
19200da83c2eSBarry Smith }
19210da83c2eSBarry Smith 
1922422a814eSBarry Smith /*
1923422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1924422a814eSBarry Smith */
19257087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
192671f1c65dSBarry Smith {
192771f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
192871f1c65dSBarry Smith   PetscErrorCode  ierr;
1929d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19302e5835c6SStefano Zampini   const MatScalar *v;
193154f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
193271f1c65dSBarry Smith 
193371f1c65dSBarry Smith   PetscFunctionBegin;
193471f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
193571f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
193671f1c65dSBarry Smith   diag = a->diag;
193771f1c65dSBarry Smith   if (!a->idiag) {
1938dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19393bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
194071f1c65dSBarry Smith   }
19412e5835c6SStefano Zampini 
194271f1c65dSBarry Smith   mdiag = a->mdiag;
194371f1c65dSBarry Smith   idiag = a->idiag;
19442e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1945422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
194671f1c65dSBarry Smith     for (i=0; i<m; i++) {
194771f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1948899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1949899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1950899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19517b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19527b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19537b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1954a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1955899639b0SHong Zhang       }
195671f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
195771f1c65dSBarry Smith     }
195871f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
195971f1c65dSBarry Smith   } else {
196071f1c65dSBarry Smith     for (i=0; i<m; i++) {
196171f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
196271f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
196371f1c65dSBarry Smith     }
1964dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
196571f1c65dSBarry Smith   }
196671f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19672e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
196871f1c65dSBarry Smith   PetscFunctionReturn(0);
196971f1c65dSBarry Smith }
197071f1c65dSBarry Smith 
1971c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
197241f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
197317ab2063SBarry Smith {
1974416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1975e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19762e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
197754f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1978dfbe8321SBarry Smith   PetscErrorCode    ierr;
19793d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
198097f1f81fSBarry Smith   const PetscInt    *idx,*diag;
198117ab2063SBarry Smith 
19823a40ed3dSBarry Smith   PetscFunctionBegin;
1983b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1984b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1985b215bc84SStefano Zampini     PetscFunctionReturn(0);
1986b215bc84SStefano Zampini   }
1987b965ef7fSBarry Smith   its = its*lits;
198891723122SBarry Smith 
198971f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
199071f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
199171f1c65dSBarry Smith   a->fshift = fshift;
199271f1c65dSBarry Smith   a->omega  = omega;
1993ed480e8bSBarry Smith 
199471f1c65dSBarry Smith   diag  = a->diag;
199571f1c65dSBarry Smith   t     = a->ssor_work;
1996ed480e8bSBarry Smith   idiag = a->idiag;
199771f1c65dSBarry Smith   mdiag = a->mdiag;
1998ed480e8bSBarry Smith 
19992e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
20001ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
20013649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
2002ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
200317ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
200417ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
2005ed480e8bSBarry Smith     bs = b;
200617ab2063SBarry Smith     for (i=0; i<m; i++) {
200771f1c65dSBarry Smith       d   = fshift + mdiag[i];
2008416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2009ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20102e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
201117ab2063SBarry Smith       sum = b[i]*d/omega;
2012003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
201317ab2063SBarry Smith       x[i] = sum;
201417ab2063SBarry Smith     }
20151ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20163649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20172e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2018efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20193a40ed3dSBarry Smith     PetscFunctionReturn(0);
202017ab2063SBarry Smith   }
2021c783ea89SBarry Smith 
20222205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20232205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20244c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2025887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
202617ab2063SBarry Smith 
202717ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
202817ab2063SBarry Smith 
2029887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
203017ab2063SBarry Smith     */
203117ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
203217ab2063SBarry Smith 
203317ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
203417ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2035416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2036ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20372e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
203817ab2063SBarry Smith       sum = b[i];
2039e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2040ed480e8bSBarry Smith       x[i] = sum*idiag[i];
204117ab2063SBarry Smith     }
204217ab2063SBarry Smith 
204317ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20442e5835c6SStefano Zampini     v = aa;
20452205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
204617ab2063SBarry Smith 
204717ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2048ed480e8bSBarry Smith     ts   = t;
2049416022c9SBarry Smith     diag = a->diag;
205017ab2063SBarry Smith     for (i=0; i<m; i++) {
2051416022c9SBarry Smith       n   = diag[i] - a->i[i];
2052ed480e8bSBarry Smith       idx = a->j + a->i[i];
20532e5835c6SStefano Zampini       v   = aa + a->i[i];
205417ab2063SBarry Smith       sum = t[i];
2055003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2056ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2057733d66baSBarry Smith       /*  x = x + t */
2058733d66baSBarry Smith       x[i] += t[i];
205917ab2063SBarry Smith     }
206017ab2063SBarry Smith 
2061dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20621ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20633649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20643a40ed3dSBarry Smith     PetscFunctionReturn(0);
206517ab2063SBarry Smith   }
206617ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
206717ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
206817ab2063SBarry Smith       for (i=0; i<m; i++) {
2069416022c9SBarry Smith         n   = diag[i] - a->i[i];
2070ed480e8bSBarry Smith         idx = a->j + a->i[i];
20712e5835c6SStefano Zampini         v   = aa + a->i[i];
207217ab2063SBarry Smith         sum = b[i];
2073e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20745c99c7daSBarry Smith         t[i] = sum;
2075ed480e8bSBarry Smith         x[i] = sum*idiag[i];
207617ab2063SBarry Smith       }
20775c99c7daSBarry Smith       xb   = t;
2078efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20793a40ed3dSBarry Smith     } else xb = b;
208017ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
208117ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2082416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2083ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20842e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
208517ab2063SBarry Smith         sum = xb[i];
2086e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20875c99c7daSBarry Smith         if (xb == b) {
2088ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20895c99c7daSBarry Smith         } else {
2090b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
209117ab2063SBarry Smith         }
20925c99c7daSBarry Smith       }
2093b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
209417ab2063SBarry Smith     }
209517ab2063SBarry Smith     its--;
209617ab2063SBarry Smith   }
209717ab2063SBarry Smith   while (its--) {
209817ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
209917ab2063SBarry Smith       for (i=0; i<m; i++) {
2100b19a5dc2SMark Adams         /* lower */
2101b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2102ed480e8bSBarry Smith         idx = a->j + a->i[i];
21032e5835c6SStefano Zampini         v   = aa + a->i[i];
210417ab2063SBarry Smith         sum = b[i];
2105e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2106b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2107b19a5dc2SMark Adams         /* upper */
2108b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2109b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21102e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2111b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2112b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
211317ab2063SBarry Smith       }
2114b19a5dc2SMark Adams       xb   = t;
21159f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2116b19a5dc2SMark Adams     } else xb = b;
211717ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
211817ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2119b19a5dc2SMark Adams         sum = xb[i];
2120b19a5dc2SMark Adams         if (xb == b) {
2121b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2122416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2123ed480e8bSBarry Smith           idx = a->j + a->i[i];
21242e5835c6SStefano Zampini           v   = aa + a->i[i];
2125e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2126ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2127b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2128b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2129b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21302e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2131b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2132b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
213317ab2063SBarry Smith         }
2134b19a5dc2SMark Adams       }
2135b19a5dc2SMark Adams       if (xb == b) {
21369f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2137b19a5dc2SMark Adams       } else {
2138b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2139b19a5dc2SMark Adams       }
214017ab2063SBarry Smith     }
214117ab2063SBarry Smith   }
21422e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21431ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21443649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2145365a8a9eSBarry Smith   PetscFunctionReturn(0);
214617ab2063SBarry Smith }
214717ab2063SBarry Smith 
21482af78befSBarry Smith 
2149dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
215017ab2063SBarry Smith {
2151416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21524e220ebcSLois Curfman McInnes 
21533a40ed3dSBarry Smith   PetscFunctionBegin;
21544e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21553966268fSBarry Smith   info->nz_allocated = a->maxnz;
21563966268fSBarry Smith   info->nz_used      = a->nz;
21573966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21583966268fSBarry Smith   info->assemblies   = A->num_ass;
21593966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21607adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2161d5f3da31SBarry Smith   if (A->factortype) {
21624e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21634e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21644e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21654e220ebcSLois Curfman McInnes   } else {
21664e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21674e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21684e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21694e220ebcSLois Curfman McInnes   }
21703a40ed3dSBarry Smith   PetscFunctionReturn(0);
217117ab2063SBarry Smith }
217217ab2063SBarry Smith 
21732b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
217417ab2063SBarry Smith {
2175416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2176c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21776849ba73SBarry Smith   PetscErrorCode    ierr;
217897b48c8fSBarry Smith   const PetscScalar *xx;
21792e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2180c7da8527SEric Chamberland   PetscInt          d = 0;
218117ab2063SBarry Smith 
21823a40ed3dSBarry Smith   PetscFunctionBegin;
218397b48c8fSBarry Smith   if (x && b) {
218497b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
218597b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
218697b48c8fSBarry Smith     for (i=0; i<N; i++) {
218797b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2188447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
218997b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
219097b48c8fSBarry Smith     }
219197b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
219297b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
219397b48c8fSBarry Smith   }
219497b48c8fSBarry Smith 
21952e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
2196a9817697SBarry Smith   if (a->keepnonzeropattern) {
2197f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2198e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
21992e5835c6SStefano Zampini       ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2200f1e2ffcdSBarry Smith     }
2201f4df32b1SMatthew Knepley     if (diag != 0.0) {
2202c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2203c7da8527SEric Chamberland         d = rows[i];
2204447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2205c7da8527SEric 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);
2206c7da8527SEric Chamberland       }
2207f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2208447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22092e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2210f1e2ffcdSBarry Smith       }
2211f1e2ffcdSBarry Smith     }
2212f1e2ffcdSBarry Smith   } else {
2213f4df32b1SMatthew Knepley     if (diag != 0.0) {
221417ab2063SBarry Smith       for (i=0; i<N; i++) {
2215e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22167ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2217447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2218447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2219447d62f5SStefano Zampini           } else {
2220416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
22212e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2222bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2223447d62f5SStefano Zampini           }
2224447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2225f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
222617ab2063SBarry Smith         }
222717ab2063SBarry Smith       }
22283a40ed3dSBarry Smith     } else {
222917ab2063SBarry Smith       for (i=0; i<N; i++) {
2230e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2231416022c9SBarry Smith         a->ilen[rows[i]] = 0;
223217ab2063SBarry Smith       }
223317ab2063SBarry Smith     }
2234e56f5c9eSBarry Smith     A->nonzerostate++;
2235f1e2ffcdSBarry Smith   }
22362e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22378c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2238c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2239e2cf4d64SStefano Zampini #endif
22404099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22413a40ed3dSBarry Smith   PetscFunctionReturn(0);
224217ab2063SBarry Smith }
224317ab2063SBarry Smith 
22446e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22456e169961SBarry Smith {
22466e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22476e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22486e169961SBarry Smith   PetscErrorCode    ierr;
22492b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22506e169961SBarry Smith   const PetscScalar *xx;
22512e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22526e169961SBarry Smith 
22536e169961SBarry Smith   PetscFunctionBegin;
22542e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22552e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
22566e169961SBarry Smith   if (x && b) {
22576e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22586e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22592b40b63fSBarry Smith     vecs = PETSC_TRUE;
22606e169961SBarry Smith   }
22611795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22626e169961SBarry Smith   for (i=0; i<N; i++) {
22636e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22642e5835c6SStefano Zampini     ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22652205254eSKarl Rupp 
22666e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22676e169961SBarry Smith   }
22686e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22696e169961SBarry Smith     if (!zeroed[i]) {
22706e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22714cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22722e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22732e5835c6SStefano Zampini           aa[j] = 0.0;
22746e169961SBarry Smith         }
22756e169961SBarry Smith       }
22764cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22776e169961SBarry Smith   }
22786e169961SBarry Smith   if (x && b) {
22796e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22806e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22816e169961SBarry Smith   }
22826e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22836e169961SBarry Smith   if (diag != 0.0) {
22846e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22851d5a398dSstefano_zampini     if (missing) {
22861d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22874cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22884cf107fdSStefano 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]);
22891d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22901d5a398dSstefano_zampini       }
22911d5a398dSstefano_zampini     } else {
22926e169961SBarry Smith       for (i=0; i<N; i++) {
22932e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
22946e169961SBarry Smith       }
22956e169961SBarry Smith     }
22961d5a398dSstefano_zampini   }
22972e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22988c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2299c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2300e2cf4d64SStefano Zampini #endif
23014099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23026e169961SBarry Smith   PetscFunctionReturn(0);
23036e169961SBarry Smith }
23046e169961SBarry Smith 
2305a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
230617ab2063SBarry Smith {
2307416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
23082e5835c6SStefano Zampini   const PetscScalar *aa = a->a;
230997f1f81fSBarry Smith   PetscInt          *itmp;
23102e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23112e5835c6SStefano Zampini   PetscErrorCode    ierr;
23122e5835c6SStefano Zampini   PetscBool         rest = PETSC_FALSE;
23132e5835c6SStefano Zampini #endif
231417ab2063SBarry Smith 
23153a40ed3dSBarry Smith   PetscFunctionBegin;
23162e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23172e5835c6SStefano Zampini   if (v && A->offloadmask == PETSC_OFFLOAD_GPU) {
23182e5835c6SStefano Zampini     /* triggers copy to CPU */
23192e5835c6SStefano Zampini     rest = PETSC_TRUE;
23202e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
23212e5835c6SStefano Zampini   } else aa = a->a;
23222e5835c6SStefano Zampini #endif
2323416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
23242e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
232517ab2063SBarry Smith   if (idx) {
2326bfeeae90SHong Zhang     itmp = a->j + a->i[row];
232726fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2328f4259b30SLisandro Dalcin     else *idx = NULL;
232917ab2063SBarry Smith   }
23302e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23312e5835c6SStefano Zampini   if (rest) {
23322e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
23332e5835c6SStefano Zampini   }
23342e5835c6SStefano Zampini #endif
23353a40ed3dSBarry Smith   PetscFunctionReturn(0);
233617ab2063SBarry Smith }
233717ab2063SBarry Smith 
2338a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
233917ab2063SBarry Smith {
23403a40ed3dSBarry Smith   PetscFunctionBegin;
23412e5835c6SStefano Zampini   *nz = 0;
23422e5835c6SStefano Zampini   if (idx) *idx = NULL;
23432e5835c6SStefano Zampini   if (v) *v = NULL;
23443a40ed3dSBarry Smith   PetscFunctionReturn(0);
234517ab2063SBarry Smith }
234617ab2063SBarry Smith 
2347dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
234817ab2063SBarry Smith {
2349416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
23502e5835c6SStefano Zampini   const MatScalar *v;
235136db0b34SBarry Smith   PetscReal       sum = 0.0;
23526849ba73SBarry Smith   PetscErrorCode  ierr;
235397f1f81fSBarry Smith   PetscInt        i,j;
235417ab2063SBarry Smith 
23553a40ed3dSBarry Smith   PetscFunctionBegin;
23562e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
235717ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2358570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2359570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
236073cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2361570b7f6dSBarry Smith #else
2362416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
236336db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
236417ab2063SBarry Smith     }
23658f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2366570b7f6dSBarry Smith #endif
2367ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23683a40ed3dSBarry Smith   } else if (type == NORM_1) {
236936db0b34SBarry Smith     PetscReal *tmp;
237097f1f81fSBarry Smith     PetscInt  *jj = a->j;
23711795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2372064f8208SBarry Smith     *nrm = 0.0;
2373416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2374bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
237517ab2063SBarry Smith     }
2376d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2377064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
237817ab2063SBarry Smith     }
2379606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
238051f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23813a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2382064f8208SBarry Smith     *nrm = 0.0;
2383d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23842e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
238517ab2063SBarry Smith       sum = 0.0;
2386416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23872e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
238817ab2063SBarry Smith       }
2389064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
239017ab2063SBarry Smith     }
239151f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2392f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23932e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
23943a40ed3dSBarry Smith   PetscFunctionReturn(0);
239517ab2063SBarry Smith }
239617ab2063SBarry Smith 
23974e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23984e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23994e938277SHong Zhang {
24004e938277SHong Zhang   PetscErrorCode ierr;
24014e938277SHong Zhang   PetscInt       i,j,anzj;
24024e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
24034e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
24044e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
24054e938277SHong Zhang 
24064e938277SHong Zhang   PetscFunctionBegin;
24074e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2408854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2409785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2410785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
24114e938277SHong Zhang 
24124e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
24134e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
241426fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
24154e938277SHong Zhang   /* Form ati for csr format of A^T. */
241626fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
24174e938277SHong Zhang 
24184e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2419580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
24204e938277SHong Zhang 
24214e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
24224e938277SHong Zhang   for (i=0;i<am;i++) {
24234e938277SHong Zhang     anzj = ai[i+1] - ai[i];
24244e938277SHong Zhang     for (j=0;j<anzj;j++) {
24254e938277SHong Zhang       atj[atfill[*aj]] = i;
24264e938277SHong Zhang       atfill[*aj++]   += 1;
24274e938277SHong Zhang     }
24284e938277SHong Zhang   }
24294e938277SHong Zhang 
24304e938277SHong Zhang   /* Clean up temporary space and complete requests. */
24314e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2432ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
243333d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2434b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2435a2f3521dSMark F. Adams 
24364e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
24374e938277SHong Zhang   b->free_a  = PETSC_FALSE;
24384e938277SHong Zhang   b->free_ij = PETSC_TRUE;
24394e938277SHong Zhang   b->nonew   = 0;
24404e938277SHong Zhang   PetscFunctionReturn(0);
24414e938277SHong Zhang }
24424e938277SHong Zhang 
24437087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2444cd0d46ebSvictorle {
24453d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
244654f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
24472e5835c6SStefano Zampini   const MatScalar *va,*vb;
24486849ba73SBarry Smith   PetscErrorCode  ierr;
244997f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2450cd0d46ebSvictorle 
2451cd0d46ebSvictorle   PetscFunctionBegin;
2452cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2453cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24545485867bSBarry Smith   if (ma!=nb || na!=mb) {
24555485867bSBarry Smith     *f = PETSC_FALSE;
24565485867bSBarry Smith     PetscFunctionReturn(0);
24575485867bSBarry Smith   }
24582e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr);
24592e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr);
2460cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2461cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2462785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2463785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2464cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2465cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2466cd0d46ebSvictorle 
2467cd0d46ebSvictorle   *f = PETSC_TRUE;
2468cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2469cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
247097f1f81fSBarry Smith       PetscInt    idc,idr;
24715485867bSBarry Smith       PetscScalar vc,vr;
2472cd0d46ebSvictorle       /* column/row index/value */
24735485867bSBarry Smith       idc = adx[aptr[i]];
24745485867bSBarry Smith       idr = bdx[bptr[idc]];
24755485867bSBarry Smith       vc  = va[aptr[i]];
24765485867bSBarry Smith       vr  = vb[bptr[idc]];
24775485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24785485867bSBarry Smith         *f = PETSC_FALSE;
24795485867bSBarry Smith         goto done;
2480cd0d46ebSvictorle       } else {
24815485867bSBarry Smith         aptr[i]++;
24825485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2483cd0d46ebSvictorle       }
2484cd0d46ebSvictorle     }
2485cd0d46ebSvictorle   }
2486cd0d46ebSvictorle done:
2487cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24883aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
24892e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr);
24902e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr);
2491cd0d46ebSvictorle   PetscFunctionReturn(0);
2492cd0d46ebSvictorle }
2493cd0d46ebSvictorle 
24947087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24951cbb95d3SBarry Smith {
24963d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
249754f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
249854f21887SBarry Smith   MatScalar      *va,*vb;
24991cbb95d3SBarry Smith   PetscErrorCode ierr;
25001cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
25011cbb95d3SBarry Smith 
25021cbb95d3SBarry Smith   PetscFunctionBegin;
25031cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
25041cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
25051cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
25061cbb95d3SBarry Smith     *f = PETSC_FALSE;
25071cbb95d3SBarry Smith     PetscFunctionReturn(0);
25081cbb95d3SBarry Smith   }
25091cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
25101cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
25111cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2512785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2513785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
25141cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
25151cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
25161cbb95d3SBarry Smith 
25171cbb95d3SBarry Smith   *f = PETSC_TRUE;
25181cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
25191cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
25201cbb95d3SBarry Smith       PetscInt    idc,idr;
25211cbb95d3SBarry Smith       PetscScalar vc,vr;
25221cbb95d3SBarry Smith       /* column/row index/value */
25231cbb95d3SBarry Smith       idc = adx[aptr[i]];
25241cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
25251cbb95d3SBarry Smith       vc  = va[aptr[i]];
25261cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
25271cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
25281cbb95d3SBarry Smith         *f = PETSC_FALSE;
25291cbb95d3SBarry Smith         goto done;
25301cbb95d3SBarry Smith       } else {
25311cbb95d3SBarry Smith         aptr[i]++;
25321cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
25331cbb95d3SBarry Smith       }
25341cbb95d3SBarry Smith     }
25351cbb95d3SBarry Smith   }
25361cbb95d3SBarry Smith done:
25371cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
25381cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
25391cbb95d3SBarry Smith   PetscFunctionReturn(0);
25401cbb95d3SBarry Smith }
25411cbb95d3SBarry Smith 
2542ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25439e29f15eSvictorle {
2544dfbe8321SBarry Smith   PetscErrorCode ierr;
25456e111a19SKarl Rupp 
25469e29f15eSvictorle   PetscFunctionBegin;
25475485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25489e29f15eSvictorle   PetscFunctionReturn(0);
25499e29f15eSvictorle }
25509e29f15eSvictorle 
2551ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25521cbb95d3SBarry Smith {
25531cbb95d3SBarry Smith   PetscErrorCode ierr;
25546e111a19SKarl Rupp 
25551cbb95d3SBarry Smith   PetscFunctionBegin;
25561cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25571cbb95d3SBarry Smith   PetscFunctionReturn(0);
25581cbb95d3SBarry Smith }
25591cbb95d3SBarry Smith 
2560dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
256117ab2063SBarry Smith {
2562416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2563fff8e43fSBarry Smith   const PetscScalar *l,*r;
2564fff8e43fSBarry Smith   PetscScalar       x;
256554f21887SBarry Smith   MatScalar         *v;
2566dfbe8321SBarry Smith   PetscErrorCode    ierr;
2567fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2568fff8e43fSBarry Smith   const PetscInt    *jj;
256917ab2063SBarry Smith 
25703a40ed3dSBarry Smith   PetscFunctionBegin;
257117ab2063SBarry Smith   if (ll) {
25723ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25733ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2574e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2575e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2576fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
25772e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
257817ab2063SBarry Smith     for (i=0; i<m; i++) {
257917ab2063SBarry Smith       x = l[i];
2580416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25812205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
258217ab2063SBarry Smith     }
2583fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2584efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
25852e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
258617ab2063SBarry Smith   }
258717ab2063SBarry Smith   if (rr) {
2588e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2589e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2590fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
25912e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
25922e5835c6SStefano Zampini     jj = a->j;
25932205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
25942e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
2595fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2596efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
259717ab2063SBarry Smith   }
2598acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
25998c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2600c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2601e2cf4d64SStefano Zampini #endif
26023a40ed3dSBarry Smith   PetscFunctionReturn(0);
260317ab2063SBarry Smith }
260417ab2063SBarry Smith 
26057dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
260617ab2063SBarry Smith {
2607db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
26086849ba73SBarry Smith   PetscErrorCode    ierr;
2609d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
261097f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
26115d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
26122e5835c6SStefano Zampini   const PetscScalar *aa;
26135d0c19d7SBarry Smith   PetscInt          nrows,ncols;
261497f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
261554f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2616416022c9SBarry Smith   Mat               C;
2617cdc6f3adSToby Isaac   PetscBool         stride;
261817ab2063SBarry Smith 
26193a40ed3dSBarry Smith   PetscFunctionBegin;
262017ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2621b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2622b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
262317ab2063SBarry Smith 
2624251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2625ff718158SBarry Smith   if (stride) {
2626ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2627ff718158SBarry Smith   } else {
2628ff718158SBarry Smith     first = 0;
2629ff718158SBarry Smith     step  = 0;
2630ff718158SBarry Smith   }
2631fee21e36SBarry Smith   if (stride && step == 1) {
263202834360SBarry Smith     /* special case of contiguous rows */
2633dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
263402834360SBarry Smith     /* loop over new rows determining lens and starting points */
263502834360SBarry Smith     for (i=0; i<nrows; i++) {
2636bfeeae90SHong Zhang       kstart = ai[irow[i]];
2637a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2638a91a9bebSLisandro Dalcin       starts[i] = kstart;
263902834360SBarry Smith       for (k=kstart; k<kend; k++) {
2640bfeeae90SHong Zhang         if (aj[k] >= first) {
264102834360SBarry Smith           starts[i] = k;
264202834360SBarry Smith           break;
264302834360SBarry Smith         }
264402834360SBarry Smith       }
2645a2744918SBarry Smith       sum = 0;
264602834360SBarry Smith       while (k < kend) {
2647bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2648a2744918SBarry Smith         sum++;
264902834360SBarry Smith       }
2650a2744918SBarry Smith       lens[i] = sum;
265102834360SBarry Smith     }
265202834360SBarry Smith     /* create submatrix */
2653cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
265497f1f81fSBarry Smith       PetscInt n_cols,n_rows;
265508480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2656e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2657d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
265808480c60SBarry Smith       C    = *B;
26593a40ed3dSBarry Smith     } else {
26603bef6203SJed Brown       PetscInt rbs,cbs;
2661ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2662f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26633bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26643bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26653bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26667adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2667ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
266808480c60SBarry Smith     }
2669db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2670db02288aSLois Curfman McInnes 
267102834360SBarry Smith     /* loop over rows inserting into submatrix */
2672db02288aSLois Curfman McInnes     a_new = c->a;
2673db02288aSLois Curfman McInnes     j_new = c->j;
2674db02288aSLois Curfman McInnes     i_new = c->i;
26752e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
267602834360SBarry Smith     for (i=0; i<nrows; i++) {
2677a2744918SBarry Smith       ii    = starts[i];
2678a2744918SBarry Smith       lensi = lens[i];
2679a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2680a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
268102834360SBarry Smith       }
26822e5835c6SStefano Zampini       ierr       = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr);
2683a2744918SBarry Smith       a_new     += lensi;
2684a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2685a2744918SBarry Smith       c->ilen[i] = lensi;
268602834360SBarry Smith     }
26872e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
26880e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26893a40ed3dSBarry Smith   } else {
269002834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26911795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2692854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26934dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2694d9ef940eSSatish 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);
26954dcab191SBarry Smith       smap[icol[i]] = i+1;
26964dcab191SBarry Smith     }
26974dcab191SBarry Smith 
269802834360SBarry Smith     /* determine lens of each row */
269902834360SBarry Smith     for (i=0; i<nrows; i++) {
2700bfeeae90SHong Zhang       kstart  = ai[irow[i]];
270102834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
270202834360SBarry Smith       lens[i] = 0;
270302834360SBarry Smith       for (k=kstart; k<kend; k++) {
2704bfeeae90SHong Zhang         if (smap[aj[k]]) {
270502834360SBarry Smith           lens[i]++;
270602834360SBarry Smith         }
270702834360SBarry Smith       }
270802834360SBarry Smith     }
270917ab2063SBarry Smith     /* Create and fill new matrix */
2710a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2711ace3abfcSBarry Smith       PetscBool equal;
27120f5bd95cSBarry Smith 
271399141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2714e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2715580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2716f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2717580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
271808480c60SBarry Smith       C    = *B;
27193a40ed3dSBarry Smith     } else {
27203bef6203SJed Brown       PetscInt rbs,cbs;
2721ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2722f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
27233bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
27243bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
27253bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
27267adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2727ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
272808480c60SBarry Smith     }
27292e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
273099141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
273117ab2063SBarry Smith     for (i=0; i<nrows; i++) {
273299141d43SSatish Balay       row      = irow[i];
2733bfeeae90SHong Zhang       kstart   = ai[row];
273499141d43SSatish Balay       kend     = kstart + a->ilen[row];
2735bfeeae90SHong Zhang       mat_i    = c->i[i];
273699141d43SSatish Balay       mat_j    = c->j + mat_i;
273799141d43SSatish Balay       mat_a    = c->a + mat_i;
273899141d43SSatish Balay       mat_ilen = c->ilen + i;
273917ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2740bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2741ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
27422e5835c6SStefano Zampini           *mat_a++ = aa[k];
274399141d43SSatish Balay           (*mat_ilen)++;
274499141d43SSatish Balay 
274517ab2063SBarry Smith         }
274617ab2063SBarry Smith       }
274717ab2063SBarry Smith     }
27482e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
274902834360SBarry Smith     /* Free work space */
275002834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2751606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2752606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2753cdc6f3adSToby Isaac     /* sort */
2754cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2755cdc6f3adSToby Isaac       PetscInt ilen;
2756cdc6f3adSToby Isaac 
2757cdc6f3adSToby Isaac       mat_i = c->i[i];
2758cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2759cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2760cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2761390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2762cdc6f3adSToby Isaac     }
276302834360SBarry Smith   }
27648c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2765b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2766305c6ccfSStefano Zampini #endif
27676d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27686d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
276917ab2063SBarry Smith 
277017ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2771416022c9SBarry Smith   *B   = C;
27723a40ed3dSBarry Smith   PetscFunctionReturn(0);
277317ab2063SBarry Smith }
277417ab2063SBarry Smith 
2775fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
277682d44351SHong Zhang {
277782d44351SHong Zhang   PetscErrorCode ierr;
277882d44351SHong Zhang   Mat            B;
277982d44351SHong Zhang 
278082d44351SHong Zhang   PetscFunctionBegin;
2781c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
278282d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
278382d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
278433d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
278582d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
278682d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
278782d44351SHong Zhang     *subMat = B;
2788c2d650bdSHong Zhang   } else {
2789c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2790c2d650bdSHong Zhang   }
279182d44351SHong Zhang   PetscFunctionReturn(0);
279282d44351SHong Zhang }
279382d44351SHong Zhang 
27949a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2795a871dcd8SBarry Smith {
279663b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2797dfbe8321SBarry Smith   PetscErrorCode ierr;
279863b91edcSBarry Smith   Mat            outA;
2799ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
280063b91edcSBarry Smith 
28013a40ed3dSBarry Smith   PetscFunctionBegin;
2802e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
28031df811f5SHong Zhang 
2804b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2805b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2806a871dcd8SBarry Smith 
280763b91edcSBarry Smith   outA             = inA;
2808d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2809f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2810f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
28112205254eSKarl Rupp 
2812c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
28136bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
28142205254eSKarl Rupp 
2815c3122656SLisandro Dalcin   a->row = row;
28162205254eSKarl Rupp 
2817c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
28186bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
28192205254eSKarl Rupp 
2820c3122656SLisandro Dalcin   a->col = col;
282163b91edcSBarry Smith 
282236db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
28236bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
28244c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
28253bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2826f0ec6fceSSatish Balay 
282794a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2828854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
28293bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
283094a9d846SBarry Smith   }
283163b91edcSBarry Smith 
2832f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2833137fb511SHong Zhang   if (row_identity && col_identity) {
2834ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2835137fb511SHong Zhang   } else {
2836719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2837137fb511SHong Zhang   }
28383a40ed3dSBarry Smith   PetscFunctionReturn(0);
2839a871dcd8SBarry Smith }
2840a871dcd8SBarry Smith 
2841f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2842f0b747eeSBarry Smith {
2843f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2844dfa0f9e5SStefano Zampini   PetscScalar    *v;
2845efee365bSSatish Balay   PetscErrorCode ierr;
2846c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
28473a40ed3dSBarry Smith 
28483a40ed3dSBarry Smith   PetscFunctionBegin;
2849dfa0f9e5SStefano Zampini   ierr = MatSeqAIJGetArray(inA,&v);CHKERRQ(ierr);
2850c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
2851dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
2852efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2853dfa0f9e5SStefano Zampini   ierr = MatSeqAIJRestoreArray(inA,&v);CHKERRQ(ierr);
2854acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
28553a40ed3dSBarry Smith   PetscFunctionReturn(0);
2856f0b747eeSBarry Smith }
2857f0b747eeSBarry Smith 
2858f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
285916b64355SHong Zhang {
286016b64355SHong Zhang   PetscErrorCode ierr;
286116b64355SHong Zhang   PetscInt       i;
286216b64355SHong Zhang 
286316b64355SHong Zhang   PetscFunctionBegin;
286416b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
286516b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
286616b64355SHong Zhang 
286716b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
286816b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
286916b64355SHong Zhang     }
287016b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
287116b64355SHong Zhang 
287216b64355SHong Zhang     if (submatj->rbuf1) {
287316b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
287416b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
287516b64355SHong Zhang     }
287616b64355SHong Zhang 
287716b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
287816b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
287916b64355SHong Zhang     }
288016b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
288116b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
288216b64355SHong Zhang   }
288316b64355SHong Zhang 
288416b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
288516b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
288616b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
288716b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
288816b64355SHong Zhang #else
288916b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
289016b64355SHong Zhang #endif
289116b64355SHong Zhang 
289216b64355SHong Zhang   if (!submatj->allcolumns) {
289316b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
289416b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
289516b64355SHong Zhang #else
289616b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
289716b64355SHong Zhang #endif
289816b64355SHong Zhang   }
289916b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
290016b64355SHong Zhang 
290116b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
290216b64355SHong Zhang   PetscFunctionReturn(0);
290316b64355SHong Zhang }
290416b64355SHong Zhang 
29050fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
290616b64355SHong Zhang {
290716b64355SHong Zhang   PetscErrorCode ierr;
290816b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
29095c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
291016b64355SHong Zhang 
291116b64355SHong Zhang   PetscFunctionBegin;
291234136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2913f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
291416b64355SHong Zhang   PetscFunctionReturn(0);
291516b64355SHong Zhang }
291616b64355SHong Zhang 
29172d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
29182d033e1fSHong Zhang {
29192d033e1fSHong Zhang   PetscErrorCode ierr;
29202d033e1fSHong Zhang   PetscInt       i;
29210fb991dcSHong Zhang   Mat            C;
29220fb991dcSHong Zhang   Mat_SeqAIJ     *c;
29230fb991dcSHong Zhang   Mat_SubSppt    *submatj;
29242d033e1fSHong Zhang 
29252d033e1fSHong Zhang   PetscFunctionBegin;
29262d033e1fSHong Zhang   for (i=0; i<n; i++) {
29270fb991dcSHong Zhang     C       = (*mat)[i];
29280fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
29290fb991dcSHong Zhang     submatj = c->submatis1;
29302d033e1fSHong Zhang     if (submatj) {
2931682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
293234136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2933f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
293434136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
29352d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
29362d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
29372d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2938682e4c99SStefano Zampini       }
29392d033e1fSHong Zhang     } else {
29402d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
29412d033e1fSHong Zhang     }
29422d033e1fSHong Zhang   }
294386e85357SHong Zhang 
294463a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
294563a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
294663a75b2aSHong Zhang 
29472d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
29482d033e1fSHong Zhang   PetscFunctionReturn(0);
29492d033e1fSHong Zhang }
29502d033e1fSHong Zhang 
29517dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2952cddf8d76SBarry Smith {
2953dfbe8321SBarry Smith   PetscErrorCode ierr;
295497f1f81fSBarry Smith   PetscInt       i;
2955cddf8d76SBarry Smith 
29563a40ed3dSBarry Smith   PetscFunctionBegin;
2957cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2958df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2959cddf8d76SBarry Smith   }
2960cddf8d76SBarry Smith 
2961cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29627dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2963cddf8d76SBarry Smith   }
29643a40ed3dSBarry Smith   PetscFunctionReturn(0);
2965cddf8d76SBarry Smith }
2966cddf8d76SBarry Smith 
296797f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29684dcbc457SBarry Smith {
2969e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29706849ba73SBarry Smith   PetscErrorCode ierr;
29715d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29725d0c19d7SBarry Smith   const PetscInt *idx;
297397f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2974f1af5d2fSBarry Smith   PetscBT        table;
2975bbd702dbSSatish Balay 
29763a40ed3dSBarry Smith   PetscFunctionBegin;
2977d0f46423SBarry Smith   m  = A->rmap->n;
2978e4d965acSSatish Balay   ai = a->i;
2979bfeeae90SHong Zhang   aj = a->j;
29808a047759SSatish Balay 
2981e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
298206763907SSatish Balay 
2983854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
298453b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
298506763907SSatish Balay 
2986e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2987b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2988e4d965acSSatish Balay     isz  = 0;
29896831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2990e4d965acSSatish Balay 
2991e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29924dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2993b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2994e4d965acSSatish Balay 
2995dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2996e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29972205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29984dcbc457SBarry Smith     }
299906763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
30006bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
3001e4d965acSSatish Balay 
300204a348a9SBarry Smith     k = 0;
300304a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
300404a348a9SBarry Smith       n = isz;
300506763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
3006e4d965acSSatish Balay         row   = nidx[k];
3007e4d965acSSatish Balay         start = ai[row];
3008e4d965acSSatish Balay         end   = ai[row+1];
300904a348a9SBarry Smith         for (l = start; l<end; l++) {
3010efb16452SHong Zhang           val = aj[l];
30112205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
3012e4d965acSSatish Balay         }
3013e4d965acSSatish Balay       }
3014e4d965acSSatish Balay     }
301570b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
3016e4d965acSSatish Balay   }
301794bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
3018606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
30193a40ed3dSBarry Smith   PetscFunctionReturn(0);
30204dcbc457SBarry Smith }
302117ab2063SBarry Smith 
30220513a670SBarry Smith /* -------------------------------------------------------------- */
3023dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
30240513a670SBarry Smith {
30250513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
30266849ba73SBarry Smith   PetscErrorCode ierr;
30273b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
30285d0c19d7SBarry Smith   const PetscInt *row,*col;
30295d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
303056cd22aeSBarry Smith   IS             icolp,irowp;
30310298fd71SBarry Smith   PetscInt       *cwork = NULL;
30320298fd71SBarry Smith   PetscScalar    *vwork = NULL;
30330513a670SBarry Smith 
30343a40ed3dSBarry Smith   PetscFunctionBegin;
30354c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
303656cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
30374c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
303856cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
30390513a670SBarry Smith 
30400513a670SBarry Smith   /* determine lengths of permuted rows */
3041854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
30422205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
3043ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
3044f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
304533d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
30467adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
3047ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
3048606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
30490513a670SBarry Smith 
3050785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
30510513a670SBarry Smith   for (i=0; i<m; i++) {
305232ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30532205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3054cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
305532ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30560513a670SBarry Smith   }
3057606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30582205254eSKarl Rupp 
30593c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30602205254eSKarl Rupp 
30618c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3062b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30639fe5e383SStefano Zampini #endif
30640513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30650513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
306656cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
306756cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30686bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30696bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30706768869dSprj-   if (rowp == colp) {
30716768869dSprj-     if (A->symmetric) {
30726768869dSprj-       ierr = MatSetOption(*B,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
30736768869dSprj-     }
30746768869dSprj-     if (A->hermitian) {
30756768869dSprj-       ierr = MatSetOption(*B,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
30766768869dSprj-     }
30776768869dSprj-   }
30783a40ed3dSBarry Smith   PetscFunctionReturn(0);
30790513a670SBarry Smith }
30800513a670SBarry Smith 
3081dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3082cb5b572fSBarry Smith {
3083dfbe8321SBarry Smith   PetscErrorCode ierr;
3084cb5b572fSBarry Smith 
3085cb5b572fSBarry Smith   PetscFunctionBegin;
308633f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
308733f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3088be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3089be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30902e5835c6SStefano Zampini     const PetscScalar *aa;
3091be6bf707SBarry Smith 
30922e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30934d805d7cSStefano 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]);
30942e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3095cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
30962e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3097cb5b572fSBarry Smith   } else {
3098cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3099cb5b572fSBarry Smith   }
3100cb5b572fSBarry Smith   PetscFunctionReturn(0);
3101cb5b572fSBarry Smith }
3102cb5b572fSBarry Smith 
31034994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3104273d9f13SBarry Smith {
3105dfbe8321SBarry Smith   PetscErrorCode ierr;
3106273d9f13SBarry Smith 
3107273d9f13SBarry Smith   PetscFunctionBegin;
3108f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3109273d9f13SBarry Smith   PetscFunctionReturn(0);
3110273d9f13SBarry Smith }
3111273d9f13SBarry Smith 
3112f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
31136c0721eeSBarry Smith {
31146c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
31156e111a19SKarl Rupp 
31166c0721eeSBarry Smith   PetscFunctionBegin;
31176c0721eeSBarry Smith   *array = a->a;
31186c0721eeSBarry Smith   PetscFunctionReturn(0);
31196c0721eeSBarry Smith }
31206c0721eeSBarry Smith 
3121f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
31226c0721eeSBarry Smith {
31236c0721eeSBarry Smith   PetscFunctionBegin;
3124f38c1e66SStefano Zampini   *array = NULL;
31256c0721eeSBarry Smith   PetscFunctionReturn(0);
31266c0721eeSBarry Smith }
3127273d9f13SBarry Smith 
31288229c054SShri Abhyankar /*
31298229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
31308229c054SShri Abhyankar    have different nonzero structure.
31318229c054SShri Abhyankar */
3132b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3133ec7775f6SShri Abhyankar {
3134b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3135ec7775f6SShri Abhyankar 
3136ec7775f6SShri Abhyankar   PetscFunctionBegin;
3137ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3138ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3139b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3140b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3141b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31428af7cee1SJed Brown     nnz[i] = 0;
31438af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3144b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3145b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31468af7cee1SJed Brown       nnz[i]++;
31478af7cee1SJed Brown     }
31488af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3149ec7775f6SShri Abhyankar   }
3150ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3151ec7775f6SShri Abhyankar }
3152ec7775f6SShri Abhyankar 
3153b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3154b264fe52SHong Zhang {
3155b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3156b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3157b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3158b264fe52SHong Zhang   PetscErrorCode ierr;
3159b264fe52SHong Zhang 
3160b264fe52SHong Zhang   PetscFunctionBegin;
3161b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3162b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3163b264fe52SHong Zhang   PetscFunctionReturn(0);
3164b264fe52SHong Zhang }
3165b264fe52SHong Zhang 
3166f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3167ac90fabeSBarry Smith {
3168dfbe8321SBarry Smith   PetscErrorCode ierr;
3169ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3170ac90fabeSBarry Smith 
3171ac90fabeSBarry Smith   PetscFunctionBegin;
317241f5e1b1SStefano Zampini   if (str == UNKNOWN_NONZERO_PATTERN && x->nz == y->nz) {
317381fa06acSBarry Smith     PetscBool e;
317481fa06acSBarry Smith     ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
317581fa06acSBarry Smith     if (e) {
317681fa06acSBarry Smith       ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
317781fa06acSBarry Smith       if (e) {
317881fa06acSBarry Smith         str = SAME_NONZERO_PATTERN;
317981fa06acSBarry Smith       }
318081fa06acSBarry Smith     }
318181fa06acSBarry Smith   }
3182ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31832e5835c6SStefano Zampini     const PetscScalar *xa;
31842e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
318581fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
318681fa06acSBarry Smith 
318781fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31882e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31892e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31902e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31912e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31922e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
319341f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3194acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3195a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3196ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3197ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3198ac90fabeSBarry Smith   } else {
31998229c054SShri Abhyankar     Mat      B;
32008229c054SShri Abhyankar     PetscInt *nnz;
3201785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3202ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3203bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
320481fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
32052e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
32068229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3207ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3208ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
320928be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
32108229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3211ac90fabeSBarry Smith   }
3212ac90fabeSBarry Smith   PetscFunctionReturn(0);
3213ac90fabeSBarry Smith }
3214ac90fabeSBarry Smith 
32157087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
3216354c94deSBarry Smith {
3217354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3218354c94deSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3219354c94deSBarry Smith   PetscInt       i,nz;
3220354c94deSBarry Smith   PetscScalar    *a;
3221*ce496241SStefano Zampini   PetscErrorCode ierr;
3222354c94deSBarry Smith 
3223354c94deSBarry Smith   PetscFunctionBegin;
3224354c94deSBarry Smith   nz = aij->nz;
3225*ce496241SStefano Zampini   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
32262205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3227*ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3228354c94deSBarry Smith #else
3229354c94deSBarry Smith   PetscFunctionBegin;
3230354c94deSBarry Smith #endif
3231354c94deSBarry Smith   PetscFunctionReturn(0);
3232354c94deSBarry Smith }
3233354c94deSBarry Smith 
3234985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3235e34fafa9SBarry Smith {
3236e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3237e34fafa9SBarry Smith   PetscErrorCode  ierr;
3238d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3239e34fafa9SBarry Smith   PetscReal       atmp;
3240985db425SBarry Smith   PetscScalar     *x;
3241*ce496241SStefano Zampini   const MatScalar *aa,*av;
3242e34fafa9SBarry Smith 
3243e34fafa9SBarry Smith   PetscFunctionBegin;
3244e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3245*ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3246*ce496241SStefano Zampini   aa = av;
3247e34fafa9SBarry Smith   ai = a->i;
3248e34fafa9SBarry Smith   aj = a->j;
3249e34fafa9SBarry Smith 
3250985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3251475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3252e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3253e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3254e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3255e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3256e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3257985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3258985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3259985db425SBarry Smith       aa++; aj++;
3260985db425SBarry Smith     }
3261985db425SBarry Smith   }
3262475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3263*ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3264985db425SBarry Smith   PetscFunctionReturn(0);
3265985db425SBarry Smith }
3266985db425SBarry Smith 
3267985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3268985db425SBarry Smith {
3269985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3270985db425SBarry Smith   PetscErrorCode  ierr;
3271d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3272985db425SBarry Smith   PetscScalar     *x;
3273*ce496241SStefano Zampini   const MatScalar *aa,*av;
3274985db425SBarry Smith 
3275985db425SBarry Smith   PetscFunctionBegin;
3276e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3277*ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3278*ce496241SStefano Zampini   aa = av;
3279985db425SBarry Smith   ai = a->i;
3280985db425SBarry Smith   aj = a->j;
3281985db425SBarry Smith 
3282985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3283fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3284985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3285e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3286985db425SBarry Smith   for (i=0; i<m; i++) {
3287985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3288d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3289985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3290985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3291985db425SBarry Smith       x[i] = 0.0;
3292985db425SBarry Smith       if (idx) {
3293985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3294985db425SBarry Smith           if (aj[j] > j) {
3295985db425SBarry Smith             idx[i] = j;
3296985db425SBarry Smith             break;
3297985db425SBarry Smith           }
3298985db425SBarry Smith         }
32991a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
33001a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3301985db425SBarry Smith       }
3302985db425SBarry Smith     }
3303985db425SBarry Smith     for (j=0; j<ncols; j++) {
3304985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3305985db425SBarry Smith       aa++; aj++;
3306985db425SBarry Smith     }
3307985db425SBarry Smith   }
3308fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3309*ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3310985db425SBarry Smith   PetscFunctionReturn(0);
3311985db425SBarry Smith }
3312985db425SBarry Smith 
3313c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3314c87e5d42SMatthew Knepley {
3315c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3316c87e5d42SMatthew Knepley   PetscErrorCode  ierr;
3317c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3318*ce496241SStefano Zampini   PetscScalar     *x;
3319*ce496241SStefano Zampini   const MatScalar *aa,*av;
3320c87e5d42SMatthew Knepley 
3321c87e5d42SMatthew Knepley   PetscFunctionBegin;
3322*ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3323*ce496241SStefano Zampini   aa = av;
3324c87e5d42SMatthew Knepley   ai = a->i;
3325c87e5d42SMatthew Knepley   aj = a->j;
3326c87e5d42SMatthew Knepley 
3327c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3328f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3329c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3330f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3331c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3332c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3333f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3334f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3335f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3336f07e67edSHong Zhang       x[i] = 0.0;
3337f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3338289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3339f07e67edSHong Zhang           if (aj[j] > j) {
3340f07e67edSHong Zhang             idx[i] = j;
33412205254eSKarl Rupp             break;
33422205254eSKarl Rupp           }
3343289a08f5SMatthew Knepley         }
3344f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3345f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3346f07e67edSHong Zhang       }
3347289a08f5SMatthew Knepley     }
3348c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3349f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3350c87e5d42SMatthew Knepley       aa++; aj++;
3351c87e5d42SMatthew Knepley     }
3352c87e5d42SMatthew Knepley   }
3353f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3354*ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3355c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3356c87e5d42SMatthew Knepley }
3357c87e5d42SMatthew Knepley 
3358985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3359985db425SBarry Smith {
3360985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3361985db425SBarry Smith   PetscErrorCode  ierr;
3362d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3363d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3364985db425SBarry Smith   PetscScalar     *x;
3365*ce496241SStefano Zampini   const MatScalar *aa,*av;
3366985db425SBarry Smith 
3367985db425SBarry Smith   PetscFunctionBegin;
3368e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3369*ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3370*ce496241SStefano Zampini   aa = av;
3371985db425SBarry Smith   ai = a->i;
3372985db425SBarry Smith   aj = a->j;
3373985db425SBarry Smith 
3374985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3375fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3376985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3377f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3378985db425SBarry Smith   for (i=0; i<m; i++) {
3379985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3380d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3381985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3382985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3383985db425SBarry Smith       x[i] = 0.0;
3384985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3385985db425SBarry Smith         for (j=0; j<ncols; j++) {
3386985db425SBarry Smith           if (aj[j] > j) {
3387985db425SBarry Smith             idx[i] = j;
3388985db425SBarry Smith             break;
3389985db425SBarry Smith           }
3390985db425SBarry Smith         }
3391fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3392fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3393985db425SBarry Smith       }
3394985db425SBarry Smith     }
3395985db425SBarry Smith     for (j=0; j<ncols; j++) {
3396985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3397985db425SBarry Smith       aa++; aj++;
3398e34fafa9SBarry Smith     }
3399e34fafa9SBarry Smith   }
3400fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3401*ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3402e34fafa9SBarry Smith   PetscFunctionReturn(0);
3403e34fafa9SBarry Smith }
3404bbead8a2SBarry Smith 
3405713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3406bbead8a2SBarry Smith {
3407bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3408bbead8a2SBarry Smith   PetscErrorCode  ierr;
340933d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3410bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
34110da83c2eSBarry Smith   const PetscReal shift = 0.0;
34121a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3413bbead8a2SBarry Smith 
3414bbead8a2SBarry Smith   PetscFunctionBegin;
3415a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
34164a0d0026SBarry Smith   if (a->ibdiagvalid) {
34174a0d0026SBarry Smith     if (values) *values = a->ibdiag;
34184a0d0026SBarry Smith     PetscFunctionReturn(0);
34194a0d0026SBarry Smith   }
3420bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3421bbead8a2SBarry Smith   if (!a->ibdiag) {
3422785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
34233bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3424bbead8a2SBarry Smith   }
3425bbead8a2SBarry Smith   diag = a->ibdiag;
3426bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3427bbead8a2SBarry Smith   /* factor and invert each block */
3428bbead8a2SBarry Smith   switch (bs) {
3429bbead8a2SBarry Smith   case 1:
3430bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3431bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3432ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3433ec1892c8SHong Zhang         if (allowzeropivot) {
34347b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34357b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34367b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34377b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
34387b6c816cSBarry 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);
3439ec1892c8SHong Zhang       }
3440bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3441bbead8a2SBarry Smith     }
3442bbead8a2SBarry Smith     break;
3443bbead8a2SBarry Smith   case 2:
3444bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3445bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3446bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3447a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34487b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
344996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3450bbead8a2SBarry Smith       diag += 4;
3451bbead8a2SBarry Smith     }
3452bbead8a2SBarry Smith     break;
3453bbead8a2SBarry Smith   case 3:
3454bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3455bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3456bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3457a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34587b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3460bbead8a2SBarry Smith       diag += 9;
3461bbead8a2SBarry Smith     }
3462bbead8a2SBarry Smith     break;
3463bbead8a2SBarry Smith   case 4:
3464bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3465bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3466bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3467a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34687b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3470bbead8a2SBarry Smith       diag += 16;
3471bbead8a2SBarry Smith     }
3472bbead8a2SBarry Smith     break;
3473bbead8a2SBarry Smith   case 5:
3474bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3475bbead8a2SBarry 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;
3476bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3477a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34787b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
347996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3480bbead8a2SBarry Smith       diag += 25;
3481bbead8a2SBarry Smith     }
3482bbead8a2SBarry Smith     break;
3483bbead8a2SBarry Smith   case 6:
3484bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3485bbead8a2SBarry 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;
3486bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3487a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34887b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
348996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3490bbead8a2SBarry Smith       diag += 36;
3491bbead8a2SBarry Smith     }
3492bbead8a2SBarry Smith     break;
3493bbead8a2SBarry Smith   case 7:
3494bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3495bbead8a2SBarry 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;
3496bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3497a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34987b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
349996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3500bbead8a2SBarry Smith       diag += 49;
3501bbead8a2SBarry Smith     }
3502bbead8a2SBarry Smith     break;
3503bbead8a2SBarry Smith   default:
3504dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3505bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3506bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3507bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3508bbead8a2SBarry Smith       }
3509bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
35105f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
35117b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
351296b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3513bbead8a2SBarry Smith       diag += bs2;
3514bbead8a2SBarry Smith     }
3515bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3516bbead8a2SBarry Smith   }
3517bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3518bbead8a2SBarry Smith   PetscFunctionReturn(0);
3519bbead8a2SBarry Smith }
3520bbead8a2SBarry Smith 
352173a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
352273a71a0fSBarry Smith {
352373a71a0fSBarry Smith   PetscErrorCode ierr;
352473a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
352573a71a0fSBarry Smith   PetscScalar    a;
352673a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
352773a71a0fSBarry Smith 
352873a71a0fSBarry Smith   PetscFunctionBegin;
352973a71a0fSBarry Smith   if (!x->assembled) {
353073a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
353173a71a0fSBarry Smith     for (i=0; i<m; i++) {
353273a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
353373a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
353473a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
353573a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
353673a71a0fSBarry Smith       }
353773a71a0fSBarry Smith     }
3538e2ce353bSJunchao Zhang   } else {
3539e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3540e2ce353bSJunchao Zhang   }
3541*ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3542*ce496241SStefano Zampini   if (x->offloadmask != PETSC_OFFLOAD_UNALLOCATED) x->offloadmask = PETSC_OFFLOAD_CPU;
3543*ce496241SStefano Zampini #endif
354473a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
354573a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
354673a71a0fSBarry Smith   PetscFunctionReturn(0);
354773a71a0fSBarry Smith }
354873a71a0fSBarry Smith 
3549679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3550679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3551679944adSJunchao Zhang {
3552679944adSJunchao Zhang   PetscErrorCode ierr;
3553679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3554679944adSJunchao Zhang   PetscScalar    a;
3555679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3556679944adSJunchao Zhang 
3557679944adSJunchao Zhang   PetscFunctionBegin;
3558679944adSJunchao Zhang   nskip = high - low;
3559679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3560679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3561679944adSJunchao Zhang   for (i=0; i<m; i++) {
3562679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3563679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3564679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3565679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3566679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3567679944adSJunchao Zhang     }
3568e2ce353bSJunchao Zhang   }
3569679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3570679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3571679944adSJunchao Zhang   PetscFunctionReturn(0);
3572679944adSJunchao Zhang }
3573679944adSJunchao Zhang 
3574679944adSJunchao Zhang 
3575682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35760a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3577cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3578cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3579cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
358097304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35817c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35827c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3583f4259b30SLisandro Dalcin                                         NULL,
3584f4259b30SLisandro Dalcin                                         NULL,
3585f4259b30SLisandro Dalcin                                         NULL,
3586f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3587cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3588f4259b30SLisandro Dalcin                                         NULL,
358941f059aeSBarry Smith                                         MatSOR_SeqAIJ,
359091e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
359197304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3592cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3593cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3594cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3595cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3596f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3597cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3598cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3599cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3600d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3601f4259b30SLisandro Dalcin                                         NULL,
3602f4259b30SLisandro Dalcin                                         NULL,
3603f4259b30SLisandro Dalcin                                         NULL,
3604f4259b30SLisandro Dalcin                                         NULL,
36054994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3606f4259b30SLisandro Dalcin                                         NULL,
3607f4259b30SLisandro Dalcin                                         NULL,
3608f4259b30SLisandro Dalcin                                         NULL,
3609f4259b30SLisandro Dalcin                                         NULL,
3610d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3611f4259b30SLisandro Dalcin                                         NULL,
3612f4259b30SLisandro Dalcin                                         NULL,
3613cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3614f4259b30SLisandro Dalcin                                         NULL,
3615d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
36167dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3617cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3618cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3619cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3620d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3621cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
36227d68702bSBarry Smith                                         MatShift_SeqAIJ,
362379299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
36246e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
362573a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
36263b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
36273b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
36283b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3629a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
363093dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3631f4259b30SLisandro Dalcin                                         NULL,
3632f4259b30SLisandro Dalcin                                         NULL,
3633cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3634f4259b30SLisandro Dalcin                                         NULL,
3635f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3636b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3637b9b97703SBarry Smith                                         MatView_SeqAIJ,
3638f4259b30SLisandro Dalcin                                         NULL,
3639f4259b30SLisandro Dalcin                                         NULL,
3640f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3641321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3642f4259b30SLisandro Dalcin                                         NULL,
3643f4259b30SLisandro Dalcin                                         NULL,
3644f4259b30SLisandro Dalcin                                         NULL,
3645d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3646c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3647f4259b30SLisandro Dalcin                                         NULL,
3648f4259b30SLisandro Dalcin                                         NULL,
3649f4259b30SLisandro Dalcin                                         NULL,
3650f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36513acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3652f4259b30SLisandro Dalcin                                         NULL,
3653f4259b30SLisandro Dalcin                                         NULL,
3654f4259b30SLisandro Dalcin                                         NULL,
36556ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3656f4259b30SLisandro Dalcin                                         NULL,
3657f4259b30SLisandro Dalcin                                         NULL,
3658f4259b30SLisandro Dalcin                                         NULL,
3659bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3660d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36611cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3662f4259b30SLisandro Dalcin                                         NULL,
3663f4259b30SLisandro Dalcin                                         NULL,
3664f4259b30SLisandro Dalcin                                         NULL,
3665f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3666f4259b30SLisandro Dalcin                                         NULL,
366726be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3668f4259b30SLisandro Dalcin                                         NULL,
3669f4259b30SLisandro Dalcin                                         NULL,
36708fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3671f4259b30SLisandro Dalcin                                         NULL,
3672f4259b30SLisandro Dalcin                                         NULL,
36736fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3674f4259b30SLisandro Dalcin                                         NULL,
36754222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3676f4259b30SLisandro Dalcin                                         NULL,
3677f4259b30SLisandro Dalcin                                         NULL,
367887d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3679f4259b30SLisandro Dalcin                                         NULL,
3680d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
368199cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3682f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3683f4259b30SLisandro Dalcin                                         NULL,
3684f4259b30SLisandro Dalcin                                         NULL,
3685cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3686f4259b30SLisandro Dalcin                                         NULL,
36872af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3688f4259b30SLisandro Dalcin                                         NULL,
3689599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3690f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3691f4259b30SLisandro Dalcin                                         NULL,
3692f4259b30SLisandro Dalcin                                         NULL,
3693f4259b30SLisandro Dalcin                                         NULL,
3694f4259b30SLisandro Dalcin                                         NULL,
3695f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3696f4259b30SLisandro Dalcin                                         NULL,
3697f4259b30SLisandro Dalcin                                         NULL,
3698f4259b30SLisandro Dalcin                                         NULL,
3699b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
37000716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3701bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
370237868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
37030da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3704f4259b30SLisandro Dalcin                                         NULL,
3705f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3706f4259b30SLisandro Dalcin                                         NULL,
3707f4259b30SLisandro Dalcin                                         NULL,
370875648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3709b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3710b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
37112b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3712f4259b30SLisandro Dalcin                                         NULL,
3713f4259b30SLisandro Dalcin                                         NULL,
37143964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3715f4259b30SLisandro Dalcin                                  /*139*/NULL,
3716f4259b30SLisandro Dalcin                                         NULL,
3717f4259b30SLisandro Dalcin                                         NULL,
37183a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
37199c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
37204222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
37214222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3722f4259b30SLisandro Dalcin                                         NULL,
3723f4259b30SLisandro Dalcin                                         NULL
37249e29f15eSvictorle };
372517ab2063SBarry Smith 
37267087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3727bef8e0ddSBarry Smith {
3728bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
372997f1f81fSBarry Smith   PetscInt   i,nz,n;
3730bef8e0ddSBarry Smith 
3731bef8e0ddSBarry Smith   PetscFunctionBegin;
3732bef8e0ddSBarry Smith   nz = aij->maxnz;
3733d0f46423SBarry Smith   n  = mat->rmap->n;
3734bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3735bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3736bef8e0ddSBarry Smith   }
3737bef8e0ddSBarry Smith   aij->nz = nz;
3738bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3739bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3740bef8e0ddSBarry Smith   }
3741bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3742bef8e0ddSBarry Smith }
3743bef8e0ddSBarry Smith 
3744a3bb6f32SFande Kong /*
3745e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3746a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3747a3bb6f32SFande Kong  * */
3748a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3749a3bb6f32SFande Kong {
3750a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3751a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3752a3bb6f32SFande Kong   PetscTablePosition tpos;
375325b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
375425b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3755a3bb6f32SFande Kong   PetscErrorCode     ierr;
3756a3bb6f32SFande Kong 
3757a3bb6f32SFande Kong   PetscFunctionBegin;
3758a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3759a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3760a3bb6f32SFande Kong   /* use a table */
3761a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3762a3bb6f32SFande Kong   ec = 0;
376325b670f0SStefano Zampini   for (i=0; i<nz; i++) {
376425b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3765a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3766a3bb6f32SFande Kong     if (!data) {
3767a3bb6f32SFande Kong       /* one based table */
3768a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3769a3bb6f32SFande Kong     }
3770a3bb6f32SFande Kong   }
3771a3bb6f32SFande Kong   /* form array of columns we need */
3772a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3773a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3774a3bb6f32SFande Kong   while (tpos) {
3775a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3776a3bb6f32SFande Kong     gid--;
3777a3bb6f32SFande Kong     lid--;
3778a3bb6f32SFande Kong     garray[lid] = gid;
3779a3bb6f32SFande Kong   }
3780a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3781a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3782a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3783a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3784a3bb6f32SFande Kong   }
3785a3bb6f32SFande Kong   /* compact out the extra columns in B */
378625b670f0SStefano Zampini   for (i=0; i<nz; i++) {
378725b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3788a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3789a3bb6f32SFande Kong     lid--;
379025b670f0SStefano Zampini     jj[i] = lid;
3791a3bb6f32SFande Kong   }
3792ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3793a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
379425b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3795a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3796a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3797a3bb6f32SFande Kong   PetscFunctionReturn(0);
3798a3bb6f32SFande Kong }
3799a3bb6f32SFande Kong 
3800bef8e0ddSBarry Smith /*@
3801bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3802bef8e0ddSBarry Smith        in the matrix.
3803bef8e0ddSBarry Smith 
3804bef8e0ddSBarry Smith   Input Parameters:
3805bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3806bef8e0ddSBarry Smith -  indices - the column indices
3807bef8e0ddSBarry Smith 
380815091d37SBarry Smith   Level: advanced
380915091d37SBarry Smith 
3810bef8e0ddSBarry Smith   Notes:
3811bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3812bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3813bef8e0ddSBarry Smith   of the MatSetValues() operation.
3814bef8e0ddSBarry Smith 
3815bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3816d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3817bef8e0ddSBarry Smith 
3818bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3819bef8e0ddSBarry Smith 
3820b9617806SBarry Smith     The indices should start with zero, not one.
3821b9617806SBarry Smith 
3822bef8e0ddSBarry Smith @*/
38237087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3824bef8e0ddSBarry Smith {
38254ac538c5SBarry Smith   PetscErrorCode ierr;
3826bef8e0ddSBarry Smith 
3827bef8e0ddSBarry Smith   PetscFunctionBegin;
38280700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38294482741eSBarry Smith   PetscValidPointer(indices,2);
38304ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3831bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3832bef8e0ddSBarry Smith }
3833bef8e0ddSBarry Smith 
3834be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3835be6bf707SBarry Smith 
38367087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3837be6bf707SBarry Smith {
3838be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38396849ba73SBarry Smith   PetscErrorCode ierr;
3840d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3841be6bf707SBarry Smith 
3842be6bf707SBarry Smith   PetscFunctionBegin;
3843169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3844be6bf707SBarry Smith 
3845be6bf707SBarry Smith   /* allocate space for values if not already there */
3846be6bf707SBarry Smith   if (!aij->saved_values) {
3847854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38483bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3849be6bf707SBarry Smith   }
3850be6bf707SBarry Smith 
3851be6bf707SBarry Smith   /* copy values over */
3852580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3853be6bf707SBarry Smith   PetscFunctionReturn(0);
3854be6bf707SBarry Smith }
3855be6bf707SBarry Smith 
3856be6bf707SBarry Smith /*@
3857be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3858be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3859be6bf707SBarry Smith        nonlinear portion.
3860be6bf707SBarry Smith 
3861be6bf707SBarry Smith    Collect on Mat
3862be6bf707SBarry Smith 
3863be6bf707SBarry Smith   Input Parameters:
38640e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3865be6bf707SBarry Smith 
386615091d37SBarry Smith   Level: advanced
386715091d37SBarry Smith 
3868be6bf707SBarry Smith   Common Usage, with SNESSolve():
3869be6bf707SBarry Smith $    Create Jacobian matrix
3870be6bf707SBarry Smith $    Set linear terms into matrix
3871be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3872be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3873be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3874512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3875be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3876be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3877be6bf707SBarry Smith $    In your Jacobian routine
3878be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3879be6bf707SBarry Smith $      Set nonlinear terms in matrix
3880be6bf707SBarry Smith 
3881be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3882be6bf707SBarry Smith $    // build linear portion of Jacobian
3883512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3884be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3885be6bf707SBarry Smith $    loop over nonlinear iterations
3886be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3887be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3888be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3889be6bf707SBarry Smith $       Solve linear system with Jacobian
3890be6bf707SBarry Smith $    endloop
3891be6bf707SBarry Smith 
3892be6bf707SBarry Smith   Notes:
3893be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3894512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3895be6bf707SBarry Smith     calling this routine.
3896be6bf707SBarry Smith 
38970c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38980c468ba9SBarry Smith     and does not allocated additional space.
38990c468ba9SBarry Smith 
3900be6bf707SBarry Smith .seealso: MatRetrieveValues()
3901be6bf707SBarry Smith 
3902be6bf707SBarry Smith @*/
39037087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3904be6bf707SBarry Smith {
39054ac538c5SBarry Smith   PetscErrorCode ierr;
3906be6bf707SBarry Smith 
3907be6bf707SBarry Smith   PetscFunctionBegin;
39080700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3909e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3910e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39114ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3912be6bf707SBarry Smith   PetscFunctionReturn(0);
3913be6bf707SBarry Smith }
3914be6bf707SBarry Smith 
39157087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3916be6bf707SBarry Smith {
3917be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
39186849ba73SBarry Smith   PetscErrorCode ierr;
3919d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3920be6bf707SBarry Smith 
3921be6bf707SBarry Smith   PetscFunctionBegin;
3922169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3923f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3924be6bf707SBarry Smith   /* copy values over */
3925580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3926be6bf707SBarry Smith   PetscFunctionReturn(0);
3927be6bf707SBarry Smith }
3928be6bf707SBarry Smith 
3929be6bf707SBarry Smith /*@
3930be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3931be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3932be6bf707SBarry Smith        nonlinear portion.
3933be6bf707SBarry Smith 
3934be6bf707SBarry Smith    Collect on Mat
3935be6bf707SBarry Smith 
3936be6bf707SBarry Smith   Input Parameters:
3937386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3938be6bf707SBarry Smith 
393915091d37SBarry Smith   Level: advanced
394015091d37SBarry Smith 
3941be6bf707SBarry Smith .seealso: MatStoreValues()
3942be6bf707SBarry Smith 
3943be6bf707SBarry Smith @*/
39447087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3945be6bf707SBarry Smith {
39464ac538c5SBarry Smith   PetscErrorCode ierr;
3947be6bf707SBarry Smith 
3948be6bf707SBarry Smith   PetscFunctionBegin;
39490700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3950e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3951e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39524ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3953be6bf707SBarry Smith   PetscFunctionReturn(0);
3954be6bf707SBarry Smith }
3955be6bf707SBarry Smith 
3956f83d6046SBarry Smith 
3957be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
395817ab2063SBarry Smith /*@C
3959682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39600d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39616e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
396251c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39632bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
396417ab2063SBarry Smith 
3965d083f849SBarry Smith    Collective
3966db81eaa0SLois Curfman McInnes 
396717ab2063SBarry Smith    Input Parameters:
3968db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
396917ab2063SBarry Smith .  m - number of rows
397017ab2063SBarry Smith .  n - number of columns
397117ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
397251c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39730298fd71SBarry Smith          (possibly different for each row) or NULL
397417ab2063SBarry Smith 
397517ab2063SBarry Smith    Output Parameter:
3976416022c9SBarry Smith .  A - the matrix
397717ab2063SBarry Smith 
3978175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3979f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3980175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3981175b88e8SBarry Smith 
3982b259b22eSLois Curfman McInnes    Notes:
398349a6f317SBarry Smith    If nnz is given then nz is ignored
398449a6f317SBarry Smith 
398517ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
398617ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39870002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
398844cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
398917ab2063SBarry Smith 
399017ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39910298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39923d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39936da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
399417ab2063SBarry Smith 
3995682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39964fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3997682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39986c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39996c7ebb05SLois Curfman McInnes 
40006c7ebb05SLois Curfman McInnes    Options Database Keys:
4001698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
40029db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
400317ab2063SBarry Smith 
4004027ccd11SLois Curfman McInnes    Level: intermediate
4005027ccd11SLois Curfman McInnes 
400669b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
400736db0b34SBarry Smith 
400817ab2063SBarry Smith @*/
40097087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
401017ab2063SBarry Smith {
4011dfbe8321SBarry Smith   PetscErrorCode ierr;
40126945ee14SBarry Smith 
40133a40ed3dSBarry Smith   PetscFunctionBegin;
4014f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
4015117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
4016c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
4017d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
4018273d9f13SBarry Smith   PetscFunctionReturn(0);
4019273d9f13SBarry Smith }
4020273d9f13SBarry Smith 
4021273d9f13SBarry Smith /*@C
4022273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
4023273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
4024273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
4025273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
4026273d9f13SBarry Smith 
4027d083f849SBarry Smith    Collective
4028273d9f13SBarry Smith 
4029273d9f13SBarry Smith    Input Parameters:
40301c4f3114SJed Brown +  B - The matrix
4031273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
4032273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
40330298fd71SBarry Smith          (possibly different for each row) or NULL
4034273d9f13SBarry Smith 
4035273d9f13SBarry Smith    Notes:
403649a6f317SBarry Smith      If nnz is given then nz is ignored
403749a6f317SBarry Smith 
4038273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4039273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4040273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4041273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4042273d9f13SBarry Smith 
4043273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40440298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4045273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4046273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4047273d9f13SBarry Smith 
4048aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4049aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4050aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4051aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4052aa95bbe8SBarry Smith 
4053a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4054a96a251dSBarry Smith    entries or columns indices
4055a96a251dSBarry Smith 
4056273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4057273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4058273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4059273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4060273d9f13SBarry Smith 
4061273d9f13SBarry Smith    Options Database Keys:
4062698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
406347b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4064273d9f13SBarry Smith 
4065273d9f13SBarry Smith    Level: intermediate
4066273d9f13SBarry Smith 
406719b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
406819b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4069273d9f13SBarry Smith 
4070273d9f13SBarry Smith @*/
40717087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4072273d9f13SBarry Smith {
40734ac538c5SBarry Smith   PetscErrorCode ierr;
4074a23d5eceSKris Buschelman 
4075a23d5eceSKris Buschelman   PetscFunctionBegin;
40766ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40776ba663aaSJed Brown   PetscValidType(B,1);
40784ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4079a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4080a23d5eceSKris Buschelman }
4081a23d5eceSKris Buschelman 
40827087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4083a23d5eceSKris Buschelman {
4084273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40852576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40866849ba73SBarry Smith   PetscErrorCode ierr;
408797f1f81fSBarry Smith   PetscInt       i;
4088273d9f13SBarry Smith 
4089273d9f13SBarry Smith   PetscFunctionBegin;
40902576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4091a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4092c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4093c461c341SBarry Smith     nz             = 0;
4094c461c341SBarry Smith   }
409526283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
409626283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4097899cda47SBarry Smith 
4098435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
409960e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4100cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4101d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
410260e0710aSBarry 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]);
410360e0710aSBarry 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);
4104b73539f3SBarry Smith     }
4105b73539f3SBarry Smith   }
4106b73539f3SBarry Smith 
4107273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
41082205254eSKarl Rupp 
4109273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4110273d9f13SBarry Smith 
4111ab93d7beSBarry Smith   if (!skipallocation) {
41122ee49352SLisandro Dalcin     if (!b->imax) {
4113071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4114071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4115071fcb05SBarry Smith     }
4116071fcb05SBarry Smith     if (!b->ilen) {
4117071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4118071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4119071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4120071fcb05SBarry Smith     } else {
4121071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
41222ee49352SLisandro Dalcin     }
4123846b4da1SFande Kong     if (!b->ipre) {
4124846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4125846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4126846b4da1SFande Kong     }
4127273d9f13SBarry Smith     if (!nnz) {
4128435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4129c62bd62aSJed Brown       else if (nz < 0) nz = 1;
41305d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4131d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4132d0f46423SBarry Smith       nz = nz*B->rmap->n;
4133273d9f13SBarry Smith     } else {
4134c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4135c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4136c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4137273d9f13SBarry Smith     }
4138ab93d7beSBarry Smith 
4139273d9f13SBarry Smith     /* allocate the matrix space */
414053dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41412ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4142396832f4SHong Zhang     if (B->structure_only) {
41435848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41445848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4145396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4146396832f4SHong Zhang     } else {
4147dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41483bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4149396832f4SHong Zhang     }
4150bfeeae90SHong Zhang     b->i[0] = 0;
4151d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41525da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41535da197adSKris Buschelman     }
4154396832f4SHong Zhang     if (B->structure_only) {
4155396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4156396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4157396832f4SHong Zhang     } else {
4158273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4159e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4160396832f4SHong Zhang     }
4161e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4162c461c341SBarry Smith   } else {
4163e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4164e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4165c461c341SBarry Smith   }
4166273d9f13SBarry Smith 
4167846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4168846b4da1SFande Kong     /* reserve user-requested sparsity */
4169580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4170846b4da1SFande Kong   }
4171846b4da1SFande Kong 
4172846b4da1SFande Kong 
4173273d9f13SBarry Smith   b->nz               = 0;
4174273d9f13SBarry Smith   b->maxnz            = nz;
4175273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41762205254eSKarl Rupp   if (realalloc) {
41772205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41782205254eSKarl Rupp   }
4179cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4180cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4181273d9f13SBarry Smith   PetscFunctionReturn(0);
4182273d9f13SBarry Smith }
4183273d9f13SBarry Smith 
4184846b4da1SFande Kong 
4185846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4186846b4da1SFande Kong {
4187846b4da1SFande Kong   Mat_SeqAIJ     *a;
4188a5bbaf83SFande Kong   PetscInt       i;
4189846b4da1SFande Kong   PetscErrorCode ierr;
4190846b4da1SFande Kong 
4191846b4da1SFande Kong   PetscFunctionBegin;
4192846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
419314d0e64fSAlex Lindsay 
419414d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
419514d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
419614d0e64fSAlex Lindsay 
4197846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41982c814fdeSFande Kong   /* if no saved info, we error out */
4199fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
42002c814fdeSFande Kong 
4201fb4dc15dSAlex 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");
42022c814fdeSFande Kong 
4203580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4204580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4205846b4da1SFande Kong   a->i[0] = 0;
4206846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4207846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4208846b4da1SFande Kong   }
4209846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4210846b4da1SFande Kong   a->nz               = 0;
4211846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4212846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4213846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4214846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4215846b4da1SFande Kong   PetscFunctionReturn(0);
4216846b4da1SFande Kong }
4217846b4da1SFande Kong 
421858d36128SBarry Smith /*@
4219a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4220a1661176SMatthew Knepley 
4221a1661176SMatthew Knepley    Input Parameters:
4222a1661176SMatthew Knepley +  B - the matrix
4223a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4224a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4225a1661176SMatthew Knepley -  v - optional values in the matrix
4226a1661176SMatthew Knepley 
4227a1661176SMatthew Knepley    Level: developer
4228a1661176SMatthew Knepley 
42296a9b8d82SBarry Smith    Notes:
423058d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
423158d36128SBarry Smith 
42326a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
42336a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
42346a9b8d82SBarry Smith 
42356a9b8d82SBarry Smith     Developer Notes:
42366a9b8d82SBarry 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
42376a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
42386a9b8d82SBarry Smith 
42396a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
42406a9b8d82SBarry Smith 
42416a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4242a1661176SMatthew Knepley @*/
4243a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4244a1661176SMatthew Knepley {
4245a1661176SMatthew Knepley   PetscErrorCode ierr;
4246a1661176SMatthew Knepley 
4247a1661176SMatthew Knepley   PetscFunctionBegin;
42480700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42496ba663aaSJed Brown   PetscValidType(B,1);
42504ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4251a1661176SMatthew Knepley   PetscFunctionReturn(0);
4252a1661176SMatthew Knepley }
4253a1661176SMatthew Knepley 
42547087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4255a1661176SMatthew Knepley {
4256a1661176SMatthew Knepley   PetscInt       i;
4257a1661176SMatthew Knepley   PetscInt       m,n;
4258a1661176SMatthew Knepley   PetscInt       nz;
42596a9b8d82SBarry Smith   PetscInt       *nnz;
4260a1661176SMatthew Knepley   PetscErrorCode ierr;
4261a1661176SMatthew Knepley 
4262a1661176SMatthew Knepley   PetscFunctionBegin;
426365e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4264779a8d59SSatish Balay 
4265779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4266779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4267779a8d59SSatish Balay 
4268779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4269854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4270a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4271b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
427265e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4273a1661176SMatthew Knepley     nnz[i] = nz;
4274a1661176SMatthew Knepley   }
4275a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4276a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4277a1661176SMatthew Knepley 
4278a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4279071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4280a1661176SMatthew Knepley   }
4281a1661176SMatthew Knepley 
4282a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4283a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4284a1661176SMatthew Knepley 
42857827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4286a1661176SMatthew Knepley   PetscFunctionReturn(0);
4287a1661176SMatthew Knepley }
4288a1661176SMatthew Knepley 
4289c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4290af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4291170fe5c8SBarry Smith 
4292170fe5c8SBarry Smith /*
4293170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4294170fe5c8SBarry Smith 
4295170fe5c8SBarry Smith                n                       p                          p
42962da392ccSBarry Smith         [             ]       [             ]         [                 ]
42972da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
42982da392ccSBarry Smith         [             ]       [             ]         [                 ]
4299170fe5c8SBarry Smith 
4300170fe5c8SBarry Smith */
4301170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4302170fe5c8SBarry Smith {
4303170fe5c8SBarry Smith   PetscErrorCode    ierr;
4304170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4305170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4306170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
430786214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4308170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4309170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4310170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
431186214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
431286214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4313170fe5c8SBarry Smith 
4314170fe5c8SBarry Smith   PetscFunctionBegin;
4315d0f46423SBarry Smith   m    = A->rmap->n;
4316d0f46423SBarry Smith   n    = A->cmap->n;
4317d0f46423SBarry Smith   p    = B->cmap->n;
4318170fe5c8SBarry Smith   a    = sub_a->v;
4319170fe5c8SBarry Smith   b    = sub_b->a;
4320170fe5c8SBarry Smith   c    = sub_c->v;
432186214ceeSStefano Zampini   if (clda == m) {
4322580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
432386214ceeSStefano Zampini   } else {
432486214ceeSStefano Zampini     for (j=0;j<p;j++)
432586214ceeSStefano Zampini       for (i=0;i<m;i++)
432686214ceeSStefano Zampini         c[j*clda + i] = 0.0;
432786214ceeSStefano Zampini   }
4328170fe5c8SBarry Smith   ii  = sub_b->i;
4329170fe5c8SBarry Smith   idx = sub_b->j;
4330170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4331170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4332170fe5c8SBarry Smith     while (q-->0) {
433386214ceeSStefano Zampini       c_q = c + clda*(*idx);
433486214ceeSStefano Zampini       a_q = a + alda*i;
4335854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4336170fe5c8SBarry Smith       idx++;
4337170fe5c8SBarry Smith       b++;
4338170fe5c8SBarry Smith     }
4339170fe5c8SBarry Smith   }
4340170fe5c8SBarry Smith   PetscFunctionReturn(0);
4341170fe5c8SBarry Smith }
4342170fe5c8SBarry Smith 
43434222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4344170fe5c8SBarry Smith {
4345170fe5c8SBarry Smith   PetscErrorCode ierr;
4346d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
434786214ceeSStefano Zampini   PetscBool      cisdense;
4348170fe5c8SBarry Smith 
4349170fe5c8SBarry Smith   PetscFunctionBegin;
435060e0710aSBarry 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);
43514222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
43524222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
435386214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
435486214ceeSStefano Zampini   if (!cisdense) {
435586214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
435686214ceeSStefano Zampini   }
435786214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4358d73949e8SHong Zhang 
43594222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4360170fe5c8SBarry Smith   PetscFunctionReturn(0);
4361170fe5c8SBarry Smith }
4362170fe5c8SBarry Smith 
4363170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
43640bad9183SKris Buschelman /*MC
4365fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
43660bad9183SKris Buschelman    based on compressed sparse row format.
43670bad9183SKris Buschelman 
43680bad9183SKris Buschelman    Options Database Keys:
43690bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
43700bad9183SKris Buschelman 
43710bad9183SKris Buschelman    Level: beginner
43720bad9183SKris Buschelman 
43730cd7f59aSBarry Smith    Notes:
43740cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
43750cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
43760cd7f59aSBarry Smith     in the matrix
43770cd7f59aSBarry Smith 
43780cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
43790cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
43800cd7f59aSBarry Smith 
43810cd7f59aSBarry Smith   Developer Notes:
43820cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
43830cd7f59aSBarry Smith 
4384f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
43850bad9183SKris Buschelman M*/
43860bad9183SKris Buschelman 
4387ccd284c7SBarry Smith /*MC
4388ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4389ccd284c7SBarry Smith 
4390ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4391ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
43920cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4393ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4394ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4395ccd284c7SBarry Smith 
4396ccd284c7SBarry Smith    Options Database Keys:
4397ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4398ccd284c7SBarry Smith 
439995452b02SPatrick Sanan   Developer Notes:
4400ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4401ccd284c7SBarry Smith    enough exist.
4402ccd284c7SBarry Smith 
4403ccd284c7SBarry Smith   Level: beginner
4404ccd284c7SBarry Smith 
4405ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4406ccd284c7SBarry Smith M*/
4407ccd284c7SBarry Smith 
4408ccd284c7SBarry Smith /*MC
4409ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4410ccd284c7SBarry Smith 
4411ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4412ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4413ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4414ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4415ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4416ccd284c7SBarry Smith 
4417ccd284c7SBarry Smith    Options Database Keys:
4418ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4419ccd284c7SBarry Smith 
4420ccd284c7SBarry Smith   Level: beginner
4421ccd284c7SBarry Smith 
4422ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4423ccd284c7SBarry Smith M*/
4424ccd284c7SBarry Smith 
44257906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
44267906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
44277906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
44287906f579SHong Zhang #endif
4429d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4430d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4431d24d4204SJose E. Roman #endif
44327906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
44337906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
44347906f579SHong Zhang #endif
44357906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
44367906f579SHong Zhang 
4437d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4438c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
44394222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
44407906f579SHong Zhang 
44418c778c55SBarry Smith /*@C
44428f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
44438c778c55SBarry Smith 
44448c778c55SBarry Smith    Not Collective
44458c778c55SBarry Smith 
44468c778c55SBarry Smith    Input Parameter:
4447579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
44488c778c55SBarry Smith 
44498c778c55SBarry Smith    Output Parameter:
44508c778c55SBarry Smith .   array - pointer to the data
44518c778c55SBarry Smith 
44528c778c55SBarry Smith    Level: intermediate
44538c778c55SBarry Smith 
4454774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
44558c778c55SBarry Smith @*/
44568c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
44578c778c55SBarry Smith {
44588c778c55SBarry Smith   PetscErrorCode ierr;
44598c778c55SBarry Smith 
44608c778c55SBarry Smith   PetscFunctionBegin;
44618c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
44622e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
44632e5835c6SStefano Zampini   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
44642e5835c6SStefano Zampini #endif
44658c778c55SBarry Smith   PetscFunctionReturn(0);
44668c778c55SBarry Smith }
44678c778c55SBarry Smith 
446821e72a00SBarry Smith /*@C
44698f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
44708f1ea47aSStefano Zampini 
44718f1ea47aSStefano Zampini    Not Collective
44728f1ea47aSStefano Zampini 
44738f1ea47aSStefano Zampini    Input Parameter:
44748f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44758f1ea47aSStefano Zampini 
44768f1ea47aSStefano Zampini    Output Parameter:
44778f1ea47aSStefano Zampini .   array - pointer to the data
44788f1ea47aSStefano Zampini 
44798f1ea47aSStefano Zampini    Level: intermediate
44808f1ea47aSStefano Zampini 
44818f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
44828f1ea47aSStefano Zampini @*/
44838f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
44848f1ea47aSStefano Zampini {
44858c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4486c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44878f1ea47aSStefano Zampini #endif
44888f1ea47aSStefano Zampini   PetscErrorCode ierr;
44898f1ea47aSStefano Zampini 
44908f1ea47aSStefano Zampini   PetscFunctionBegin;
44918c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4492c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44938f1ea47aSStefano Zampini #endif
44948f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44958c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4496c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
44978f1ea47aSStefano Zampini #endif
44988f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44998f1ea47aSStefano Zampini }
45008f1ea47aSStefano Zampini 
45018f1ea47aSStefano Zampini /*@C
45028f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
45038f1ea47aSStefano Zampini 
45048f1ea47aSStefano Zampini    Not Collective
45058f1ea47aSStefano Zampini 
45068f1ea47aSStefano Zampini    Input Parameter:
45078f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45088f1ea47aSStefano Zampini 
45098f1ea47aSStefano Zampini    Output Parameter:
45108f1ea47aSStefano Zampini .   array - pointer to the data
45118f1ea47aSStefano Zampini 
45128f1ea47aSStefano Zampini    Level: intermediate
45138f1ea47aSStefano Zampini 
45148f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
45158f1ea47aSStefano Zampini @*/
45168f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
45178f1ea47aSStefano Zampini {
45188c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4519c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
45208f1ea47aSStefano Zampini #endif
45218f1ea47aSStefano Zampini   PetscErrorCode ierr;
45228f1ea47aSStefano Zampini 
45238f1ea47aSStefano Zampini   PetscFunctionBegin;
45248c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4525c70f7ee4SJunchao Zhang   oval = A->offloadmask;
45268f1ea47aSStefano Zampini #endif
45278f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
45288c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4529c70f7ee4SJunchao Zhang   A->offloadmask = oval;
45308f1ea47aSStefano Zampini #endif
45318f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45328f1ea47aSStefano Zampini }
45338f1ea47aSStefano Zampini 
45348f1ea47aSStefano Zampini /*@C
453521e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
453621e72a00SBarry Smith 
453721e72a00SBarry Smith    Not Collective
453821e72a00SBarry Smith 
453921e72a00SBarry Smith    Input Parameter:
4540579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
454121e72a00SBarry Smith 
454221e72a00SBarry Smith    Output Parameter:
454321e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
454421e72a00SBarry Smith 
454521e72a00SBarry Smith    Level: intermediate
454621e72a00SBarry Smith 
454721e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
454821e72a00SBarry Smith @*/
454921e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
455021e72a00SBarry Smith {
455121e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
455221e72a00SBarry Smith 
455321e72a00SBarry Smith   PetscFunctionBegin;
455421e72a00SBarry Smith   *nz = aij->rmax;
455521e72a00SBarry Smith   PetscFunctionReturn(0);
455621e72a00SBarry Smith }
455721e72a00SBarry Smith 
45588c778c55SBarry Smith /*@C
4559579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
45608c778c55SBarry Smith 
45618c778c55SBarry Smith    Not Collective
45628c778c55SBarry Smith 
45638c778c55SBarry Smith    Input Parameters:
4564a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4565a2b725a8SWilliam Gropp -  array - pointer to the data
45668c778c55SBarry Smith 
45678c778c55SBarry Smith    Level: intermediate
45688c778c55SBarry Smith 
4569774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
45708c778c55SBarry Smith @*/
45718c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
45728c778c55SBarry Smith {
45738c778c55SBarry Smith   PetscErrorCode ierr;
45748c778c55SBarry Smith 
45758c778c55SBarry Smith   PetscFunctionBegin;
45768c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
45778c778c55SBarry Smith   PetscFunctionReturn(0);
45788c778c55SBarry Smith }
45798c778c55SBarry Smith 
458034b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
45810ce8acdeSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
458202fe1965SBarry Smith #endif
45833d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
45843d0639e7SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat);
45853d0639e7SStefano Zampini #endif
458602fe1965SBarry Smith 
45878cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4588273d9f13SBarry Smith {
4589273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4590dfbe8321SBarry Smith   PetscErrorCode ierr;
459138baddfdSBarry Smith   PetscMPIInt    size;
4592273d9f13SBarry Smith 
4593273d9f13SBarry Smith   PetscFunctionBegin;
4594ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
4595e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4596273d9f13SBarry Smith 
4597b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
45982205254eSKarl Rupp 
4599b0a32e0cSBarry Smith   B->data = (void*)b;
46002205254eSKarl Rupp 
4601549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4602071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
46032205254eSKarl Rupp 
4604f4259b30SLisandro Dalcin   b->row                = NULL;
4605f4259b30SLisandro Dalcin   b->col                = NULL;
4606f4259b30SLisandro Dalcin   b->icol               = NULL;
4607b810aeb4SBarry Smith   b->reallocs           = 0;
460836db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4609f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4610416022c9SBarry Smith   b->nonew              = 0;
4611f4259b30SLisandro Dalcin   b->diag               = NULL;
4612f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4613f4259b30SLisandro Dalcin   B->spptr              = NULL;
4614f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4615f4259b30SLisandro Dalcin   b->idiag              = NULL;
4616f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4617f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
461871f1c65dSBarry Smith   b->omega              = 1.0;
461971f1c65dSBarry Smith   b->fshift             = 0.0;
462071f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4621bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4622a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
462317ab2063SBarry Smith 
462435d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4625bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4626bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
46278c778c55SBarry Smith 
4628b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4629bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4630bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4631b3866ffcSBarry Smith #endif
463217f1a0eaSHong Zhang 
4633bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4634bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4635bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4636bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4637bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4638bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
46394dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
46409779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
46414a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4642191b95cbSRichard Tran Mills #endif
464334b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
464402fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
46454222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4646fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
464702fe1965SBarry Smith #endif
46483d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
46493d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
46503d0639e7SStefano Zampini #endif
4651bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4652af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4653af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4654af8000cdSHong Zhang #endif
4655d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4656d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4657d24d4204SJose E. Roman #endif
465863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
465963c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
46604222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
466163c07aadSStefano Zampini #endif
4662b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4663d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4664c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4665bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4666bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4667bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4668846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4669bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4670bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
46714222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
46724222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
46734222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
46744108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
467517667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
46764099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
46773a40ed3dSBarry Smith   PetscFunctionReturn(0);
467817ab2063SBarry Smith }
467917ab2063SBarry Smith 
4680b24902e0SBarry Smith /*
4681b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4682b24902e0SBarry Smith */
4683ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
468417ab2063SBarry Smith {
46852a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
46866849ba73SBarry Smith   PetscErrorCode ierr;
4687071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
468817ab2063SBarry Smith 
46893a40ed3dSBarry Smith   PetscFunctionBegin;
4690ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4691273d9f13SBarry Smith 
4692d5f3da31SBarry Smith   C->factortype = A->factortype;
4693f4259b30SLisandro Dalcin   c->row        = NULL;
4694f4259b30SLisandro Dalcin   c->col        = NULL;
4695f4259b30SLisandro Dalcin   c->icol       = NULL;
46966ad4291fSHong Zhang   c->reallocs   = 0;
469717ab2063SBarry Smith 
46986ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
469917ab2063SBarry Smith 
4700aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4701aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4702eec197d1SBarry Smith 
4703071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4704071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4705071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4706071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
47073bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
470817ab2063SBarry Smith 
470917ab2063SBarry Smith   /* allocate the matrix space */
4710f77e22a1SHong Zhang   if (mallocmatspace) {
4711dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
47123bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
47132205254eSKarl Rupp 
4714f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
47152205254eSKarl Rupp 
4716580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
471717ab2063SBarry Smith     if (m > 0) {
4718580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4719be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
47202e5835c6SStefano Zampini         const PetscScalar *aa;
47212e5835c6SStefano Zampini 
47222e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
47232e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
47242e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4725be6bf707SBarry Smith       } else {
4726580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
472717ab2063SBarry Smith       }
472808480c60SBarry Smith     }
4729f77e22a1SHong Zhang   }
473017ab2063SBarry Smith 
47316ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4732416022c9SBarry Smith   c->roworiented       = a->roworiented;
4733416022c9SBarry Smith   c->nonew             = a->nonew;
4734416022c9SBarry Smith   if (a->diag) {
4735854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4736071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
47373bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4738071fcb05SBarry Smith   } else c->diag = NULL;
47392205254eSKarl Rupp 
4740f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4741f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4742f4259b30SLisandro Dalcin   c->idiag              = NULL;
4743f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4744a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4745e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4746e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
47476ad4291fSHong Zhang 
4748893ad86cSHong Zhang   c->rmax         = a->rmax;
4749416022c9SBarry Smith   c->nz           = a->nz;
47508ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4751273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4752754ec7b1SSatish Balay 
47536ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
47546ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4755cd6b891eSBarry Smith   if (a->compressedrow.use) {
47566ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4757dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4758580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4759580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
476027ea64f8SHong Zhang   } else {
476127ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
47620298fd71SBarry Smith     c->compressedrow.i      = NULL;
47630298fd71SBarry Smith     c->compressedrow.rindex = NULL;
47646ad4291fSHong Zhang   }
4765ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4766e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
47674846f1f5SKris Buschelman 
47682205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4769140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
47703a40ed3dSBarry Smith   PetscFunctionReturn(0);
477117ab2063SBarry Smith }
477217ab2063SBarry Smith 
4773b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4774b24902e0SBarry Smith {
4775b24902e0SBarry Smith   PetscErrorCode ierr;
4776b24902e0SBarry Smith 
4777b24902e0SBarry Smith   PetscFunctionBegin;
4778ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
47794b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4780cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
478133d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4782cfd3f464SBarry Smith   }
4783a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4784f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4785b24902e0SBarry Smith   PetscFunctionReturn(0);
4786b24902e0SBarry Smith }
4787b24902e0SBarry Smith 
4788112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4789fbdbba38SShri Abhyankar {
479052f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
479152f91c60SVaclav Hapla   PetscErrorCode ierr;
479252f91c60SVaclav Hapla 
479352f91c60SVaclav Hapla   PetscFunctionBegin;
479452f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
479552f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4796c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4797c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
479852f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
479952f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
480052f91c60SVaclav Hapla   if (isbinary) {
480152f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
480252f91c60SVaclav Hapla   } else if (ishdf5) {
480352f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
480452f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
480552f91c60SVaclav Hapla #else
480652f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
480752f91c60SVaclav Hapla #endif
480852f91c60SVaclav Hapla   } else {
480952f91c60SVaclav 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);
481052f91c60SVaclav Hapla   }
481152f91c60SVaclav Hapla   PetscFunctionReturn(0);
481252f91c60SVaclav Hapla }
481352f91c60SVaclav Hapla 
48143ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
481552f91c60SVaclav Hapla {
48163ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4817fbdbba38SShri Abhyankar   PetscErrorCode ierr;
48183ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4819fbdbba38SShri Abhyankar 
4820fbdbba38SShri Abhyankar   PetscFunctionBegin;
48213ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4822bbead8a2SBarry Smith 
48233ea6fe3dSLisandro Dalcin   /* read in matrix header */
48243ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
48253ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4826fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
48273ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
48283ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4829bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4830fbdbba38SShri Abhyankar 
48313ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
48323ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
48333ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
48343ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
48353ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
48363ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
48373ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
48383ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
48393ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
48403ea6fe3dSLisandro Dalcin 
48413ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
48423ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
48433ea6fe3dSLisandro 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);
48443ea6fe3dSLisandro Dalcin 
4845fbdbba38SShri Abhyankar   /* read in row lengths */
48463ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
48473ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
48483ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
48493ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
48503ea6fe3dSLisandro 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);
48513ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
48523ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
48533ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
485460e0710aSBarry 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);
48553ea6fe3dSLisandro Dalcin   /* store row lengths */
48563ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
48573ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4858fbdbba38SShri Abhyankar 
48593ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
48603ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
48613ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
48623ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
48633ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
48643ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4865fbdbba38SShri Abhyankar 
48663ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
48673ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4868fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4869fbdbba38SShri Abhyankar }
4870fbdbba38SShri Abhyankar 
4871ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
48727264ac53SSatish Balay {
48737264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4874dfbe8321SBarry Smith   PetscErrorCode ierr;
4875eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4876eeffb40dSHong Zhang   PetscInt k;
4877eeffb40dSHong Zhang #endif
48787264ac53SSatish Balay 
48793a40ed3dSBarry Smith   PetscFunctionBegin;
4880bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4881d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4882ca44d042SBarry Smith     *flg = PETSC_FALSE;
4883ca44d042SBarry Smith     PetscFunctionReturn(0);
4884bcd2baecSBarry Smith   }
48857264ac53SSatish Balay 
48867264ac53SSatish Balay   /* if the a->i are the same */
4887580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4888abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
48897264ac53SSatish Balay 
48907264ac53SSatish Balay   /* if a->j are the same */
4891580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4892abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4893bcd2baecSBarry Smith 
4894bcd2baecSBarry Smith   /* if a->a are the same */
4895eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4896eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4897eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4898eeffb40dSHong Zhang       *flg = PETSC_FALSE;
48993a40ed3dSBarry Smith       PetscFunctionReturn(0);
4900eeffb40dSHong Zhang     }
4901eeffb40dSHong Zhang   }
4902eeffb40dSHong Zhang #else
4903580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4904eeffb40dSHong Zhang #endif
4905eeffb40dSHong Zhang   PetscFunctionReturn(0);
49067264ac53SSatish Balay }
490736db0b34SBarry Smith 
490805869f15SSatish Balay /*@
490936db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
491036db0b34SBarry Smith               provided by the user.
491136db0b34SBarry Smith 
4912d083f849SBarry Smith       Collective
491336db0b34SBarry Smith 
491436db0b34SBarry Smith    Input Parameters:
491536db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
491636db0b34SBarry Smith .   m - number of rows
491736db0b34SBarry Smith .   n - number of columns
4918483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
491936db0b34SBarry Smith .   j - column indices
492036db0b34SBarry Smith -   a - matrix values
492136db0b34SBarry Smith 
492236db0b34SBarry Smith    Output Parameter:
492336db0b34SBarry Smith .   mat - the matrix
492436db0b34SBarry Smith 
492536db0b34SBarry Smith    Level: intermediate
492636db0b34SBarry Smith 
492736db0b34SBarry Smith    Notes:
49280551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4929292fb18eSBarry Smith     once the matrix is destroyed and not before
493036db0b34SBarry Smith 
493136db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
493236db0b34SBarry Smith 
4933bfeeae90SHong Zhang        The i and j indices are 0 based
493436db0b34SBarry Smith 
4935a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4936a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
49378eef79e4SBarry Smith     as shown
4938a4552177SSatish Balay 
49398eef79e4SBarry Smith $        1 0 0
49408eef79e4SBarry Smith $        2 0 3
49418eef79e4SBarry Smith $        4 5 6
49428eef79e4SBarry Smith $
49438eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
49448eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
49458eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4946a4552177SSatish Balay 
49479985e31cSBarry Smith 
494869b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
494936db0b34SBarry Smith 
495036db0b34SBarry Smith @*/
4951c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
495236db0b34SBarry Smith {
4953dfbe8321SBarry Smith   PetscErrorCode ierr;
4954cbcfb4deSHong Zhang   PetscInt       ii;
495536db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4956cbcfb4deSHong Zhang   PetscInt jj;
495736db0b34SBarry Smith 
495836db0b34SBarry Smith   PetscFunctionBegin;
495941096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4960f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4961f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4962a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4963ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4964f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
4965ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4966071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4967071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4968ab93d7beSBarry Smith 
496936db0b34SBarry Smith   aij->i            = i;
497036db0b34SBarry Smith   aij->j            = j;
497136db0b34SBarry Smith   aij->a            = a;
497236db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
497336db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4974e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4975e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
497636db0b34SBarry Smith 
497736db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
497836db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
497976bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
498060e0710aSBarry 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]);
49819985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4982a061629eSStefano 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);
4983a061629eSStefano 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);
49849985e31cSBarry Smith       }
498536db0b34SBarry Smith     }
498676bd3646SJed Brown   }
498776bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
498836db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
498960e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
499060e0710aSBarry 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]);
499136db0b34SBarry Smith     }
499276bd3646SJed Brown   }
499336db0b34SBarry Smith 
4994b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4995b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
499636db0b34SBarry Smith   PetscFunctionReturn(0);
499736db0b34SBarry Smith }
499880ef6e79SMatthew G Knepley /*@C
4999d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
50008a0b0e6bSVictor Minden               provided by the user.
50018a0b0e6bSVictor Minden 
5002d083f849SBarry Smith       Collective
50038a0b0e6bSVictor Minden 
50048a0b0e6bSVictor Minden    Input Parameters:
50058a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
50068a0b0e6bSVictor Minden .   m   - number of rows
50078a0b0e6bSVictor Minden .   n   - number of columns
50088a0b0e6bSVictor Minden .   i   - row indices
50098a0b0e6bSVictor Minden .   j   - column indices
50101230e6d1SVictor Minden .   a   - matrix values
50111230e6d1SVictor Minden .   nz  - number of nonzeros
50121230e6d1SVictor Minden -   idx - 0 or 1 based
50138a0b0e6bSVictor Minden 
50148a0b0e6bSVictor Minden    Output Parameter:
50158a0b0e6bSVictor Minden .   mat - the matrix
50168a0b0e6bSVictor Minden 
50178a0b0e6bSVictor Minden    Level: intermediate
50188a0b0e6bSVictor Minden 
50198a0b0e6bSVictor Minden    Notes:
50208a0b0e6bSVictor Minden        The i and j indices are 0 based
50218a0b0e6bSVictor Minden 
50228a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
50238a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
50248a0b0e6bSVictor Minden     as shown:
50258a0b0e6bSVictor Minden 
50268a0b0e6bSVictor Minden         1 0 0
50278a0b0e6bSVictor Minden         2 0 3
50288a0b0e6bSVictor Minden         4 5 6
50298a0b0e6bSVictor Minden 
50308a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
50318a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
50328a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
50338a0b0e6bSVictor Minden 
50348a0b0e6bSVictor Minden 
503569b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
50368a0b0e6bSVictor Minden 
50378a0b0e6bSVictor Minden @*/
5038c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
50398a0b0e6bSVictor Minden {
50408a0b0e6bSVictor Minden   PetscErrorCode ierr;
5041d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
50428a0b0e6bSVictor Minden 
50438a0b0e6bSVictor Minden 
50448a0b0e6bSVictor Minden   PetscFunctionBegin;
50451795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
50461230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5047c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
50481230e6d1SVictor Minden   }
50498a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
50508a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
50518a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
50521230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
50531230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
50541230e6d1SVictor Minden     if (idx) {
50551230e6d1SVictor Minden       row = i[ii] - 1;
50561230e6d1SVictor Minden       col = j[ii] - 1;
50571230e6d1SVictor Minden     } else {
50581230e6d1SVictor Minden       row = i[ii];
50591230e6d1SVictor Minden       col = j[ii];
50608a0b0e6bSVictor Minden     }
50611230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
50628a0b0e6bSVictor Minden   }
50638a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
50648a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5065d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
50668a0b0e6bSVictor Minden   PetscFunctionReturn(0);
50678a0b0e6bSVictor Minden }
506836db0b34SBarry Smith 
5069acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5070acf2f550SJed Brown {
5071acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5072acf2f550SJed Brown   PetscErrorCode ierr;
5073acf2f550SJed Brown 
5074acf2f550SJed Brown   PetscFunctionBegin;
5075acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5076acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
50772205254eSKarl Rupp 
5078acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5079acf2f550SJed Brown   PetscFunctionReturn(0);
5080acf2f550SJed Brown }
5081acf2f550SJed Brown 
50829c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
50839c8f2541SHong Zhang {
50849c8f2541SHong Zhang   PetscErrorCode ierr;
50858761c3d6SHong Zhang   PetscMPIInt    size;
50869c8f2541SHong Zhang 
50879c8f2541SHong Zhang   PetscFunctionBegin;
5088ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
50897bbdc51dSHong Zhang   if (size == 1) {
50907bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
50917bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
50927bbdc51dSHong Zhang     } else {
50938761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
50947bbdc51dSHong Zhang     }
50958761c3d6SHong Zhang   } else {
50969c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
50978761c3d6SHong Zhang   }
50989c8f2541SHong Zhang   PetscFunctionReturn(0);
50999c8f2541SHong Zhang }
51009c8f2541SHong Zhang 
510181824310SBarry Smith /*
510253dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
510353dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
510453dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
510553dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
510653dd7562SDmitry Karpeev  */
510753dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
510853dd7562SDmitry Karpeev {
510953dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
511053dd7562SDmitry Karpeev   PetscErrorCode ierr;
511153dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
511253dd7562SDmitry Karpeev   PetscBool      seqaij;
511353dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
511453dd7562SDmitry Karpeev   PetscScalar    v;
511553dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
511653dd7562SDmitry Karpeev 
511753dd7562SDmitry Karpeev   PetscFunctionBegin;
511853dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
511953dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
51204099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
512153dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
512253dd7562SDmitry Karpeev   if (rowemb) {
512353dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
512453dd7562SDmitry 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);
512553dd7562SDmitry Karpeev   } else {
51266c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
512753dd7562SDmitry Karpeev   }
512853dd7562SDmitry Karpeev   if (colemb) {
512953dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
513053dd7562SDmitry 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);
513153dd7562SDmitry Karpeev   } else {
513253dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
513353dd7562SDmitry Karpeev   }
513453dd7562SDmitry Karpeev 
513553dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
513653dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
513753dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
513853dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
513953dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
514053dd7562SDmitry Karpeev     }
514153dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
514253dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
514353dd7562SDmitry Karpeev   }
514453dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
514553dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
514653dd7562SDmitry Karpeev   }
514753dd7562SDmitry Karpeev   count = 0;
514853dd7562SDmitry Karpeev   rowindices = NULL;
514953dd7562SDmitry Karpeev   colindices = NULL;
515053dd7562SDmitry Karpeev   if (rowemb) {
515153dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
515253dd7562SDmitry Karpeev   }
515353dd7562SDmitry Karpeev   if (colemb) {
515453dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
515553dd7562SDmitry Karpeev   }
515653dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
515753dd7562SDmitry Karpeev     PetscInt row;
515853dd7562SDmitry Karpeev     row = i;
515953dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
516053dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
516153dd7562SDmitry Karpeev       PetscInt col;
516253dd7562SDmitry Karpeev       col  = Baij->j[count];
516353dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
516453dd7562SDmitry Karpeev       v    = Baij->a[count];
516553dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
516653dd7562SDmitry Karpeev       ++count;
516753dd7562SDmitry Karpeev     }
516853dd7562SDmitry Karpeev   }
516953dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
517053dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
517153dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
517253dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
517353dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
517453dd7562SDmitry Karpeev   PetscFunctionReturn(0);
517553dd7562SDmitry Karpeev }
517653dd7562SDmitry Karpeev 
51774099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
51784099cc6bSBarry Smith 
51794099cc6bSBarry Smith /*@C
51804099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
51814099cc6bSBarry Smith 
51824099cc6bSBarry Smith    Collective on Mat
51834099cc6bSBarry Smith 
51844099cc6bSBarry Smith    Input Parameters:
51854099cc6bSBarry Smith +  mat      - the matrix object
51864099cc6bSBarry Smith -  matype   - matrix type
51874099cc6bSBarry Smith 
51884099cc6bSBarry Smith    Options Database Key:
51894099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
51904099cc6bSBarry Smith 
51914099cc6bSBarry Smith 
51924099cc6bSBarry Smith   Level: intermediate
51934099cc6bSBarry Smith 
51944099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
51954099cc6bSBarry Smith @*/
51964099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
51974099cc6bSBarry Smith {
5198fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
51994099cc6bSBarry Smith   PetscBool      sametype;
52004099cc6bSBarry Smith 
52014099cc6bSBarry Smith   PetscFunctionBegin;
52024099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
52034099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
52044099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
52054099cc6bSBarry Smith 
52064099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
52074099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
52084099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
52094099cc6bSBarry Smith   PetscFunctionReturn(0);
52104099cc6bSBarry Smith }
52114099cc6bSBarry Smith 
52124099cc6bSBarry Smith 
52134099cc6bSBarry Smith /*@C
52144099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
52154099cc6bSBarry Smith 
52164099cc6bSBarry Smith    Not Collective
52174099cc6bSBarry Smith 
52184099cc6bSBarry Smith    Input Parameters:
52194099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
52204099cc6bSBarry Smith -  function - routine to convert to subtype
52214099cc6bSBarry Smith 
52224099cc6bSBarry Smith    Notes:
52234099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
52244099cc6bSBarry Smith 
52254099cc6bSBarry Smith 
52264099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
52274099cc6bSBarry Smith $     -mat_seqaij_type my_mat
52284099cc6bSBarry Smith 
52294099cc6bSBarry Smith    Level: advanced
52304099cc6bSBarry Smith 
52314099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
52324099cc6bSBarry Smith 
52334099cc6bSBarry Smith 
52344099cc6bSBarry Smith   Level: advanced
52354099cc6bSBarry Smith @*/
5236388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
52374099cc6bSBarry Smith {
52384099cc6bSBarry Smith   PetscErrorCode ierr;
52394099cc6bSBarry Smith 
52404099cc6bSBarry Smith   PetscFunctionBegin;
52419cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
52424099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
52434099cc6bSBarry Smith   PetscFunctionReturn(0);
52444099cc6bSBarry Smith }
52454099cc6bSBarry Smith 
52464099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
52474099cc6bSBarry Smith 
52484099cc6bSBarry Smith /*@C
52494099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
52504099cc6bSBarry Smith 
52514099cc6bSBarry Smith   Not Collective
52524099cc6bSBarry Smith 
52534099cc6bSBarry Smith   Level: advanced
52544099cc6bSBarry Smith 
5255f719121fSJed Brown   Developers Note: CUSPARSE does not yet support the MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
52564099cc6bSBarry Smith 
52574099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
52584099cc6bSBarry Smith @*/
52594099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
52604099cc6bSBarry Smith {
52614099cc6bSBarry Smith   PetscErrorCode ierr;
52624099cc6bSBarry Smith 
52634099cc6bSBarry Smith   PetscFunctionBegin;
52644099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
52654099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
52664099cc6bSBarry Smith 
52674099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
52684099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
52694dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
52709779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
52716b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5272485f9817SRichard Tran Mills #endif
52734099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
52744099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
52754099cc6bSBarry Smith #endif
52764099cc6bSBarry Smith   PetscFunctionReturn(0);
52774099cc6bSBarry Smith }
527853dd7562SDmitry Karpeev 
527953dd7562SDmitry Karpeev /*
528081824310SBarry Smith     Special version for direct calls from Fortran
528181824310SBarry Smith */
5282af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
528381824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
528481824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
528581824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
528681824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
528781824310SBarry Smith #endif
528881824310SBarry Smith 
528981824310SBarry Smith /* Change these macros so can be used in void function */
529081824310SBarry Smith #undef CHKERRQ
5291ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
529281824310SBarry Smith #undef SETERRQ2
5293e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
52944994cf47SJed Brown #undef SETERRQ3
52954994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
529681824310SBarry Smith 
529719caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
529881824310SBarry Smith {
529981824310SBarry Smith   Mat            A  = *AA;
530081824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
530181824310SBarry Smith   InsertMode     is = *isis;
530281824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
530381824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
530481824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
530581824310SBarry Smith   PetscErrorCode ierr;
530681824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
530754f21887SBarry Smith   MatScalar      *ap,value,*aa;
5308ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5309ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
531081824310SBarry Smith 
531181824310SBarry Smith   PetscFunctionBegin;
53124994cf47SJed Brown   MatCheckPreallocated(A,1);
531381824310SBarry Smith   imax  = a->imax;
531481824310SBarry Smith   ai    = a->i;
531581824310SBarry Smith   ailen = a->ilen;
531681824310SBarry Smith   aj    = a->j;
531781824310SBarry Smith   aa    = a->a;
531881824310SBarry Smith 
531981824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
532081824310SBarry Smith     row = im[k];
532181824310SBarry Smith     if (row < 0) continue;
5322cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
532381824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
532481824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
532581824310SBarry Smith     low  = 0;
532681824310SBarry Smith     high = nrow;
532781824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
532881824310SBarry Smith       if (in[l] < 0) continue;
5329cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
533081824310SBarry Smith       col = in[l];
53312205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
53322205254eSKarl Rupp       else value = v[k + l*m];
53332205254eSKarl Rupp 
533481824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
533581824310SBarry Smith 
53362205254eSKarl Rupp       if (col <= lastcol) low = 0;
53372205254eSKarl Rupp       else high = nrow;
533881824310SBarry Smith       lastcol = col;
533981824310SBarry Smith       while (high-low > 5) {
534081824310SBarry Smith         t = (low+high)/2;
534181824310SBarry Smith         if (rp[t] > col) high = t;
534281824310SBarry Smith         else             low  = t;
534381824310SBarry Smith       }
534481824310SBarry Smith       for (i=low; i<high; i++) {
534581824310SBarry Smith         if (rp[i] > col) break;
534681824310SBarry Smith         if (rp[i] == col) {
534781824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
534881824310SBarry Smith           else                  ap[i] = value;
534981824310SBarry Smith           goto noinsert;
535081824310SBarry Smith         }
535181824310SBarry Smith       }
535281824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
535381824310SBarry Smith       if (nonew == 1) goto noinsert;
5354ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5355fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
535681824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
535781824310SBarry Smith       /* shift up all the later entries in this row */
535881824310SBarry Smith       for (ii=N; ii>=i; ii--) {
535981824310SBarry Smith         rp[ii+1] = rp[ii];
536081824310SBarry Smith         ap[ii+1] = ap[ii];
536181824310SBarry Smith       }
536281824310SBarry Smith       rp[i] = col;
536381824310SBarry Smith       ap[i] = value;
5364e56f5c9eSBarry Smith       A->nonzerostate++;
536581824310SBarry Smith noinsert:;
536681824310SBarry Smith       low = i + 1;
536781824310SBarry Smith     }
536881824310SBarry Smith     ailen[row] = nrow;
536981824310SBarry Smith   }
537081824310SBarry Smith   PetscFunctionReturnVoid();
537181824310SBarry Smith }
5372