xref: /petsc/src/mat/impls/aij/seq/aij.c (revision ddea5d601081b8d3ba49f4b67516b76abb728e3b)
1d5d45c9bSBarry Smith /*
23369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
3d5d45c9bSBarry Smith   matrix storage format.
4d5d45c9bSBarry Smith */
53369ce9aSBarry Smith 
6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
7c6db04a5SJed Brown #include <petscblaslapack.h>
8c6db04a5SJed Brown #include <petscbt.h>
9af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
100716a85fSBarry Smith 
114099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
124099cc6bSBarry Smith {
134099cc6bSBarry Smith   PetscErrorCode       ierr;
144099cc6bSBarry Smith   PetscBool            flg;
154099cc6bSBarry Smith   char                 type[256];
164099cc6bSBarry Smith 
174099cc6bSBarry Smith   PetscFunctionBegin;
181e1ea65dSPierre Jolivet   ierr = PetscObjectOptionsBegin((PetscObject)A);CHKERRQ(ierr);
194099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
204099cc6bSBarry Smith   if (flg) {
214099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
224099cc6bSBarry Smith   }
234099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
244099cc6bSBarry Smith   PetscFunctionReturn(0);
254099cc6bSBarry Smith }
264099cc6bSBarry Smith 
270716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
280716a85fSBarry Smith {
290716a85fSBarry Smith   PetscErrorCode ierr;
300716a85fSBarry Smith   PetscInt       i,m,n;
310716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
320716a85fSBarry Smith 
330716a85fSBarry Smith   PetscFunctionBegin;
340716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
35580bdb30SBarry Smith   ierr = PetscArrayzero(norms,n);CHKERRQ(ierr);
360716a85fSBarry Smith   if (type == NORM_2) {
370716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
380716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
390716a85fSBarry Smith     }
400716a85fSBarry Smith   } else if (type == NORM_1) {
410716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
420716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
430716a85fSBarry Smith     }
440716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
450716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
460716a85fSBarry Smith       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
470716a85fSBarry Smith     }
480716a85fSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");
490716a85fSBarry Smith 
500716a85fSBarry Smith   if (type == NORM_2) {
518f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
520716a85fSBarry Smith   }
530716a85fSBarry Smith   PetscFunctionReturn(0);
540716a85fSBarry Smith }
550716a85fSBarry Smith 
563a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
573a062f41SBarry Smith {
583a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
593a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
603a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
613a062f41SBarry Smith   PetscInt        *rows;
623a062f41SBarry Smith   PetscErrorCode  ierr;
633a062f41SBarry Smith 
643a062f41SBarry Smith   PetscFunctionBegin;
653a062f41SBarry Smith   for (i=0; i<m; i++) {
663a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
673a062f41SBarry Smith       cnt++;
683a062f41SBarry Smith     }
693a062f41SBarry Smith   }
703a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
713a062f41SBarry Smith   cnt  = 0;
723a062f41SBarry Smith   for (i=0; i<m; i++) {
733a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
743a062f41SBarry Smith       rows[cnt] = i;
753a062f41SBarry Smith       cnt++;
763a062f41SBarry Smith     }
773a062f41SBarry Smith   }
783a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
793a062f41SBarry Smith   PetscFunctionReturn(0);
803a062f41SBarry Smith }
813a062f41SBarry Smith 
82f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
836ce1633cSBarry Smith {
846ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
856ce1633cSBarry Smith   const MatScalar *aa = a->a;
866ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
87b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
886ce1633cSBarry Smith   PetscInt        *rows;
896ce1633cSBarry Smith   PetscErrorCode  ierr;
906ce1633cSBarry Smith 
916ce1633cSBarry Smith   PetscFunctionBegin;
926ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
936ce1633cSBarry Smith   diag = a->diag;
946ce1633cSBarry Smith   for (i=0; i<m; i++) {
95b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
966ce1633cSBarry Smith       cnt++;
976ce1633cSBarry Smith     }
986ce1633cSBarry Smith   }
99785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1006ce1633cSBarry Smith   cnt  = 0;
1016ce1633cSBarry Smith   for (i=0; i<m; i++) {
102b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1036ce1633cSBarry Smith       rows[cnt++] = i;
1046ce1633cSBarry Smith     }
1056ce1633cSBarry Smith   }
106f1f41ecbSJed Brown   *nrows = cnt;
107f1f41ecbSJed Brown   *zrows = rows;
108f1f41ecbSJed Brown   PetscFunctionReturn(0);
109f1f41ecbSJed Brown }
110f1f41ecbSJed Brown 
111f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
112f1f41ecbSJed Brown {
113f1f41ecbSJed Brown   PetscInt       nrows,*rows;
114f1f41ecbSJed Brown   PetscErrorCode ierr;
115f1f41ecbSJed Brown 
116f1f41ecbSJed Brown   PetscFunctionBegin;
1170298fd71SBarry Smith   *zrows = NULL;
118f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
119ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1206ce1633cSBarry Smith   PetscFunctionReturn(0);
1216ce1633cSBarry Smith }
1226ce1633cSBarry Smith 
123b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
124b3a44c85SBarry Smith {
125b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
126b3a44c85SBarry Smith   const MatScalar *aa;
127b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
128b3a44c85SBarry Smith   const PetscInt  *ii;
129b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
130b3a44c85SBarry Smith   PetscErrorCode  ierr;
131b3a44c85SBarry Smith 
132b3a44c85SBarry Smith   PetscFunctionBegin;
1332e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
134f4259b30SLisandro Dalcin   *keptrows = NULL;
135b3a44c85SBarry Smith   ii        = a->i;
136b3a44c85SBarry Smith   for (i=0; i<m; i++) {
137b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
138b3a44c85SBarry Smith     if (!n) {
139b3a44c85SBarry Smith       cnt++;
140b3a44c85SBarry Smith       goto ok1;
141b3a44c85SBarry Smith     }
1422e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
143b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
144b3a44c85SBarry Smith     }
145b3a44c85SBarry Smith     cnt++;
146b3a44c85SBarry Smith ok1:;
147b3a44c85SBarry Smith   }
1482e5835c6SStefano Zampini   if (!cnt) {
1492e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1502e5835c6SStefano Zampini     PetscFunctionReturn(0);
1512e5835c6SStefano Zampini   }
152854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
153b3a44c85SBarry Smith   cnt  = 0;
154b3a44c85SBarry Smith   for (i=0; i<m; i++) {
155b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
156b3a44c85SBarry Smith     if (!n) continue;
1572e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
158b3a44c85SBarry Smith       if (aa[j] != 0.0) {
159b3a44c85SBarry Smith         rows[cnt++] = i;
160b3a44c85SBarry Smith         break;
161b3a44c85SBarry Smith       }
162b3a44c85SBarry Smith     }
163b3a44c85SBarry Smith   }
1642e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
165b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
166b3a44c85SBarry Smith   PetscFunctionReturn(0);
167b3a44c85SBarry Smith }
168b3a44c85SBarry Smith 
1697087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
17079299369SBarry Smith {
17179299369SBarry Smith   PetscErrorCode    ierr;
17279299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17399e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17499e65526SBarry Smith   const PetscInt    *diag;
1752e5835c6SStefano Zampini   MatScalar         *aa;
17699e65526SBarry Smith   const PetscScalar *v;
177ace3abfcSBarry Smith   PetscBool         missing;
1788c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
179837a59e1SRichard Tran Mills   PetscBool         inserted = PETSC_FALSE;
180837a59e1SRichard Tran Mills #endif
18179299369SBarry Smith 
18279299369SBarry Smith   PetscFunctionBegin;
18309f38230SBarry Smith   if (Y->assembled) {
1840298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
18509f38230SBarry Smith     if (!missing) {
18679299369SBarry Smith       diag = aij->diag;
18799e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
1882e5835c6SStefano Zampini       ierr = MatSeqAIJGetArray(Y,&aa);CHKERRQ(ierr);
18979299369SBarry Smith       if (is == INSERT_VALUES) {
1908c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
191837a59e1SRichard Tran Mills         inserted = PETSC_TRUE;
192837a59e1SRichard Tran Mills #endif
19379299369SBarry Smith         for (i=0; i<m; i++) {
19479299369SBarry Smith           aa[diag[i]] = v[i];
19579299369SBarry Smith         }
19679299369SBarry Smith       } else {
19779299369SBarry Smith         for (i=0; i<m; i++) {
1988c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
199837a59e1SRichard Tran Mills           if (v[i] != 0.0) inserted = PETSC_TRUE;
200837a59e1SRichard Tran Mills #endif
20179299369SBarry Smith           aa[diag[i]] += v[i];
20279299369SBarry Smith         }
20379299369SBarry Smith       }
2042e5835c6SStefano Zampini       ierr = MatSeqAIJRestoreArray(Y,&aa);CHKERRQ(ierr);
2058c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
206837a59e1SRichard Tran Mills       if (inserted) Y->offloadmask = PETSC_OFFLOAD_CPU;
207837a59e1SRichard Tran Mills #endif
20899e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
20979299369SBarry Smith       PetscFunctionReturn(0);
21079299369SBarry Smith     }
211acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
21209f38230SBarry Smith   }
21309f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
21409f38230SBarry Smith   PetscFunctionReturn(0);
21509f38230SBarry Smith }
21679299369SBarry Smith 
2171a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21817ab2063SBarry Smith {
219416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
220dfbe8321SBarry Smith   PetscErrorCode ierr;
22197f1f81fSBarry Smith   PetscInt       i,ishift;
22217ab2063SBarry Smith 
2233a40ed3dSBarry Smith   PetscFunctionBegin;
224d0f46423SBarry Smith   *m = A->rmap->n;
2253a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
226bfeeae90SHong Zhang   ishift = 0;
22753e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2282462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
229bfeeae90SHong Zhang   } else if (oshift == 1) {
2301a83f524SJed Brown     PetscInt *tia;
231d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2323b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
233854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2341a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2351a83f524SJed Brown     *ia = tia;
236ecc77c7aSBarry Smith     if (ja) {
2371a83f524SJed Brown       PetscInt *tja;
238854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2391a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2401a83f524SJed Brown       *ja = tja;
241ecc77c7aSBarry Smith     }
2426945ee14SBarry Smith   } else {
243ecc77c7aSBarry Smith     *ia = a->i;
244ecc77c7aSBarry Smith     if (ja) *ja = a->j;
245a2ce50c7SBarry Smith   }
2463a40ed3dSBarry Smith   PetscFunctionReturn(0);
247a2744918SBarry Smith }
248a2744918SBarry Smith 
2491a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2506945ee14SBarry Smith {
251dfbe8321SBarry Smith   PetscErrorCode ierr;
2526945ee14SBarry Smith 
2533a40ed3dSBarry Smith   PetscFunctionBegin;
2543a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
255bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
256606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
257ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
258bcd2baecSBarry Smith   }
2593a40ed3dSBarry Smith   PetscFunctionReturn(0);
26017ab2063SBarry Smith }
26117ab2063SBarry Smith 
2621a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2633b2fbd54SBarry Smith {
2643b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
265dfbe8321SBarry Smith   PetscErrorCode ierr;
266d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
26797f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2683b2fbd54SBarry Smith 
2693a40ed3dSBarry Smith   PetscFunctionBegin;
270899cda47SBarry Smith   *nn = n;
2713a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2723b2fbd54SBarry Smith   if (symmetric) {
2732462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2743b2fbd54SBarry Smith   } else {
275b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
276854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
277b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2783b2fbd54SBarry Smith     jj   = a->j;
2793b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
280bfeeae90SHong Zhang       collengths[jj[i]]++;
2813b2fbd54SBarry Smith     }
2823b2fbd54SBarry Smith     cia[0] = oshift;
2833b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2843b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2853b2fbd54SBarry Smith     }
286580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2873b2fbd54SBarry Smith     jj   = a->j;
288a93ec695SBarry Smith     for (row=0; row<m; row++) {
289a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
290a93ec695SBarry Smith       for (i=0; i<mr; i++) {
291bfeeae90SHong Zhang         col = *jj++;
2922205254eSKarl Rupp 
2933b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2943b2fbd54SBarry Smith       }
2953b2fbd54SBarry Smith     }
296606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2973b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2983b2fbd54SBarry Smith   }
2993a40ed3dSBarry Smith   PetscFunctionReturn(0);
3003b2fbd54SBarry Smith }
3013b2fbd54SBarry Smith 
3021a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
3033b2fbd54SBarry Smith {
304dfbe8321SBarry Smith   PetscErrorCode ierr;
305606d414cSSatish Balay 
3063a40ed3dSBarry Smith   PetscFunctionBegin;
3073a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3083b2fbd54SBarry Smith 
309606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
310606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3113a40ed3dSBarry Smith   PetscFunctionReturn(0);
3123b2fbd54SBarry Smith }
3133b2fbd54SBarry Smith 
3147cee066cSHong Zhang /*
3157cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3167cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
317040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3187cee066cSHong Zhang */
3197cee066cSHong 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)
3207cee066cSHong Zhang {
3217cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3227cee066cSHong Zhang   PetscErrorCode ierr;
3237cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
324071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3257cee066cSHong Zhang   PetscInt       *cspidx;
326071fcb05SBarry Smith   const PetscInt *jj;
3277cee066cSHong Zhang 
3287cee066cSHong Zhang   PetscFunctionBegin;
3297cee066cSHong Zhang   *nn = n;
3307cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
331625f6d37SHong Zhang 
332b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
333854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
334b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
335b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3367cee066cSHong Zhang   jj   = a->j;
3377cee066cSHong Zhang   for (i=0; i<nz; i++) {
3387cee066cSHong Zhang     collengths[jj[i]]++;
3397cee066cSHong Zhang   }
3407cee066cSHong Zhang   cia[0] = oshift;
3417cee066cSHong Zhang   for (i=0; i<n; i++) {
3427cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3437cee066cSHong Zhang   }
344580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3457cee066cSHong Zhang   jj   = a->j;
3467cee066cSHong Zhang   for (row=0; row<m; row++) {
3477cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3487cee066cSHong Zhang     for (i=0; i<mr; i++) {
3497cee066cSHong Zhang       col         = *jj++;
350071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
351071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
352071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3537cee066cSHong Zhang     }
3547cee066cSHong Zhang   }
3557cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
356071fcb05SBarry Smith   *ia    = cia;
357071fcb05SBarry Smith   *ja    = cja;
3587cee066cSHong Zhang   *spidx = cspidx;
3597cee066cSHong Zhang   PetscFunctionReturn(0);
3607cee066cSHong Zhang }
3617cee066cSHong Zhang 
3627cee066cSHong 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)
3637cee066cSHong Zhang {
3647cee066cSHong Zhang   PetscErrorCode ierr;
3657cee066cSHong Zhang 
3667cee066cSHong Zhang   PetscFunctionBegin;
3675243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3687cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3697cee066cSHong Zhang   PetscFunctionReturn(0);
3707cee066cSHong Zhang }
3717cee066cSHong Zhang 
37287d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
37387d4246cSBarry Smith {
37487d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
37587d4246cSBarry Smith   PetscInt       *ai = a->i;
37687d4246cSBarry Smith   PetscErrorCode ierr;
37787d4246cSBarry Smith 
37887d4246cSBarry Smith   PetscFunctionBegin;
379580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
3808c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
381c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
382e2cf4d64SStefano Zampini #endif
38387d4246cSBarry Smith   PetscFunctionReturn(0);
38487d4246cSBarry Smith }
38587d4246cSBarry Smith 
386bd04181cSBarry Smith /*
387bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
388bd04181cSBarry Smith 
389bd04181cSBarry Smith       -   a single row of values is set with each call
390bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
391bd04181cSBarry Smith       -   the values are always added to the matrix, not set
392bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
393bd04181cSBarry Smith 
3941f763a69SBarry Smith      This does NOT assume the global column indices are sorted
395bd04181cSBarry Smith 
3961f763a69SBarry Smith */
397bd04181cSBarry Smith 
398af0996ceSBarry Smith #include <petsc/private/isimpl.h>
399189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
400189e4007SBarry Smith {
401189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4021f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
4031f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4041f763a69SBarry Smith   PetscInt       lastcol = -1;
405189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
406189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
407189e4007SBarry Smith 
408f38dd0b8SBarry Smith   row  = ridx[im[0]];
4091f763a69SBarry Smith   rp   = aj + ai[row];
4101f763a69SBarry Smith   ap   = aa + ai[row];
4111f763a69SBarry Smith   nrow = ailen[row];
412189e4007SBarry Smith   low  = 0;
413189e4007SBarry Smith   high = nrow;
414189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
415189e4007SBarry Smith     col = cidx[in[l]];
416f38dd0b8SBarry Smith     value = v[l];
417189e4007SBarry Smith 
418189e4007SBarry Smith     if (col <= lastcol) low = 0;
419189e4007SBarry Smith     else high = nrow;
420189e4007SBarry Smith     lastcol = col;
421189e4007SBarry Smith     while (high-low > 5) {
422189e4007SBarry Smith       t = (low+high)/2;
423189e4007SBarry Smith       if (rp[t] > col) high = t;
424189e4007SBarry Smith       else low = t;
425189e4007SBarry Smith     }
426189e4007SBarry Smith     for (i=low; i<high; i++) {
427189e4007SBarry Smith       if (rp[i] == col) {
4281f763a69SBarry Smith         ap[i] += value;
429189e4007SBarry Smith         low = i + 1;
4301f763a69SBarry Smith         break;
431189e4007SBarry Smith       }
432189e4007SBarry Smith     }
433189e4007SBarry Smith   }
4348c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
435c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
436e2cf4d64SStefano Zampini #endif
437f38dd0b8SBarry Smith   return 0;
438189e4007SBarry Smith }
439189e4007SBarry Smith 
44097f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
44117ab2063SBarry Smith {
442416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
443e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
44497f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4456849ba73SBarry Smith   PetscErrorCode ierr;
446e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
447ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
448ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
449ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
4508c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
451e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
452e2cf4d64SStefano Zampini #endif
45317ab2063SBarry Smith 
4543a40ed3dSBarry Smith   PetscFunctionBegin;
455ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
456ce496241SStefano Zampini   if (A->offloadmask == PETSC_OFFLOAD_GPU) {
457ce496241SStefano Zampini     const PetscScalar *dummy;
458ce496241SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&dummy);CHKERRQ(ierr);
459ce496241SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&dummy);CHKERRQ(ierr);
460ce496241SStefano Zampini   }
461ce496241SStefano Zampini #endif
462ce496241SStefano Zampini   aa = a->a;
46317ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
464416022c9SBarry Smith     row = im[k];
4655ef9f2a5SBarry Smith     if (row < 0) continue;
466cf9c20a2SJed 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);
467720833daSHong Zhang     rp   = aj + ai[row];
468876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
46917ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
470416022c9SBarry Smith     low  = 0;
471c71e6ed7SBarry Smith     high = nrow;
47217ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4735ef9f2a5SBarry Smith       if (in[l] < 0) continue;
474cf9c20a2SJed 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);
475bfeeae90SHong Zhang       col = in[l];
476071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
477071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
47836db0b34SBarry Smith 
4792205254eSKarl Rupp       if (col <= lastcol) low = 0;
4802205254eSKarl Rupp       else high = nrow;
481e2ee6c50SBarry Smith       lastcol = col;
482416022c9SBarry Smith       while (high-low > 5) {
483416022c9SBarry Smith         t = (low+high)/2;
484416022c9SBarry Smith         if (rp[t] > col) high = t;
485416022c9SBarry Smith         else low = t;
48617ab2063SBarry Smith       }
487416022c9SBarry Smith       for (i=low; i<high; i++) {
48817ab2063SBarry Smith         if (rp[i] > col) break;
48917ab2063SBarry Smith         if (rp[i] == col) {
490876c6284SHong Zhang           if (!A->structure_only) {
4910c0d7e18SFande Kong             if (is == ADD_VALUES) {
4920c0d7e18SFande Kong               ap[i] += value;
4930c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4940c0d7e18SFande Kong             }
49517ab2063SBarry Smith             else ap[i] = value;
4968c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
497e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
498e2cf4d64SStefano Zampini #endif
499720833daSHong Zhang           }
500e44c0bd4SBarry Smith           low = i + 1;
50117ab2063SBarry Smith           goto noinsert;
50217ab2063SBarry Smith         }
50317ab2063SBarry Smith       }
504dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
505c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
506e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
507720833daSHong Zhang       if (A->structure_only) {
508876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
509720833daSHong Zhang       } else {
510fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
511720833daSHong Zhang       }
512c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
513416022c9SBarry Smith       /* shift up all the later entries in this row */
514580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
51517ab2063SBarry Smith       rp[i] = col;
516580bdb30SBarry Smith       if (!A->structure_only) {
517580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
518580bdb30SBarry Smith         ap[i] = value;
519580bdb30SBarry Smith       }
520416022c9SBarry Smith       low = i + 1;
521e56f5c9eSBarry Smith       A->nonzerostate++;
5228c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
523e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
524e2cf4d64SStefano Zampini #endif
525e44c0bd4SBarry Smith noinsert:;
52617ab2063SBarry Smith     }
52717ab2063SBarry Smith     ailen[row] = nrow;
52817ab2063SBarry Smith   }
5298c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
530c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
531e2cf4d64SStefano Zampini #endif
5323a40ed3dSBarry Smith   PetscFunctionReturn(0);
53317ab2063SBarry Smith }
53417ab2063SBarry Smith 
53519b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
53619b08ed1SBarry Smith {
53719b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
53819b08ed1SBarry Smith   PetscInt       *rp,k,row;
53919b08ed1SBarry Smith   PetscInt       *ai = a->i;
54019b08ed1SBarry Smith   PetscErrorCode ierr;
54119b08ed1SBarry Smith   PetscInt       *aj = a->j;
54219b08ed1SBarry Smith   MatScalar      *aa = a->a,*ap;
54319b08ed1SBarry Smith 
54419b08ed1SBarry Smith   PetscFunctionBegin;
54519b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
54619b08ed1SBarry 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);
54719b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
54819b08ed1SBarry Smith     row  = im[k];
54919b08ed1SBarry Smith     rp   = aj + ai[row];
55019b08ed1SBarry Smith     ap   = aa + ai[row];
55119b08ed1SBarry Smith 
55219b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
55319b08ed1SBarry Smith     if (!A->structure_only) {
55419b08ed1SBarry Smith       if (v) {
55519b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
55619b08ed1SBarry Smith         v   += n;
55719b08ed1SBarry Smith       } else {
55819b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
55919b08ed1SBarry Smith       }
56019b08ed1SBarry Smith     }
56119b08ed1SBarry Smith     a->ilen[row] = n;
56219b08ed1SBarry Smith     a->imax[row] = n;
56319b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
56419b08ed1SBarry Smith     a->nz       += n;
56519b08ed1SBarry Smith   }
5668c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
56719b08ed1SBarry Smith   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
56819b08ed1SBarry Smith #endif
56919b08ed1SBarry Smith   PetscFunctionReturn(0);
57019b08ed1SBarry Smith }
57119b08ed1SBarry Smith 
57219b08ed1SBarry Smith /*@
57319b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
57419b08ed1SBarry Smith 
57519b08ed1SBarry Smith   Input Parameters:
57619b08ed1SBarry Smith +  A - the SeqAIJ matrix
57719b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
57819b08ed1SBarry Smith 
57919b08ed1SBarry Smith   Level: advanced
58019b08ed1SBarry Smith 
58119b08ed1SBarry Smith   Notes:
58219b08ed1SBarry 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.
58319b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
58419b08ed1SBarry Smith     as always with multiple matrix assemblies.
58519b08ed1SBarry Smith 
58619b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
58719b08ed1SBarry Smith @*/
58819b08ed1SBarry Smith 
58919b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
59019b08ed1SBarry Smith {
59119b08ed1SBarry Smith   PetscErrorCode ierr;
59219b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
59319b08ed1SBarry Smith 
59419b08ed1SBarry Smith   PetscFunctionBegin;
59519b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
59619b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
59719b08ed1SBarry Smith   a->maxnz  = nztotal;
59819b08ed1SBarry Smith   if (!a->imax) {
59919b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
60019b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60119b08ed1SBarry Smith   }
60219b08ed1SBarry Smith   if (!a->ilen) {
60319b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
60419b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60519b08ed1SBarry Smith   } else {
60619b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60719b08ed1SBarry Smith   }
60819b08ed1SBarry Smith 
60919b08ed1SBarry Smith   /* allocate the matrix space */
61019b08ed1SBarry Smith   if (A->structure_only) {
61119b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
61219b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
61319b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
61419b08ed1SBarry Smith   } else {
61519b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
61619b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
61719b08ed1SBarry Smith   }
61819b08ed1SBarry Smith   a->i[0] = 0;
61919b08ed1SBarry Smith   if (A->structure_only) {
62019b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
62119b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
62219b08ed1SBarry Smith   } else {
62319b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
62419b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
62519b08ed1SBarry Smith   }
62619b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
62719b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
62819b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
62919b08ed1SBarry Smith   PetscFunctionReturn(0);
63019b08ed1SBarry Smith }
63119b08ed1SBarry Smith 
632071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
633071fcb05SBarry Smith {
634071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
635071fcb05SBarry Smith   PetscInt       *rp,k,row;
636071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
637071fcb05SBarry Smith   PetscErrorCode ierr;
638071fcb05SBarry Smith   PetscInt       *aj = a->j;
639071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
640071fcb05SBarry Smith 
641071fcb05SBarry Smith   PetscFunctionBegin;
642071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
643071fcb05SBarry Smith     row  = im[k];
64419b08ed1SBarry 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);
645071fcb05SBarry Smith     rp   = aj + ai[row];
646071fcb05SBarry Smith     ap   = aa + ai[row];
647071fcb05SBarry Smith     if (!A->was_assembled) {
648071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
649071fcb05SBarry Smith     }
650071fcb05SBarry Smith     if (!A->structure_only) {
651071fcb05SBarry Smith       if (v) {
652071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
653071fcb05SBarry Smith         v   += n;
654071fcb05SBarry Smith       } else {
655071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
656071fcb05SBarry Smith       }
657071fcb05SBarry Smith     }
658071fcb05SBarry Smith     ailen[row] = n;
659071fcb05SBarry Smith     a->nz      += n;
660071fcb05SBarry Smith   }
6618c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
662c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
663e2cf4d64SStefano Zampini #endif
664071fcb05SBarry Smith   PetscFunctionReturn(0);
665071fcb05SBarry Smith }
666071fcb05SBarry Smith 
667a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6687eb43aa7SLois Curfman McInnes {
6697eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
67097f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
67197f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
67254f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
6737eb43aa7SLois Curfman McInnes 
6743a40ed3dSBarry Smith   PetscFunctionBegin;
6757eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6767eb43aa7SLois Curfman McInnes     row = im[k];
677e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
678e32f2f54SBarry 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);
679bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6807eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6817eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
682e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
683e32f2f54SBarry 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);
684bfeeae90SHong Zhang       col  = in[l];
6857eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6867eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6877eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6887eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6897eb43aa7SLois Curfman McInnes         else low = t;
6907eb43aa7SLois Curfman McInnes       }
6917eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6927eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6937eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
694b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6957eb43aa7SLois Curfman McInnes           goto finished;
6967eb43aa7SLois Curfman McInnes         }
6977eb43aa7SLois Curfman McInnes       }
69897e567efSBarry Smith       *v++ = 0.0;
6997eb43aa7SLois Curfman McInnes finished:;
7007eb43aa7SLois Curfman McInnes     }
7017eb43aa7SLois Curfman McInnes   }
7023a40ed3dSBarry Smith   PetscFunctionReturn(0);
7037eb43aa7SLois Curfman McInnes }
7047eb43aa7SLois Curfman McInnes 
7053ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
70617ab2063SBarry Smith {
7073ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
708c898d852SStefano Zampini   const PetscScalar *av;
7093ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
7103ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
7116849ba73SBarry Smith   PetscErrorCode    ierr;
71217ab2063SBarry Smith 
7133a40ed3dSBarry Smith   PetscFunctionBegin;
7143ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7152205254eSKarl Rupp 
7163ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7173ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7183ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7193ea6fe3dSLisandro Dalcin   nz = A->nz;
720416022c9SBarry Smith 
7213ea6fe3dSLisandro Dalcin   /* write matrix header */
7223ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7233ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7243ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
725416022c9SBarry Smith 
7263ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7273ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7283ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7293ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7303ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7313ea6fe3dSLisandro Dalcin   /* store column indices */
7323ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
733416022c9SBarry Smith   /* store nonzero values */
734c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
735c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
736c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
737b37d52dbSMark F. Adams 
7383ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7393ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7403a40ed3dSBarry Smith   PetscFunctionReturn(0);
74117ab2063SBarry Smith }
742416022c9SBarry Smith 
7437dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7447dc0baabSHong Zhang {
7457dc0baabSHong Zhang   PetscErrorCode ierr;
7467dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7477dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7487dc0baabSHong Zhang 
7497dc0baabSHong Zhang   PetscFunctionBegin;
7507dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7517dc0baabSHong Zhang   for (i=0; i<m; i++) {
7527dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7537dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7547dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7557dc0baabSHong Zhang     }
7567dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7577dc0baabSHong Zhang   }
7587dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7597dc0baabSHong Zhang   PetscFunctionReturn(0);
7607dc0baabSHong Zhang }
7617dc0baabSHong Zhang 
76209573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
763cd155464SBarry Smith 
764dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
765416022c9SBarry Smith {
766416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
767c898d852SStefano Zampini   const PetscScalar *av;
768dfbe8321SBarry Smith   PetscErrorCode    ierr;
76960e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
770e060cb09SBarry Smith   const char        *name;
771f3ef73ceSBarry Smith   PetscViewerFormat format;
77217ab2063SBarry Smith 
7733a40ed3dSBarry Smith   PetscFunctionBegin;
7747dc0baabSHong Zhang   if (A->structure_only) {
7757dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7767dc0baabSHong Zhang     PetscFunctionReturn(0);
7777dc0baabSHong Zhang   }
77843e49210SHong Zhang 
779b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
7802e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7812e5835c6SStefano Zampini 
782c898d852SStefano Zampini   /* trigger copy to CPU if needed */
783c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
784c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
78571c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
78697f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
78760e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
788c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
789d00d2cf4SBarry Smith       nofinalvalue = 1;
790d00d2cf4SBarry Smith     }
791d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
792d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
79377431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
794fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
795fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
796fbfe6fa7SJed Brown #else
79777431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
798fbfe6fa7SJed Brown #endif
799b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
80017ab2063SBarry Smith 
80117ab2063SBarry Smith     for (i=0; i<m; i++) {
80260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
803aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
804a9bf72d8SJed 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);
80517ab2063SBarry Smith #else
80660e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
80717ab2063SBarry Smith #endif
80817ab2063SBarry Smith       }
80917ab2063SBarry Smith     }
810d00d2cf4SBarry Smith     if (nofinalvalue) {
811c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
812c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
813c337ccceSJed Brown #else
814d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
815c337ccceSJed Brown #endif
816d00d2cf4SBarry Smith     }
817317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
818fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
819d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
820fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
821d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
82244cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
82377431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
82460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
825aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
82636db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
82760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
82836db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
82960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
83036db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
83160e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8326831982aSBarry Smith         }
83344cd7ae7SLois Curfman McInnes #else
83460e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
83544cd7ae7SLois Curfman McInnes #endif
83644cd7ae7SLois Curfman McInnes       }
837b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
83844cd7ae7SLois Curfman McInnes     }
839d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
840fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
84197f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
842d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
843854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
844496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
845496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
84660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
847496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
848aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
84936db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
850496be53dSLois Curfman McInnes #else
851496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
852496be53dSLois Curfman McInnes #endif
853496be53dSLois Curfman McInnes         }
854496be53dSLois Curfman McInnes       }
855496be53dSLois Curfman McInnes     }
8562e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
85777431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8582e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8592205254eSKarl Rupp       if (i+4<m) {
8602205254eSKarl 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);
8612205254eSKarl Rupp       } else if (i+3<m) {
8622205254eSKarl 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);
8632205254eSKarl Rupp       } else if (i+2<m) {
8642205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8652205254eSKarl Rupp       } else if (i+1<m) {
8662205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8672205254eSKarl Rupp       } else if (i<m) {
8682205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8692205254eSKarl Rupp       } else {
8702205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8712205254eSKarl Rupp       }
872496be53dSLois Curfman McInnes     }
873b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
874606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
875496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
87660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
87777431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
878496be53dSLois Curfman McInnes       }
879b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
880496be53dSLois Curfman McInnes     }
881b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
882496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
88360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
884496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
885aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
88636db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
88760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8886831982aSBarry Smith           }
889496be53dSLois Curfman McInnes #else
89060e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
891496be53dSLois Curfman McInnes #endif
892496be53dSLois Curfman McInnes         }
893496be53dSLois Curfman McInnes       }
894b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
895496be53dSLois Curfman McInnes     }
896d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
897fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
89897f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
89987828ca2SBarry Smith     PetscScalar value;
90068f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
90168f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
90268f1ed48SBarry Smith 
90368f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
90468f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
90568f1ed48SBarry Smith         realonly = PETSC_FALSE;
90668f1ed48SBarry Smith         break;
90768f1ed48SBarry Smith       }
90868f1ed48SBarry Smith     }
90968f1ed48SBarry Smith #endif
91002594712SBarry Smith 
911d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
91202594712SBarry Smith     for (i=0; i<m; i++) {
91302594712SBarry Smith       jcnt = 0;
914d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
915e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
91602594712SBarry Smith           value = a->a[cnt++];
917e24b481bSBarry Smith           jcnt++;
91802594712SBarry Smith         } else {
91902594712SBarry Smith           value = 0.0;
92002594712SBarry Smith         }
921aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
92268f1ed48SBarry Smith         if (realonly) {
92360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
92468f1ed48SBarry Smith         } else {
92560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
92668f1ed48SBarry Smith         }
92702594712SBarry Smith #else
92860e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
92902594712SBarry Smith #endif
93002594712SBarry Smith       }
931b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
93202594712SBarry Smith     }
933d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9343c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
935150b93efSMatthew G. Knepley     PetscInt fshift=1;
936d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9373c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
93819303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9393c215bfdSMatthew Knepley #else
94019303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9413c215bfdSMatthew Knepley #endif
942d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9433c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
94460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9453c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
946a9a0e077SKarl 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);
9473c215bfdSMatthew Knepley #else
948150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9493c215bfdSMatthew Knepley #endif
9503c215bfdSMatthew Knepley       }
9513c215bfdSMatthew Knepley     }
952d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9533a40ed3dSBarry Smith   } else {
954d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
955d5f3da31SBarry Smith     if (A->factortype) {
95616cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
95716cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
95816cd7e1dSShri Abhyankar         /* L part */
95960e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
96016cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
96116cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
96260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
96316cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9646712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
96516cd7e1dSShri Abhyankar           } else {
96660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
96716cd7e1dSShri Abhyankar           }
96816cd7e1dSShri Abhyankar #else
96960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
97016cd7e1dSShri Abhyankar #endif
97116cd7e1dSShri Abhyankar         }
97216cd7e1dSShri Abhyankar         /* diagonal */
97316cd7e1dSShri Abhyankar         j = a->diag[i];
97416cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97516cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
97660e0710aSBarry 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);
97716cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9786712e2f1SBarry 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);
97916cd7e1dSShri Abhyankar         } else {
98060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
98116cd7e1dSShri Abhyankar         }
98216cd7e1dSShri Abhyankar #else
98360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
98416cd7e1dSShri Abhyankar #endif
98516cd7e1dSShri Abhyankar 
98616cd7e1dSShri Abhyankar         /* U part */
98760e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
98816cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
98916cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
99060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
99116cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
99222ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
99316cd7e1dSShri Abhyankar           } else {
99460e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
99516cd7e1dSShri Abhyankar           }
99616cd7e1dSShri Abhyankar #else
99760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
99816cd7e1dSShri Abhyankar #endif
99916cd7e1dSShri Abhyankar         }
100016cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
100116cd7e1dSShri Abhyankar       }
100216cd7e1dSShri Abhyankar     } else {
100317ab2063SBarry Smith       for (i=0; i<m; i++) {
100477431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
100560e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
1006aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
100736db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
100860e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
100936db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
101060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
10113a40ed3dSBarry Smith           } else {
101260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
101317ab2063SBarry Smith           }
101417ab2063SBarry Smith #else
101560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
101617ab2063SBarry Smith #endif
101717ab2063SBarry Smith         }
1018b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
101917ab2063SBarry Smith       }
102016cd7e1dSShri Abhyankar     }
1021d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
102217ab2063SBarry Smith   }
1023b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10243a40ed3dSBarry Smith   PetscFunctionReturn(0);
1025416022c9SBarry Smith }
1026416022c9SBarry Smith 
10279804daf3SBarry Smith #include <petscdraw.h>
1028dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1029416022c9SBarry Smith {
1030480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1031416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1032dfbe8321SBarry Smith   PetscErrorCode    ierr;
1033383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1034383922c3SLisandro Dalcin   int               color;
1035b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1036b0a32e0cSBarry Smith   PetscViewer       viewer;
1037f3ef73ceSBarry Smith   PetscViewerFormat format;
1038cddf8d76SBarry Smith 
10393a40ed3dSBarry Smith   PetscFunctionBegin;
1040480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1041b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1042b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1043383922c3SLisandro Dalcin 
1044416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10450513a670SBarry Smith 
1046fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1047383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10480513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1049b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1050416022c9SBarry Smith     for (i=0; i<m; i++) {
1051cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1052bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1053bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
105436db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
1055b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1056cddf8d76SBarry Smith       }
1057cddf8d76SBarry Smith     }
1058b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1059cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1060cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1061bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1062bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1063cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
1064b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1065cddf8d76SBarry Smith       }
1066cddf8d76SBarry Smith     }
1067b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1068cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1069cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1070bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1071bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
107236db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
1073b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1074416022c9SBarry Smith       }
1075416022c9SBarry Smith     }
1076383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10770513a670SBarry Smith   } else {
10780513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10790513a670SBarry Smith     /* first determine max of all nonzero values */
1080b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1081383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1082b0a32e0cSBarry Smith     PetscDraw popup;
10830513a670SBarry Smith 
10840513a670SBarry Smith     for (i=0; i<nz; i++) {
10850513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
10860513a670SBarry Smith     }
1087383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1088b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
108945f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1090383922c3SLisandro Dalcin 
1091383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10920513a670SBarry Smith     for (i=0; i<m; i++) {
1093383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1094383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1095bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1096383922c3SLisandro Dalcin         x_l = a->j[j];
1097383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1098b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
1099b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
11000513a670SBarry Smith         count++;
11010513a670SBarry Smith       }
11020513a670SBarry Smith     }
1103383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
11040513a670SBarry Smith   }
1105480ef9eaSBarry Smith   PetscFunctionReturn(0);
1106480ef9eaSBarry Smith }
1107cddf8d76SBarry Smith 
11089804daf3SBarry Smith #include <petscdraw.h>
1109dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1110480ef9eaSBarry Smith {
1111dfbe8321SBarry Smith   PetscErrorCode ierr;
1112b0a32e0cSBarry Smith   PetscDraw      draw;
111336db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1114ace3abfcSBarry Smith   PetscBool      isnull;
1115480ef9eaSBarry Smith 
1116480ef9eaSBarry Smith   PetscFunctionBegin;
1117b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1118b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1119480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1120480ef9eaSBarry Smith 
1121d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1122480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1123b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1124832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1125b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11260298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1127832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11283a40ed3dSBarry Smith   PetscFunctionReturn(0);
1129416022c9SBarry Smith }
1130416022c9SBarry Smith 
1131dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1132416022c9SBarry Smith {
1133dfbe8321SBarry Smith   PetscErrorCode ierr;
1134ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1135416022c9SBarry Smith 
11363a40ed3dSBarry Smith   PetscFunctionBegin;
1137251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1138251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1139251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1140c45a1595SBarry Smith   if (iascii) {
11413a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11420f5bd95cSBarry Smith   } else if (isbinary) {
11433a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11440f5bd95cSBarry Smith   } else if (isdraw) {
11453a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
114611aeaf0aSBarry Smith   }
11474108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11483a40ed3dSBarry Smith   PetscFunctionReturn(0);
114917ab2063SBarry Smith }
115019bcc07fSBarry Smith 
1151dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
115217ab2063SBarry Smith {
1153416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11546849ba73SBarry Smith   PetscErrorCode ierr;
1155580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1156d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
115754f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11583447b6efSHong Zhang   PetscReal      ratio  = 0.6;
115917ab2063SBarry Smith 
11603a40ed3dSBarry Smith   PetscFunctionBegin;
11613a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1162071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1163b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1164b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1165b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1166b215bc84SStefano Zampini     PetscFunctionReturn(0);
1167b215bc84SStefano Zampini   }
116817ab2063SBarry Smith 
116943ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
117017ab2063SBarry Smith   for (i=1; i<m; i++) {
1171416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
117217ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
117394a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
117417ab2063SBarry Smith     if (fshift) {
1175bfeeae90SHong Zhang       ip = aj + ai[i];
1176bfeeae90SHong Zhang       ap = aa + ai[i];
117717ab2063SBarry Smith       N  = ailen[i];
1178580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1179580bdb30SBarry Smith       if (!A->structure_only) {
1180580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
118117ab2063SBarry Smith       }
118217ab2063SBarry Smith     }
118317ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
118417ab2063SBarry Smith   }
118517ab2063SBarry Smith   if (m) {
118617ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
118717ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
118817ab2063SBarry Smith   }
11897b083b7cSBarry Smith 
119017ab2063SBarry Smith   /* reset ilen and imax for each row */
11917b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1192396832f4SHong Zhang   if (A->structure_only) {
1193071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1194071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1195396832f4SHong Zhang   } else { /* !A->structure_only */
119617ab2063SBarry Smith     for (i=0; i<m; i++) {
119717ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11987b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
119917ab2063SBarry Smith     }
1200396832f4SHong Zhang   }
1201bfeeae90SHong Zhang   a->nz = ai[m];
120265e19b50SBarry 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);
120317ab2063SBarry Smith 
120409f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1205d0f46423SBarry 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);
1206ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1207ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
12082205254eSKarl Rupp 
12098e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1210dd5f02e7SSatish Balay   a->reallocs         = 0;
12116712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
121236db0b34SBarry Smith   a->rmax             = rmax;
12134e220ebcSLois Curfman McInnes 
1214396832f4SHong Zhang   if (!A->structure_only) {
121511e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1216396832f4SHong Zhang   }
12174108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12183a40ed3dSBarry Smith   PetscFunctionReturn(0);
121917ab2063SBarry Smith }
122017ab2063SBarry Smith 
122199cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
122299cafbc1SBarry Smith {
122399cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
122499cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12252e5835c6SStefano Zampini   MatScalar      *aa;
1226acf2f550SJed Brown   PetscErrorCode ierr;
122799cafbc1SBarry Smith 
122899cafbc1SBarry Smith   PetscFunctionBegin;
12292e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
123099cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
12312e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1232acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12338c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1234c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1235e2cf4d64SStefano Zampini #endif
123699cafbc1SBarry Smith   PetscFunctionReturn(0);
123799cafbc1SBarry Smith }
123899cafbc1SBarry Smith 
123999cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
124099cafbc1SBarry Smith {
124199cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
124299cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12432e5835c6SStefano Zampini   MatScalar      *aa;
1244acf2f550SJed Brown   PetscErrorCode ierr;
124599cafbc1SBarry Smith 
124699cafbc1SBarry Smith   PetscFunctionBegin;
12472e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
124899cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12492e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1250acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12518c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1252c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1253e2cf4d64SStefano Zampini #endif
125499cafbc1SBarry Smith   PetscFunctionReturn(0);
125599cafbc1SBarry Smith }
125699cafbc1SBarry Smith 
1257dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
125817ab2063SBarry Smith {
1259416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1260dfbe8321SBarry Smith   PetscErrorCode ierr;
12613a40ed3dSBarry Smith 
12623a40ed3dSBarry Smith   PetscFunctionBegin;
1263580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1264acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12658c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1266c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1267e2cf4d64SStefano Zampini #endif
12683a40ed3dSBarry Smith   PetscFunctionReturn(0);
126917ab2063SBarry Smith }
1270416022c9SBarry Smith 
1271dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
127217ab2063SBarry Smith {
1273416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1274dfbe8321SBarry Smith   PetscErrorCode ierr;
1275d5d45c9bSBarry Smith 
12763a40ed3dSBarry Smith   PetscFunctionBegin;
1277aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1278d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
127917ab2063SBarry Smith #endif
1280e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12816bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12826bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
128305b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1284d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1285071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1286071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1287846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
128871f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
128905b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12906bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
129105b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1292cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1293a30b2313SHong Zhang 
12944108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1295bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1296901853e0SKris Buschelman 
12976718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12986718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12996718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
13006718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
13016718818eSStefano Zampini      due to different matrix sizes */
13026718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
13036718818eSStefano Zampini 
1304f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1305bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1306bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1307bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1308bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1309bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1310bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
13114222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
13124222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1313e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1314fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
13154222ddf1SHong Zhang #endif
13163d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
13173d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13183d0639e7SStefano Zampini #endif
13194222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1320af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1321af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1322af8000cdSHong Zhang #endif
1323d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1324d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1325d24d4204SJose E. Roman #endif
132663c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
132763c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13284222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
132963c07aadSStefano Zampini #endif
1330b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1331c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1332c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1333bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1334bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1335846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1336bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1337bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13384222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13394222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13404222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
1341ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL);CHKERRQ(ierr);
13423a40ed3dSBarry Smith   PetscFunctionReturn(0);
134317ab2063SBarry Smith }
134417ab2063SBarry Smith 
1345ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
134617ab2063SBarry Smith {
1347416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13484846f1f5SKris Buschelman   PetscErrorCode ierr;
13493a40ed3dSBarry Smith 
13503a40ed3dSBarry Smith   PetscFunctionBegin;
1351a65d3064SKris Buschelman   switch (op) {
1352a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13534e0d8c25SBarry Smith     a->roworiented = flg;
1354a65d3064SKris Buschelman     break;
1355a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1356a9817697SBarry Smith     a->keepnonzeropattern = flg;
1357a65d3064SKris Buschelman     break;
1358512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1359512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1360a65d3064SKris Buschelman     break;
1361a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13624e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1363a65d3064SKris Buschelman     break;
1364a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13654e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1366a65d3064SKris Buschelman     break;
136728b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
136828b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
136928b2fa4aSMatthew Knepley     break;
1370a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13714e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13720df259c2SBarry Smith     break;
13733d472b54SHong Zhang   case MAT_SPD:
1374b1646e73SJed Brown   case MAT_SYMMETRIC:
1375b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1376b1646e73SJed Brown   case MAT_HERMITIAN:
1377b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1378957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13795021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13805021d80fSJed Brown     break;
13818c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1382a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1383a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1384290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1385a65d3064SKris Buschelman     break;
1386b87ac2d8SJed Brown   case MAT_USE_INODES:
1387b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1388b87ac2d8SJed Brown     break;
1389c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1390c10200c1SHong Zhang     A->submat_singleis = flg;
1391c10200c1SHong Zhang     break;
1392071fcb05SBarry Smith   case MAT_SORTED_FULL:
1393071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1394071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1395071fcb05SBarry Smith     break;
13961a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
13971a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
13981a2c6b5cSJunchao Zhang     break;
1399a65d3064SKris Buschelman   default:
1400e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1401a65d3064SKris Buschelman   }
14023a40ed3dSBarry Smith   PetscFunctionReturn(0);
140317ab2063SBarry Smith }
140417ab2063SBarry Smith 
1405dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
140617ab2063SBarry Smith {
1407416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14086849ba73SBarry Smith   PetscErrorCode    ierr;
1409fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1410c898d852SStefano Zampini   PetscScalar       *x;
1411c898d852SStefano Zampini   const PetscScalar *aa;
141217ab2063SBarry Smith 
14133a40ed3dSBarry Smith   PetscFunctionBegin;
1414d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1415e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1416c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1417d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1418d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1419fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14202c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1421fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1422c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
142335e7444dSHong Zhang     PetscFunctionReturn(0);
142435e7444dSHong Zhang   }
142535e7444dSHong Zhang 
1426fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
142735e7444dSHong Zhang   for (i=0; i<n; i++) {
1428fdc842d1SBarry Smith     x[i] = 0.0;
142935e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
143035e7444dSHong Zhang       if (aj[j] == i) {
143135e7444dSHong Zhang         x[i] = aa[j];
143217ab2063SBarry Smith         break;
143317ab2063SBarry Smith       }
143417ab2063SBarry Smith     }
143517ab2063SBarry Smith   }
1436fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1437c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14383a40ed3dSBarry Smith   PetscFunctionReturn(0);
143917ab2063SBarry Smith }
144017ab2063SBarry Smith 
1441c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1442dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
144317ab2063SBarry Smith {
1444416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1445d9ca1df4SBarry Smith   PetscScalar       *y;
1446d9ca1df4SBarry Smith   const PetscScalar *x;
1447dfbe8321SBarry Smith   PetscErrorCode    ierr;
1448d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14495c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1450d9ca1df4SBarry Smith   const MatScalar   *v;
1451a77337e4SBarry Smith   PetscScalar       alpha;
1452d9ca1df4SBarry Smith   PetscInt          n,i,j;
1453d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14543447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1455ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14565c897100SBarry Smith #endif
145717ab2063SBarry Smith 
14583a40ed3dSBarry Smith   PetscFunctionBegin;
14592e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1460d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14611ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14625c897100SBarry Smith 
14635c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1464bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14655c897100SBarry Smith #else
14663447b6efSHong Zhang   if (usecprow) {
14673447b6efSHong Zhang     m    = cprow.nrows;
14683447b6efSHong Zhang     ii   = cprow.i;
14697b2bb3b9SHong Zhang     ridx = cprow.rindex;
14703447b6efSHong Zhang   } else {
14713447b6efSHong Zhang     ii = a->i;
14723447b6efSHong Zhang   }
147317ab2063SBarry Smith   for (i=0; i<m; i++) {
14743447b6efSHong Zhang     idx = a->j + ii[i];
14753447b6efSHong Zhang     v   = a->a + ii[i];
14763447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14773447b6efSHong Zhang     if (usecprow) {
14787b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14793447b6efSHong Zhang     } else {
148017ab2063SBarry Smith       alpha = x[i];
14813447b6efSHong Zhang     }
148204fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
148317ab2063SBarry Smith   }
14845c897100SBarry Smith #endif
1485dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1486d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14871ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14883a40ed3dSBarry Smith   PetscFunctionReturn(0);
148917ab2063SBarry Smith }
149017ab2063SBarry Smith 
1491dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14925c897100SBarry Smith {
1493dfbe8321SBarry Smith   PetscErrorCode ierr;
14945c897100SBarry Smith 
14955c897100SBarry Smith   PetscFunctionBegin;
1496170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14975c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14985c897100SBarry Smith   PetscFunctionReturn(0);
14995c897100SBarry Smith }
15005c897100SBarry Smith 
1501c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
150278b84d54SShri Abhyankar 
1503dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
150417ab2063SBarry Smith {
1505416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1506d9fead3dSBarry Smith   PetscScalar       *y;
150754f21887SBarry Smith   const PetscScalar *x;
150854f21887SBarry Smith   const MatScalar   *aa;
1509dfbe8321SBarry Smith   PetscErrorCode    ierr;
1510003131ecSBarry Smith   PetscInt          m=A->rmap->n;
15110298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
15127b083b7cSBarry Smith   PetscInt          n,i;
1513362ced78SSatish Balay   PetscScalar       sum;
1514ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
151517ab2063SBarry Smith 
1516b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
151797952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1518fee21e36SBarry Smith #endif
1519fee21e36SBarry Smith 
15203a40ed3dSBarry Smith   PetscFunctionBegin;
1521b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1522b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1523b215bc84SStefano Zampini     PetscFunctionReturn(0);
1524b215bc84SStefano Zampini   }
15253649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15261ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1527416022c9SBarry Smith   ii   = a->i;
15284eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1529580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
153097952fefSHong Zhang     m    = a->compressedrow.nrows;
153197952fefSHong Zhang     ii   = a->compressedrow.i;
153297952fefSHong Zhang     ridx = a->compressedrow.rindex;
153397952fefSHong Zhang     for (i=0; i<m; i++) {
153497952fefSHong Zhang       n           = ii[i+1] - ii[i];
153597952fefSHong Zhang       aj          = a->j + ii[i];
153697952fefSHong Zhang       aa          = a->a + ii[i];
153797952fefSHong Zhang       sum         = 0.0;
1538003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1539003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
154097952fefSHong Zhang       y[*ridx++] = sum;
154197952fefSHong Zhang     }
154297952fefSHong Zhang   } else { /* do not use compressed row format */
1543b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15443d3eaba7SBarry Smith     aj   = a->j;
15453d3eaba7SBarry Smith     aa   = a->a;
1546b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1547b05257ddSBarry Smith #else
154817ab2063SBarry Smith     for (i=0; i<m; i++) {
1549003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1550003131ecSBarry Smith       aj          = a->j + ii[i];
1551003131ecSBarry Smith       aa          = a->a + ii[i];
155217ab2063SBarry Smith       sum         = 0.0;
1553003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
155417ab2063SBarry Smith       y[i] = sum;
155517ab2063SBarry Smith     }
15568d195f9aSBarry Smith #endif
1557b05257ddSBarry Smith   }
15587b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15593649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15601ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15613a40ed3dSBarry Smith   PetscFunctionReturn(0);
156217ab2063SBarry Smith }
156317ab2063SBarry Smith 
1564b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1565b434eb95SMatthew G. Knepley {
1566b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1567b434eb95SMatthew G. Knepley   PetscScalar       *y;
1568b434eb95SMatthew G. Knepley   const PetscScalar *x;
1569b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1570b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1571b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1572b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1573b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1574b434eb95SMatthew G. Knepley   PetscScalar       sum;
1575b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1576b434eb95SMatthew G. Knepley 
1577b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1578b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1579b434eb95SMatthew G. Knepley #endif
1580b434eb95SMatthew G. Knepley 
1581b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1582b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1583b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1584b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1585b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1586b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1587b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1588b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1589b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1590b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1591b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1592b434eb95SMatthew G. Knepley       sum         = 0.0;
1593b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1594b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1595b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1596b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1597b434eb95SMatthew G. Knepley     }
1598b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15993d3eaba7SBarry Smith     ii = a->i;
1600b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1601b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1602b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1603b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1604b434eb95SMatthew G. Knepley       sum         = 0.0;
1605b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1606b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1607b434eb95SMatthew G. Knepley       y[i] = sum;
1608b434eb95SMatthew G. Knepley     }
1609b434eb95SMatthew G. Knepley   }
1610b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1611b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1612b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1613b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1614b434eb95SMatthew G. Knepley }
1615b434eb95SMatthew G. Knepley 
1616b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1617b434eb95SMatthew G. Knepley {
1618b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1619b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1620b434eb95SMatthew G. Knepley   const PetscScalar *x;
1621b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1622b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1623b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1624b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1625b434eb95SMatthew G. Knepley   PetscScalar       sum;
1626b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1627b434eb95SMatthew G. Knepley 
1628b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1629b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1630d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1631b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1632b434eb95SMatthew G. Knepley     if (zz != yy) {
1633580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1634b434eb95SMatthew G. Knepley     }
1635b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1636b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1637b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1638b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1639b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1640b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1641b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1642b434eb95SMatthew G. Knepley       sum = y[*ridx];
1643b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1644b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1645b434eb95SMatthew G. Knepley     }
1646b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16473d3eaba7SBarry Smith     ii = a->i;
1648b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1649b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1650b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1651b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1652b434eb95SMatthew G. Knepley       sum = y[i];
1653b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1654b434eb95SMatthew G. Knepley       z[i] = sum;
1655b434eb95SMatthew G. Knepley     }
1656b434eb95SMatthew G. Knepley   }
1657b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1658b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1659d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1660b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1661b434eb95SMatthew G. Knepley }
1662b434eb95SMatthew G. Knepley 
1663c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1664dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
166517ab2063SBarry Smith {
1666416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1667f15663dcSBarry Smith   PetscScalar       *y,*z;
1668f15663dcSBarry Smith   const PetscScalar *x;
166954f21887SBarry Smith   const MatScalar   *aa;
1670dfbe8321SBarry Smith   PetscErrorCode    ierr;
1671d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1672d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1673362ced78SSatish Balay   PetscScalar       sum;
1674ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16759ea0dfa2SSatish Balay 
16763a40ed3dSBarry Smith   PetscFunctionBegin;
1677b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1678b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1679b215bc84SStefano Zampini     PetscFunctionReturn(0);
1680b215bc84SStefano Zampini   }
1681f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1682d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16834eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16844eb6d288SHong Zhang     if (zz != yy) {
1685580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16864eb6d288SHong Zhang     }
168797952fefSHong Zhang     m    = a->compressedrow.nrows;
168897952fefSHong Zhang     ii   = a->compressedrow.i;
168997952fefSHong Zhang     ridx = a->compressedrow.rindex;
169097952fefSHong Zhang     for (i=0; i<m; i++) {
169197952fefSHong Zhang       n   = ii[i+1] - ii[i];
169297952fefSHong Zhang       aj  = a->j + ii[i];
169397952fefSHong Zhang       aa  = a->a + ii[i];
169497952fefSHong Zhang       sum = y[*ridx];
1695f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
169697952fefSHong Zhang       z[*ridx++] = sum;
169797952fefSHong Zhang     }
169897952fefSHong Zhang   } else { /* do not use compressed row format */
16993d3eaba7SBarry Smith     ii = a->i;
1700f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
17013d3eaba7SBarry Smith     aj = a->j;
17023d3eaba7SBarry Smith     aa = a->a;
1703f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1704f15663dcSBarry Smith #else
170517ab2063SBarry Smith     for (i=0; i<m; i++) {
1706f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1707f15663dcSBarry Smith       aj  = a->j + ii[i];
1708f15663dcSBarry Smith       aa  = a->a + ii[i];
170917ab2063SBarry Smith       sum = y[i];
1710f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
171117ab2063SBarry Smith       z[i] = sum;
171217ab2063SBarry Smith     }
171302ab625aSSatish Balay #endif
1714f15663dcSBarry Smith   }
1715dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1716f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1717d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
17183a40ed3dSBarry Smith   PetscFunctionReturn(0);
171917ab2063SBarry Smith }
172017ab2063SBarry Smith 
172117ab2063SBarry Smith /*
172217ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
172317ab2063SBarry Smith */
1724dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
172517ab2063SBarry Smith {
1726416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17276849ba73SBarry Smith   PetscErrorCode ierr;
1728d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
172917ab2063SBarry Smith 
17303a40ed3dSBarry Smith   PetscFunctionBegin;
173109f38230SBarry Smith   if (!a->diag) {
1732785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17333bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
173409f38230SBarry Smith   }
1735d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
173609f38230SBarry Smith     a->diag[i] = a->i[i+1];
1737bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1738bfeeae90SHong Zhang       if (a->j[j] == i) {
173909f38230SBarry Smith         a->diag[i] = j;
174017ab2063SBarry Smith         break;
174117ab2063SBarry Smith       }
174217ab2063SBarry Smith     }
174317ab2063SBarry Smith   }
17443a40ed3dSBarry Smith   PetscFunctionReturn(0);
174517ab2063SBarry Smith }
174617ab2063SBarry Smith 
174761ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
174861ecd0c6SBarry Smith {
174961ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
175061ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
175161ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
175261ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
175361ecd0c6SBarry Smith   PetscErrorCode    ierr;
175461ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
175561ecd0c6SBarry Smith 
175661ecd0c6SBarry Smith   PetscFunctionBegin;
175761ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
175861ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
175961ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
176061ecd0c6SBarry Smith     PetscFunctionReturn(0);
176161ecd0c6SBarry Smith   }
176261ecd0c6SBarry Smith 
176361ecd0c6SBarry Smith   if (a->diagonaldense) {
176461ecd0c6SBarry Smith     cnt = 0;
176561ecd0c6SBarry Smith   } else {
176661ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
176761ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
176861ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
176961ecd0c6SBarry Smith         cnt++;
177061ecd0c6SBarry Smith         mdiag[i] = 1;
177161ecd0c6SBarry Smith       }
177261ecd0c6SBarry Smith     }
177361ecd0c6SBarry Smith   }
177461ecd0c6SBarry Smith   if (!cnt) {
177561ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
177661ecd0c6SBarry Smith   } else {
1777b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1778b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
177961ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
178061ecd0c6SBarry Smith 
178161ecd0c6SBarry Smith     a->a = NULL;
178261ecd0c6SBarry Smith     a->j = NULL;
178361ecd0c6SBarry Smith     a->i = NULL;
178461ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
178561ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
178661ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1787447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
178861ecd0c6SBarry Smith     }
178961ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
179061ecd0c6SBarry Smith 
179161ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
179261ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
179361ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1794447d62f5SStefano Zampini       if (i < A->cmap->n) {
179561ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
179661ecd0c6SBarry Smith       }
1797447d62f5SStefano Zampini     }
179861ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179961ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180061ecd0c6SBarry Smith     if (singlemalloc) {
180161ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
180261ecd0c6SBarry Smith     } else {
180361ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
180461ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
180561ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
180661ecd0c6SBarry Smith     }
180761ecd0c6SBarry Smith   }
180861ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
180961ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
181061ecd0c6SBarry Smith   PetscFunctionReturn(0);
181161ecd0c6SBarry Smith }
181261ecd0c6SBarry Smith 
1813be5855fcSBarry Smith /*
1814be5855fcSBarry Smith      Checks for missing diagonals
1815be5855fcSBarry Smith */
1816ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1817be5855fcSBarry Smith {
1818be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18197734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1820994fe344SLisandro Dalcin   PetscErrorCode ierr;
1821be5855fcSBarry Smith 
1822be5855fcSBarry Smith   PetscFunctionBegin;
182309f38230SBarry Smith   *missing = PETSC_FALSE;
18247734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
182509f38230SBarry Smith     *missing = PETSC_TRUE;
182609f38230SBarry Smith     if (d) *d = 0;
1827994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
182809f38230SBarry Smith   } else {
182901445905SHong Zhang     PetscInt n;
183001445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1831f1e2ffcdSBarry Smith     diag = a->diag;
183201445905SHong Zhang     for (i=0; i<n; i++) {
18337734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
183409f38230SBarry Smith         *missing = PETSC_TRUE;
183509f38230SBarry Smith         if (d) *d = i;
1836994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1837358d2f5dSShri Abhyankar         break;
183809f38230SBarry Smith       }
1839be5855fcSBarry Smith     }
1840be5855fcSBarry Smith   }
1841be5855fcSBarry Smith   PetscFunctionReturn(0);
1842be5855fcSBarry Smith }
1843be5855fcSBarry Smith 
18440da83c2eSBarry Smith #include <petscblaslapack.h>
18450da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18460da83c2eSBarry Smith 
18470da83c2eSBarry Smith /*
18480da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18490da83c2eSBarry Smith */
18500da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18510da83c2eSBarry Smith {
18520da83c2eSBarry Smith   PetscErrorCode  ierr;
18530da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18540da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18550da83c2eSBarry Smith   const PetscReal shift = 0.0;
18560da83c2eSBarry Smith   PetscInt        ipvt[5];
18570da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18580da83c2eSBarry Smith 
18590da83c2eSBarry Smith   PetscFunctionBegin;
18600da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18610da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18620da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18630da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18640da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18650da83c2eSBarry Smith   }
18660da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18670da83c2eSBarry Smith   if (bsizemax > 7) {
18680da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18690da83c2eSBarry Smith   }
18700da83c2eSBarry Smith   ncnt = 0;
18710da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18720da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18730da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18740da83c2eSBarry Smith     switch (bsizes[i]) {
18750da83c2eSBarry Smith     case 1:
18760da83c2eSBarry Smith       *diag = 1.0/(*diag);
18770da83c2eSBarry Smith       break;
18780da83c2eSBarry Smith     case 2:
18790da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18800da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18810da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18820da83c2eSBarry Smith       break;
18830da83c2eSBarry Smith     case 3:
18840da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18850da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18860da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18870da83c2eSBarry Smith       break;
18880da83c2eSBarry Smith     case 4:
18890da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18900da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18910da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18920da83c2eSBarry Smith       break;
18930da83c2eSBarry Smith     case 5:
18940da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18950da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18960da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18970da83c2eSBarry Smith       break;
18980da83c2eSBarry Smith     case 6:
18990da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19000da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19010da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
19020da83c2eSBarry Smith       break;
19030da83c2eSBarry Smith     case 7:
19040da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19050da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19060da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
19070da83c2eSBarry Smith       break;
19080da83c2eSBarry Smith     default:
19090da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19100da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19110da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19120da83c2eSBarry Smith     }
19130da83c2eSBarry Smith     ncnt   += bsizes[i];
19140da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19150da83c2eSBarry Smith   }
19160da83c2eSBarry Smith   if (bsizemax > 7) {
19170da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19180da83c2eSBarry Smith   }
19190da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19200da83c2eSBarry Smith   PetscFunctionReturn(0);
19210da83c2eSBarry Smith }
19220da83c2eSBarry Smith 
1923422a814eSBarry Smith /*
1924422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1925422a814eSBarry Smith */
19267087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
192771f1c65dSBarry Smith {
192871f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
192971f1c65dSBarry Smith   PetscErrorCode  ierr;
1930d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19312e5835c6SStefano Zampini   const MatScalar *v;
193254f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
193371f1c65dSBarry Smith 
193471f1c65dSBarry Smith   PetscFunctionBegin;
193571f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
193671f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
193771f1c65dSBarry Smith   diag = a->diag;
193871f1c65dSBarry Smith   if (!a->idiag) {
1939dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19403bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
194171f1c65dSBarry Smith   }
19422e5835c6SStefano Zampini 
194371f1c65dSBarry Smith   mdiag = a->mdiag;
194471f1c65dSBarry Smith   idiag = a->idiag;
19452e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1946422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
194771f1c65dSBarry Smith     for (i=0; i<m; i++) {
194871f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1949899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1950899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1951899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19527b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19537b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19547b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1955a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1956899639b0SHong Zhang       }
195771f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
195871f1c65dSBarry Smith     }
195971f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
196071f1c65dSBarry Smith   } else {
196171f1c65dSBarry Smith     for (i=0; i<m; i++) {
196271f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
196371f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
196471f1c65dSBarry Smith     }
1965dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
196671f1c65dSBarry Smith   }
196771f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19682e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
196971f1c65dSBarry Smith   PetscFunctionReturn(0);
197071f1c65dSBarry Smith }
197171f1c65dSBarry Smith 
1972c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
197341f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
197417ab2063SBarry Smith {
1975416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1976e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19772e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
197854f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1979dfbe8321SBarry Smith   PetscErrorCode    ierr;
19803d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
198197f1f81fSBarry Smith   const PetscInt    *idx,*diag;
198217ab2063SBarry Smith 
19833a40ed3dSBarry Smith   PetscFunctionBegin;
1984b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1985b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1986b215bc84SStefano Zampini     PetscFunctionReturn(0);
1987b215bc84SStefano Zampini   }
1988b965ef7fSBarry Smith   its = its*lits;
198991723122SBarry Smith 
199071f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
199171f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
199271f1c65dSBarry Smith   a->fshift = fshift;
199371f1c65dSBarry Smith   a->omega  = omega;
1994ed480e8bSBarry Smith 
199571f1c65dSBarry Smith   diag  = a->diag;
199671f1c65dSBarry Smith   t     = a->ssor_work;
1997ed480e8bSBarry Smith   idiag = a->idiag;
199871f1c65dSBarry Smith   mdiag = a->mdiag;
1999ed480e8bSBarry Smith 
20002e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
20011ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
20023649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
2003ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
200417ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
200517ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
2006ed480e8bSBarry Smith     bs = b;
200717ab2063SBarry Smith     for (i=0; i<m; i++) {
200871f1c65dSBarry Smith       d   = fshift + mdiag[i];
2009416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2010ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20112e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
201217ab2063SBarry Smith       sum = b[i]*d/omega;
2013003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
201417ab2063SBarry Smith       x[i] = sum;
201517ab2063SBarry Smith     }
20161ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20173649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20182e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2019efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20203a40ed3dSBarry Smith     PetscFunctionReturn(0);
202117ab2063SBarry Smith   }
2022c783ea89SBarry Smith 
20232205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20242205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20254c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2026887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
202717ab2063SBarry Smith 
202817ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
202917ab2063SBarry Smith 
2030887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
203117ab2063SBarry Smith     */
203217ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
203317ab2063SBarry Smith 
203417ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
203517ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2036416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2037ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20382e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
203917ab2063SBarry Smith       sum = b[i];
2040e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2041ed480e8bSBarry Smith       x[i] = sum*idiag[i];
204217ab2063SBarry Smith     }
204317ab2063SBarry Smith 
204417ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20452e5835c6SStefano Zampini     v = aa;
20462205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
204717ab2063SBarry Smith 
204817ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2049ed480e8bSBarry Smith     ts   = t;
2050416022c9SBarry Smith     diag = a->diag;
205117ab2063SBarry Smith     for (i=0; i<m; i++) {
2052416022c9SBarry Smith       n   = diag[i] - a->i[i];
2053ed480e8bSBarry Smith       idx = a->j + a->i[i];
20542e5835c6SStefano Zampini       v   = aa + a->i[i];
205517ab2063SBarry Smith       sum = t[i];
2056003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2057ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2058733d66baSBarry Smith       /*  x = x + t */
2059733d66baSBarry Smith       x[i] += t[i];
206017ab2063SBarry Smith     }
206117ab2063SBarry Smith 
2062dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20631ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20643649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20653a40ed3dSBarry Smith     PetscFunctionReturn(0);
206617ab2063SBarry Smith   }
206717ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
206817ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
206917ab2063SBarry Smith       for (i=0; i<m; i++) {
2070416022c9SBarry Smith         n   = diag[i] - a->i[i];
2071ed480e8bSBarry Smith         idx = a->j + a->i[i];
20722e5835c6SStefano Zampini         v   = aa + a->i[i];
207317ab2063SBarry Smith         sum = b[i];
2074e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20755c99c7daSBarry Smith         t[i] = sum;
2076ed480e8bSBarry Smith         x[i] = sum*idiag[i];
207717ab2063SBarry Smith       }
20785c99c7daSBarry Smith       xb   = t;
2079efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20803a40ed3dSBarry Smith     } else xb = b;
208117ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
208217ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2083416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2084ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20852e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
208617ab2063SBarry Smith         sum = xb[i];
2087e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20885c99c7daSBarry Smith         if (xb == b) {
2089ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20905c99c7daSBarry Smith         } else {
2091b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
209217ab2063SBarry Smith         }
20935c99c7daSBarry Smith       }
2094b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
209517ab2063SBarry Smith     }
209617ab2063SBarry Smith     its--;
209717ab2063SBarry Smith   }
209817ab2063SBarry Smith   while (its--) {
209917ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
210017ab2063SBarry Smith       for (i=0; i<m; i++) {
2101b19a5dc2SMark Adams         /* lower */
2102b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2103ed480e8bSBarry Smith         idx = a->j + a->i[i];
21042e5835c6SStefano Zampini         v   = aa + a->i[i];
210517ab2063SBarry Smith         sum = b[i];
2106e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2107b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2108b19a5dc2SMark Adams         /* upper */
2109b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2110b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21112e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2112b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2113b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
211417ab2063SBarry Smith       }
2115b19a5dc2SMark Adams       xb   = t;
21169f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2117b19a5dc2SMark Adams     } else xb = b;
211817ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
211917ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2120b19a5dc2SMark Adams         sum = xb[i];
2121b19a5dc2SMark Adams         if (xb == b) {
2122b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2123416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2124ed480e8bSBarry Smith           idx = a->j + a->i[i];
21252e5835c6SStefano Zampini           v   = aa + a->i[i];
2126e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2127ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2128b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2129b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2130b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21312e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2132b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2133b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
213417ab2063SBarry Smith         }
2135b19a5dc2SMark Adams       }
2136b19a5dc2SMark Adams       if (xb == b) {
21379f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2138b19a5dc2SMark Adams       } else {
2139b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2140b19a5dc2SMark Adams       }
214117ab2063SBarry Smith     }
214217ab2063SBarry Smith   }
21432e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21441ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21453649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2146365a8a9eSBarry Smith   PetscFunctionReturn(0);
214717ab2063SBarry Smith }
214817ab2063SBarry 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;
2341cb4a9cd9SHong Zhang   if (nz)  *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) {
3071dc29a518SPierre Jolivet     ierr = MatPropagateSymmetryOptions(A,*B);CHKERRQ(ierr);
30726768869dSprj-   }
30733a40ed3dSBarry Smith   PetscFunctionReturn(0);
30740513a670SBarry Smith }
30750513a670SBarry Smith 
3076dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3077cb5b572fSBarry Smith {
3078dfbe8321SBarry Smith   PetscErrorCode ierr;
3079cb5b572fSBarry Smith 
3080cb5b572fSBarry Smith   PetscFunctionBegin;
308133f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
308233f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3083be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3084be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30852e5835c6SStefano Zampini     const PetscScalar *aa;
3086be6bf707SBarry Smith 
30872e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30884d805d7cSStefano 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]);
30892e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3090cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
30912e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3092cb5b572fSBarry Smith   } else {
3093cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3094cb5b572fSBarry Smith   }
3095cb5b572fSBarry Smith   PetscFunctionReturn(0);
3096cb5b572fSBarry Smith }
3097cb5b572fSBarry Smith 
30984994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3099273d9f13SBarry Smith {
3100dfbe8321SBarry Smith   PetscErrorCode ierr;
3101273d9f13SBarry Smith 
3102273d9f13SBarry Smith   PetscFunctionBegin;
3103f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3104273d9f13SBarry Smith   PetscFunctionReturn(0);
3105273d9f13SBarry Smith }
3106273d9f13SBarry Smith 
3107f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
31086c0721eeSBarry Smith {
31096c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
31106e111a19SKarl Rupp 
31116c0721eeSBarry Smith   PetscFunctionBegin;
31126c0721eeSBarry Smith   *array = a->a;
31136c0721eeSBarry Smith   PetscFunctionReturn(0);
31146c0721eeSBarry Smith }
31156c0721eeSBarry Smith 
3116f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
31176c0721eeSBarry Smith {
31186c0721eeSBarry Smith   PetscFunctionBegin;
3119f38c1e66SStefano Zampini   *array = NULL;
31206c0721eeSBarry Smith   PetscFunctionReturn(0);
31216c0721eeSBarry Smith }
3122273d9f13SBarry Smith 
31238229c054SShri Abhyankar /*
31248229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
31258229c054SShri Abhyankar    have different nonzero structure.
31268229c054SShri Abhyankar */
3127b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3128ec7775f6SShri Abhyankar {
3129b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3130ec7775f6SShri Abhyankar 
3131ec7775f6SShri Abhyankar   PetscFunctionBegin;
3132ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3133ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3134b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3135b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3136b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31378af7cee1SJed Brown     nnz[i] = 0;
31388af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3139b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3140b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31418af7cee1SJed Brown       nnz[i]++;
31428af7cee1SJed Brown     }
31438af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3144ec7775f6SShri Abhyankar   }
3145ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3146ec7775f6SShri Abhyankar }
3147ec7775f6SShri Abhyankar 
3148b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3149b264fe52SHong Zhang {
3150b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3151b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3152b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3153b264fe52SHong Zhang   PetscErrorCode ierr;
3154b264fe52SHong Zhang 
3155b264fe52SHong Zhang   PetscFunctionBegin;
3156b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3157b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3158b264fe52SHong Zhang   PetscFunctionReturn(0);
3159b264fe52SHong Zhang }
3160b264fe52SHong Zhang 
3161f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3162ac90fabeSBarry Smith {
3163dfbe8321SBarry Smith   PetscErrorCode ierr;
3164ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3165ac90fabeSBarry Smith 
3166ac90fabeSBarry Smith   PetscFunctionBegin;
316741f5e1b1SStefano Zampini   if (str == UNKNOWN_NONZERO_PATTERN && x->nz == y->nz) {
316881fa06acSBarry Smith     PetscBool e;
316981fa06acSBarry Smith     ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
317081fa06acSBarry Smith     if (e) {
317181fa06acSBarry Smith       ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
317281fa06acSBarry Smith       if (e) {
317381fa06acSBarry Smith         str = SAME_NONZERO_PATTERN;
317481fa06acSBarry Smith       }
317581fa06acSBarry Smith     }
317681fa06acSBarry Smith   }
3177ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31782e5835c6SStefano Zampini     const PetscScalar *xa;
31792e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
318081fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
318181fa06acSBarry Smith 
318281fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31832e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31842e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31852e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31862e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31872e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
318841f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3189acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3190a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3191ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3192ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3193ac90fabeSBarry Smith   } else {
31948229c054SShri Abhyankar     Mat      B;
31958229c054SShri Abhyankar     PetscInt *nnz;
3196785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3197ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3198bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
319981fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
32002e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
32018229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3202ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3203ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
320428be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
32058229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3206ac90fabeSBarry Smith   }
3207ac90fabeSBarry Smith   PetscFunctionReturn(0);
3208ac90fabeSBarry Smith }
3209ac90fabeSBarry Smith 
32102726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3211354c94deSBarry Smith {
3212354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3213354c94deSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3214354c94deSBarry Smith   PetscInt       i,nz;
3215354c94deSBarry Smith   PetscScalar    *a;
3216ce496241SStefano Zampini   PetscErrorCode ierr;
3217354c94deSBarry Smith 
3218354c94deSBarry Smith   PetscFunctionBegin;
3219354c94deSBarry Smith   nz = aij->nz;
3220ce496241SStefano Zampini   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
32212205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3222ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3223354c94deSBarry Smith #else
3224354c94deSBarry Smith   PetscFunctionBegin;
3225354c94deSBarry Smith #endif
3226354c94deSBarry Smith   PetscFunctionReturn(0);
3227354c94deSBarry Smith }
3228354c94deSBarry Smith 
3229985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3230e34fafa9SBarry Smith {
3231e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3232e34fafa9SBarry Smith   PetscErrorCode  ierr;
3233d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3234e34fafa9SBarry Smith   PetscReal       atmp;
3235985db425SBarry Smith   PetscScalar     *x;
3236ce496241SStefano Zampini   const MatScalar *aa,*av;
3237e34fafa9SBarry Smith 
3238e34fafa9SBarry Smith   PetscFunctionBegin;
3239e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3240ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3241ce496241SStefano Zampini   aa = av;
3242e34fafa9SBarry Smith   ai = a->i;
3243e34fafa9SBarry Smith   aj = a->j;
3244e34fafa9SBarry Smith 
3245985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3246475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3247e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3248e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3249e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3250e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3251e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3252985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3253985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3254985db425SBarry Smith       aa++; aj++;
3255985db425SBarry Smith     }
3256985db425SBarry Smith   }
3257475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3258ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3259985db425SBarry Smith   PetscFunctionReturn(0);
3260985db425SBarry Smith }
3261985db425SBarry Smith 
3262985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3263985db425SBarry Smith {
3264985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3265985db425SBarry Smith   PetscErrorCode  ierr;
3266d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3267985db425SBarry Smith   PetscScalar     *x;
3268ce496241SStefano Zampini   const MatScalar *aa,*av;
3269985db425SBarry Smith 
3270985db425SBarry Smith   PetscFunctionBegin;
3271e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3272ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3273ce496241SStefano Zampini   aa = av;
3274985db425SBarry Smith   ai = a->i;
3275985db425SBarry Smith   aj = a->j;
3276985db425SBarry Smith 
3277985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3278fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3279985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3280e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3281985db425SBarry Smith   for (i=0; i<m; i++) {
3282985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3283d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3284985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3285985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3286985db425SBarry Smith       x[i] = 0.0;
3287985db425SBarry Smith       if (idx) {
3288985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3289985db425SBarry Smith           if (aj[j] > j) {
3290985db425SBarry Smith             idx[i] = j;
3291985db425SBarry Smith             break;
3292985db425SBarry Smith           }
3293985db425SBarry Smith         }
32941a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32951a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3296985db425SBarry Smith       }
3297985db425SBarry Smith     }
3298985db425SBarry Smith     for (j=0; j<ncols; j++) {
3299985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3300985db425SBarry Smith       aa++; aj++;
3301985db425SBarry Smith     }
3302985db425SBarry Smith   }
3303fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3304ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3305985db425SBarry Smith   PetscFunctionReturn(0);
3306985db425SBarry Smith }
3307985db425SBarry Smith 
3308c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3309c87e5d42SMatthew Knepley {
3310c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3311c87e5d42SMatthew Knepley   PetscErrorCode  ierr;
3312c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3313ce496241SStefano Zampini   PetscScalar     *x;
3314ce496241SStefano Zampini   const MatScalar *aa,*av;
3315c87e5d42SMatthew Knepley 
3316c87e5d42SMatthew Knepley   PetscFunctionBegin;
3317ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3318ce496241SStefano Zampini   aa = av;
3319c87e5d42SMatthew Knepley   ai = a->i;
3320c87e5d42SMatthew Knepley   aj = a->j;
3321c87e5d42SMatthew Knepley 
3322c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3323f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3324c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3325f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3326c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3327c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3328f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3329f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3330f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3331f07e67edSHong Zhang       x[i] = 0.0;
3332f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3333289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3334f07e67edSHong Zhang           if (aj[j] > j) {
3335f07e67edSHong Zhang             idx[i] = j;
33362205254eSKarl Rupp             break;
33372205254eSKarl Rupp           }
3338289a08f5SMatthew Knepley         }
3339f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3340f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3341f07e67edSHong Zhang       }
3342289a08f5SMatthew Knepley     }
3343c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3344f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3345c87e5d42SMatthew Knepley       aa++; aj++;
3346c87e5d42SMatthew Knepley     }
3347c87e5d42SMatthew Knepley   }
3348f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3349ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3350c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3351c87e5d42SMatthew Knepley }
3352c87e5d42SMatthew Knepley 
3353985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3354985db425SBarry Smith {
3355985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3356985db425SBarry Smith   PetscErrorCode  ierr;
3357d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3358d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3359985db425SBarry Smith   PetscScalar     *x;
3360ce496241SStefano Zampini   const MatScalar *aa,*av;
3361985db425SBarry Smith 
3362985db425SBarry Smith   PetscFunctionBegin;
3363e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3364ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3365ce496241SStefano Zampini   aa = av;
3366985db425SBarry Smith   ai = a->i;
3367985db425SBarry Smith   aj = a->j;
3368985db425SBarry Smith 
3369985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3370fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3371985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3372f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3373985db425SBarry Smith   for (i=0; i<m; i++) {
3374985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3375d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3376985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3377985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3378985db425SBarry Smith       x[i] = 0.0;
3379985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3380985db425SBarry Smith         for (j=0; j<ncols; j++) {
3381985db425SBarry Smith           if (aj[j] > j) {
3382985db425SBarry Smith             idx[i] = j;
3383985db425SBarry Smith             break;
3384985db425SBarry Smith           }
3385985db425SBarry Smith         }
3386fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3387fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3388985db425SBarry Smith       }
3389985db425SBarry Smith     }
3390985db425SBarry Smith     for (j=0; j<ncols; j++) {
3391985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3392985db425SBarry Smith       aa++; aj++;
3393e34fafa9SBarry Smith     }
3394e34fafa9SBarry Smith   }
3395fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3396ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3397e34fafa9SBarry Smith   PetscFunctionReturn(0);
3398e34fafa9SBarry Smith }
3399bbead8a2SBarry Smith 
3400713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3401bbead8a2SBarry Smith {
3402bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3403bbead8a2SBarry Smith   PetscErrorCode  ierr;
340433d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3405bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
34060da83c2eSBarry Smith   const PetscReal shift = 0.0;
34071a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3408bbead8a2SBarry Smith 
3409bbead8a2SBarry Smith   PetscFunctionBegin;
3410a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
34114a0d0026SBarry Smith   if (a->ibdiagvalid) {
34124a0d0026SBarry Smith     if (values) *values = a->ibdiag;
34134a0d0026SBarry Smith     PetscFunctionReturn(0);
34144a0d0026SBarry Smith   }
3415bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3416bbead8a2SBarry Smith   if (!a->ibdiag) {
3417785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
34183bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3419bbead8a2SBarry Smith   }
3420bbead8a2SBarry Smith   diag = a->ibdiag;
3421bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3422bbead8a2SBarry Smith   /* factor and invert each block */
3423bbead8a2SBarry Smith   switch (bs) {
3424bbead8a2SBarry Smith   case 1:
3425bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3426bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3427ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3428ec1892c8SHong Zhang         if (allowzeropivot) {
34297b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34307b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34317b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34327b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
34337b6c816cSBarry 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);
3434ec1892c8SHong Zhang       }
3435bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3436bbead8a2SBarry Smith     }
3437bbead8a2SBarry Smith     break;
3438bbead8a2SBarry Smith   case 2:
3439bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3440bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3441bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3442a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34437b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
344496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3445bbead8a2SBarry Smith       diag += 4;
3446bbead8a2SBarry Smith     }
3447bbead8a2SBarry Smith     break;
3448bbead8a2SBarry Smith   case 3:
3449bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3450bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3451bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3452a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34537b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3455bbead8a2SBarry Smith       diag += 9;
3456bbead8a2SBarry Smith     }
3457bbead8a2SBarry Smith     break;
3458bbead8a2SBarry Smith   case 4:
3459bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3460bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3461bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3462a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34637b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3465bbead8a2SBarry Smith       diag += 16;
3466bbead8a2SBarry Smith     }
3467bbead8a2SBarry Smith     break;
3468bbead8a2SBarry Smith   case 5:
3469bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3470bbead8a2SBarry 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;
3471bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3472a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34737b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
347496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3475bbead8a2SBarry Smith       diag += 25;
3476bbead8a2SBarry Smith     }
3477bbead8a2SBarry Smith     break;
3478bbead8a2SBarry Smith   case 6:
3479bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3480bbead8a2SBarry 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;
3481bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3482a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34837b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
348496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3485bbead8a2SBarry Smith       diag += 36;
3486bbead8a2SBarry Smith     }
3487bbead8a2SBarry Smith     break;
3488bbead8a2SBarry Smith   case 7:
3489bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3490bbead8a2SBarry 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;
3491bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3492a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34937b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
349496b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3495bbead8a2SBarry Smith       diag += 49;
3496bbead8a2SBarry Smith     }
3497bbead8a2SBarry Smith     break;
3498bbead8a2SBarry Smith   default:
3499dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3500bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3501bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3502bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3503bbead8a2SBarry Smith       }
3504bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
35055f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
35067b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
350796b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3508bbead8a2SBarry Smith       diag += bs2;
3509bbead8a2SBarry Smith     }
3510bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3511bbead8a2SBarry Smith   }
3512bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3513bbead8a2SBarry Smith   PetscFunctionReturn(0);
3514bbead8a2SBarry Smith }
3515bbead8a2SBarry Smith 
351673a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
351773a71a0fSBarry Smith {
351873a71a0fSBarry Smith   PetscErrorCode ierr;
351973a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
352073a71a0fSBarry Smith   PetscScalar    a;
352173a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
352273a71a0fSBarry Smith 
352373a71a0fSBarry Smith   PetscFunctionBegin;
352473a71a0fSBarry Smith   if (!x->assembled) {
352573a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
352673a71a0fSBarry Smith     for (i=0; i<m; i++) {
352773a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
352873a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
352973a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
353073a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
353173a71a0fSBarry Smith       }
353273a71a0fSBarry Smith     }
3533e2ce353bSJunchao Zhang   } else {
3534e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3535e2ce353bSJunchao Zhang   }
3536ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3537ce496241SStefano Zampini   if (x->offloadmask != PETSC_OFFLOAD_UNALLOCATED) x->offloadmask = PETSC_OFFLOAD_CPU;
3538ce496241SStefano Zampini #endif
353973a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
354073a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
354173a71a0fSBarry Smith   PetscFunctionReturn(0);
354273a71a0fSBarry Smith }
354373a71a0fSBarry Smith 
3544679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3545679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3546679944adSJunchao Zhang {
3547679944adSJunchao Zhang   PetscErrorCode ierr;
3548679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3549679944adSJunchao Zhang   PetscScalar    a;
3550679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3551679944adSJunchao Zhang 
3552679944adSJunchao Zhang   PetscFunctionBegin;
3553679944adSJunchao Zhang   nskip = high - low;
3554679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3555679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3556679944adSJunchao Zhang   for (i=0; i<m; i++) {
3557679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3558679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3559679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3560679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3561679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3562679944adSJunchao Zhang     }
3563e2ce353bSJunchao Zhang   }
3564679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3565679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3566679944adSJunchao Zhang   PetscFunctionReturn(0);
3567679944adSJunchao Zhang }
3568679944adSJunchao Zhang 
3569682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35700a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3571cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3572cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3573cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
357497304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35757c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35767c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3577f4259b30SLisandro Dalcin                                         NULL,
3578f4259b30SLisandro Dalcin                                         NULL,
3579f4259b30SLisandro Dalcin                                         NULL,
3580f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3581cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3582f4259b30SLisandro Dalcin                                         NULL,
358341f059aeSBarry Smith                                         MatSOR_SeqAIJ,
358491e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
358597304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3586cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3587cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3588cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3589cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3590f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3591cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3592cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3593cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3594d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3595f4259b30SLisandro Dalcin                                         NULL,
3596f4259b30SLisandro Dalcin                                         NULL,
3597f4259b30SLisandro Dalcin                                         NULL,
3598f4259b30SLisandro Dalcin                                         NULL,
35994994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3600f4259b30SLisandro Dalcin                                         NULL,
3601f4259b30SLisandro Dalcin                                         NULL,
3602f4259b30SLisandro Dalcin                                         NULL,
3603f4259b30SLisandro Dalcin                                         NULL,
3604d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3605f4259b30SLisandro Dalcin                                         NULL,
3606f4259b30SLisandro Dalcin                                         NULL,
3607cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3608f4259b30SLisandro Dalcin                                         NULL,
3609d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
36107dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3611cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3612cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3613cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3614d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3615cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
36167d68702bSBarry Smith                                         MatShift_SeqAIJ,
361779299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
36186e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
361973a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
36203b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
36213b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
36223b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3623a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
362493dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3625f4259b30SLisandro Dalcin                                         NULL,
3626f4259b30SLisandro Dalcin                                         NULL,
3627cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3628f4259b30SLisandro Dalcin                                         NULL,
3629f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3630b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3631b9b97703SBarry Smith                                         MatView_SeqAIJ,
3632f4259b30SLisandro Dalcin                                         NULL,
3633f4259b30SLisandro Dalcin                                         NULL,
3634f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3635321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3636f4259b30SLisandro Dalcin                                         NULL,
3637f4259b30SLisandro Dalcin                                         NULL,
3638f4259b30SLisandro Dalcin                                         NULL,
3639d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3640c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3641f4259b30SLisandro Dalcin                                         NULL,
3642f4259b30SLisandro Dalcin                                         NULL,
3643f4259b30SLisandro Dalcin                                         NULL,
3644f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36453acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3646f4259b30SLisandro Dalcin                                         NULL,
3647f4259b30SLisandro Dalcin                                         NULL,
3648f4259b30SLisandro Dalcin                                         NULL,
36496ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3650f4259b30SLisandro Dalcin                                         NULL,
3651f4259b30SLisandro Dalcin                                         NULL,
3652f4259b30SLisandro Dalcin                                         NULL,
3653bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3654d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36551cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3656f4259b30SLisandro Dalcin                                         NULL,
3657f4259b30SLisandro Dalcin                                         NULL,
3658f4259b30SLisandro Dalcin                                         NULL,
3659f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3660f4259b30SLisandro Dalcin                                         NULL,
366126be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3662f4259b30SLisandro Dalcin                                         NULL,
3663f4259b30SLisandro Dalcin                                         NULL,
36648fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3665f4259b30SLisandro Dalcin                                         NULL,
3666f4259b30SLisandro Dalcin                                         NULL,
36676fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3668f4259b30SLisandro Dalcin                                         NULL,
36694222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3670f4259b30SLisandro Dalcin                                         NULL,
3671f4259b30SLisandro Dalcin                                         NULL,
367287d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3673f4259b30SLisandro Dalcin                                         NULL,
3674d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
367599cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3676f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3677f4259b30SLisandro Dalcin                                         NULL,
3678f4259b30SLisandro Dalcin                                         NULL,
3679cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3680f4259b30SLisandro Dalcin                                         NULL,
36812af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3682f4259b30SLisandro Dalcin                                         NULL,
3683599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3684f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3685f4259b30SLisandro Dalcin                                         NULL,
3686f4259b30SLisandro Dalcin                                         NULL,
3687f4259b30SLisandro Dalcin                                         NULL,
3688f4259b30SLisandro Dalcin                                         NULL,
3689f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3690f4259b30SLisandro Dalcin                                         NULL,
3691f4259b30SLisandro Dalcin                                         NULL,
3692f4259b30SLisandro Dalcin                                         NULL,
3693b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36940716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3695bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
369637868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36970da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3698f4259b30SLisandro Dalcin                                         NULL,
3699f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3700f4259b30SLisandro Dalcin                                         NULL,
3701f4259b30SLisandro Dalcin                                         NULL,
370275648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3703b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3704b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
37052b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3706f4259b30SLisandro Dalcin                                         NULL,
3707f4259b30SLisandro Dalcin                                         NULL,
37083964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3709f4259b30SLisandro Dalcin                                  /*139*/NULL,
3710f4259b30SLisandro Dalcin                                         NULL,
3711f4259b30SLisandro Dalcin                                         NULL,
37123a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
37139c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
37144222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
37154222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3716f4259b30SLisandro Dalcin                                         NULL,
3717f4259b30SLisandro Dalcin                                         NULL
37189e29f15eSvictorle };
371917ab2063SBarry Smith 
37207087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3721bef8e0ddSBarry Smith {
3722bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
372397f1f81fSBarry Smith   PetscInt   i,nz,n;
3724bef8e0ddSBarry Smith 
3725bef8e0ddSBarry Smith   PetscFunctionBegin;
3726bef8e0ddSBarry Smith   nz = aij->maxnz;
3727d0f46423SBarry Smith   n  = mat->rmap->n;
3728bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3729bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3730bef8e0ddSBarry Smith   }
3731bef8e0ddSBarry Smith   aij->nz = nz;
3732bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3733bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3734bef8e0ddSBarry Smith   }
3735bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3736bef8e0ddSBarry Smith }
3737bef8e0ddSBarry Smith 
3738a3bb6f32SFande Kong /*
3739*ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3740*ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3741*ddea5d60SJunchao Zhang  */
3742a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3743a3bb6f32SFande Kong {
3744a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3745a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3746a3bb6f32SFande Kong   PetscTablePosition tpos;
374725b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
374825b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3749a3bb6f32SFande Kong   PetscErrorCode     ierr;
3750a3bb6f32SFande Kong 
3751a3bb6f32SFande Kong   PetscFunctionBegin;
3752a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3753a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3754a3bb6f32SFande Kong   /* use a table */
3755a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3756a3bb6f32SFande Kong   ec = 0;
375725b670f0SStefano Zampini   for (i=0; i<nz; i++) {
375825b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3759a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3760a3bb6f32SFande Kong     if (!data) {
3761a3bb6f32SFande Kong       /* one based table */
3762a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3763a3bb6f32SFande Kong     }
3764a3bb6f32SFande Kong   }
3765a3bb6f32SFande Kong   /* form array of columns we need */
3766b3c64f9dSJunchao Zhang   ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr);
3767a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3768a3bb6f32SFande Kong   while (tpos) {
3769a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3770a3bb6f32SFande Kong     gid--;
3771a3bb6f32SFande Kong     lid--;
3772a3bb6f32SFande Kong     garray[lid] = gid;
3773a3bb6f32SFande Kong   }
3774a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3775a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3776a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3777a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3778a3bb6f32SFande Kong   }
3779a3bb6f32SFande Kong   /* compact out the extra columns in B */
378025b670f0SStefano Zampini   for (i=0; i<nz; i++) {
378125b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3782a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3783a3bb6f32SFande Kong     lid--;
378425b670f0SStefano Zampini     jj[i] = lid;
3785a3bb6f32SFande Kong   }
3786ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3787a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
378825b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3789a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3790a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3791a3bb6f32SFande Kong   PetscFunctionReturn(0);
3792a3bb6f32SFande Kong }
3793a3bb6f32SFande Kong 
3794bef8e0ddSBarry Smith /*@
3795bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3796bef8e0ddSBarry Smith        in the matrix.
3797bef8e0ddSBarry Smith 
3798bef8e0ddSBarry Smith   Input Parameters:
3799bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3800bef8e0ddSBarry Smith -  indices - the column indices
3801bef8e0ddSBarry Smith 
380215091d37SBarry Smith   Level: advanced
380315091d37SBarry Smith 
3804bef8e0ddSBarry Smith   Notes:
3805bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3806bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3807bef8e0ddSBarry Smith   of the MatSetValues() operation.
3808bef8e0ddSBarry Smith 
3809bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3810d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3811bef8e0ddSBarry Smith 
3812bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3813bef8e0ddSBarry Smith 
3814b9617806SBarry Smith     The indices should start with zero, not one.
3815b9617806SBarry Smith 
3816bef8e0ddSBarry Smith @*/
38177087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3818bef8e0ddSBarry Smith {
38194ac538c5SBarry Smith   PetscErrorCode ierr;
3820bef8e0ddSBarry Smith 
3821bef8e0ddSBarry Smith   PetscFunctionBegin;
38220700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38234482741eSBarry Smith   PetscValidPointer(indices,2);
38244ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3825bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3826bef8e0ddSBarry Smith }
3827bef8e0ddSBarry Smith 
3828be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3829be6bf707SBarry Smith 
38307087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3831be6bf707SBarry Smith {
3832be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38336849ba73SBarry Smith   PetscErrorCode ierr;
3834d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3835be6bf707SBarry Smith 
3836be6bf707SBarry Smith   PetscFunctionBegin;
3837169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3838be6bf707SBarry Smith 
3839be6bf707SBarry Smith   /* allocate space for values if not already there */
3840be6bf707SBarry Smith   if (!aij->saved_values) {
3841854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38423bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3843be6bf707SBarry Smith   }
3844be6bf707SBarry Smith 
3845be6bf707SBarry Smith   /* copy values over */
3846580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3847be6bf707SBarry Smith   PetscFunctionReturn(0);
3848be6bf707SBarry Smith }
3849be6bf707SBarry Smith 
3850be6bf707SBarry Smith /*@
3851be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3852be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3853be6bf707SBarry Smith        nonlinear portion.
3854be6bf707SBarry Smith 
3855be6bf707SBarry Smith    Collect on Mat
3856be6bf707SBarry Smith 
3857be6bf707SBarry Smith   Input Parameters:
38580e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3859be6bf707SBarry Smith 
386015091d37SBarry Smith   Level: advanced
386115091d37SBarry Smith 
3862be6bf707SBarry Smith   Common Usage, with SNESSolve():
3863be6bf707SBarry Smith $    Create Jacobian matrix
3864be6bf707SBarry Smith $    Set linear terms into matrix
3865be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3866be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3867be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3868512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3869be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3870be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3871be6bf707SBarry Smith $    In your Jacobian routine
3872be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3873be6bf707SBarry Smith $      Set nonlinear terms in matrix
3874be6bf707SBarry Smith 
3875be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3876be6bf707SBarry Smith $    // build linear portion of Jacobian
3877512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3878be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3879be6bf707SBarry Smith $    loop over nonlinear iterations
3880be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3881be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3882be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3883be6bf707SBarry Smith $       Solve linear system with Jacobian
3884be6bf707SBarry Smith $    endloop
3885be6bf707SBarry Smith 
3886be6bf707SBarry Smith   Notes:
3887be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3888512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3889be6bf707SBarry Smith     calling this routine.
3890be6bf707SBarry Smith 
38910c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38920c468ba9SBarry Smith     and does not allocated additional space.
38930c468ba9SBarry Smith 
3894be6bf707SBarry Smith .seealso: MatRetrieveValues()
3895be6bf707SBarry Smith 
3896be6bf707SBarry Smith @*/
38977087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3898be6bf707SBarry Smith {
38994ac538c5SBarry Smith   PetscErrorCode ierr;
3900be6bf707SBarry Smith 
3901be6bf707SBarry Smith   PetscFunctionBegin;
39020700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3903e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3904e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39054ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3906be6bf707SBarry Smith   PetscFunctionReturn(0);
3907be6bf707SBarry Smith }
3908be6bf707SBarry Smith 
39097087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3910be6bf707SBarry Smith {
3911be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
39126849ba73SBarry Smith   PetscErrorCode ierr;
3913d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3914be6bf707SBarry Smith 
3915be6bf707SBarry Smith   PetscFunctionBegin;
3916169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3917f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3918be6bf707SBarry Smith   /* copy values over */
3919580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3920be6bf707SBarry Smith   PetscFunctionReturn(0);
3921be6bf707SBarry Smith }
3922be6bf707SBarry Smith 
3923be6bf707SBarry Smith /*@
3924be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3925be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3926be6bf707SBarry Smith        nonlinear portion.
3927be6bf707SBarry Smith 
3928be6bf707SBarry Smith    Collect on Mat
3929be6bf707SBarry Smith 
3930be6bf707SBarry Smith   Input Parameters:
3931386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3932be6bf707SBarry Smith 
393315091d37SBarry Smith   Level: advanced
393415091d37SBarry Smith 
3935be6bf707SBarry Smith .seealso: MatStoreValues()
3936be6bf707SBarry Smith 
3937be6bf707SBarry Smith @*/
39387087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3939be6bf707SBarry Smith {
39404ac538c5SBarry Smith   PetscErrorCode ierr;
3941be6bf707SBarry Smith 
3942be6bf707SBarry Smith   PetscFunctionBegin;
39430700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3944e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3945e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39464ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3947be6bf707SBarry Smith   PetscFunctionReturn(0);
3948be6bf707SBarry Smith }
3949be6bf707SBarry Smith 
3950be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
395117ab2063SBarry Smith /*@C
3952682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39530d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39546e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
395551c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39562bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
395717ab2063SBarry Smith 
3958d083f849SBarry Smith    Collective
3959db81eaa0SLois Curfman McInnes 
396017ab2063SBarry Smith    Input Parameters:
3961db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
396217ab2063SBarry Smith .  m - number of rows
396317ab2063SBarry Smith .  n - number of columns
396417ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
396551c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39660298fd71SBarry Smith          (possibly different for each row) or NULL
396717ab2063SBarry Smith 
396817ab2063SBarry Smith    Output Parameter:
3969416022c9SBarry Smith .  A - the matrix
397017ab2063SBarry Smith 
3971175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3972f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3973175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3974175b88e8SBarry Smith 
3975b259b22eSLois Curfman McInnes    Notes:
397649a6f317SBarry Smith    If nnz is given then nz is ignored
397749a6f317SBarry Smith 
397817ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
397917ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39800002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
398144cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
398217ab2063SBarry Smith 
398317ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39840298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39853d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39866da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
398717ab2063SBarry Smith 
3988682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39894fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3990682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39916c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39926c7ebb05SLois Curfman McInnes 
39936c7ebb05SLois Curfman McInnes    Options Database Keys:
3994698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39959db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
399617ab2063SBarry Smith 
3997027ccd11SLois Curfman McInnes    Level: intermediate
3998027ccd11SLois Curfman McInnes 
399969b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
400036db0b34SBarry Smith 
400117ab2063SBarry Smith @*/
40027087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
400317ab2063SBarry Smith {
4004dfbe8321SBarry Smith   PetscErrorCode ierr;
40056945ee14SBarry Smith 
40063a40ed3dSBarry Smith   PetscFunctionBegin;
4007f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
4008117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
4009c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
4010d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
4011273d9f13SBarry Smith   PetscFunctionReturn(0);
4012273d9f13SBarry Smith }
4013273d9f13SBarry Smith 
4014273d9f13SBarry Smith /*@C
4015273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
4016273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
4017273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
4018273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
4019273d9f13SBarry Smith 
4020d083f849SBarry Smith    Collective
4021273d9f13SBarry Smith 
4022273d9f13SBarry Smith    Input Parameters:
40231c4f3114SJed Brown +  B - The matrix
4024273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
4025273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
40260298fd71SBarry Smith          (possibly different for each row) or NULL
4027273d9f13SBarry Smith 
4028273d9f13SBarry Smith    Notes:
402949a6f317SBarry Smith      If nnz is given then nz is ignored
403049a6f317SBarry Smith 
4031273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4032273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4033273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4034273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4035273d9f13SBarry Smith 
4036273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40370298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4038273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4039273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4040273d9f13SBarry Smith 
4041aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4042aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4043aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4044aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4045aa95bbe8SBarry Smith 
4046a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4047a96a251dSBarry Smith    entries or columns indices
4048a96a251dSBarry Smith 
4049273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4050273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4051273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4052273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4053273d9f13SBarry Smith 
4054273d9f13SBarry Smith    Options Database Keys:
4055698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
405647b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4057273d9f13SBarry Smith 
4058273d9f13SBarry Smith    Level: intermediate
4059273d9f13SBarry Smith 
406019b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
406119b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4062273d9f13SBarry Smith 
4063273d9f13SBarry Smith @*/
40647087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4065273d9f13SBarry Smith {
40664ac538c5SBarry Smith   PetscErrorCode ierr;
4067a23d5eceSKris Buschelman 
4068a23d5eceSKris Buschelman   PetscFunctionBegin;
40696ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40706ba663aaSJed Brown   PetscValidType(B,1);
40714ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4072a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4073a23d5eceSKris Buschelman }
4074a23d5eceSKris Buschelman 
40757087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4076a23d5eceSKris Buschelman {
4077273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40782576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40796849ba73SBarry Smith   PetscErrorCode ierr;
408097f1f81fSBarry Smith   PetscInt       i;
4081273d9f13SBarry Smith 
4082273d9f13SBarry Smith   PetscFunctionBegin;
40832576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4084a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4085c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4086c461c341SBarry Smith     nz             = 0;
4087c461c341SBarry Smith   }
408826283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
408926283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4090899cda47SBarry Smith 
4091435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
409260e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4093cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4094d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
409560e0710aSBarry 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]);
409660e0710aSBarry 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);
4097b73539f3SBarry Smith     }
4098b73539f3SBarry Smith   }
4099b73539f3SBarry Smith 
4100273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
41012205254eSKarl Rupp 
4102273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4103273d9f13SBarry Smith 
4104ab93d7beSBarry Smith   if (!skipallocation) {
41052ee49352SLisandro Dalcin     if (!b->imax) {
4106071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4107071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4108071fcb05SBarry Smith     }
4109071fcb05SBarry Smith     if (!b->ilen) {
4110071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4111071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4112071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4113071fcb05SBarry Smith     } else {
4114071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
41152ee49352SLisandro Dalcin     }
4116846b4da1SFande Kong     if (!b->ipre) {
4117846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4118846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4119846b4da1SFande Kong     }
4120273d9f13SBarry Smith     if (!nnz) {
4121435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4122c62bd62aSJed Brown       else if (nz < 0) nz = 1;
41235d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4124d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4125d0f46423SBarry Smith       nz = nz*B->rmap->n;
4126273d9f13SBarry Smith     } else {
4127c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4128c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4129c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4130273d9f13SBarry Smith     }
4131ab93d7beSBarry Smith 
4132273d9f13SBarry Smith     /* allocate the matrix space */
413353dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41342ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4135396832f4SHong Zhang     if (B->structure_only) {
41365848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41375848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4138396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4139396832f4SHong Zhang     } else {
4140dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41413bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4142396832f4SHong Zhang     }
4143bfeeae90SHong Zhang     b->i[0] = 0;
4144d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41455da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41465da197adSKris Buschelman     }
4147396832f4SHong Zhang     if (B->structure_only) {
4148396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4149396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4150396832f4SHong Zhang     } else {
4151273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4152e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4153396832f4SHong Zhang     }
4154e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4155c461c341SBarry Smith   } else {
4156e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4157e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4158c461c341SBarry Smith   }
4159273d9f13SBarry Smith 
4160846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4161846b4da1SFande Kong     /* reserve user-requested sparsity */
4162580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4163846b4da1SFande Kong   }
4164846b4da1SFande Kong 
4165273d9f13SBarry Smith   b->nz               = 0;
4166273d9f13SBarry Smith   b->maxnz            = nz;
4167273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41682205254eSKarl Rupp   if (realalloc) {
41692205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41702205254eSKarl Rupp   }
4171cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4172cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4173273d9f13SBarry Smith   PetscFunctionReturn(0);
4174273d9f13SBarry Smith }
4175273d9f13SBarry Smith 
4176846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4177846b4da1SFande Kong {
4178846b4da1SFande Kong   Mat_SeqAIJ     *a;
4179a5bbaf83SFande Kong   PetscInt       i;
4180846b4da1SFande Kong   PetscErrorCode ierr;
4181846b4da1SFande Kong 
4182846b4da1SFande Kong   PetscFunctionBegin;
4183846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
418414d0e64fSAlex Lindsay 
418514d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
418614d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
418714d0e64fSAlex Lindsay 
4188846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41892c814fdeSFande Kong   /* if no saved info, we error out */
4190fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
41912c814fdeSFande Kong 
4192fb4dc15dSAlex 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");
41932c814fdeSFande Kong 
4194580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4195580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4196846b4da1SFande Kong   a->i[0] = 0;
4197846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4198846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4199846b4da1SFande Kong   }
4200846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4201846b4da1SFande Kong   a->nz               = 0;
4202846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4203846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4204846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4205846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4206846b4da1SFande Kong   PetscFunctionReturn(0);
4207846b4da1SFande Kong }
4208846b4da1SFande Kong 
420958d36128SBarry Smith /*@
4210a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4211a1661176SMatthew Knepley 
4212a1661176SMatthew Knepley    Input Parameters:
4213a1661176SMatthew Knepley +  B - the matrix
4214a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4215a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4216a1661176SMatthew Knepley -  v - optional values in the matrix
4217a1661176SMatthew Knepley 
4218a1661176SMatthew Knepley    Level: developer
4219a1661176SMatthew Knepley 
42206a9b8d82SBarry Smith    Notes:
422158d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
422258d36128SBarry Smith 
42236a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
42246a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
42256a9b8d82SBarry Smith 
42266a9b8d82SBarry Smith     Developer Notes:
42276a9b8d82SBarry 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
42286a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
42296a9b8d82SBarry Smith 
42306a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
42316a9b8d82SBarry Smith 
42326a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4233a1661176SMatthew Knepley @*/
4234a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4235a1661176SMatthew Knepley {
4236a1661176SMatthew Knepley   PetscErrorCode ierr;
4237a1661176SMatthew Knepley 
4238a1661176SMatthew Knepley   PetscFunctionBegin;
42390700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42406ba663aaSJed Brown   PetscValidType(B,1);
42414ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4242a1661176SMatthew Knepley   PetscFunctionReturn(0);
4243a1661176SMatthew Knepley }
4244a1661176SMatthew Knepley 
42457087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4246a1661176SMatthew Knepley {
4247a1661176SMatthew Knepley   PetscInt       i;
4248a1661176SMatthew Knepley   PetscInt       m,n;
4249a1661176SMatthew Knepley   PetscInt       nz;
42506a9b8d82SBarry Smith   PetscInt       *nnz;
4251a1661176SMatthew Knepley   PetscErrorCode ierr;
4252a1661176SMatthew Knepley 
4253a1661176SMatthew Knepley   PetscFunctionBegin;
425465e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4255779a8d59SSatish Balay 
4256779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4257779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4258779a8d59SSatish Balay 
4259779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4260854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4261a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4262b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
426365e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4264a1661176SMatthew Knepley     nnz[i] = nz;
4265a1661176SMatthew Knepley   }
4266a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4267a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4268a1661176SMatthew Knepley 
4269a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4270071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4271a1661176SMatthew Knepley   }
4272a1661176SMatthew Knepley 
4273a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4274a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4275a1661176SMatthew Knepley 
42767827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4277a1661176SMatthew Knepley   PetscFunctionReturn(0);
4278a1661176SMatthew Knepley }
4279a1661176SMatthew Knepley 
4280ad7e164aSPierre Jolivet /*@
4281ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4282ad7e164aSPierre Jolivet 
4283ad7e164aSPierre Jolivet    Input Parameters:
4284ad7e164aSPierre Jolivet +  A - left-hand side matrix
4285ad7e164aSPierre Jolivet .  B - right-hand side matrix
4286ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4287ad7e164aSPierre Jolivet 
4288ad7e164aSPierre Jolivet    Output Parameter:
4289ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4290ad7e164aSPierre Jolivet 
4291ad7e164aSPierre Jolivet    Level: intermediate
4292ad7e164aSPierre Jolivet 
4293ad7e164aSPierre Jolivet    Notes:
4294ad7e164aSPierre Jolivet       MAT_REUSE_MATRIX can only be used when the nonzero structure of the product matrix has not changed from that last call to MatSeqAIJKron().
4295ad7e164aSPierre Jolivet 
4296ad7e164aSPierre Jolivet .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4297ad7e164aSPierre Jolivet @*/
4298ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4299ad7e164aSPierre Jolivet {
4300ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4301ad7e164aSPierre Jolivet 
4302ad7e164aSPierre Jolivet   PetscFunctionBegin;
4303ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4304ad7e164aSPierre Jolivet   PetscValidType(A,1);
4305ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4306ad7e164aSPierre Jolivet   PetscValidType(B,2);
4307ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4308ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4309ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4310ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4311ad7e164aSPierre Jolivet   }
4312ad7e164aSPierre Jolivet   ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr);
4313ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4314ad7e164aSPierre Jolivet }
4315ad7e164aSPierre Jolivet 
4316ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4317ad7e164aSPierre Jolivet {
4318ad7e164aSPierre Jolivet   Mat            newmat;
4319ad7e164aSPierre Jolivet   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4320ad7e164aSPierre Jolivet   Mat_SeqAIJ     *b = (Mat_SeqAIJ*)B->data;
4321ad7e164aSPierre Jolivet   PetscScalar    *v;
4322ad7e164aSPierre Jolivet   PetscInt       *i,*j,m,n,p,q,nnz = 0,am = A->rmap->n,bm = B->rmap->n,an = A->cmap->n, bn = B->cmap->n;
4323ad7e164aSPierre Jolivet   PetscBool      flg;
4324ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4325ad7e164aSPierre Jolivet 
4326ad7e164aSPierre Jolivet   PetscFunctionBegin;
4327ad7e164aSPierre Jolivet   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4328ad7e164aSPierre Jolivet   if (!A->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4329ad7e164aSPierre Jolivet   if (B->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4330ad7e164aSPierre Jolivet   if (!B->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4331ad7e164aSPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
4332ad7e164aSPierre Jolivet   if (!flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
4333ad7e164aSPierre Jolivet   if (reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4334ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
4335ad7e164aSPierre Jolivet     ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr);
4336ad7e164aSPierre Jolivet     ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr);
4337ad7e164aSPierre Jolivet     ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr);
4338ad7e164aSPierre Jolivet     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
4339ad7e164aSPierre Jolivet     i[0] = 0;
4340ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4341ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4342ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4343ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4344ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4345ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4346ad7e164aSPierre Jolivet           }
4347ad7e164aSPierre Jolivet         }
4348ad7e164aSPierre Jolivet       }
4349ad7e164aSPierre Jolivet     }
4350ad7e164aSPierre Jolivet     ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr);
4351ad7e164aSPierre Jolivet     *C = newmat;
4352ad7e164aSPierre Jolivet     ierr = PetscFree2(i,j);CHKERRQ(ierr);
4353ad7e164aSPierre Jolivet     nnz = 0;
4354ad7e164aSPierre Jolivet   }
4355ad7e164aSPierre Jolivet   ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr);
4356ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4357ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4358ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4359ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4360ad7e164aSPierre Jolivet           v[nnz++] = a->a[n] * b->a[q];
4361ad7e164aSPierre Jolivet         }
4362ad7e164aSPierre Jolivet       }
4363ad7e164aSPierre Jolivet     }
4364ad7e164aSPierre Jolivet   }
4365ad7e164aSPierre Jolivet   ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr);
4366ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4367ad7e164aSPierre Jolivet }
4368ad7e164aSPierre Jolivet 
4369c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4370af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4371170fe5c8SBarry Smith 
4372170fe5c8SBarry Smith /*
4373170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4374170fe5c8SBarry Smith 
4375170fe5c8SBarry Smith                n                       p                          p
43762da392ccSBarry Smith         [             ]       [             ]         [                 ]
43772da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
43782da392ccSBarry Smith         [             ]       [             ]         [                 ]
4379170fe5c8SBarry Smith 
4380170fe5c8SBarry Smith */
4381170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4382170fe5c8SBarry Smith {
4383170fe5c8SBarry Smith   PetscErrorCode    ierr;
4384170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4385170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4386170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
438786214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4388170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4389170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4390170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
439186214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
439286214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4393170fe5c8SBarry Smith 
4394170fe5c8SBarry Smith   PetscFunctionBegin;
4395d0f46423SBarry Smith   m    = A->rmap->n;
4396d0f46423SBarry Smith   n    = A->cmap->n;
4397d0f46423SBarry Smith   p    = B->cmap->n;
4398170fe5c8SBarry Smith   a    = sub_a->v;
4399170fe5c8SBarry Smith   b    = sub_b->a;
4400170fe5c8SBarry Smith   c    = sub_c->v;
440186214ceeSStefano Zampini   if (clda == m) {
4402580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
440386214ceeSStefano Zampini   } else {
440486214ceeSStefano Zampini     for (j=0;j<p;j++)
440586214ceeSStefano Zampini       for (i=0;i<m;i++)
440686214ceeSStefano Zampini         c[j*clda + i] = 0.0;
440786214ceeSStefano Zampini   }
4408170fe5c8SBarry Smith   ii  = sub_b->i;
4409170fe5c8SBarry Smith   idx = sub_b->j;
4410170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4411170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4412170fe5c8SBarry Smith     while (q-->0) {
441386214ceeSStefano Zampini       c_q = c + clda*(*idx);
441486214ceeSStefano Zampini       a_q = a + alda*i;
4415854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4416170fe5c8SBarry Smith       idx++;
4417170fe5c8SBarry Smith       b++;
4418170fe5c8SBarry Smith     }
4419170fe5c8SBarry Smith   }
4420170fe5c8SBarry Smith   PetscFunctionReturn(0);
4421170fe5c8SBarry Smith }
4422170fe5c8SBarry Smith 
44234222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4424170fe5c8SBarry Smith {
4425170fe5c8SBarry Smith   PetscErrorCode ierr;
4426d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
442786214ceeSStefano Zampini   PetscBool      cisdense;
4428170fe5c8SBarry Smith 
4429170fe5c8SBarry Smith   PetscFunctionBegin;
443060e0710aSBarry 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);
44314222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
44324222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
443386214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
443486214ceeSStefano Zampini   if (!cisdense) {
443586214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
443686214ceeSStefano Zampini   }
443786214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4438d73949e8SHong Zhang 
44394222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4440170fe5c8SBarry Smith   PetscFunctionReturn(0);
4441170fe5c8SBarry Smith }
4442170fe5c8SBarry Smith 
4443170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
44440bad9183SKris Buschelman /*MC
4445fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
44460bad9183SKris Buschelman    based on compressed sparse row format.
44470bad9183SKris Buschelman 
44480bad9183SKris Buschelman    Options Database Keys:
44490bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
44500bad9183SKris Buschelman 
44510bad9183SKris Buschelman    Level: beginner
44520bad9183SKris Buschelman 
44530cd7f59aSBarry Smith    Notes:
44540cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
44550cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
44560cd7f59aSBarry Smith     in the matrix
44570cd7f59aSBarry Smith 
44580cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
44590cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
44600cd7f59aSBarry Smith 
44610cd7f59aSBarry Smith   Developer Notes:
44620cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
44630cd7f59aSBarry Smith 
4464f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
44650bad9183SKris Buschelman M*/
44660bad9183SKris Buschelman 
4467ccd284c7SBarry Smith /*MC
4468ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4469ccd284c7SBarry Smith 
4470ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4471ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
44720cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4473ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4474ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4475ccd284c7SBarry Smith 
4476ccd284c7SBarry Smith    Options Database Keys:
4477ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4478ccd284c7SBarry Smith 
447995452b02SPatrick Sanan   Developer Notes:
4480ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4481ccd284c7SBarry Smith    enough exist.
4482ccd284c7SBarry Smith 
4483ccd284c7SBarry Smith   Level: beginner
4484ccd284c7SBarry Smith 
4485ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4486ccd284c7SBarry Smith M*/
4487ccd284c7SBarry Smith 
4488ccd284c7SBarry Smith /*MC
4489ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4490ccd284c7SBarry Smith 
4491ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4492ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4493ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4494ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4495ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4496ccd284c7SBarry Smith 
4497ccd284c7SBarry Smith    Options Database Keys:
4498ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4499ccd284c7SBarry Smith 
4500ccd284c7SBarry Smith   Level: beginner
4501ccd284c7SBarry Smith 
4502ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4503ccd284c7SBarry Smith M*/
4504ccd284c7SBarry Smith 
45057906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
45067906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
45077906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
45087906f579SHong Zhang #endif
4509d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4510d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4511d24d4204SJose E. Roman #endif
45127906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
45137906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
45147906f579SHong Zhang #endif
45157906f579SHong Zhang 
4516d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4517c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
45184222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
45197906f579SHong Zhang 
45208c778c55SBarry Smith /*@C
45218f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
45228c778c55SBarry Smith 
45238c778c55SBarry Smith    Not Collective
45248c778c55SBarry Smith 
45258c778c55SBarry Smith    Input Parameter:
4526579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
45278c778c55SBarry Smith 
45288c778c55SBarry Smith    Output Parameter:
45298c778c55SBarry Smith .   array - pointer to the data
45308c778c55SBarry Smith 
45318c778c55SBarry Smith    Level: intermediate
45328c778c55SBarry Smith 
4533774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
45348c778c55SBarry Smith @*/
45358c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
45368c778c55SBarry Smith {
45378c778c55SBarry Smith   PetscErrorCode ierr;
45388c778c55SBarry Smith 
45398c778c55SBarry Smith   PetscFunctionBegin;
45408c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
45412e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
45422e5835c6SStefano Zampini   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
45432e5835c6SStefano Zampini #endif
45448c778c55SBarry Smith   PetscFunctionReturn(0);
45458c778c55SBarry Smith }
45468c778c55SBarry Smith 
454721e72a00SBarry Smith /*@C
45488f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
45498f1ea47aSStefano Zampini 
45508f1ea47aSStefano Zampini    Not Collective
45518f1ea47aSStefano Zampini 
45528f1ea47aSStefano Zampini    Input Parameter:
45538f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45548f1ea47aSStefano Zampini 
45558f1ea47aSStefano Zampini    Output Parameter:
45568f1ea47aSStefano Zampini .   array - pointer to the data
45578f1ea47aSStefano Zampini 
45588f1ea47aSStefano Zampini    Level: intermediate
45598f1ea47aSStefano Zampini 
45608f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
45618f1ea47aSStefano Zampini @*/
45628f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
45638f1ea47aSStefano Zampini {
45648c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4565c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
45668f1ea47aSStefano Zampini #endif
45678f1ea47aSStefano Zampini   PetscErrorCode ierr;
45688f1ea47aSStefano Zampini 
45698f1ea47aSStefano Zampini   PetscFunctionBegin;
45708c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4571c70f7ee4SJunchao Zhang   oval = A->offloadmask;
45728f1ea47aSStefano Zampini #endif
45738f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
45748c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4575c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
45768f1ea47aSStefano Zampini #endif
45778f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45788f1ea47aSStefano Zampini }
45798f1ea47aSStefano Zampini 
45808f1ea47aSStefano Zampini /*@C
45818f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
45828f1ea47aSStefano Zampini 
45838f1ea47aSStefano Zampini    Not Collective
45848f1ea47aSStefano Zampini 
45858f1ea47aSStefano Zampini    Input Parameter:
45868f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45878f1ea47aSStefano Zampini 
45888f1ea47aSStefano Zampini    Output Parameter:
45898f1ea47aSStefano Zampini .   array - pointer to the data
45908f1ea47aSStefano Zampini 
45918f1ea47aSStefano Zampini    Level: intermediate
45928f1ea47aSStefano Zampini 
45938f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
45948f1ea47aSStefano Zampini @*/
45958f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
45968f1ea47aSStefano Zampini {
45978c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4598c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
45998f1ea47aSStefano Zampini #endif
46008f1ea47aSStefano Zampini   PetscErrorCode ierr;
46018f1ea47aSStefano Zampini 
46028f1ea47aSStefano Zampini   PetscFunctionBegin;
46038c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4604c70f7ee4SJunchao Zhang   oval = A->offloadmask;
46058f1ea47aSStefano Zampini #endif
46068f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
46078c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4608c70f7ee4SJunchao Zhang   A->offloadmask = oval;
46098f1ea47aSStefano Zampini #endif
46108f1ea47aSStefano Zampini   PetscFunctionReturn(0);
46118f1ea47aSStefano Zampini }
46128f1ea47aSStefano Zampini 
46138f1ea47aSStefano Zampini /*@C
461421e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
461521e72a00SBarry Smith 
461621e72a00SBarry Smith    Not Collective
461721e72a00SBarry Smith 
461821e72a00SBarry Smith    Input Parameter:
4619579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
462021e72a00SBarry Smith 
462121e72a00SBarry Smith    Output Parameter:
462221e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
462321e72a00SBarry Smith 
462421e72a00SBarry Smith    Level: intermediate
462521e72a00SBarry Smith 
462621e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
462721e72a00SBarry Smith @*/
462821e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
462921e72a00SBarry Smith {
463021e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
463121e72a00SBarry Smith 
463221e72a00SBarry Smith   PetscFunctionBegin;
463321e72a00SBarry Smith   *nz = aij->rmax;
463421e72a00SBarry Smith   PetscFunctionReturn(0);
463521e72a00SBarry Smith }
463621e72a00SBarry Smith 
46378c778c55SBarry Smith /*@C
4638579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
46398c778c55SBarry Smith 
46408c778c55SBarry Smith    Not Collective
46418c778c55SBarry Smith 
46428c778c55SBarry Smith    Input Parameters:
4643a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4644a2b725a8SWilliam Gropp -  array - pointer to the data
46458c778c55SBarry Smith 
46468c778c55SBarry Smith    Level: intermediate
46478c778c55SBarry Smith 
4648774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
46498c778c55SBarry Smith @*/
46508c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
46518c778c55SBarry Smith {
46528c778c55SBarry Smith   PetscErrorCode ierr;
46538c778c55SBarry Smith 
46548c778c55SBarry Smith   PetscFunctionBegin;
46558c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
46568c778c55SBarry Smith   PetscFunctionReturn(0);
46578c778c55SBarry Smith }
46588c778c55SBarry Smith 
465934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
46600ce8acdeSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
466102fe1965SBarry Smith #endif
46623d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
46633d0639e7SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat);
46643d0639e7SStefano Zampini #endif
466502fe1965SBarry Smith 
46668cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4667273d9f13SBarry Smith {
4668273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4669dfbe8321SBarry Smith   PetscErrorCode ierr;
467038baddfdSBarry Smith   PetscMPIInt    size;
4671273d9f13SBarry Smith 
4672273d9f13SBarry Smith   PetscFunctionBegin;
4673ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
4674e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4675273d9f13SBarry Smith 
4676b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
46772205254eSKarl Rupp 
4678b0a32e0cSBarry Smith   B->data = (void*)b;
46792205254eSKarl Rupp 
4680549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4681071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
46822205254eSKarl Rupp 
4683f4259b30SLisandro Dalcin   b->row                = NULL;
4684f4259b30SLisandro Dalcin   b->col                = NULL;
4685f4259b30SLisandro Dalcin   b->icol               = NULL;
4686b810aeb4SBarry Smith   b->reallocs           = 0;
468736db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4688f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4689416022c9SBarry Smith   b->nonew              = 0;
4690f4259b30SLisandro Dalcin   b->diag               = NULL;
4691f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4692f4259b30SLisandro Dalcin   B->spptr              = NULL;
4693f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4694f4259b30SLisandro Dalcin   b->idiag              = NULL;
4695f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4696f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
469771f1c65dSBarry Smith   b->omega              = 1.0;
469871f1c65dSBarry Smith   b->fshift             = 0.0;
469971f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4700bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4701a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
470217ab2063SBarry Smith 
470335d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4704bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4705bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
47068c778c55SBarry Smith 
4707b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4708bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4709bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4710b3866ffcSBarry Smith #endif
471117f1a0eaSHong Zhang 
4712bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4713bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4714bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4715bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4716bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4717bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
47184dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
47199779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
47204a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4721191b95cbSRichard Tran Mills #endif
472234b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
472302fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
47244222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4725fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
472602fe1965SBarry Smith #endif
47273d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47283d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
47293d0639e7SStefano Zampini #endif
4730bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4731af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4732af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4733af8000cdSHong Zhang #endif
4734d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4735d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4736d24d4204SJose E. Roman #endif
473763c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
473863c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
47394222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
474063c07aadSStefano Zampini #endif
4741b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4742d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4743c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4744bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4745bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4746bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4747846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4748bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4749bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
47504222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
47514222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
47524222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4753ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr);
47544108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
475517667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
47564099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
47573a40ed3dSBarry Smith   PetscFunctionReturn(0);
475817ab2063SBarry Smith }
475917ab2063SBarry Smith 
4760b24902e0SBarry Smith /*
4761b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4762b24902e0SBarry Smith */
4763ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
476417ab2063SBarry Smith {
47652a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
47666849ba73SBarry Smith   PetscErrorCode ierr;
4767071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
476817ab2063SBarry Smith 
47693a40ed3dSBarry Smith   PetscFunctionBegin;
4770ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4771273d9f13SBarry Smith 
4772d5f3da31SBarry Smith   C->factortype = A->factortype;
4773f4259b30SLisandro Dalcin   c->row        = NULL;
4774f4259b30SLisandro Dalcin   c->col        = NULL;
4775f4259b30SLisandro Dalcin   c->icol       = NULL;
47766ad4291fSHong Zhang   c->reallocs   = 0;
477717ab2063SBarry Smith 
47786ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
477917ab2063SBarry Smith 
4780aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4781aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4782eec197d1SBarry Smith 
4783071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4784071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4785071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4786071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
47873bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
478817ab2063SBarry Smith 
478917ab2063SBarry Smith   /* allocate the matrix space */
4790f77e22a1SHong Zhang   if (mallocmatspace) {
4791dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
47923bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
47932205254eSKarl Rupp 
4794f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
47952205254eSKarl Rupp 
4796580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
479717ab2063SBarry Smith     if (m > 0) {
4798580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4799be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
48002e5835c6SStefano Zampini         const PetscScalar *aa;
48012e5835c6SStefano Zampini 
48022e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
48032e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
48042e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4805be6bf707SBarry Smith       } else {
4806580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
480717ab2063SBarry Smith       }
480808480c60SBarry Smith     }
4809f77e22a1SHong Zhang   }
481017ab2063SBarry Smith 
48116ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4812416022c9SBarry Smith   c->roworiented       = a->roworiented;
4813416022c9SBarry Smith   c->nonew             = a->nonew;
4814416022c9SBarry Smith   if (a->diag) {
4815854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4816071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
48173bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4818071fcb05SBarry Smith   } else c->diag = NULL;
48192205254eSKarl Rupp 
4820f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4821f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4822f4259b30SLisandro Dalcin   c->idiag              = NULL;
4823f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4824a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4825e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4826e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
48276ad4291fSHong Zhang 
4828893ad86cSHong Zhang   c->rmax         = a->rmax;
4829416022c9SBarry Smith   c->nz           = a->nz;
48308ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4831273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4832754ec7b1SSatish Balay 
48336ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
48346ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4835cd6b891eSBarry Smith   if (a->compressedrow.use) {
48366ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4837dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4838580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4839580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
484027ea64f8SHong Zhang   } else {
484127ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
48420298fd71SBarry Smith     c->compressedrow.i      = NULL;
48430298fd71SBarry Smith     c->compressedrow.rindex = NULL;
48446ad4291fSHong Zhang   }
4845ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4846e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
48474846f1f5SKris Buschelman 
48482205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4849140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
48503a40ed3dSBarry Smith   PetscFunctionReturn(0);
485117ab2063SBarry Smith }
485217ab2063SBarry Smith 
4853b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4854b24902e0SBarry Smith {
4855b24902e0SBarry Smith   PetscErrorCode ierr;
4856b24902e0SBarry Smith 
4857b24902e0SBarry Smith   PetscFunctionBegin;
4858ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
48594b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4860cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
486133d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4862cfd3f464SBarry Smith   }
4863a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4864f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4865b24902e0SBarry Smith   PetscFunctionReturn(0);
4866b24902e0SBarry Smith }
4867b24902e0SBarry Smith 
4868112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4869fbdbba38SShri Abhyankar {
487052f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
487152f91c60SVaclav Hapla   PetscErrorCode ierr;
487252f91c60SVaclav Hapla 
487352f91c60SVaclav Hapla   PetscFunctionBegin;
487452f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
487552f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4876c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4877c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
487852f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
487952f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
488052f91c60SVaclav Hapla   if (isbinary) {
488152f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
488252f91c60SVaclav Hapla   } else if (ishdf5) {
488352f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
488452f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
488552f91c60SVaclav Hapla #else
488652f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
488752f91c60SVaclav Hapla #endif
488852f91c60SVaclav Hapla   } else {
488952f91c60SVaclav 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);
489052f91c60SVaclav Hapla   }
489152f91c60SVaclav Hapla   PetscFunctionReturn(0);
489252f91c60SVaclav Hapla }
489352f91c60SVaclav Hapla 
48943ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
489552f91c60SVaclav Hapla {
48963ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4897fbdbba38SShri Abhyankar   PetscErrorCode ierr;
48983ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4899fbdbba38SShri Abhyankar 
4900fbdbba38SShri Abhyankar   PetscFunctionBegin;
49013ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4902bbead8a2SBarry Smith 
49033ea6fe3dSLisandro Dalcin   /* read in matrix header */
49043ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
49053ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4906fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
49073ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
49083ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4909bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4910fbdbba38SShri Abhyankar 
49113ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
49123ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
49133ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
49143ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
49153ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
49163ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
49173ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
49183ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
49193ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
49203ea6fe3dSLisandro Dalcin 
49213ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
49223ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
49233ea6fe3dSLisandro 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);
49243ea6fe3dSLisandro Dalcin 
4925fbdbba38SShri Abhyankar   /* read in row lengths */
49263ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
49273ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
49283ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
49293ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
49303ea6fe3dSLisandro 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);
49313ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
49323ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
49333ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
493460e0710aSBarry 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);
49353ea6fe3dSLisandro Dalcin   /* store row lengths */
49363ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
49373ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4938fbdbba38SShri Abhyankar 
49393ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
49403ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
49413ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
49423ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
49433ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
49443ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4945fbdbba38SShri Abhyankar 
49463ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49473ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4948fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4949fbdbba38SShri Abhyankar }
4950fbdbba38SShri Abhyankar 
4951ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
49527264ac53SSatish Balay {
49537264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4954dfbe8321SBarry Smith   PetscErrorCode ierr;
4955eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4956eeffb40dSHong Zhang   PetscInt k;
4957eeffb40dSHong Zhang #endif
49587264ac53SSatish Balay 
49593a40ed3dSBarry Smith   PetscFunctionBegin;
4960bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4961d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4962ca44d042SBarry Smith     *flg = PETSC_FALSE;
4963ca44d042SBarry Smith     PetscFunctionReturn(0);
4964bcd2baecSBarry Smith   }
49657264ac53SSatish Balay 
49667264ac53SSatish Balay   /* if the a->i are the same */
4967580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4968abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
49697264ac53SSatish Balay 
49707264ac53SSatish Balay   /* if a->j are the same */
4971580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4972abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4973bcd2baecSBarry Smith 
4974bcd2baecSBarry Smith   /* if a->a are the same */
4975eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4976eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4977eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4978eeffb40dSHong Zhang       *flg = PETSC_FALSE;
49793a40ed3dSBarry Smith       PetscFunctionReturn(0);
4980eeffb40dSHong Zhang     }
4981eeffb40dSHong Zhang   }
4982eeffb40dSHong Zhang #else
4983580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4984eeffb40dSHong Zhang #endif
4985eeffb40dSHong Zhang   PetscFunctionReturn(0);
49867264ac53SSatish Balay }
498736db0b34SBarry Smith 
498805869f15SSatish Balay /*@
498936db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
499036db0b34SBarry Smith               provided by the user.
499136db0b34SBarry Smith 
4992d083f849SBarry Smith       Collective
499336db0b34SBarry Smith 
499436db0b34SBarry Smith    Input Parameters:
499536db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
499636db0b34SBarry Smith .   m - number of rows
499736db0b34SBarry Smith .   n - number of columns
4998483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
499936db0b34SBarry Smith .   j - column indices
500036db0b34SBarry Smith -   a - matrix values
500136db0b34SBarry Smith 
500236db0b34SBarry Smith    Output Parameter:
500336db0b34SBarry Smith .   mat - the matrix
500436db0b34SBarry Smith 
500536db0b34SBarry Smith    Level: intermediate
500636db0b34SBarry Smith 
500736db0b34SBarry Smith    Notes:
50080551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5009292fb18eSBarry Smith     once the matrix is destroyed and not before
501036db0b34SBarry Smith 
501136db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
501236db0b34SBarry Smith 
5013bfeeae90SHong Zhang        The i and j indices are 0 based
501436db0b34SBarry Smith 
5015a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5016a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
50178eef79e4SBarry Smith     as shown
5018a4552177SSatish Balay 
50198eef79e4SBarry Smith $        1 0 0
50208eef79e4SBarry Smith $        2 0 3
50218eef79e4SBarry Smith $        4 5 6
50228eef79e4SBarry Smith $
50238eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
50248eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
50258eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5026a4552177SSatish Balay 
502769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
502836db0b34SBarry Smith 
502936db0b34SBarry Smith @*/
5030c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
503136db0b34SBarry Smith {
5032dfbe8321SBarry Smith   PetscErrorCode ierr;
5033cbcfb4deSHong Zhang   PetscInt       ii;
503436db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5035cbcfb4deSHong Zhang   PetscInt jj;
503636db0b34SBarry Smith 
503736db0b34SBarry Smith   PetscFunctionBegin;
503841096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5039f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5040f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5041a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
5042ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5043f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
5044ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
5045071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
5046071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
5047ab93d7beSBarry Smith 
504836db0b34SBarry Smith   aij->i            = i;
504936db0b34SBarry Smith   aij->j            = j;
505036db0b34SBarry Smith   aij->a            = a;
505136db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
505236db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5053e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5054e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
505536db0b34SBarry Smith 
505636db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
505736db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
505876bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
505960e0710aSBarry 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]);
50609985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
5061a061629eSStefano 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);
5062a061629eSStefano 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);
50639985e31cSBarry Smith       }
506436db0b34SBarry Smith     }
506576bd3646SJed Brown   }
506676bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
506736db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
506860e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
506960e0710aSBarry 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]);
507036db0b34SBarry Smith     }
507176bd3646SJed Brown   }
507236db0b34SBarry Smith 
5073b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5074b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
507536db0b34SBarry Smith   PetscFunctionReturn(0);
507636db0b34SBarry Smith }
507780ef6e79SMatthew G Knepley /*@C
5078d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
50798a0b0e6bSVictor Minden               provided by the user.
50808a0b0e6bSVictor Minden 
5081d083f849SBarry Smith       Collective
50828a0b0e6bSVictor Minden 
50838a0b0e6bSVictor Minden    Input Parameters:
50848a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
50858a0b0e6bSVictor Minden .   m   - number of rows
50868a0b0e6bSVictor Minden .   n   - number of columns
50878a0b0e6bSVictor Minden .   i   - row indices
50888a0b0e6bSVictor Minden .   j   - column indices
50891230e6d1SVictor Minden .   a   - matrix values
50901230e6d1SVictor Minden .   nz  - number of nonzeros
50911230e6d1SVictor Minden -   idx - 0 or 1 based
50928a0b0e6bSVictor Minden 
50938a0b0e6bSVictor Minden    Output Parameter:
50948a0b0e6bSVictor Minden .   mat - the matrix
50958a0b0e6bSVictor Minden 
50968a0b0e6bSVictor Minden    Level: intermediate
50978a0b0e6bSVictor Minden 
50988a0b0e6bSVictor Minden    Notes:
50998a0b0e6bSVictor Minden        The i and j indices are 0 based
51008a0b0e6bSVictor Minden 
51018a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
51028a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
51038a0b0e6bSVictor Minden     as shown:
51048a0b0e6bSVictor Minden 
51058a0b0e6bSVictor Minden         1 0 0
51068a0b0e6bSVictor Minden         2 0 3
51078a0b0e6bSVictor Minden         4 5 6
51088a0b0e6bSVictor Minden 
51098a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
51108a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
51118a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
51128a0b0e6bSVictor Minden 
511369b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
51148a0b0e6bSVictor Minden 
51158a0b0e6bSVictor Minden @*/
5116c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
51178a0b0e6bSVictor Minden {
51188a0b0e6bSVictor Minden   PetscErrorCode ierr;
5119d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
51208a0b0e6bSVictor Minden 
51218a0b0e6bSVictor Minden   PetscFunctionBegin;
51221795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
51231230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5124c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
51251230e6d1SVictor Minden   }
51268a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
51278a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
51288a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
51291230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
51301230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
51311230e6d1SVictor Minden     if (idx) {
51321230e6d1SVictor Minden       row = i[ii] - 1;
51331230e6d1SVictor Minden       col = j[ii] - 1;
51341230e6d1SVictor Minden     } else {
51351230e6d1SVictor Minden       row = i[ii];
51361230e6d1SVictor Minden       col = j[ii];
51378a0b0e6bSVictor Minden     }
51381230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
51398a0b0e6bSVictor Minden   }
51408a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
51418a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5142d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
51438a0b0e6bSVictor Minden   PetscFunctionReturn(0);
51448a0b0e6bSVictor Minden }
514536db0b34SBarry Smith 
5146acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5147acf2f550SJed Brown {
5148acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5149acf2f550SJed Brown   PetscErrorCode ierr;
5150acf2f550SJed Brown 
5151acf2f550SJed Brown   PetscFunctionBegin;
5152acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5153acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
51542205254eSKarl Rupp 
5155acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5156acf2f550SJed Brown   PetscFunctionReturn(0);
5157acf2f550SJed Brown }
5158acf2f550SJed Brown 
51599c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
51609c8f2541SHong Zhang {
51619c8f2541SHong Zhang   PetscErrorCode ierr;
51628761c3d6SHong Zhang   PetscMPIInt    size;
51639c8f2541SHong Zhang 
51649c8f2541SHong Zhang   PetscFunctionBegin;
5165ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
51667bbdc51dSHong Zhang   if (size == 1) {
51677bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
51687bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
51697bbdc51dSHong Zhang     } else {
51708761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
51717bbdc51dSHong Zhang     }
51728761c3d6SHong Zhang   } else {
51739c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
51748761c3d6SHong Zhang   }
51759c8f2541SHong Zhang   PetscFunctionReturn(0);
51769c8f2541SHong Zhang }
51779c8f2541SHong Zhang 
517881824310SBarry Smith /*
517953dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
518053dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
518153dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
518253dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
518353dd7562SDmitry Karpeev  */
518453dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
518553dd7562SDmitry Karpeev {
518653dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
518753dd7562SDmitry Karpeev   PetscErrorCode ierr;
518853dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
518953dd7562SDmitry Karpeev   PetscBool      seqaij;
519053dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
519153dd7562SDmitry Karpeev   PetscScalar    v;
519253dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
519353dd7562SDmitry Karpeev 
519453dd7562SDmitry Karpeev   PetscFunctionBegin;
519553dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
519653dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
51974099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
519853dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
519953dd7562SDmitry Karpeev   if (rowemb) {
520053dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
520153dd7562SDmitry 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);
520253dd7562SDmitry Karpeev   } else {
52036c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
520453dd7562SDmitry Karpeev   }
520553dd7562SDmitry Karpeev   if (colemb) {
520653dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
520753dd7562SDmitry 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);
520853dd7562SDmitry Karpeev   } else {
520953dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
521053dd7562SDmitry Karpeev   }
521153dd7562SDmitry Karpeev 
521253dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
521353dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
521453dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
521553dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
521653dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
521753dd7562SDmitry Karpeev     }
521853dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
521953dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
522053dd7562SDmitry Karpeev   }
522153dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
522253dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
522353dd7562SDmitry Karpeev   }
522453dd7562SDmitry Karpeev   count = 0;
522553dd7562SDmitry Karpeev   rowindices = NULL;
522653dd7562SDmitry Karpeev   colindices = NULL;
522753dd7562SDmitry Karpeev   if (rowemb) {
522853dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
522953dd7562SDmitry Karpeev   }
523053dd7562SDmitry Karpeev   if (colemb) {
523153dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
523253dd7562SDmitry Karpeev   }
523353dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
523453dd7562SDmitry Karpeev     PetscInt row;
523553dd7562SDmitry Karpeev     row = i;
523653dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
523753dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
523853dd7562SDmitry Karpeev       PetscInt col;
523953dd7562SDmitry Karpeev       col  = Baij->j[count];
524053dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
524153dd7562SDmitry Karpeev       v    = Baij->a[count];
524253dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
524353dd7562SDmitry Karpeev       ++count;
524453dd7562SDmitry Karpeev     }
524553dd7562SDmitry Karpeev   }
524653dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
524753dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
524853dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
524953dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
525053dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
525153dd7562SDmitry Karpeev   PetscFunctionReturn(0);
525253dd7562SDmitry Karpeev }
525353dd7562SDmitry Karpeev 
52544099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
52554099cc6bSBarry Smith 
52564099cc6bSBarry Smith /*@C
52574099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
52584099cc6bSBarry Smith 
52594099cc6bSBarry Smith    Collective on Mat
52604099cc6bSBarry Smith 
52614099cc6bSBarry Smith    Input Parameters:
52624099cc6bSBarry Smith +  mat      - the matrix object
52634099cc6bSBarry Smith -  matype   - matrix type
52644099cc6bSBarry Smith 
52654099cc6bSBarry Smith    Options Database Key:
52664099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
52674099cc6bSBarry Smith 
52684099cc6bSBarry Smith   Level: intermediate
52694099cc6bSBarry Smith 
52704099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
52714099cc6bSBarry Smith @*/
52724099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
52734099cc6bSBarry Smith {
5274fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
52754099cc6bSBarry Smith   PetscBool      sametype;
52764099cc6bSBarry Smith 
52774099cc6bSBarry Smith   PetscFunctionBegin;
52784099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
52794099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
52804099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
52814099cc6bSBarry Smith 
52824099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
52834099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
52844099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
52854099cc6bSBarry Smith   PetscFunctionReturn(0);
52864099cc6bSBarry Smith }
52874099cc6bSBarry Smith 
52884099cc6bSBarry Smith /*@C
52894099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
52904099cc6bSBarry Smith 
52914099cc6bSBarry Smith    Not Collective
52924099cc6bSBarry Smith 
52934099cc6bSBarry Smith    Input Parameters:
52944099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
52954099cc6bSBarry Smith -  function - routine to convert to subtype
52964099cc6bSBarry Smith 
52974099cc6bSBarry Smith    Notes:
52984099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
52994099cc6bSBarry Smith 
53004099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
53014099cc6bSBarry Smith $     -mat_seqaij_type my_mat
53024099cc6bSBarry Smith 
53034099cc6bSBarry Smith    Level: advanced
53044099cc6bSBarry Smith 
53054099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
53064099cc6bSBarry Smith 
53074099cc6bSBarry Smith   Level: advanced
53084099cc6bSBarry Smith @*/
5309388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
53104099cc6bSBarry Smith {
53114099cc6bSBarry Smith   PetscErrorCode ierr;
53124099cc6bSBarry Smith 
53134099cc6bSBarry Smith   PetscFunctionBegin;
53149cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
53154099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
53164099cc6bSBarry Smith   PetscFunctionReturn(0);
53174099cc6bSBarry Smith }
53184099cc6bSBarry Smith 
53194099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
53204099cc6bSBarry Smith 
53214099cc6bSBarry Smith /*@C
53224099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
53234099cc6bSBarry Smith 
53244099cc6bSBarry Smith   Not Collective
53254099cc6bSBarry Smith 
53264099cc6bSBarry Smith   Level: advanced
53274099cc6bSBarry Smith 
5328f719121fSJed Brown   Developers Note: CUSPARSE does not yet support the MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
53294099cc6bSBarry Smith 
53304099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
53314099cc6bSBarry Smith @*/
53324099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
53334099cc6bSBarry Smith {
53344099cc6bSBarry Smith   PetscErrorCode ierr;
53354099cc6bSBarry Smith 
53364099cc6bSBarry Smith   PetscFunctionBegin;
53374099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
53384099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
53394099cc6bSBarry Smith 
53404099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
53414099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
53424dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
53439779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
53446b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5345485f9817SRichard Tran Mills #endif
53464099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
53474099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
53484099cc6bSBarry Smith #endif
53494099cc6bSBarry Smith   PetscFunctionReturn(0);
53504099cc6bSBarry Smith }
535153dd7562SDmitry Karpeev 
535253dd7562SDmitry Karpeev /*
535381824310SBarry Smith     Special version for direct calls from Fortran
535481824310SBarry Smith */
5355af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
535681824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
535781824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
535881824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
535981824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
536081824310SBarry Smith #endif
536181824310SBarry Smith 
536281824310SBarry Smith /* Change these macros so can be used in void function */
536381824310SBarry Smith #undef CHKERRQ
5364ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
536581824310SBarry Smith #undef SETERRQ2
5366e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
53674994cf47SJed Brown #undef SETERRQ3
53684994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
536981824310SBarry Smith 
537019caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
537181824310SBarry Smith {
537281824310SBarry Smith   Mat            A  = *AA;
537381824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
537481824310SBarry Smith   InsertMode     is = *isis;
537581824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
537681824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
537781824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
537881824310SBarry Smith   PetscErrorCode ierr;
537981824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
538054f21887SBarry Smith   MatScalar      *ap,value,*aa;
5381ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5382ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
538381824310SBarry Smith 
538481824310SBarry Smith   PetscFunctionBegin;
53854994cf47SJed Brown   MatCheckPreallocated(A,1);
538681824310SBarry Smith   imax  = a->imax;
538781824310SBarry Smith   ai    = a->i;
538881824310SBarry Smith   ailen = a->ilen;
538981824310SBarry Smith   aj    = a->j;
539081824310SBarry Smith   aa    = a->a;
539181824310SBarry Smith 
539281824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
539381824310SBarry Smith     row = im[k];
539481824310SBarry Smith     if (row < 0) continue;
5395cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
539681824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
539781824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
539881824310SBarry Smith     low  = 0;
539981824310SBarry Smith     high = nrow;
540081824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
540181824310SBarry Smith       if (in[l] < 0) continue;
5402cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
540381824310SBarry Smith       col = in[l];
54042205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
54052205254eSKarl Rupp       else value = v[k + l*m];
54062205254eSKarl Rupp 
540781824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
540881824310SBarry Smith 
54092205254eSKarl Rupp       if (col <= lastcol) low = 0;
54102205254eSKarl Rupp       else high = nrow;
541181824310SBarry Smith       lastcol = col;
541281824310SBarry Smith       while (high-low > 5) {
541381824310SBarry Smith         t = (low+high)/2;
541481824310SBarry Smith         if (rp[t] > col) high = t;
541581824310SBarry Smith         else             low  = t;
541681824310SBarry Smith       }
541781824310SBarry Smith       for (i=low; i<high; i++) {
541881824310SBarry Smith         if (rp[i] > col) break;
541981824310SBarry Smith         if (rp[i] == col) {
542081824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
542181824310SBarry Smith           else                  ap[i] = value;
542281824310SBarry Smith           goto noinsert;
542381824310SBarry Smith         }
542481824310SBarry Smith       }
542581824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
542681824310SBarry Smith       if (nonew == 1) goto noinsert;
5427ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5428fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
542981824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
543081824310SBarry Smith       /* shift up all the later entries in this row */
543181824310SBarry Smith       for (ii=N; ii>=i; ii--) {
543281824310SBarry Smith         rp[ii+1] = rp[ii];
543381824310SBarry Smith         ap[ii+1] = ap[ii];
543481824310SBarry Smith       }
543581824310SBarry Smith       rp[i] = col;
543681824310SBarry Smith       ap[i] = value;
5437e56f5c9eSBarry Smith       A->nonzerostate++;
543881824310SBarry Smith noinsert:;
543981824310SBarry Smith       low = i + 1;
544081824310SBarry Smith     }
544181824310SBarry Smith     ailen[row] = nrow;
544281824310SBarry Smith   }
544381824310SBarry Smith   PetscFunctionReturnVoid();
544481824310SBarry Smith }
5445