xref: /petsc/src/mat/impls/aij/seq/aij.c (revision d60b7d5cda9a3148fab971d2544cf20a2ffedfa6)
1d5d45c9bSBarry Smith /*
23369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
3d5d45c9bSBarry Smith   matrix storage format.
4d5d45c9bSBarry Smith */
53369ce9aSBarry Smith 
67c4f633dSBarry Smith 
7c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
8c6db04a5SJed Brown #include <petscblaslapack.h>
9c6db04a5SJed Brown #include <petscbt.h>
10af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
110716a85fSBarry Smith 
124099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
134099cc6bSBarry Smith {
144099cc6bSBarry Smith   PetscErrorCode       ierr;
154099cc6bSBarry Smith   PetscBool            flg;
164099cc6bSBarry Smith   char                 type[256];
174099cc6bSBarry Smith 
184099cc6bSBarry Smith   PetscFunctionBegin;
194099cc6bSBarry Smith   ierr = PetscObjectOptionsBegin((PetscObject)A);
204099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
214099cc6bSBarry Smith   if (flg) {
224099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
234099cc6bSBarry Smith   }
244099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
254099cc6bSBarry Smith   PetscFunctionReturn(0);
264099cc6bSBarry Smith }
274099cc6bSBarry Smith 
280716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
290716a85fSBarry Smith {
300716a85fSBarry Smith   PetscErrorCode ierr;
310716a85fSBarry Smith   PetscInt       i,m,n;
320716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
330716a85fSBarry Smith 
340716a85fSBarry Smith   PetscFunctionBegin;
350716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
36580bdb30SBarry Smith   ierr = PetscArrayzero(norms,n);CHKERRQ(ierr);
370716a85fSBarry Smith   if (type == NORM_2) {
380716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
390716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
400716a85fSBarry Smith     }
410716a85fSBarry Smith   } else if (type == NORM_1) {
420716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
430716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
440716a85fSBarry Smith     }
450716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
460716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
470716a85fSBarry Smith       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
480716a85fSBarry Smith     }
490716a85fSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");
500716a85fSBarry Smith 
510716a85fSBarry Smith   if (type == NORM_2) {
528f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
530716a85fSBarry Smith   }
540716a85fSBarry Smith   PetscFunctionReturn(0);
550716a85fSBarry Smith }
560716a85fSBarry Smith 
573a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
583a062f41SBarry Smith {
593a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
603a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
613a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
623a062f41SBarry Smith   PetscInt        *rows;
633a062f41SBarry Smith   PetscErrorCode  ierr;
643a062f41SBarry Smith 
653a062f41SBarry Smith   PetscFunctionBegin;
663a062f41SBarry Smith   for (i=0; i<m; i++) {
673a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
683a062f41SBarry Smith       cnt++;
693a062f41SBarry Smith     }
703a062f41SBarry Smith   }
713a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
723a062f41SBarry Smith   cnt  = 0;
733a062f41SBarry Smith   for (i=0; i<m; i++) {
743a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
753a062f41SBarry Smith       rows[cnt] = i;
763a062f41SBarry Smith       cnt++;
773a062f41SBarry Smith     }
783a062f41SBarry Smith   }
793a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
803a062f41SBarry Smith   PetscFunctionReturn(0);
813a062f41SBarry Smith }
823a062f41SBarry Smith 
83f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
846ce1633cSBarry Smith {
856ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
866ce1633cSBarry Smith   const MatScalar *aa = a->a;
876ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
88b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
896ce1633cSBarry Smith   PetscInt        *rows;
906ce1633cSBarry Smith   PetscErrorCode  ierr;
916ce1633cSBarry Smith 
926ce1633cSBarry Smith   PetscFunctionBegin;
936ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
946ce1633cSBarry Smith   diag = a->diag;
956ce1633cSBarry Smith   for (i=0; i<m; i++) {
96b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
976ce1633cSBarry Smith       cnt++;
986ce1633cSBarry Smith     }
996ce1633cSBarry Smith   }
100785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1016ce1633cSBarry Smith   cnt  = 0;
1026ce1633cSBarry Smith   for (i=0; i<m; i++) {
103b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1046ce1633cSBarry Smith       rows[cnt++] = i;
1056ce1633cSBarry Smith     }
1066ce1633cSBarry Smith   }
107f1f41ecbSJed Brown   *nrows = cnt;
108f1f41ecbSJed Brown   *zrows = rows;
109f1f41ecbSJed Brown   PetscFunctionReturn(0);
110f1f41ecbSJed Brown }
111f1f41ecbSJed Brown 
112f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
113f1f41ecbSJed Brown {
114f1f41ecbSJed Brown   PetscInt       nrows,*rows;
115f1f41ecbSJed Brown   PetscErrorCode ierr;
116f1f41ecbSJed Brown 
117f1f41ecbSJed Brown   PetscFunctionBegin;
1180298fd71SBarry Smith   *zrows = NULL;
119f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
120ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1216ce1633cSBarry Smith   PetscFunctionReturn(0);
1226ce1633cSBarry Smith }
1236ce1633cSBarry Smith 
124b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
125b3a44c85SBarry Smith {
126b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
127b3a44c85SBarry Smith   const MatScalar *aa;
128b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
129b3a44c85SBarry Smith   const PetscInt  *ii;
130b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
131b3a44c85SBarry Smith   PetscErrorCode  ierr;
132b3a44c85SBarry Smith 
133b3a44c85SBarry Smith   PetscFunctionBegin;
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     }
142b3a44c85SBarry Smith     aa = a->a + ii[i];
143b3a44c85SBarry Smith     for (j=0; j<n; j++) {
144b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
145b3a44c85SBarry Smith     }
146b3a44c85SBarry Smith     cnt++;
147b3a44c85SBarry Smith ok1:;
148b3a44c85SBarry Smith   }
149b3a44c85SBarry Smith   if (!cnt) PetscFunctionReturn(0);
150854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
151b3a44c85SBarry Smith   cnt  = 0;
152b3a44c85SBarry Smith   for (i=0; i<m; i++) {
153b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
154b3a44c85SBarry Smith     if (!n) continue;
155b3a44c85SBarry Smith     aa = a->a + ii[i];
156b3a44c85SBarry Smith     for (j=0; j<n; j++) {
157b3a44c85SBarry Smith       if (aa[j] != 0.0) {
158b3a44c85SBarry Smith         rows[cnt++] = i;
159b3a44c85SBarry Smith         break;
160b3a44c85SBarry Smith       }
161b3a44c85SBarry Smith     }
162b3a44c85SBarry Smith   }
163b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
164b3a44c85SBarry Smith   PetscFunctionReturn(0);
165b3a44c85SBarry Smith }
166b3a44c85SBarry Smith 
1677087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
16879299369SBarry Smith {
16979299369SBarry Smith   PetscErrorCode    ierr;
17079299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17199e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17299e65526SBarry Smith   const PetscInt    *diag;
17354f21887SBarry Smith   MatScalar         *aa = aij->a;
17499e65526SBarry Smith   const PetscScalar *v;
175ace3abfcSBarry Smith   PetscBool         missing;
1768c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
177837a59e1SRichard Tran Mills   PetscBool         inserted = PETSC_FALSE;
178837a59e1SRichard Tran Mills #endif
17979299369SBarry Smith 
18079299369SBarry Smith   PetscFunctionBegin;
18109f38230SBarry Smith   if (Y->assembled) {
1820298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
18309f38230SBarry Smith     if (!missing) {
18479299369SBarry Smith       diag = aij->diag;
18599e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
18679299369SBarry Smith       if (is == INSERT_VALUES) {
1878c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
188837a59e1SRichard Tran Mills         inserted = PETSC_TRUE;
189837a59e1SRichard Tran Mills #endif
19079299369SBarry Smith         for (i=0; i<m; i++) {
19179299369SBarry Smith           aa[diag[i]] = v[i];
19279299369SBarry Smith         }
19379299369SBarry Smith       } else {
19479299369SBarry Smith         for (i=0; i<m; i++) {
1958c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
196837a59e1SRichard Tran Mills           if (v[i] != 0.0) inserted = PETSC_TRUE;
197837a59e1SRichard Tran Mills #endif
19879299369SBarry Smith           aa[diag[i]] += v[i];
19979299369SBarry Smith         }
20079299369SBarry Smith       }
2018c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
202837a59e1SRichard Tran Mills       if (inserted) Y->offloadmask = PETSC_OFFLOAD_CPU;
203837a59e1SRichard Tran Mills #endif
20499e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
20579299369SBarry Smith       PetscFunctionReturn(0);
20679299369SBarry Smith     }
207acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
20809f38230SBarry Smith   }
20909f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
21009f38230SBarry Smith   PetscFunctionReturn(0);
21109f38230SBarry Smith }
21279299369SBarry Smith 
2131a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21417ab2063SBarry Smith {
215416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
216dfbe8321SBarry Smith   PetscErrorCode ierr;
21797f1f81fSBarry Smith   PetscInt       i,ishift;
21817ab2063SBarry Smith 
2193a40ed3dSBarry Smith   PetscFunctionBegin;
220d0f46423SBarry Smith   *m = A->rmap->n;
2213a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
222bfeeae90SHong Zhang   ishift = 0;
22353e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2242462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
225bfeeae90SHong Zhang   } else if (oshift == 1) {
2261a83f524SJed Brown     PetscInt *tia;
227d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2283b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
229854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2301a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2311a83f524SJed Brown     *ia = tia;
232ecc77c7aSBarry Smith     if (ja) {
2331a83f524SJed Brown       PetscInt *tja;
234854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2351a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2361a83f524SJed Brown       *ja = tja;
237ecc77c7aSBarry Smith     }
2386945ee14SBarry Smith   } else {
239ecc77c7aSBarry Smith     *ia = a->i;
240ecc77c7aSBarry Smith     if (ja) *ja = a->j;
241a2ce50c7SBarry Smith   }
2423a40ed3dSBarry Smith   PetscFunctionReturn(0);
243a2744918SBarry Smith }
244a2744918SBarry Smith 
2451a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2466945ee14SBarry Smith {
247dfbe8321SBarry Smith   PetscErrorCode ierr;
2486945ee14SBarry Smith 
2493a40ed3dSBarry Smith   PetscFunctionBegin;
2503a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
251bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
252606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
253ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
254bcd2baecSBarry Smith   }
2553a40ed3dSBarry Smith   PetscFunctionReturn(0);
25617ab2063SBarry Smith }
25717ab2063SBarry Smith 
2581a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2593b2fbd54SBarry Smith {
2603b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
261dfbe8321SBarry Smith   PetscErrorCode ierr;
262d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
26397f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2643b2fbd54SBarry Smith 
2653a40ed3dSBarry Smith   PetscFunctionBegin;
266899cda47SBarry Smith   *nn = n;
2673a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2683b2fbd54SBarry Smith   if (symmetric) {
2692462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2703b2fbd54SBarry Smith   } else {
271b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
272854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
273b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2743b2fbd54SBarry Smith     jj   = a->j;
2753b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
276bfeeae90SHong Zhang       collengths[jj[i]]++;
2773b2fbd54SBarry Smith     }
2783b2fbd54SBarry Smith     cia[0] = oshift;
2793b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2803b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2813b2fbd54SBarry Smith     }
282580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2833b2fbd54SBarry Smith     jj   = a->j;
284a93ec695SBarry Smith     for (row=0; row<m; row++) {
285a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
286a93ec695SBarry Smith       for (i=0; i<mr; i++) {
287bfeeae90SHong Zhang         col = *jj++;
2882205254eSKarl Rupp 
2893b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2903b2fbd54SBarry Smith       }
2913b2fbd54SBarry Smith     }
292606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2933b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2943b2fbd54SBarry Smith   }
2953a40ed3dSBarry Smith   PetscFunctionReturn(0);
2963b2fbd54SBarry Smith }
2973b2fbd54SBarry Smith 
2981a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2993b2fbd54SBarry Smith {
300dfbe8321SBarry Smith   PetscErrorCode ierr;
301606d414cSSatish Balay 
3023a40ed3dSBarry Smith   PetscFunctionBegin;
3033a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3043b2fbd54SBarry Smith 
305606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
306606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3073a40ed3dSBarry Smith   PetscFunctionReturn(0);
3083b2fbd54SBarry Smith }
3093b2fbd54SBarry Smith 
3107cee066cSHong Zhang /*
3117cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3127cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
313040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3147cee066cSHong Zhang */
3157cee066cSHong 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)
3167cee066cSHong Zhang {
3177cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3187cee066cSHong Zhang   PetscErrorCode ierr;
3197cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
320071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3217cee066cSHong Zhang   PetscInt       *cspidx;
322071fcb05SBarry Smith   const PetscInt *jj;
3237cee066cSHong Zhang 
3247cee066cSHong Zhang   PetscFunctionBegin;
3257cee066cSHong Zhang   *nn = n;
3267cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
327625f6d37SHong Zhang 
328b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
329854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
330b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
331b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3327cee066cSHong Zhang   jj   = a->j;
3337cee066cSHong Zhang   for (i=0; i<nz; i++) {
3347cee066cSHong Zhang     collengths[jj[i]]++;
3357cee066cSHong Zhang   }
3367cee066cSHong Zhang   cia[0] = oshift;
3377cee066cSHong Zhang   for (i=0; i<n; i++) {
3387cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3397cee066cSHong Zhang   }
340580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3417cee066cSHong Zhang   jj   = a->j;
3427cee066cSHong Zhang   for (row=0; row<m; row++) {
3437cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3447cee066cSHong Zhang     for (i=0; i<mr; i++) {
3457cee066cSHong Zhang       col         = *jj++;
346071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
347071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
348071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3497cee066cSHong Zhang     }
3507cee066cSHong Zhang   }
3517cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
352071fcb05SBarry Smith   *ia    = cia;
353071fcb05SBarry Smith   *ja    = cja;
3547cee066cSHong Zhang   *spidx = cspidx;
3557cee066cSHong Zhang   PetscFunctionReturn(0);
3567cee066cSHong Zhang }
3577cee066cSHong Zhang 
3587cee066cSHong 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)
3597cee066cSHong Zhang {
3607cee066cSHong Zhang   PetscErrorCode ierr;
3617cee066cSHong Zhang 
3627cee066cSHong Zhang   PetscFunctionBegin;
3635243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3647cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3657cee066cSHong Zhang   PetscFunctionReturn(0);
3667cee066cSHong Zhang }
3677cee066cSHong Zhang 
36887d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
36987d4246cSBarry Smith {
37087d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
37187d4246cSBarry Smith   PetscInt       *ai = a->i;
37287d4246cSBarry Smith   PetscErrorCode ierr;
37387d4246cSBarry Smith 
37487d4246cSBarry Smith   PetscFunctionBegin;
375580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
3768c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
377c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
378e2cf4d64SStefano Zampini #endif
37987d4246cSBarry Smith   PetscFunctionReturn(0);
38087d4246cSBarry Smith }
38187d4246cSBarry Smith 
382bd04181cSBarry Smith /*
383bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
384bd04181cSBarry Smith 
385bd04181cSBarry Smith       -   a single row of values is set with each call
386bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
387bd04181cSBarry Smith       -   the values are always added to the matrix, not set
388bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
389bd04181cSBarry Smith 
3901f763a69SBarry Smith      This does NOT assume the global column indices are sorted
391bd04181cSBarry Smith 
3921f763a69SBarry Smith */
393bd04181cSBarry Smith 
394af0996ceSBarry Smith #include <petsc/private/isimpl.h>
395189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
396189e4007SBarry Smith {
397189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3981f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
3991f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4001f763a69SBarry Smith   PetscInt       lastcol = -1;
401189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
402189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
403189e4007SBarry Smith 
404f38dd0b8SBarry Smith   row  = ridx[im[0]];
4051f763a69SBarry Smith   rp   = aj + ai[row];
4061f763a69SBarry Smith   ap   = aa + ai[row];
4071f763a69SBarry Smith   nrow = ailen[row];
408189e4007SBarry Smith   low  = 0;
409189e4007SBarry Smith   high = nrow;
410189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
411189e4007SBarry Smith     col = cidx[in[l]];
412f38dd0b8SBarry Smith     value = v[l];
413189e4007SBarry Smith 
414189e4007SBarry Smith     if (col <= lastcol) low = 0;
415189e4007SBarry Smith     else high = nrow;
416189e4007SBarry Smith     lastcol = col;
417189e4007SBarry Smith     while (high-low > 5) {
418189e4007SBarry Smith       t = (low+high)/2;
419189e4007SBarry Smith       if (rp[t] > col) high = t;
420189e4007SBarry Smith       else low = t;
421189e4007SBarry Smith     }
422189e4007SBarry Smith     for (i=low; i<high; i++) {
423189e4007SBarry Smith       if (rp[i] == col) {
4241f763a69SBarry Smith         ap[i] += value;
425189e4007SBarry Smith         low = i + 1;
4261f763a69SBarry Smith         break;
427189e4007SBarry Smith       }
428189e4007SBarry Smith     }
429189e4007SBarry Smith   }
4308c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
431c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
432e2cf4d64SStefano Zampini #endif
433f38dd0b8SBarry Smith   return 0;
434189e4007SBarry Smith }
435189e4007SBarry Smith 
43697f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
43717ab2063SBarry Smith {
438416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
439e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
44097f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4416849ba73SBarry Smith   PetscErrorCode ierr;
442e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
443d8cdefa3SHong Zhang   MatScalar      *ap=NULL,value=0.0,*aa = a->a;
444ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
445ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
4468c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
447e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
448e2cf4d64SStefano Zampini #endif
44917ab2063SBarry Smith 
4503a40ed3dSBarry Smith   PetscFunctionBegin;
45117ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
452416022c9SBarry Smith     row = im[k];
4535ef9f2a5SBarry Smith     if (row < 0) continue;
454cf9c20a2SJed 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);
455720833daSHong Zhang     rp   = aj + ai[row];
456876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
45717ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
458416022c9SBarry Smith     low  = 0;
459c71e6ed7SBarry Smith     high = nrow;
46017ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4615ef9f2a5SBarry Smith       if (in[l] < 0) continue;
462cf9c20a2SJed 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);
463bfeeae90SHong Zhang       col = in[l];
464071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
465071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
46636db0b34SBarry Smith 
4672205254eSKarl Rupp       if (col <= lastcol) low = 0;
4682205254eSKarl Rupp       else high = nrow;
469e2ee6c50SBarry Smith       lastcol = col;
470416022c9SBarry Smith       while (high-low > 5) {
471416022c9SBarry Smith         t = (low+high)/2;
472416022c9SBarry Smith         if (rp[t] > col) high = t;
473416022c9SBarry Smith         else low = t;
47417ab2063SBarry Smith       }
475416022c9SBarry Smith       for (i=low; i<high; i++) {
47617ab2063SBarry Smith         if (rp[i] > col) break;
47717ab2063SBarry Smith         if (rp[i] == col) {
478876c6284SHong Zhang           if (!A->structure_only) {
4790c0d7e18SFande Kong             if (is == ADD_VALUES) {
4800c0d7e18SFande Kong               ap[i] += value;
4810c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4820c0d7e18SFande Kong             }
48317ab2063SBarry Smith             else ap[i] = value;
4848c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
485e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
486e2cf4d64SStefano Zampini #endif
487720833daSHong Zhang           }
488e44c0bd4SBarry Smith           low = i + 1;
48917ab2063SBarry Smith           goto noinsert;
49017ab2063SBarry Smith         }
49117ab2063SBarry Smith       }
492dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
493c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
494e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
495720833daSHong Zhang       if (A->structure_only) {
496876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
497720833daSHong Zhang       } else {
498fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
499720833daSHong Zhang       }
500c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
501416022c9SBarry Smith       /* shift up all the later entries in this row */
502580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
50317ab2063SBarry Smith       rp[i] = col;
504580bdb30SBarry Smith       if (!A->structure_only){
505580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
506580bdb30SBarry Smith         ap[i] = value;
507580bdb30SBarry Smith       }
508416022c9SBarry Smith       low = i + 1;
509e56f5c9eSBarry Smith       A->nonzerostate++;
5108c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
511e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
512e2cf4d64SStefano Zampini #endif
513e44c0bd4SBarry Smith noinsert:;
51417ab2063SBarry Smith     }
51517ab2063SBarry Smith     ailen[row] = nrow;
51617ab2063SBarry Smith   }
5178c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
518c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
519e2cf4d64SStefano Zampini #endif
5203a40ed3dSBarry Smith   PetscFunctionReturn(0);
52117ab2063SBarry Smith }
52217ab2063SBarry Smith 
52319b08ed1SBarry Smith 
52419b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
52519b08ed1SBarry Smith {
52619b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
52719b08ed1SBarry Smith   PetscInt       *rp,k,row;
52819b08ed1SBarry Smith   PetscInt       *ai = a->i;
52919b08ed1SBarry Smith   PetscErrorCode ierr;
53019b08ed1SBarry Smith   PetscInt       *aj = a->j;
53119b08ed1SBarry Smith   MatScalar      *aa = a->a,*ap;
53219b08ed1SBarry Smith 
53319b08ed1SBarry Smith   PetscFunctionBegin;
53419b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
53519b08ed1SBarry 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);
53619b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
53719b08ed1SBarry Smith     row  = im[k];
53819b08ed1SBarry Smith     rp   = aj + ai[row];
53919b08ed1SBarry Smith     ap   = aa + ai[row];
54019b08ed1SBarry Smith 
54119b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
54219b08ed1SBarry Smith     if (!A->structure_only) {
54319b08ed1SBarry Smith       if (v) {
54419b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
54519b08ed1SBarry Smith         v   += n;
54619b08ed1SBarry Smith       } else {
54719b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
54819b08ed1SBarry Smith       }
54919b08ed1SBarry Smith     }
55019b08ed1SBarry Smith     a->ilen[row] = n;
55119b08ed1SBarry Smith     a->imax[row] = n;
55219b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
55319b08ed1SBarry Smith     a->nz       += n;
55419b08ed1SBarry Smith   }
5558c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
55619b08ed1SBarry Smith   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
55719b08ed1SBarry Smith #endif
55819b08ed1SBarry Smith   PetscFunctionReturn(0);
55919b08ed1SBarry Smith }
56019b08ed1SBarry Smith 
56119b08ed1SBarry Smith /*@
56219b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
56319b08ed1SBarry Smith 
56419b08ed1SBarry Smith   Input Parameters:
56519b08ed1SBarry Smith +  A - the SeqAIJ matrix
56619b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
56719b08ed1SBarry Smith 
56819b08ed1SBarry Smith   Level: advanced
56919b08ed1SBarry Smith 
57019b08ed1SBarry Smith   Notes:
57119b08ed1SBarry 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.
57219b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
57319b08ed1SBarry Smith     as always with multiple matrix assemblies.
57419b08ed1SBarry Smith 
57519b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
57619b08ed1SBarry Smith @*/
57719b08ed1SBarry Smith 
57819b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
57919b08ed1SBarry Smith {
58019b08ed1SBarry Smith   PetscErrorCode ierr;
58119b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
58219b08ed1SBarry Smith 
58319b08ed1SBarry Smith   PetscFunctionBegin;
58419b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
58519b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
58619b08ed1SBarry Smith   a->maxnz  = nztotal;
58719b08ed1SBarry Smith   if (!a->imax) {
58819b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
58919b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59019b08ed1SBarry Smith   }
59119b08ed1SBarry Smith   if (!a->ilen) {
59219b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
59319b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59419b08ed1SBarry Smith   } else {
59519b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59619b08ed1SBarry Smith   }
59719b08ed1SBarry Smith 
59819b08ed1SBarry Smith   /* allocate the matrix space */
59919b08ed1SBarry Smith   if (A->structure_only) {
60019b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
60119b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
60219b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
60319b08ed1SBarry Smith   } else {
60419b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
60519b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
60619b08ed1SBarry Smith   }
60719b08ed1SBarry Smith   a->i[0] = 0;
60819b08ed1SBarry Smith   if (A->structure_only) {
60919b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
61019b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
61119b08ed1SBarry Smith   } else {
61219b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
61319b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
61419b08ed1SBarry Smith   }
61519b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
61619b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
61719b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
61819b08ed1SBarry Smith   PetscFunctionReturn(0);
61919b08ed1SBarry Smith }
62019b08ed1SBarry Smith 
621071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
622071fcb05SBarry Smith {
623071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
624071fcb05SBarry Smith   PetscInt       *rp,k,row;
625071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
626071fcb05SBarry Smith   PetscErrorCode ierr;
627071fcb05SBarry Smith   PetscInt       *aj = a->j;
628071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
629071fcb05SBarry Smith 
630071fcb05SBarry Smith   PetscFunctionBegin;
631071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
632071fcb05SBarry Smith     row  = im[k];
63319b08ed1SBarry 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);
634071fcb05SBarry Smith     rp   = aj + ai[row];
635071fcb05SBarry Smith     ap   = aa + ai[row];
636071fcb05SBarry Smith     if (!A->was_assembled) {
637071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
638071fcb05SBarry Smith     }
639071fcb05SBarry Smith     if (!A->structure_only) {
640071fcb05SBarry Smith       if (v) {
641071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
642071fcb05SBarry Smith         v   += n;
643071fcb05SBarry Smith       } else {
644071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
645071fcb05SBarry Smith       }
646071fcb05SBarry Smith     }
647071fcb05SBarry Smith     ailen[row] = n;
648071fcb05SBarry Smith     a->nz      += n;
649071fcb05SBarry Smith   }
6508c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
651c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
652e2cf4d64SStefano Zampini #endif
653071fcb05SBarry Smith   PetscFunctionReturn(0);
654071fcb05SBarry Smith }
655071fcb05SBarry Smith 
65681824310SBarry Smith 
657a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6587eb43aa7SLois Curfman McInnes {
6597eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
66097f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
66197f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
66254f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
6637eb43aa7SLois Curfman McInnes 
6643a40ed3dSBarry Smith   PetscFunctionBegin;
6657eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6667eb43aa7SLois Curfman McInnes     row = im[k];
667e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
668e32f2f54SBarry 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);
669bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6707eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6717eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
672e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
673e32f2f54SBarry 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);
674bfeeae90SHong Zhang       col  = in[l];
6757eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6767eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6777eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6787eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6797eb43aa7SLois Curfman McInnes         else low = t;
6807eb43aa7SLois Curfman McInnes       }
6817eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6827eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6837eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
684b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6857eb43aa7SLois Curfman McInnes           goto finished;
6867eb43aa7SLois Curfman McInnes         }
6877eb43aa7SLois Curfman McInnes       }
68897e567efSBarry Smith       *v++ = 0.0;
6897eb43aa7SLois Curfman McInnes finished:;
6907eb43aa7SLois Curfman McInnes     }
6917eb43aa7SLois Curfman McInnes   }
6923a40ed3dSBarry Smith   PetscFunctionReturn(0);
6937eb43aa7SLois Curfman McInnes }
6947eb43aa7SLois Curfman McInnes 
6953ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
69617ab2063SBarry Smith {
6973ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
698c898d852SStefano Zampini   const PetscScalar *av;
6993ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
7003ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
7016849ba73SBarry Smith   PetscErrorCode    ierr;
70217ab2063SBarry Smith 
7033a40ed3dSBarry Smith   PetscFunctionBegin;
7043ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7052205254eSKarl Rupp 
7063ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7073ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7083ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7093ea6fe3dSLisandro Dalcin   nz = A->nz;
710416022c9SBarry Smith 
7113ea6fe3dSLisandro Dalcin   /* write matrix header */
7123ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7133ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7143ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
715416022c9SBarry Smith 
7163ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7173ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7183ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7193ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7203ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7213ea6fe3dSLisandro Dalcin   /* store column indices */
7223ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
723416022c9SBarry Smith   /* store nonzero values */
724c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
725c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
726c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
727b37d52dbSMark F. Adams 
7283ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7293ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7303a40ed3dSBarry Smith   PetscFunctionReturn(0);
73117ab2063SBarry Smith }
732416022c9SBarry Smith 
7337dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7347dc0baabSHong Zhang {
7357dc0baabSHong Zhang   PetscErrorCode ierr;
7367dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7377dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7387dc0baabSHong Zhang 
7397dc0baabSHong Zhang   PetscFunctionBegin;
7407dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7417dc0baabSHong Zhang   for (i=0; i<m; i++) {
7427dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7437dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7447dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7457dc0baabSHong Zhang     }
7467dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7477dc0baabSHong Zhang   }
7487dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7497dc0baabSHong Zhang   PetscFunctionReturn(0);
7507dc0baabSHong Zhang }
7517dc0baabSHong Zhang 
75209573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
753cd155464SBarry Smith 
754dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
755416022c9SBarry Smith {
756416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
757c898d852SStefano Zampini   const PetscScalar *av;
758dfbe8321SBarry Smith   PetscErrorCode    ierr;
75960e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
760e060cb09SBarry Smith   const char        *name;
761f3ef73ceSBarry Smith   PetscViewerFormat format;
76217ab2063SBarry Smith 
7633a40ed3dSBarry Smith   PetscFunctionBegin;
7647dc0baabSHong Zhang   if (A->structure_only) {
7657dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7667dc0baabSHong Zhang     PetscFunctionReturn(0);
7677dc0baabSHong Zhang   }
76843e49210SHong Zhang 
769b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
770c898d852SStefano Zampini   /* trigger copy to CPU if needed */
771c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
772c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
77371c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
77497f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
77560e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
776c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
777d00d2cf4SBarry Smith       nofinalvalue = 1;
778d00d2cf4SBarry Smith     }
779d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
780d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
78177431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
782fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
783fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
784fbfe6fa7SJed Brown #else
78577431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
786fbfe6fa7SJed Brown #endif
787b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
78817ab2063SBarry Smith 
78917ab2063SBarry Smith     for (i=0; i<m; i++) {
79060e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
791aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
792a9bf72d8SJed 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);
79317ab2063SBarry Smith #else
79460e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
79517ab2063SBarry Smith #endif
79617ab2063SBarry Smith       }
79717ab2063SBarry Smith     }
798d00d2cf4SBarry Smith     if (nofinalvalue) {
799c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
800c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
801c337ccceSJed Brown #else
802d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
803c337ccceSJed Brown #endif
804d00d2cf4SBarry Smith     }
805317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
806fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
807d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
8082950ac48SStefano Zampini   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
809cd155464SBarry Smith     PetscFunctionReturn(0);
810fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
811d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
81244cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
81377431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
81460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
815aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
81636db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
81760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81836db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
81960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
82036db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
82160e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8226831982aSBarry Smith         }
82344cd7ae7SLois Curfman McInnes #else
82460e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
82544cd7ae7SLois Curfman McInnes #endif
82644cd7ae7SLois Curfman McInnes       }
827b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
82844cd7ae7SLois Curfman McInnes     }
829d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
830fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
83197f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
832d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
833854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
834496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
835496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
83660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
837496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
838aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
83936db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
840496be53dSLois Curfman McInnes #else
841496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
842496be53dSLois Curfman McInnes #endif
843496be53dSLois Curfman McInnes         }
844496be53dSLois Curfman McInnes       }
845496be53dSLois Curfman McInnes     }
8462e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
84777431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8482e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8492205254eSKarl Rupp       if (i+4<m) {
8502205254eSKarl 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);
8512205254eSKarl Rupp       } else if (i+3<m) {
8522205254eSKarl 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);
8532205254eSKarl Rupp       } else if (i+2<m) {
8542205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8552205254eSKarl Rupp       } else if (i+1<m) {
8562205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8572205254eSKarl Rupp       } else if (i<m) {
8582205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8592205254eSKarl Rupp       } else {
8602205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8612205254eSKarl Rupp       }
862496be53dSLois Curfman McInnes     }
863b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
864606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
865496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
86660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
86777431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
868496be53dSLois Curfman McInnes       }
869b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
870496be53dSLois Curfman McInnes     }
871b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
872496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
87360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
874496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
875aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
87636db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
87760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8786831982aSBarry Smith           }
879496be53dSLois Curfman McInnes #else
88060e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
881496be53dSLois Curfman McInnes #endif
882496be53dSLois Curfman McInnes         }
883496be53dSLois Curfman McInnes       }
884b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
885496be53dSLois Curfman McInnes     }
886d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
887fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
88897f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
88987828ca2SBarry Smith     PetscScalar value;
89068f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
89168f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
89268f1ed48SBarry Smith 
89368f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
89468f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
89568f1ed48SBarry Smith         realonly = PETSC_FALSE;
89668f1ed48SBarry Smith         break;
89768f1ed48SBarry Smith       }
89868f1ed48SBarry Smith     }
89968f1ed48SBarry Smith #endif
90002594712SBarry Smith 
901d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
90202594712SBarry Smith     for (i=0; i<m; i++) {
90302594712SBarry Smith       jcnt = 0;
904d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
905e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
90602594712SBarry Smith           value = a->a[cnt++];
907e24b481bSBarry Smith           jcnt++;
90802594712SBarry Smith         } else {
90902594712SBarry Smith           value = 0.0;
91002594712SBarry Smith         }
911aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
91268f1ed48SBarry Smith         if (realonly) {
91360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
91468f1ed48SBarry Smith         } else {
91560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
91668f1ed48SBarry Smith         }
91702594712SBarry Smith #else
91860e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
91902594712SBarry Smith #endif
92002594712SBarry Smith       }
921b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
92202594712SBarry Smith     }
923d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9243c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
925150b93efSMatthew G. Knepley     PetscInt fshift=1;
926d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9273c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
92819303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9293c215bfdSMatthew Knepley #else
93019303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9313c215bfdSMatthew Knepley #endif
932d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9333c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
93460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9353c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
936a9a0e077SKarl 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);
9373c215bfdSMatthew Knepley #else
938150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9393c215bfdSMatthew Knepley #endif
9403c215bfdSMatthew Knepley       }
9413c215bfdSMatthew Knepley     }
942d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9433a40ed3dSBarry Smith   } else {
944d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
945d5f3da31SBarry Smith     if (A->factortype) {
94616cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
94716cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
94816cd7e1dSShri Abhyankar         /* L part */
94960e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
95016cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
95116cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
95260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
95316cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9546712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
95516cd7e1dSShri Abhyankar           } else {
95660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
95716cd7e1dSShri Abhyankar           }
95816cd7e1dSShri Abhyankar #else
95960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
96016cd7e1dSShri Abhyankar #endif
96116cd7e1dSShri Abhyankar         }
96216cd7e1dSShri Abhyankar         /* diagonal */
96316cd7e1dSShri Abhyankar         j = a->diag[i];
96416cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
96516cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
96660e0710aSBarry 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);
96716cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9686712e2f1SBarry 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);
96916cd7e1dSShri Abhyankar         } else {
97060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
97116cd7e1dSShri Abhyankar         }
97216cd7e1dSShri Abhyankar #else
97360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
97416cd7e1dSShri Abhyankar #endif
97516cd7e1dSShri Abhyankar 
97616cd7e1dSShri Abhyankar         /* U part */
97760e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
97816cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97916cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
98060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
98116cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
98222ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
98316cd7e1dSShri Abhyankar           } else {
98460e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
98516cd7e1dSShri Abhyankar           }
98616cd7e1dSShri Abhyankar #else
98760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
98816cd7e1dSShri Abhyankar #endif
98916cd7e1dSShri Abhyankar         }
99016cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
99116cd7e1dSShri Abhyankar       }
99216cd7e1dSShri Abhyankar     } else {
99317ab2063SBarry Smith       for (i=0; i<m; i++) {
99477431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
99560e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
996aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
99736db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
99860e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
99936db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
100060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
10013a40ed3dSBarry Smith           } else {
100260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
100317ab2063SBarry Smith           }
100417ab2063SBarry Smith #else
100560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
100617ab2063SBarry Smith #endif
100717ab2063SBarry Smith         }
1008b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
100917ab2063SBarry Smith       }
101016cd7e1dSShri Abhyankar     }
1011d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
101217ab2063SBarry Smith   }
1013b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10143a40ed3dSBarry Smith   PetscFunctionReturn(0);
1015416022c9SBarry Smith }
1016416022c9SBarry Smith 
10179804daf3SBarry Smith #include <petscdraw.h>
1018dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1019416022c9SBarry Smith {
1020480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1021416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1022dfbe8321SBarry Smith   PetscErrorCode    ierr;
1023383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1024383922c3SLisandro Dalcin   int               color;
1025b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1026b0a32e0cSBarry Smith   PetscViewer       viewer;
1027f3ef73ceSBarry Smith   PetscViewerFormat format;
1028cddf8d76SBarry Smith 
10293a40ed3dSBarry Smith   PetscFunctionBegin;
1030480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1031b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1032b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1033383922c3SLisandro Dalcin 
1034416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10350513a670SBarry Smith 
1036fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1037383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10380513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1039b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1040416022c9SBarry Smith     for (i=0; i<m; i++) {
1041cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1042bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1043bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
104436db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
1045b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1046cddf8d76SBarry Smith       }
1047cddf8d76SBarry Smith     }
1048b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1049cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1050cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1051bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1052bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1053cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
1054b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1055cddf8d76SBarry Smith       }
1056cddf8d76SBarry Smith     }
1057b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1058cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1059cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1060bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1061bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
106236db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
1063b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1064416022c9SBarry Smith       }
1065416022c9SBarry Smith     }
1066383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10670513a670SBarry Smith   } else {
10680513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10690513a670SBarry Smith     /* first determine max of all nonzero values */
1070b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1071383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1072b0a32e0cSBarry Smith     PetscDraw popup;
10730513a670SBarry Smith 
10740513a670SBarry Smith     for (i=0; i<nz; i++) {
10750513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
10760513a670SBarry Smith     }
1077383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1078b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
107945f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1080383922c3SLisandro Dalcin 
1081383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10820513a670SBarry Smith     for (i=0; i<m; i++) {
1083383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1084383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1085bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1086383922c3SLisandro Dalcin         x_l = a->j[j];
1087383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1088b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
1089b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
10900513a670SBarry Smith         count++;
10910513a670SBarry Smith       }
10920513a670SBarry Smith     }
1093383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10940513a670SBarry Smith   }
1095480ef9eaSBarry Smith   PetscFunctionReturn(0);
1096480ef9eaSBarry Smith }
1097cddf8d76SBarry Smith 
10989804daf3SBarry Smith #include <petscdraw.h>
1099dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1100480ef9eaSBarry Smith {
1101dfbe8321SBarry Smith   PetscErrorCode ierr;
1102b0a32e0cSBarry Smith   PetscDraw      draw;
110336db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1104ace3abfcSBarry Smith   PetscBool      isnull;
1105480ef9eaSBarry Smith 
1106480ef9eaSBarry Smith   PetscFunctionBegin;
1107b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1108b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1109480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1110480ef9eaSBarry Smith 
1111d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1112480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1113b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1114832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1115b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11160298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1117832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11183a40ed3dSBarry Smith   PetscFunctionReturn(0);
1119416022c9SBarry Smith }
1120416022c9SBarry Smith 
1121dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1122416022c9SBarry Smith {
1123dfbe8321SBarry Smith   PetscErrorCode ierr;
1124ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1125416022c9SBarry Smith 
11263a40ed3dSBarry Smith   PetscFunctionBegin;
1127251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1128251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1129251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1130c45a1595SBarry Smith   if (iascii) {
11313a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11320f5bd95cSBarry Smith   } else if (isbinary) {
11333a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11340f5bd95cSBarry Smith   } else if (isdraw) {
11353a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
113611aeaf0aSBarry Smith   }
11374108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11383a40ed3dSBarry Smith   PetscFunctionReturn(0);
113917ab2063SBarry Smith }
114019bcc07fSBarry Smith 
1141dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
114217ab2063SBarry Smith {
1143416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11446849ba73SBarry Smith   PetscErrorCode ierr;
1145580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1146d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
114754f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11483447b6efSHong Zhang   PetscReal      ratio  = 0.6;
114917ab2063SBarry Smith 
11503a40ed3dSBarry Smith   PetscFunctionBegin;
11513a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1152071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1153b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1154b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1155b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1156b215bc84SStefano Zampini     PetscFunctionReturn(0);
1157b215bc84SStefano Zampini   }
115817ab2063SBarry Smith 
115943ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
116017ab2063SBarry Smith   for (i=1; i<m; i++) {
1161416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
116217ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
116394a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
116417ab2063SBarry Smith     if (fshift) {
1165bfeeae90SHong Zhang       ip = aj + ai[i];
1166bfeeae90SHong Zhang       ap = aa + ai[i];
116717ab2063SBarry Smith       N  = ailen[i];
1168580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1169580bdb30SBarry Smith       if (!A->structure_only) {
1170580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
117117ab2063SBarry Smith       }
117217ab2063SBarry Smith     }
117317ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
117417ab2063SBarry Smith   }
117517ab2063SBarry Smith   if (m) {
117617ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
117717ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
117817ab2063SBarry Smith   }
11797b083b7cSBarry Smith 
118017ab2063SBarry Smith   /* reset ilen and imax for each row */
11817b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1182396832f4SHong Zhang   if (A->structure_only) {
1183071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1184071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1185396832f4SHong Zhang   } else { /* !A->structure_only */
118617ab2063SBarry Smith     for (i=0; i<m; i++) {
118717ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11887b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
118917ab2063SBarry Smith     }
1190396832f4SHong Zhang   }
1191bfeeae90SHong Zhang   a->nz = ai[m];
119265e19b50SBarry 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);
119317ab2063SBarry Smith 
119409f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1195d0f46423SBarry 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);
1196ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1197ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
11982205254eSKarl Rupp 
11998e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1200dd5f02e7SSatish Balay   a->reallocs         = 0;
12016712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
120236db0b34SBarry Smith   a->rmax             = rmax;
12034e220ebcSLois Curfman McInnes 
1204396832f4SHong Zhang   if (!A->structure_only) {
120511e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1206396832f4SHong Zhang   }
12074108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12083a40ed3dSBarry Smith   PetscFunctionReturn(0);
120917ab2063SBarry Smith }
121017ab2063SBarry Smith 
121199cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
121299cafbc1SBarry Smith {
121399cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
121499cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
121554f21887SBarry Smith   MatScalar      *aa = a->a;
1216acf2f550SJed Brown   PetscErrorCode ierr;
121799cafbc1SBarry Smith 
121899cafbc1SBarry Smith   PetscFunctionBegin;
121999cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1220acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12218c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1222c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1223e2cf4d64SStefano Zampini #endif
122499cafbc1SBarry Smith   PetscFunctionReturn(0);
122599cafbc1SBarry Smith }
122699cafbc1SBarry Smith 
122799cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
122899cafbc1SBarry Smith {
122999cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
123099cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
123154f21887SBarry Smith   MatScalar      *aa = a->a;
1232acf2f550SJed Brown   PetscErrorCode ierr;
123399cafbc1SBarry Smith 
123499cafbc1SBarry Smith   PetscFunctionBegin;
123599cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1236acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12378c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1238c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1239e2cf4d64SStefano Zampini #endif
124099cafbc1SBarry Smith   PetscFunctionReturn(0);
124199cafbc1SBarry Smith }
124299cafbc1SBarry Smith 
1243dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
124417ab2063SBarry Smith {
1245416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1246dfbe8321SBarry Smith   PetscErrorCode ierr;
12473a40ed3dSBarry Smith 
12483a40ed3dSBarry Smith   PetscFunctionBegin;
1249580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);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
12543a40ed3dSBarry Smith   PetscFunctionReturn(0);
125517ab2063SBarry Smith }
1256416022c9SBarry Smith 
1257dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
125817ab2063SBarry Smith {
1259416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1260dfbe8321SBarry Smith   PetscErrorCode ierr;
1261d5d45c9bSBarry Smith 
12623a40ed3dSBarry Smith   PetscFunctionBegin;
1263aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1264d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
126517ab2063SBarry Smith #endif
1266e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12676bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12686bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
126905b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1270d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1271071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1272071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1273846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
127471f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
127505b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12766bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
127705b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1278cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1279a30b2313SHong Zhang 
12804108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1281bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1282901853e0SKris Buschelman 
12836718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12846718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12856718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12866718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12876718818eSStefano Zampini      due to different matrix sizes */
12886718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
12896718818eSStefano Zampini 
1290f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1291bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1292bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1293bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1294bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1295bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1296bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
12974222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12984222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1299e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
13004222ddf1SHong Zhang #endif
13013d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
13023d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13033d0639e7SStefano Zampini #endif
13044222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1305af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1306af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1307af8000cdSHong Zhang #endif
1308d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1309d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1310d24d4204SJose E. Roman #endif
131163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
131263c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13134222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
131463c07aadSStefano Zampini #endif
1315b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1316c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1317c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1318bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1319bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1320846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1321bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1322bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13234222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13244222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13254222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
13263a40ed3dSBarry Smith   PetscFunctionReturn(0);
132717ab2063SBarry Smith }
132817ab2063SBarry Smith 
1329ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
133017ab2063SBarry Smith {
1331416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13324846f1f5SKris Buschelman   PetscErrorCode ierr;
13333a40ed3dSBarry Smith 
13343a40ed3dSBarry Smith   PetscFunctionBegin;
1335a65d3064SKris Buschelman   switch (op) {
1336a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13374e0d8c25SBarry Smith     a->roworiented = flg;
1338a65d3064SKris Buschelman     break;
1339a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1340a9817697SBarry Smith     a->keepnonzeropattern = flg;
1341a65d3064SKris Buschelman     break;
1342512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1343512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1344a65d3064SKris Buschelman     break;
1345a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13464e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1347a65d3064SKris Buschelman     break;
1348a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13494e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1350a65d3064SKris Buschelman     break;
135128b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
135228b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
135328b2fa4aSMatthew Knepley     break;
1354a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13554e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13560df259c2SBarry Smith     break;
13573d472b54SHong Zhang   case MAT_SPD:
1358b1646e73SJed Brown   case MAT_SYMMETRIC:
1359b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1360b1646e73SJed Brown   case MAT_HERMITIAN:
1361b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1362957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13635021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13645021d80fSJed Brown     break;
13658c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1366a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1367a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1368290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1369a65d3064SKris Buschelman     break;
1370b87ac2d8SJed Brown   case MAT_USE_INODES:
1371b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1372b87ac2d8SJed Brown     break;
1373c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1374c10200c1SHong Zhang     A->submat_singleis = flg;
1375c10200c1SHong Zhang     break;
1376071fcb05SBarry Smith   case MAT_SORTED_FULL:
1377071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1378071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1379071fcb05SBarry Smith     break;
1380a65d3064SKris Buschelman   default:
1381e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1382a65d3064SKris Buschelman   }
13833a40ed3dSBarry Smith   PetscFunctionReturn(0);
138417ab2063SBarry Smith }
138517ab2063SBarry Smith 
1386dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
138717ab2063SBarry Smith {
1388416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
13896849ba73SBarry Smith   PetscErrorCode    ierr;
1390fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1391c898d852SStefano Zampini   PetscScalar       *x;
1392c898d852SStefano Zampini   const PetscScalar *aa;
139317ab2063SBarry Smith 
13943a40ed3dSBarry Smith   PetscFunctionBegin;
1395d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1396e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1397c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1398d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1399d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1400fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14012c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1402fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1403c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
140435e7444dSHong Zhang     PetscFunctionReturn(0);
140535e7444dSHong Zhang   }
140635e7444dSHong Zhang 
1407fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
140835e7444dSHong Zhang   for (i=0; i<n; i++) {
1409fdc842d1SBarry Smith     x[i] = 0.0;
141035e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
141135e7444dSHong Zhang       if (aj[j] == i) {
141235e7444dSHong Zhang         x[i] = aa[j];
141317ab2063SBarry Smith         break;
141417ab2063SBarry Smith       }
141517ab2063SBarry Smith     }
141617ab2063SBarry Smith   }
1417fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1418c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14193a40ed3dSBarry Smith   PetscFunctionReturn(0);
142017ab2063SBarry Smith }
142117ab2063SBarry Smith 
1422c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1423dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
142417ab2063SBarry Smith {
1425416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1426d9ca1df4SBarry Smith   PetscScalar       *y;
1427d9ca1df4SBarry Smith   const PetscScalar *x;
1428dfbe8321SBarry Smith   PetscErrorCode    ierr;
1429d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14305c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1431d9ca1df4SBarry Smith   const MatScalar   *v;
1432a77337e4SBarry Smith   PetscScalar       alpha;
1433d9ca1df4SBarry Smith   PetscInt          n,i,j;
1434d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14353447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1436ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14375c897100SBarry Smith #endif
143817ab2063SBarry Smith 
14393a40ed3dSBarry Smith   PetscFunctionBegin;
14402e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1441d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14421ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14435c897100SBarry Smith 
14445c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1445bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14465c897100SBarry Smith #else
14473447b6efSHong Zhang   if (usecprow) {
14483447b6efSHong Zhang     m    = cprow.nrows;
14493447b6efSHong Zhang     ii   = cprow.i;
14507b2bb3b9SHong Zhang     ridx = cprow.rindex;
14513447b6efSHong Zhang   } else {
14523447b6efSHong Zhang     ii = a->i;
14533447b6efSHong Zhang   }
145417ab2063SBarry Smith   for (i=0; i<m; i++) {
14553447b6efSHong Zhang     idx = a->j + ii[i];
14563447b6efSHong Zhang     v   = a->a + ii[i];
14573447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14583447b6efSHong Zhang     if (usecprow) {
14597b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14603447b6efSHong Zhang     } else {
146117ab2063SBarry Smith       alpha = x[i];
14623447b6efSHong Zhang     }
146304fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
146417ab2063SBarry Smith   }
14655c897100SBarry Smith #endif
1466dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1467d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14681ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14693a40ed3dSBarry Smith   PetscFunctionReturn(0);
147017ab2063SBarry Smith }
147117ab2063SBarry Smith 
1472dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14735c897100SBarry Smith {
1474dfbe8321SBarry Smith   PetscErrorCode ierr;
14755c897100SBarry Smith 
14765c897100SBarry Smith   PetscFunctionBegin;
1477170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14785c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14795c897100SBarry Smith   PetscFunctionReturn(0);
14805c897100SBarry Smith }
14815c897100SBarry Smith 
1482c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
148378b84d54SShri Abhyankar 
1484dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
148517ab2063SBarry Smith {
1486416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1487d9fead3dSBarry Smith   PetscScalar       *y;
148854f21887SBarry Smith   const PetscScalar *x;
148954f21887SBarry Smith   const MatScalar   *aa;
1490dfbe8321SBarry Smith   PetscErrorCode    ierr;
1491003131ecSBarry Smith   PetscInt          m=A->rmap->n;
14920298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
14937b083b7cSBarry Smith   PetscInt          n,i;
1494362ced78SSatish Balay   PetscScalar       sum;
1495ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
149617ab2063SBarry Smith 
1497b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
149897952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1499fee21e36SBarry Smith #endif
1500fee21e36SBarry Smith 
15013a40ed3dSBarry Smith   PetscFunctionBegin;
1502b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1503b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1504b215bc84SStefano Zampini     PetscFunctionReturn(0);
1505b215bc84SStefano Zampini   }
15063649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15071ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1508416022c9SBarry Smith   ii   = a->i;
15094eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1510580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
151197952fefSHong Zhang     m    = a->compressedrow.nrows;
151297952fefSHong Zhang     ii   = a->compressedrow.i;
151397952fefSHong Zhang     ridx = a->compressedrow.rindex;
151497952fefSHong Zhang     for (i=0; i<m; i++) {
151597952fefSHong Zhang       n           = ii[i+1] - ii[i];
151697952fefSHong Zhang       aj          = a->j + ii[i];
151797952fefSHong Zhang       aa          = a->a + ii[i];
151897952fefSHong Zhang       sum         = 0.0;
1519003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1520003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
152197952fefSHong Zhang       y[*ridx++] = sum;
152297952fefSHong Zhang     }
152397952fefSHong Zhang   } else { /* do not use compressed row format */
1524b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15253d3eaba7SBarry Smith     aj   = a->j;
15263d3eaba7SBarry Smith     aa   = a->a;
1527b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1528b05257ddSBarry Smith #else
152917ab2063SBarry Smith     for (i=0; i<m; i++) {
1530003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1531003131ecSBarry Smith       aj          = a->j + ii[i];
1532003131ecSBarry Smith       aa          = a->a + ii[i];
153317ab2063SBarry Smith       sum         = 0.0;
1534003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
153517ab2063SBarry Smith       y[i] = sum;
153617ab2063SBarry Smith     }
15378d195f9aSBarry Smith #endif
1538b05257ddSBarry Smith   }
15397b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15403649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15411ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15423a40ed3dSBarry Smith   PetscFunctionReturn(0);
154317ab2063SBarry Smith }
154417ab2063SBarry Smith 
1545b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1546b434eb95SMatthew G. Knepley {
1547b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1548b434eb95SMatthew G. Knepley   PetscScalar       *y;
1549b434eb95SMatthew G. Knepley   const PetscScalar *x;
1550b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1551b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1552b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1553b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1554b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1555b434eb95SMatthew G. Knepley   PetscScalar       sum;
1556b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1557b434eb95SMatthew G. Knepley 
1558b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1559b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1560b434eb95SMatthew G. Knepley #endif
1561b434eb95SMatthew G. Knepley 
1562b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1563b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1564b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1565b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1566b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1567b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1568b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1569b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1570b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1571b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1572b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1573b434eb95SMatthew G. Knepley       sum         = 0.0;
1574b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1575b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1576b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1577b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1578b434eb95SMatthew G. Knepley     }
1579b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15803d3eaba7SBarry Smith     ii = a->i;
1581b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1582b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1583b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1584b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1585b434eb95SMatthew G. Knepley       sum         = 0.0;
1586b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1587b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1588b434eb95SMatthew G. Knepley       y[i] = sum;
1589b434eb95SMatthew G. Knepley     }
1590b434eb95SMatthew G. Knepley   }
1591b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1592b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1593b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1594b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1595b434eb95SMatthew G. Knepley }
1596b434eb95SMatthew G. Knepley 
1597b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1598b434eb95SMatthew G. Knepley {
1599b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1600b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1601b434eb95SMatthew G. Knepley   const PetscScalar *x;
1602b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1603b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1604b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1605b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1606b434eb95SMatthew G. Knepley   PetscScalar       sum;
1607b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1608b434eb95SMatthew G. Knepley 
1609b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1610b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1611d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1612b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1613b434eb95SMatthew G. Knepley     if (zz != yy) {
1614580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1615b434eb95SMatthew G. Knepley     }
1616b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1617b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1618b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1619b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1620b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1621b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1622b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1623b434eb95SMatthew G. Knepley       sum = y[*ridx];
1624b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1625b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1626b434eb95SMatthew G. Knepley     }
1627b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16283d3eaba7SBarry Smith     ii = a->i;
1629b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1630b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1631b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1632b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1633b434eb95SMatthew G. Knepley       sum = y[i];
1634b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1635b434eb95SMatthew G. Knepley       z[i] = sum;
1636b434eb95SMatthew G. Knepley     }
1637b434eb95SMatthew G. Knepley   }
1638b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1639b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1640d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1641b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1642b434eb95SMatthew G. Knepley }
1643b434eb95SMatthew G. Knepley 
1644c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1645dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
164617ab2063SBarry Smith {
1647416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1648f15663dcSBarry Smith   PetscScalar       *y,*z;
1649f15663dcSBarry Smith   const PetscScalar *x;
165054f21887SBarry Smith   const MatScalar   *aa;
1651dfbe8321SBarry Smith   PetscErrorCode    ierr;
1652d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1653d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1654362ced78SSatish Balay   PetscScalar       sum;
1655ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16569ea0dfa2SSatish Balay 
16573a40ed3dSBarry Smith   PetscFunctionBegin;
1658b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1659b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1660b215bc84SStefano Zampini     PetscFunctionReturn(0);
1661b215bc84SStefano Zampini   }
1662f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1663d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16644eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16654eb6d288SHong Zhang     if (zz != yy) {
1666580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16674eb6d288SHong Zhang     }
166897952fefSHong Zhang     m    = a->compressedrow.nrows;
166997952fefSHong Zhang     ii   = a->compressedrow.i;
167097952fefSHong Zhang     ridx = a->compressedrow.rindex;
167197952fefSHong Zhang     for (i=0; i<m; i++) {
167297952fefSHong Zhang       n   = ii[i+1] - ii[i];
167397952fefSHong Zhang       aj  = a->j + ii[i];
167497952fefSHong Zhang       aa  = a->a + ii[i];
167597952fefSHong Zhang       sum = y[*ridx];
1676f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
167797952fefSHong Zhang       z[*ridx++] = sum;
167897952fefSHong Zhang     }
167997952fefSHong Zhang   } else { /* do not use compressed row format */
16803d3eaba7SBarry Smith     ii = a->i;
1681f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16823d3eaba7SBarry Smith     aj = a->j;
16833d3eaba7SBarry Smith     aa = a->a;
1684f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1685f15663dcSBarry Smith #else
168617ab2063SBarry Smith     for (i=0; i<m; i++) {
1687f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1688f15663dcSBarry Smith       aj  = a->j + ii[i];
1689f15663dcSBarry Smith       aa  = a->a + ii[i];
169017ab2063SBarry Smith       sum = y[i];
1691f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
169217ab2063SBarry Smith       z[i] = sum;
169317ab2063SBarry Smith     }
169402ab625aSSatish Balay #endif
1695f15663dcSBarry Smith   }
1696dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1697f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1698d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16993a40ed3dSBarry Smith   PetscFunctionReturn(0);
170017ab2063SBarry Smith }
170117ab2063SBarry Smith 
170217ab2063SBarry Smith /*
170317ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
170417ab2063SBarry Smith */
1705dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
170617ab2063SBarry Smith {
1707416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17086849ba73SBarry Smith   PetscErrorCode ierr;
1709d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
171017ab2063SBarry Smith 
17113a40ed3dSBarry Smith   PetscFunctionBegin;
171209f38230SBarry Smith   if (!a->diag) {
1713785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17143bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
171509f38230SBarry Smith   }
1716d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
171709f38230SBarry Smith     a->diag[i] = a->i[i+1];
1718bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1719bfeeae90SHong Zhang       if (a->j[j] == i) {
172009f38230SBarry Smith         a->diag[i] = j;
172117ab2063SBarry Smith         break;
172217ab2063SBarry Smith       }
172317ab2063SBarry Smith     }
172417ab2063SBarry Smith   }
17253a40ed3dSBarry Smith   PetscFunctionReturn(0);
172617ab2063SBarry Smith }
172717ab2063SBarry Smith 
172861ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
172961ecd0c6SBarry Smith {
173061ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
173161ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
173261ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
173361ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
173461ecd0c6SBarry Smith   PetscErrorCode    ierr;
173561ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
173661ecd0c6SBarry Smith 
173761ecd0c6SBarry Smith   PetscFunctionBegin;
173861ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
173961ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
174061ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
174161ecd0c6SBarry Smith     PetscFunctionReturn(0);
174261ecd0c6SBarry Smith   }
174361ecd0c6SBarry Smith 
174461ecd0c6SBarry Smith   if (a->diagonaldense) {
174561ecd0c6SBarry Smith     cnt = 0;
174661ecd0c6SBarry Smith   } else {
174761ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
174861ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
174961ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
175061ecd0c6SBarry Smith         cnt++;
175161ecd0c6SBarry Smith         mdiag[i] = 1;
175261ecd0c6SBarry Smith       }
175361ecd0c6SBarry Smith     }
175461ecd0c6SBarry Smith   }
175561ecd0c6SBarry Smith   if (!cnt) {
175661ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
175761ecd0c6SBarry Smith   } else {
1758b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1759b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
176061ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
176161ecd0c6SBarry Smith 
176261ecd0c6SBarry Smith     a->a = NULL;
176361ecd0c6SBarry Smith     a->j = NULL;
176461ecd0c6SBarry Smith     a->i = NULL;
176561ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
176661ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
176761ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1768447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
176961ecd0c6SBarry Smith     }
177061ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
177161ecd0c6SBarry Smith 
177261ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
177361ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
177461ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1775447d62f5SStefano Zampini       if (i < A->cmap->n) {
177661ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
177761ecd0c6SBarry Smith       }
1778447d62f5SStefano Zampini     }
177961ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
178061ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
178161ecd0c6SBarry Smith     if (singlemalloc) {
178261ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
178361ecd0c6SBarry Smith     } else {
178461ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
178561ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
178661ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
178761ecd0c6SBarry Smith     }
178861ecd0c6SBarry Smith   }
178961ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
179061ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
179161ecd0c6SBarry Smith   PetscFunctionReturn(0);
179261ecd0c6SBarry Smith }
179361ecd0c6SBarry Smith 
1794be5855fcSBarry Smith /*
1795be5855fcSBarry Smith      Checks for missing diagonals
1796be5855fcSBarry Smith */
1797ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1798be5855fcSBarry Smith {
1799be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18007734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1801994fe344SLisandro Dalcin   PetscErrorCode ierr;
1802be5855fcSBarry Smith 
1803be5855fcSBarry Smith   PetscFunctionBegin;
180409f38230SBarry Smith   *missing = PETSC_FALSE;
18057734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
180609f38230SBarry Smith     *missing = PETSC_TRUE;
180709f38230SBarry Smith     if (d) *d = 0;
1808994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
180909f38230SBarry Smith   } else {
181001445905SHong Zhang     PetscInt n;
181101445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1812f1e2ffcdSBarry Smith     diag = a->diag;
181301445905SHong Zhang     for (i=0; i<n; i++) {
18147734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
181509f38230SBarry Smith         *missing = PETSC_TRUE;
181609f38230SBarry Smith         if (d) *d = i;
1817994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1818358d2f5dSShri Abhyankar         break;
181909f38230SBarry Smith       }
1820be5855fcSBarry Smith     }
1821be5855fcSBarry Smith   }
1822be5855fcSBarry Smith   PetscFunctionReturn(0);
1823be5855fcSBarry Smith }
1824be5855fcSBarry Smith 
18250da83c2eSBarry Smith #include <petscblaslapack.h>
18260da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18270da83c2eSBarry Smith 
18280da83c2eSBarry Smith /*
18290da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18300da83c2eSBarry Smith */
18310da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18320da83c2eSBarry Smith {
18330da83c2eSBarry Smith   PetscErrorCode  ierr;
18340da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18350da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18360da83c2eSBarry Smith   const PetscReal shift = 0.0;
18370da83c2eSBarry Smith   PetscInt        ipvt[5];
18380da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18390da83c2eSBarry Smith 
18400da83c2eSBarry Smith   PetscFunctionBegin;
18410da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18420da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18430da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18440da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18450da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18460da83c2eSBarry Smith   }
18470da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18480da83c2eSBarry Smith   if (bsizemax > 7) {
18490da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18500da83c2eSBarry Smith   }
18510da83c2eSBarry Smith   ncnt = 0;
18520da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18530da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18540da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18550da83c2eSBarry Smith     switch (bsizes[i]) {
18560da83c2eSBarry Smith     case 1:
18570da83c2eSBarry Smith       *diag = 1.0/(*diag);
18580da83c2eSBarry Smith       break;
18590da83c2eSBarry Smith     case 2:
18600da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18610da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18620da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18630da83c2eSBarry Smith       break;
18640da83c2eSBarry Smith     case 3:
18650da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18660da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18670da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18680da83c2eSBarry Smith       break;
18690da83c2eSBarry Smith     case 4:
18700da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18710da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18720da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18730da83c2eSBarry Smith       break;
18740da83c2eSBarry Smith     case 5:
18750da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18760da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18770da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18780da83c2eSBarry Smith       break;
18790da83c2eSBarry Smith     case 6:
18800da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18810da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18820da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
18830da83c2eSBarry Smith       break;
18840da83c2eSBarry Smith     case 7:
18850da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18860da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18870da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
18880da83c2eSBarry Smith       break;
18890da83c2eSBarry Smith     default:
18900da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18910da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18920da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
18930da83c2eSBarry Smith     }
18940da83c2eSBarry Smith     ncnt   += bsizes[i];
18950da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
18960da83c2eSBarry Smith   }
18970da83c2eSBarry Smith   if (bsizemax > 7) {
18980da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
18990da83c2eSBarry Smith   }
19000da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19010da83c2eSBarry Smith   PetscFunctionReturn(0);
19020da83c2eSBarry Smith }
19030da83c2eSBarry Smith 
1904422a814eSBarry Smith /*
1905422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1906422a814eSBarry Smith */
19077087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
190871f1c65dSBarry Smith {
190971f1c65dSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
191071f1c65dSBarry Smith   PetscErrorCode ierr;
1911d0f46423SBarry Smith   PetscInt       i,*diag,m = A->rmap->n;
191254f21887SBarry Smith   MatScalar      *v = a->a;
191354f21887SBarry Smith   PetscScalar    *idiag,*mdiag;
191471f1c65dSBarry Smith 
191571f1c65dSBarry Smith   PetscFunctionBegin;
191671f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
191771f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
191871f1c65dSBarry Smith   diag = a->diag;
191971f1c65dSBarry Smith   if (!a->idiag) {
1920dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19213bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
192271f1c65dSBarry Smith     v    = a->a;
192371f1c65dSBarry Smith   }
192471f1c65dSBarry Smith   mdiag = a->mdiag;
192571f1c65dSBarry Smith   idiag = a->idiag;
192671f1c65dSBarry Smith 
1927422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
192871f1c65dSBarry Smith     for (i=0; i<m; i++) {
192971f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1930899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1931899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1932899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19337b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19347b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19357b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1936a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1937899639b0SHong Zhang       }
193871f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
193971f1c65dSBarry Smith     }
194071f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
194171f1c65dSBarry Smith   } else {
194271f1c65dSBarry Smith     for (i=0; i<m; i++) {
194371f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
194471f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
194571f1c65dSBarry Smith     }
1946dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
194771f1c65dSBarry Smith   }
194871f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
194971f1c65dSBarry Smith   PetscFunctionReturn(0);
195071f1c65dSBarry Smith }
195171f1c65dSBarry Smith 
1952c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
195341f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
195417ab2063SBarry Smith {
1955416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1956e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
1957f4259b30SLisandro Dalcin   const MatScalar   *v,*idiag=NULL,*mdiag;
195854f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1959dfbe8321SBarry Smith   PetscErrorCode    ierr;
19603d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
196197f1f81fSBarry Smith   const PetscInt    *idx,*diag;
196217ab2063SBarry Smith 
19633a40ed3dSBarry Smith   PetscFunctionBegin;
1964b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1965b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1966b215bc84SStefano Zampini     PetscFunctionReturn(0);
1967b215bc84SStefano Zampini   }
1968b965ef7fSBarry Smith   its = its*lits;
196991723122SBarry Smith 
197071f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
197171f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
197271f1c65dSBarry Smith   a->fshift = fshift;
197371f1c65dSBarry Smith   a->omega  = omega;
1974ed480e8bSBarry Smith 
197571f1c65dSBarry Smith   diag  = a->diag;
197671f1c65dSBarry Smith   t     = a->ssor_work;
1977ed480e8bSBarry Smith   idiag = a->idiag;
197871f1c65dSBarry Smith   mdiag = a->mdiag;
1979ed480e8bSBarry Smith 
19801ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
19813649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1982ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
198317ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
198417ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1985ed480e8bSBarry Smith     bs = b;
198617ab2063SBarry Smith     for (i=0; i<m; i++) {
198771f1c65dSBarry Smith       d   = fshift + mdiag[i];
1988416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1989ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1990ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
199117ab2063SBarry Smith       sum = b[i]*d/omega;
1992003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
199317ab2063SBarry Smith       x[i] = sum;
199417ab2063SBarry Smith     }
19951ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
19963649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1997efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
19983a40ed3dSBarry Smith     PetscFunctionReturn(0);
199917ab2063SBarry Smith   }
2000c783ea89SBarry Smith 
20012205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20022205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20034c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2004887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
200517ab2063SBarry Smith 
200617ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
200717ab2063SBarry Smith 
2008887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
200917ab2063SBarry Smith     */
201017ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
201117ab2063SBarry Smith 
201217ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
201317ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2014416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2015ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
2016ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
201717ab2063SBarry Smith       sum = b[i];
2018e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2019ed480e8bSBarry Smith       x[i] = sum*idiag[i];
202017ab2063SBarry Smith     }
202117ab2063SBarry Smith 
202217ab2063SBarry Smith     /*  t = b - (2*E - D)x */
2023416022c9SBarry Smith     v = a->a;
20242205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
202517ab2063SBarry Smith 
202617ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2027ed480e8bSBarry Smith     ts   = t;
2028416022c9SBarry Smith     diag = a->diag;
202917ab2063SBarry Smith     for (i=0; i<m; i++) {
2030416022c9SBarry Smith       n   = diag[i] - a->i[i];
2031ed480e8bSBarry Smith       idx = a->j + a->i[i];
2032ed480e8bSBarry Smith       v   = a->a + a->i[i];
203317ab2063SBarry Smith       sum = t[i];
2034003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2035ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2036733d66baSBarry Smith       /*  x = x + t */
2037733d66baSBarry Smith       x[i] += t[i];
203817ab2063SBarry Smith     }
203917ab2063SBarry Smith 
2040dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20411ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20423649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20433a40ed3dSBarry Smith     PetscFunctionReturn(0);
204417ab2063SBarry Smith   }
204517ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
204617ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
204717ab2063SBarry Smith       for (i=0; i<m; i++) {
2048416022c9SBarry Smith         n   = diag[i] - a->i[i];
2049ed480e8bSBarry Smith         idx = a->j + a->i[i];
2050ed480e8bSBarry Smith         v   = a->a + a->i[i];
205117ab2063SBarry Smith         sum = b[i];
2052e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20535c99c7daSBarry Smith         t[i] = sum;
2054ed480e8bSBarry Smith         x[i] = sum*idiag[i];
205517ab2063SBarry Smith       }
20565c99c7daSBarry Smith       xb   = t;
2057efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20583a40ed3dSBarry Smith     } else xb = b;
205917ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
206017ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2061416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2062ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
2063ed480e8bSBarry Smith         v   = a->a + diag[i] + 1;
206417ab2063SBarry Smith         sum = xb[i];
2065e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20665c99c7daSBarry Smith         if (xb == b) {
2067ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20685c99c7daSBarry Smith         } else {
2069b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
207017ab2063SBarry Smith         }
20715c99c7daSBarry Smith       }
2072b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
207317ab2063SBarry Smith     }
207417ab2063SBarry Smith     its--;
207517ab2063SBarry Smith   }
207617ab2063SBarry Smith   while (its--) {
207717ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
207817ab2063SBarry Smith       for (i=0; i<m; i++) {
2079b19a5dc2SMark Adams         /* lower */
2080b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2081ed480e8bSBarry Smith         idx = a->j + a->i[i];
2082ed480e8bSBarry Smith         v   = a->a + a->i[i];
208317ab2063SBarry Smith         sum = b[i];
2084e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2085b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2086b19a5dc2SMark Adams         /* upper */
2087b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2088b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
2089b19a5dc2SMark Adams         v   = a->a + diag[i] + 1;
2090b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2091b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
209217ab2063SBarry Smith       }
2093b19a5dc2SMark Adams       xb   = t;
20949f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2095b19a5dc2SMark Adams     } else xb = b;
209617ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
209717ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2098b19a5dc2SMark Adams         sum = xb[i];
2099b19a5dc2SMark Adams         if (xb == b) {
2100b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2101416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2102ed480e8bSBarry Smith           idx = a->j + a->i[i];
2103ed480e8bSBarry Smith           v   = a->a + a->i[i];
2104e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2105ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2106b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2107b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2108b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
2109b19a5dc2SMark Adams           v   = a->a + diag[i] + 1;
2110b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2111b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
211217ab2063SBarry Smith         }
2113b19a5dc2SMark Adams       }
2114b19a5dc2SMark Adams       if (xb == b) {
21159f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2116b19a5dc2SMark Adams       } else {
2117b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2118b19a5dc2SMark Adams       }
211917ab2063SBarry Smith     }
212017ab2063SBarry Smith   }
21211ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21223649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2123365a8a9eSBarry Smith   PetscFunctionReturn(0);
212417ab2063SBarry Smith }
212517ab2063SBarry Smith 
21262af78befSBarry Smith 
2127dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
212817ab2063SBarry Smith {
2129416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21304e220ebcSLois Curfman McInnes 
21313a40ed3dSBarry Smith   PetscFunctionBegin;
21324e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21333966268fSBarry Smith   info->nz_allocated = a->maxnz;
21343966268fSBarry Smith   info->nz_used      = a->nz;
21353966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21363966268fSBarry Smith   info->assemblies   = A->num_ass;
21373966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21387adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2139d5f3da31SBarry Smith   if (A->factortype) {
21404e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21414e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21424e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21434e220ebcSLois Curfman McInnes   } else {
21444e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21454e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21464e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21474e220ebcSLois Curfman McInnes   }
21483a40ed3dSBarry Smith   PetscFunctionReturn(0);
214917ab2063SBarry Smith }
215017ab2063SBarry Smith 
21512b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
215217ab2063SBarry Smith {
2153416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2154c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21556849ba73SBarry Smith   PetscErrorCode    ierr;
215697b48c8fSBarry Smith   const PetscScalar *xx;
215797b48c8fSBarry Smith   PetscScalar       *bb;
2158c7da8527SEric Chamberland   PetscInt          d = 0;
215917ab2063SBarry Smith 
21603a40ed3dSBarry Smith   PetscFunctionBegin;
216197b48c8fSBarry Smith   if (x && b) {
216297b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
216397b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
216497b48c8fSBarry Smith     for (i=0; i<N; i++) {
216597b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2166447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
216797b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
216897b48c8fSBarry Smith     }
216997b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
217097b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
217197b48c8fSBarry Smith   }
217297b48c8fSBarry Smith 
2173a9817697SBarry Smith   if (a->keepnonzeropattern) {
2174f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2175e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2176580bdb30SBarry Smith       ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2177f1e2ffcdSBarry Smith     }
2178f4df32b1SMatthew Knepley     if (diag != 0.0) {
2179c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2180c7da8527SEric Chamberland         d = rows[i];
2181447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2182c7da8527SEric 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);
2183c7da8527SEric Chamberland       }
2184f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2185447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2186f4df32b1SMatthew Knepley         a->a[a->diag[rows[i]]] = diag;
2187f1e2ffcdSBarry Smith       }
2188f1e2ffcdSBarry Smith     }
2189f1e2ffcdSBarry Smith   } else {
2190f4df32b1SMatthew Knepley     if (diag != 0.0) {
219117ab2063SBarry Smith       for (i=0; i<N; i++) {
2192e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
21937ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2194447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2195447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2196447d62f5SStefano Zampini           } else {
2197416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
2198f4df32b1SMatthew Knepley             a->a[a->i[rows[i]]] = diag;
2199bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2200447d62f5SStefano Zampini           }
2201447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2202f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
220317ab2063SBarry Smith         }
220417ab2063SBarry Smith       }
22053a40ed3dSBarry Smith     } else {
220617ab2063SBarry Smith       for (i=0; i<N; i++) {
2207e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2208416022c9SBarry Smith         a->ilen[rows[i]] = 0;
220917ab2063SBarry Smith       }
221017ab2063SBarry Smith     }
2211e56f5c9eSBarry Smith     A->nonzerostate++;
2212f1e2ffcdSBarry Smith   }
22138c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2214c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2215e2cf4d64SStefano Zampini #endif
22164099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22173a40ed3dSBarry Smith   PetscFunctionReturn(0);
221817ab2063SBarry Smith }
221917ab2063SBarry Smith 
22206e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22216e169961SBarry Smith {
22226e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22236e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22246e169961SBarry Smith   PetscErrorCode    ierr;
22252b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22266e169961SBarry Smith   const PetscScalar *xx;
22276e169961SBarry Smith   PetscScalar       *bb;
22286e169961SBarry Smith 
22296e169961SBarry Smith   PetscFunctionBegin;
22306e169961SBarry Smith   if (x && b) {
22316e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22326e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22332b40b63fSBarry Smith     vecs = PETSC_TRUE;
22346e169961SBarry Smith   }
22351795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22366e169961SBarry Smith   for (i=0; i<N; i++) {
22376e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2238580bdb30SBarry Smith     ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22392205254eSKarl Rupp 
22406e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22416e169961SBarry Smith   }
22426e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22436e169961SBarry Smith     if (!zeroed[i]) {
22446e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22454cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22462b40b63fSBarry Smith           if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
22476e169961SBarry Smith           a->a[j] = 0.0;
22486e169961SBarry Smith         }
22496e169961SBarry Smith       }
22504cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22516e169961SBarry Smith   }
22526e169961SBarry Smith   if (x && b) {
22536e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22546e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22556e169961SBarry Smith   }
22566e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22576e169961SBarry Smith   if (diag != 0.0) {
22586e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22591d5a398dSstefano_zampini     if (missing) {
22601d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22614cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22624cf107fdSStefano 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]);
22631d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22641d5a398dSstefano_zampini       }
22651d5a398dSstefano_zampini     } else {
22666e169961SBarry Smith       for (i=0; i<N; i++) {
22676e169961SBarry Smith         a->a[a->diag[rows[i]]] = diag;
22686e169961SBarry Smith       }
22696e169961SBarry Smith     }
22701d5a398dSstefano_zampini   }
22718c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2272c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2273e2cf4d64SStefano Zampini #endif
22744099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22756e169961SBarry Smith   PetscFunctionReturn(0);
22766e169961SBarry Smith }
22776e169961SBarry Smith 
2278a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
227917ab2063SBarry Smith {
2280416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
228197f1f81fSBarry Smith   PetscInt   *itmp;
228217ab2063SBarry Smith 
22833a40ed3dSBarry Smith   PetscFunctionBegin;
2284e32f2f54SBarry Smith   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
228517ab2063SBarry Smith 
2286416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
2287bfeeae90SHong Zhang   if (v) *v = a->a + a->i[row];
228817ab2063SBarry Smith   if (idx) {
2289bfeeae90SHong Zhang     itmp = a->j + a->i[row];
229026fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2291f4259b30SLisandro Dalcin     else *idx = NULL;
229217ab2063SBarry Smith   }
22933a40ed3dSBarry Smith   PetscFunctionReturn(0);
229417ab2063SBarry Smith }
229517ab2063SBarry Smith 
2296bfeeae90SHong Zhang /* remove this function? */
2297a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
229817ab2063SBarry Smith {
22993a40ed3dSBarry Smith   PetscFunctionBegin;
23003a40ed3dSBarry Smith   PetscFunctionReturn(0);
230117ab2063SBarry Smith }
230217ab2063SBarry Smith 
2303dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
230417ab2063SBarry Smith {
2305416022c9SBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
230654f21887SBarry Smith   MatScalar      *v  = a->a;
230736db0b34SBarry Smith   PetscReal      sum = 0.0;
23086849ba73SBarry Smith   PetscErrorCode ierr;
230997f1f81fSBarry Smith   PetscInt       i,j;
231017ab2063SBarry Smith 
23113a40ed3dSBarry Smith   PetscFunctionBegin;
231217ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2313570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2314570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
231573cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2316570b7f6dSBarry Smith #else
2317416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
231836db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
231917ab2063SBarry Smith     }
23208f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2321570b7f6dSBarry Smith #endif
2322ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23233a40ed3dSBarry Smith   } else if (type == NORM_1) {
232436db0b34SBarry Smith     PetscReal *tmp;
232597f1f81fSBarry Smith     PetscInt  *jj = a->j;
23261795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2327064f8208SBarry Smith     *nrm = 0.0;
2328416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2329bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
233017ab2063SBarry Smith     }
2331d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2332064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
233317ab2063SBarry Smith     }
2334606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
233551f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23363a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2337064f8208SBarry Smith     *nrm = 0.0;
2338d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
2339bfeeae90SHong Zhang       v   = a->a + a->i[j];
234017ab2063SBarry Smith       sum = 0.0;
2341416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
2342cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
234317ab2063SBarry Smith       }
2344064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
234517ab2063SBarry Smith     }
234651f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2347f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23483a40ed3dSBarry Smith   PetscFunctionReturn(0);
234917ab2063SBarry Smith }
235017ab2063SBarry Smith 
23514e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23524e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23534e938277SHong Zhang {
23544e938277SHong Zhang   PetscErrorCode ierr;
23554e938277SHong Zhang   PetscInt       i,j,anzj;
23564e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23574e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23584e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23594e938277SHong Zhang 
23604e938277SHong Zhang   PetscFunctionBegin;
23614e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2362854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2363785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2364785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
23654e938277SHong Zhang 
23664e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23674e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
236826fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
23694e938277SHong Zhang   /* Form ati for csr format of A^T. */
237026fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
23714e938277SHong Zhang 
23724e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2373580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
23744e938277SHong Zhang 
23754e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
23764e938277SHong Zhang   for (i=0;i<am;i++) {
23774e938277SHong Zhang     anzj = ai[i+1] - ai[i];
23784e938277SHong Zhang     for (j=0;j<anzj;j++) {
23794e938277SHong Zhang       atj[atfill[*aj]] = i;
23804e938277SHong Zhang       atfill[*aj++]   += 1;
23814e938277SHong Zhang     }
23824e938277SHong Zhang   }
23834e938277SHong Zhang 
23844e938277SHong Zhang   /* Clean up temporary space and complete requests. */
23854e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2386ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
238733d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2388b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2389a2f3521dSMark F. Adams 
23904e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
23914e938277SHong Zhang   b->free_a  = PETSC_FALSE;
23924e938277SHong Zhang   b->free_ij = PETSC_TRUE;
23934e938277SHong Zhang   b->nonew   = 0;
23944e938277SHong Zhang   PetscFunctionReturn(0);
23954e938277SHong Zhang }
23964e938277SHong Zhang 
23977087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2398cd0d46ebSvictorle {
23993d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
240054f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
240154f21887SBarry Smith   MatScalar      *va,*vb;
24026849ba73SBarry Smith   PetscErrorCode ierr;
240397f1f81fSBarry Smith   PetscInt       ma,na,mb,nb, i;
2404cd0d46ebSvictorle 
2405cd0d46ebSvictorle   PetscFunctionBegin;
2406cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2407cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24085485867bSBarry Smith   if (ma!=nb || na!=mb) {
24095485867bSBarry Smith     *f = PETSC_FALSE;
24105485867bSBarry Smith     PetscFunctionReturn(0);
24115485867bSBarry Smith   }
2412cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2413cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2414cd0d46ebSvictorle   va   = aij->a; vb = bij->a;
2415785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2416785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2417cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2418cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2419cd0d46ebSvictorle 
2420cd0d46ebSvictorle   *f = PETSC_TRUE;
2421cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2422cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
242397f1f81fSBarry Smith       PetscInt    idc,idr;
24245485867bSBarry Smith       PetscScalar vc,vr;
2425cd0d46ebSvictorle       /* column/row index/value */
24265485867bSBarry Smith       idc = adx[aptr[i]];
24275485867bSBarry Smith       idr = bdx[bptr[idc]];
24285485867bSBarry Smith       vc  = va[aptr[i]];
24295485867bSBarry Smith       vr  = vb[bptr[idc]];
24305485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24315485867bSBarry Smith         *f = PETSC_FALSE;
24325485867bSBarry Smith         goto done;
2433cd0d46ebSvictorle       } else {
24345485867bSBarry Smith         aptr[i]++;
24355485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2436cd0d46ebSvictorle       }
2437cd0d46ebSvictorle     }
2438cd0d46ebSvictorle   }
2439cd0d46ebSvictorle done:
2440cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24413aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
2442cd0d46ebSvictorle   PetscFunctionReturn(0);
2443cd0d46ebSvictorle }
2444cd0d46ebSvictorle 
24457087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24461cbb95d3SBarry Smith {
24473d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
244854f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
244954f21887SBarry Smith   MatScalar      *va,*vb;
24501cbb95d3SBarry Smith   PetscErrorCode ierr;
24511cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24521cbb95d3SBarry Smith 
24531cbb95d3SBarry Smith   PetscFunctionBegin;
24541cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
24551cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24561cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24571cbb95d3SBarry Smith     *f = PETSC_FALSE;
24581cbb95d3SBarry Smith     PetscFunctionReturn(0);
24591cbb95d3SBarry Smith   }
24601cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24611cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24621cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2463785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2464785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
24651cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
24661cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
24671cbb95d3SBarry Smith 
24681cbb95d3SBarry Smith   *f = PETSC_TRUE;
24691cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
24701cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
24711cbb95d3SBarry Smith       PetscInt    idc,idr;
24721cbb95d3SBarry Smith       PetscScalar vc,vr;
24731cbb95d3SBarry Smith       /* column/row index/value */
24741cbb95d3SBarry Smith       idc = adx[aptr[i]];
24751cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
24761cbb95d3SBarry Smith       vc  = va[aptr[i]];
24771cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
24781cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
24791cbb95d3SBarry Smith         *f = PETSC_FALSE;
24801cbb95d3SBarry Smith         goto done;
24811cbb95d3SBarry Smith       } else {
24821cbb95d3SBarry Smith         aptr[i]++;
24831cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
24841cbb95d3SBarry Smith       }
24851cbb95d3SBarry Smith     }
24861cbb95d3SBarry Smith   }
24871cbb95d3SBarry Smith done:
24881cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
24891cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
24901cbb95d3SBarry Smith   PetscFunctionReturn(0);
24911cbb95d3SBarry Smith }
24921cbb95d3SBarry Smith 
2493ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24949e29f15eSvictorle {
2495dfbe8321SBarry Smith   PetscErrorCode ierr;
24966e111a19SKarl Rupp 
24979e29f15eSvictorle   PetscFunctionBegin;
24985485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
24999e29f15eSvictorle   PetscFunctionReturn(0);
25009e29f15eSvictorle }
25019e29f15eSvictorle 
2502ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25031cbb95d3SBarry Smith {
25041cbb95d3SBarry Smith   PetscErrorCode ierr;
25056e111a19SKarl Rupp 
25061cbb95d3SBarry Smith   PetscFunctionBegin;
25071cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25081cbb95d3SBarry Smith   PetscFunctionReturn(0);
25091cbb95d3SBarry Smith }
25101cbb95d3SBarry Smith 
2511dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
251217ab2063SBarry Smith {
2513416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2514fff8e43fSBarry Smith   const PetscScalar *l,*r;
2515fff8e43fSBarry Smith   PetscScalar       x;
251654f21887SBarry Smith   MatScalar         *v;
2517dfbe8321SBarry Smith   PetscErrorCode    ierr;
2518fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2519fff8e43fSBarry Smith   const PetscInt    *jj;
252017ab2063SBarry Smith 
25213a40ed3dSBarry Smith   PetscFunctionBegin;
252217ab2063SBarry Smith   if (ll) {
25233ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25243ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2525e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2526e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2527fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
2528416022c9SBarry Smith     v    = a->a;
252917ab2063SBarry Smith     for (i=0; i<m; i++) {
253017ab2063SBarry Smith       x = l[i];
2531416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25322205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
253317ab2063SBarry Smith     }
2534fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2535efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
253617ab2063SBarry Smith   }
253717ab2063SBarry Smith   if (rr) {
2538e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2539e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2540fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
2541416022c9SBarry Smith     v    = a->a; jj = a->j;
25422205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
2543fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2544efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
254517ab2063SBarry Smith   }
2546acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
25478c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2548c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2549e2cf4d64SStefano Zampini #endif
25503a40ed3dSBarry Smith   PetscFunctionReturn(0);
255117ab2063SBarry Smith }
255217ab2063SBarry Smith 
25537dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
255417ab2063SBarry Smith {
2555db02288aSLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
25566849ba73SBarry Smith   PetscErrorCode ierr;
2557d0f46423SBarry Smith   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
255897f1f81fSBarry Smith   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25595d0c19d7SBarry Smith   const PetscInt *irow,*icol;
25605d0c19d7SBarry Smith   PetscInt       nrows,ncols;
256197f1f81fSBarry Smith   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
256254f21887SBarry Smith   MatScalar      *a_new,*mat_a;
2563416022c9SBarry Smith   Mat            C;
2564cdc6f3adSToby Isaac   PetscBool      stride;
256517ab2063SBarry Smith 
25663a40ed3dSBarry Smith   PetscFunctionBegin;
256799141d43SSatish Balay 
256817ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2569b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2570b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
257117ab2063SBarry Smith 
2572251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2573ff718158SBarry Smith   if (stride) {
2574ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2575ff718158SBarry Smith   } else {
2576ff718158SBarry Smith     first = 0;
2577ff718158SBarry Smith     step  = 0;
2578ff718158SBarry Smith   }
2579fee21e36SBarry Smith   if (stride && step == 1) {
258002834360SBarry Smith     /* special case of contiguous rows */
2581dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
258202834360SBarry Smith     /* loop over new rows determining lens and starting points */
258302834360SBarry Smith     for (i=0; i<nrows; i++) {
2584bfeeae90SHong Zhang       kstart = ai[irow[i]];
2585a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2586a91a9bebSLisandro Dalcin       starts[i] = kstart;
258702834360SBarry Smith       for (k=kstart; k<kend; k++) {
2588bfeeae90SHong Zhang         if (aj[k] >= first) {
258902834360SBarry Smith           starts[i] = k;
259002834360SBarry Smith           break;
259102834360SBarry Smith         }
259202834360SBarry Smith       }
2593a2744918SBarry Smith       sum = 0;
259402834360SBarry Smith       while (k < kend) {
2595bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2596a2744918SBarry Smith         sum++;
259702834360SBarry Smith       }
2598a2744918SBarry Smith       lens[i] = sum;
259902834360SBarry Smith     }
260002834360SBarry Smith     /* create submatrix */
2601cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
260297f1f81fSBarry Smith       PetscInt n_cols,n_rows;
260308480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2604e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2605d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
260608480c60SBarry Smith       C    = *B;
26073a40ed3dSBarry Smith     } else {
26083bef6203SJed Brown       PetscInt rbs,cbs;
2609ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2610f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26113bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26123bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26133bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26147adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2615ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
261608480c60SBarry Smith     }
2617db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2618db02288aSLois Curfman McInnes 
261902834360SBarry Smith     /* loop over rows inserting into submatrix */
2620db02288aSLois Curfman McInnes     a_new = c->a;
2621db02288aSLois Curfman McInnes     j_new = c->j;
2622db02288aSLois Curfman McInnes     i_new = c->i;
2623bfeeae90SHong Zhang 
262402834360SBarry Smith     for (i=0; i<nrows; i++) {
2625a2744918SBarry Smith       ii    = starts[i];
2626a2744918SBarry Smith       lensi = lens[i];
2627a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2628a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
262902834360SBarry Smith       }
2630580bdb30SBarry Smith       ierr       = PetscArraycpy(a_new,a->a + starts[i],lensi);CHKERRQ(ierr);
2631a2744918SBarry Smith       a_new     += lensi;
2632a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2633a2744918SBarry Smith       c->ilen[i] = lensi;
263402834360SBarry Smith     }
26350e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26363a40ed3dSBarry Smith   } else {
263702834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26381795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2639854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26404dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2641d9ef940eSSatish 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);
26424dcab191SBarry Smith       smap[icol[i]] = i+1;
26434dcab191SBarry Smith     }
26444dcab191SBarry Smith 
264502834360SBarry Smith     /* determine lens of each row */
264602834360SBarry Smith     for (i=0; i<nrows; i++) {
2647bfeeae90SHong Zhang       kstart  = ai[irow[i]];
264802834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
264902834360SBarry Smith       lens[i] = 0;
265002834360SBarry Smith       for (k=kstart; k<kend; k++) {
2651bfeeae90SHong Zhang         if (smap[aj[k]]) {
265202834360SBarry Smith           lens[i]++;
265302834360SBarry Smith         }
265402834360SBarry Smith       }
265502834360SBarry Smith     }
265617ab2063SBarry Smith     /* Create and fill new matrix */
2657a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2658ace3abfcSBarry Smith       PetscBool equal;
26590f5bd95cSBarry Smith 
266099141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2661e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2662580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2663f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2664580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
266508480c60SBarry Smith       C    = *B;
26663a40ed3dSBarry Smith     } else {
26673bef6203SJed Brown       PetscInt rbs,cbs;
2668ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2669f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26703bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26713bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26723bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26737adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2674ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
267508480c60SBarry Smith     }
267699141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
267717ab2063SBarry Smith     for (i=0; i<nrows; i++) {
267899141d43SSatish Balay       row      = irow[i];
2679bfeeae90SHong Zhang       kstart   = ai[row];
268099141d43SSatish Balay       kend     = kstart + a->ilen[row];
2681bfeeae90SHong Zhang       mat_i    = c->i[i];
268299141d43SSatish Balay       mat_j    = c->j + mat_i;
268399141d43SSatish Balay       mat_a    = c->a + mat_i;
268499141d43SSatish Balay       mat_ilen = c->ilen + i;
268517ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2686bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2687ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
268899141d43SSatish Balay           *mat_a++ = a->a[k];
268999141d43SSatish Balay           (*mat_ilen)++;
269099141d43SSatish Balay 
269117ab2063SBarry Smith         }
269217ab2063SBarry Smith       }
269317ab2063SBarry Smith     }
269402834360SBarry Smith     /* Free work space */
269502834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2696606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2697606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2698cdc6f3adSToby Isaac     /* sort */
2699cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2700cdc6f3adSToby Isaac       PetscInt ilen;
2701cdc6f3adSToby Isaac 
2702cdc6f3adSToby Isaac       mat_i = c->i[i];
2703cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2704cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2705cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2706390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2707cdc6f3adSToby Isaac     }
270802834360SBarry Smith   }
27098c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2710b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2711305c6ccfSStefano Zampini #endif
27126d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27136d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
271417ab2063SBarry Smith 
271517ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2716416022c9SBarry Smith   *B   = C;
27173a40ed3dSBarry Smith   PetscFunctionReturn(0);
271817ab2063SBarry Smith }
271917ab2063SBarry Smith 
2720fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
272182d44351SHong Zhang {
272282d44351SHong Zhang   PetscErrorCode ierr;
272382d44351SHong Zhang   Mat            B;
272482d44351SHong Zhang 
272582d44351SHong Zhang   PetscFunctionBegin;
2726c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
272782d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
272882d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
272933d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
273082d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
273182d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
273282d44351SHong Zhang     *subMat = B;
2733c2d650bdSHong Zhang   } else {
2734c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2735c2d650bdSHong Zhang   }
273682d44351SHong Zhang   PetscFunctionReturn(0);
273782d44351SHong Zhang }
273882d44351SHong Zhang 
27399a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2740a871dcd8SBarry Smith {
274163b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2742dfbe8321SBarry Smith   PetscErrorCode ierr;
274363b91edcSBarry Smith   Mat            outA;
2744ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
274563b91edcSBarry Smith 
27463a40ed3dSBarry Smith   PetscFunctionBegin;
2747e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27481df811f5SHong Zhang 
2749b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2750b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2751a871dcd8SBarry Smith 
275263b91edcSBarry Smith   outA             = inA;
2753d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2754f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2755f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
27562205254eSKarl Rupp 
2757c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
27586bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
27592205254eSKarl Rupp 
2760c3122656SLisandro Dalcin   a->row = row;
27612205254eSKarl Rupp 
2762c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
27636bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
27642205254eSKarl Rupp 
2765c3122656SLisandro Dalcin   a->col = col;
276663b91edcSBarry Smith 
276736db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
27686bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
27694c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
27703bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2771f0ec6fceSSatish Balay 
277294a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2773854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
27743bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
277594a9d846SBarry Smith   }
277663b91edcSBarry Smith 
2777f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2778137fb511SHong Zhang   if (row_identity && col_identity) {
2779ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2780137fb511SHong Zhang   } else {
2781719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2782137fb511SHong Zhang   }
27833a40ed3dSBarry Smith   PetscFunctionReturn(0);
2784a871dcd8SBarry Smith }
2785a871dcd8SBarry Smith 
2786f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2787f0b747eeSBarry Smith {
2788f0b747eeSBarry Smith   Mat_SeqAIJ     *a     = (Mat_SeqAIJ*)inA->data;
2789f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
2790efee365bSSatish Balay   PetscErrorCode ierr;
2791c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
27923a40ed3dSBarry Smith 
27933a40ed3dSBarry Smith   PetscFunctionBegin;
2794c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
27958b83055fSJed Brown   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one));
2796efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2797acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
27988c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2799c70f7ee4SJunchao Zhang   if (inA->offloadmask != PETSC_OFFLOAD_UNALLOCATED) inA->offloadmask = PETSC_OFFLOAD_CPU;
2800e2cf4d64SStefano Zampini #endif
28013a40ed3dSBarry Smith   PetscFunctionReturn(0);
2802f0b747eeSBarry Smith }
2803f0b747eeSBarry Smith 
2804f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
280516b64355SHong Zhang {
280616b64355SHong Zhang   PetscErrorCode ierr;
280716b64355SHong Zhang   PetscInt       i;
280816b64355SHong Zhang 
280916b64355SHong Zhang   PetscFunctionBegin;
281016b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
281116b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
281216b64355SHong Zhang 
281316b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
281416b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
281516b64355SHong Zhang     }
281616b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
281716b64355SHong Zhang 
281816b64355SHong Zhang     if (submatj->rbuf1) {
281916b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
282016b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
282116b64355SHong Zhang     }
282216b64355SHong Zhang 
282316b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
282416b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
282516b64355SHong Zhang     }
282616b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
282716b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
282816b64355SHong Zhang   }
282916b64355SHong Zhang 
283016b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
283116b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
283216b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
283316b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
283416b64355SHong Zhang #else
283516b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
283616b64355SHong Zhang #endif
283716b64355SHong Zhang 
283816b64355SHong Zhang   if (!submatj->allcolumns) {
283916b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
284016b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
284116b64355SHong Zhang #else
284216b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
284316b64355SHong Zhang #endif
284416b64355SHong Zhang   }
284516b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
284616b64355SHong Zhang 
284716b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
284816b64355SHong Zhang   PetscFunctionReturn(0);
284916b64355SHong Zhang }
285016b64355SHong Zhang 
28510fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
285216b64355SHong Zhang {
285316b64355SHong Zhang   PetscErrorCode ierr;
285416b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28555c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
285616b64355SHong Zhang 
285716b64355SHong Zhang   PetscFunctionBegin;
285834136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2859f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
286016b64355SHong Zhang   PetscFunctionReturn(0);
286116b64355SHong Zhang }
286216b64355SHong Zhang 
28632d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
28642d033e1fSHong Zhang {
28652d033e1fSHong Zhang   PetscErrorCode ierr;
28662d033e1fSHong Zhang   PetscInt       i;
28670fb991dcSHong Zhang   Mat            C;
28680fb991dcSHong Zhang   Mat_SeqAIJ     *c;
28690fb991dcSHong Zhang   Mat_SubSppt    *submatj;
28702d033e1fSHong Zhang 
28712d033e1fSHong Zhang   PetscFunctionBegin;
28722d033e1fSHong Zhang   for (i=0; i<n; i++) {
28730fb991dcSHong Zhang     C       = (*mat)[i];
28740fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
28750fb991dcSHong Zhang     submatj = c->submatis1;
28762d033e1fSHong Zhang     if (submatj) {
2877682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
287834136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2879f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
288034136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
28812d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
28822d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
28832d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2884682e4c99SStefano Zampini       }
28852d033e1fSHong Zhang     } else {
28862d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
28872d033e1fSHong Zhang     }
28882d033e1fSHong Zhang   }
288986e85357SHong Zhang 
289063a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
289163a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
289263a75b2aSHong Zhang 
28932d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
28942d033e1fSHong Zhang   PetscFunctionReturn(0);
28952d033e1fSHong Zhang }
28962d033e1fSHong Zhang 
28977dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2898cddf8d76SBarry Smith {
2899dfbe8321SBarry Smith   PetscErrorCode ierr;
290097f1f81fSBarry Smith   PetscInt       i;
2901cddf8d76SBarry Smith 
29023a40ed3dSBarry Smith   PetscFunctionBegin;
2903cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2904df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2905cddf8d76SBarry Smith   }
2906cddf8d76SBarry Smith 
2907cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29087dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2909cddf8d76SBarry Smith   }
29103a40ed3dSBarry Smith   PetscFunctionReturn(0);
2911cddf8d76SBarry Smith }
2912cddf8d76SBarry Smith 
291397f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29144dcbc457SBarry Smith {
2915e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29166849ba73SBarry Smith   PetscErrorCode ierr;
29175d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29185d0c19d7SBarry Smith   const PetscInt *idx;
291997f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2920f1af5d2fSBarry Smith   PetscBT        table;
2921bbd702dbSSatish Balay 
29223a40ed3dSBarry Smith   PetscFunctionBegin;
2923d0f46423SBarry Smith   m  = A->rmap->n;
2924e4d965acSSatish Balay   ai = a->i;
2925bfeeae90SHong Zhang   aj = a->j;
29268a047759SSatish Balay 
2927e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
292806763907SSatish Balay 
2929854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
293053b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
293106763907SSatish Balay 
2932e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2933b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2934e4d965acSSatish Balay     isz  = 0;
29356831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2936e4d965acSSatish Balay 
2937e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29384dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2939b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2940e4d965acSSatish Balay 
2941dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2942e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29432205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29444dcbc457SBarry Smith     }
294506763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
29466bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2947e4d965acSSatish Balay 
294804a348a9SBarry Smith     k = 0;
294904a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
295004a348a9SBarry Smith       n = isz;
295106763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2952e4d965acSSatish Balay         row   = nidx[k];
2953e4d965acSSatish Balay         start = ai[row];
2954e4d965acSSatish Balay         end   = ai[row+1];
295504a348a9SBarry Smith         for (l = start; l<end; l++) {
2956efb16452SHong Zhang           val = aj[l];
29572205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2958e4d965acSSatish Balay         }
2959e4d965acSSatish Balay       }
2960e4d965acSSatish Balay     }
296170b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2962e4d965acSSatish Balay   }
296394bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2964606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
29653a40ed3dSBarry Smith   PetscFunctionReturn(0);
29664dcbc457SBarry Smith }
296717ab2063SBarry Smith 
29680513a670SBarry Smith /* -------------------------------------------------------------- */
2969dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
29700513a670SBarry Smith {
29710513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29726849ba73SBarry Smith   PetscErrorCode ierr;
29733b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
29745d0c19d7SBarry Smith   const PetscInt *row,*col;
29755d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
297656cd22aeSBarry Smith   IS             icolp,irowp;
29770298fd71SBarry Smith   PetscInt       *cwork = NULL;
29780298fd71SBarry Smith   PetscScalar    *vwork = NULL;
29790513a670SBarry Smith 
29803a40ed3dSBarry Smith   PetscFunctionBegin;
29814c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
298256cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
29834c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
298456cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
29850513a670SBarry Smith 
29860513a670SBarry Smith   /* determine lengths of permuted rows */
2987854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
29882205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
2989ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
2990f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
299133d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
29927adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2993ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2994606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
29950513a670SBarry Smith 
2996785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
29970513a670SBarry Smith   for (i=0; i<m; i++) {
299832ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
29992205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3000cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
300132ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30020513a670SBarry Smith   }
3003606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30042205254eSKarl Rupp 
30053c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30062205254eSKarl Rupp 
30078c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3008b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30099fe5e383SStefano Zampini #endif
30100513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30110513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
301256cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
301356cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30146bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30156bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30166768869dSprj-   if (rowp == colp) {
30176768869dSprj-     if (A->symmetric) {
30186768869dSprj-       ierr = MatSetOption(*B,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
30196768869dSprj-     }
30206768869dSprj-     if (A->hermitian) {
30216768869dSprj-       ierr = MatSetOption(*B,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
30226768869dSprj-     }
30236768869dSprj-   }
30243a40ed3dSBarry Smith   PetscFunctionReturn(0);
30250513a670SBarry Smith }
30260513a670SBarry Smith 
3027dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3028cb5b572fSBarry Smith {
3029dfbe8321SBarry Smith   PetscErrorCode ierr;
3030cb5b572fSBarry Smith 
3031cb5b572fSBarry Smith   PetscFunctionBegin;
303233f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
303333f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3034be6bf707SBarry Smith     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
3035be6bf707SBarry Smith     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
3036be6bf707SBarry Smith 
30374d805d7cSStefano 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]);
3038580bdb30SBarry Smith     ierr = PetscArraycpy(b->a,a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
3039cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
3040cb5b572fSBarry Smith   } else {
3041cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3042cb5b572fSBarry Smith   }
3043cb5b572fSBarry Smith   PetscFunctionReturn(0);
3044cb5b572fSBarry Smith }
3045cb5b572fSBarry Smith 
30464994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3047273d9f13SBarry Smith {
3048dfbe8321SBarry Smith   PetscErrorCode ierr;
3049273d9f13SBarry Smith 
3050273d9f13SBarry Smith   PetscFunctionBegin;
3051f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3052273d9f13SBarry Smith   PetscFunctionReturn(0);
3053273d9f13SBarry Smith }
3054273d9f13SBarry Smith 
3055f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30566c0721eeSBarry Smith {
30576c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30586e111a19SKarl Rupp 
30596c0721eeSBarry Smith   PetscFunctionBegin;
30606c0721eeSBarry Smith   *array = a->a;
30616c0721eeSBarry Smith   PetscFunctionReturn(0);
30626c0721eeSBarry Smith }
30636c0721eeSBarry Smith 
3064f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
30656c0721eeSBarry Smith {
30666c0721eeSBarry Smith   PetscFunctionBegin;
3067f38c1e66SStefano Zampini   *array = NULL;
30686c0721eeSBarry Smith   PetscFunctionReturn(0);
30696c0721eeSBarry Smith }
3070273d9f13SBarry Smith 
30718229c054SShri Abhyankar /*
30728229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
30738229c054SShri Abhyankar    have different nonzero structure.
30748229c054SShri Abhyankar */
3075b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3076ec7775f6SShri Abhyankar {
3077b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3078ec7775f6SShri Abhyankar 
3079ec7775f6SShri Abhyankar   PetscFunctionBegin;
3080ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3081ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3082b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3083b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3084b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
30858af7cee1SJed Brown     nnz[i] = 0;
30868af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3087b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3088b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
30898af7cee1SJed Brown       nnz[i]++;
30908af7cee1SJed Brown     }
30918af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3092ec7775f6SShri Abhyankar   }
3093ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3094ec7775f6SShri Abhyankar }
3095ec7775f6SShri Abhyankar 
3096b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3097b264fe52SHong Zhang {
3098b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3099b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3100b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3101b264fe52SHong Zhang   PetscErrorCode ierr;
3102b264fe52SHong Zhang 
3103b264fe52SHong Zhang   PetscFunctionBegin;
3104b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3105b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3106b264fe52SHong Zhang   PetscFunctionReturn(0);
3107b264fe52SHong Zhang }
3108b264fe52SHong Zhang 
3109f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3110ac90fabeSBarry Smith {
3111dfbe8321SBarry Smith   PetscErrorCode ierr;
3112ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3113ac90fabeSBarry Smith 
3114ac90fabeSBarry Smith   PetscFunctionBegin;
3115*d60b7d5cSBarry Smith   if (str == UNKNOWN_NONZERO_PATTERN) {
311681fa06acSBarry Smith     if (x->nz == y->nz) {
311781fa06acSBarry Smith       PetscBool e;
311881fa06acSBarry Smith       ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
311981fa06acSBarry Smith       if (e) {
312081fa06acSBarry Smith         ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
312181fa06acSBarry Smith         if (e) {
312281fa06acSBarry Smith           str = SAME_NONZERO_PATTERN;
312381fa06acSBarry Smith         }
312481fa06acSBarry Smith       }
312581fa06acSBarry Smith     }
312681fa06acSBarry Smith   }
3127ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
3128f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
312981fa06acSBarry Smith     PetscBLASInt one = 1,bnz;
313081fa06acSBarry Smith 
313181fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31328b83055fSJed Brown     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one));
3133acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3134a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
313581fa06acSBarry Smith     /* the MatAXPY_Basic* subroutines calls MatAssembly, so the matrix on the GPU will be updated */
31368c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3137c70f7ee4SJunchao Zhang     if (Y->offloadmask != PETSC_OFFLOAD_UNALLOCATED) {
3138c70f7ee4SJunchao Zhang       Y->offloadmask = PETSC_OFFLOAD_CPU;
3139e2cf4d64SStefano Zampini     }
3140e2cf4d64SStefano Zampini #endif
3141ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3142ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3143ac90fabeSBarry Smith   } else {
31448229c054SShri Abhyankar     Mat      B;
31458229c054SShri Abhyankar     PetscInt *nnz;
3146785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3147ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3148bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
314981fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
3150176df525SBarry Smith     ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr);
31518229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3152ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3153ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
315428be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
31558229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3156ac90fabeSBarry Smith   }
3157ac90fabeSBarry Smith   PetscFunctionReturn(0);
3158ac90fabeSBarry Smith }
3159ac90fabeSBarry Smith 
31607087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
3161354c94deSBarry Smith {
3162354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3163354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3164354c94deSBarry Smith   PetscInt    i,nz;
3165354c94deSBarry Smith   PetscScalar *a;
3166354c94deSBarry Smith 
3167354c94deSBarry Smith   PetscFunctionBegin;
3168354c94deSBarry Smith   nz = aij->nz;
3169354c94deSBarry Smith   a  = aij->a;
31702205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
31718c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3172c70f7ee4SJunchao Zhang   if (mat->offloadmask != PETSC_OFFLOAD_UNALLOCATED) mat->offloadmask = PETSC_OFFLOAD_CPU;
3173e2cf4d64SStefano Zampini #endif
3174354c94deSBarry Smith #else
3175354c94deSBarry Smith   PetscFunctionBegin;
3176354c94deSBarry Smith #endif
3177354c94deSBarry Smith   PetscFunctionReturn(0);
3178354c94deSBarry Smith }
3179354c94deSBarry Smith 
3180985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3181e34fafa9SBarry Smith {
3182e34fafa9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3183e34fafa9SBarry Smith   PetscErrorCode ierr;
3184d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3185e34fafa9SBarry Smith   PetscReal      atmp;
3186985db425SBarry Smith   PetscScalar    *x;
3187e34fafa9SBarry Smith   MatScalar      *aa;
3188e34fafa9SBarry Smith 
3189e34fafa9SBarry Smith   PetscFunctionBegin;
3190e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3191e34fafa9SBarry Smith   aa = a->a;
3192e34fafa9SBarry Smith   ai = a->i;
3193e34fafa9SBarry Smith   aj = a->j;
3194e34fafa9SBarry Smith 
3195985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3196475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3197e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3198e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3199e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3200e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3201e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3202985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3203985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3204985db425SBarry Smith       aa++; aj++;
3205985db425SBarry Smith     }
3206985db425SBarry Smith   }
3207475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3208985db425SBarry Smith   PetscFunctionReturn(0);
3209985db425SBarry Smith }
3210985db425SBarry Smith 
3211985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3212985db425SBarry Smith {
3213985db425SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3214985db425SBarry Smith   PetscErrorCode ierr;
3215d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3216985db425SBarry Smith   PetscScalar    *x;
3217985db425SBarry Smith   MatScalar      *aa;
3218985db425SBarry Smith 
3219985db425SBarry Smith   PetscFunctionBegin;
3220e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3221985db425SBarry Smith   aa = a->a;
3222985db425SBarry Smith   ai = a->i;
3223985db425SBarry Smith   aj = a->j;
3224985db425SBarry Smith 
3225985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3226fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3227985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3228e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3229985db425SBarry Smith   for (i=0; i<m; i++) {
3230985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3231d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3232985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3233985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3234985db425SBarry Smith       x[i] = 0.0;
3235985db425SBarry Smith       if (idx) {
3236985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3237985db425SBarry Smith           if (aj[j] > j) {
3238985db425SBarry Smith             idx[i] = j;
3239985db425SBarry Smith             break;
3240985db425SBarry Smith           }
3241985db425SBarry Smith         }
32421a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32431a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3244985db425SBarry Smith       }
3245985db425SBarry Smith     }
3246985db425SBarry Smith     for (j=0; j<ncols; j++) {
3247985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3248985db425SBarry Smith       aa++; aj++;
3249985db425SBarry Smith     }
3250985db425SBarry Smith   }
3251fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3252985db425SBarry Smith   PetscFunctionReturn(0);
3253985db425SBarry Smith }
3254985db425SBarry Smith 
3255c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3256c87e5d42SMatthew Knepley {
3257c87e5d42SMatthew Knepley   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3258c87e5d42SMatthew Knepley   PetscErrorCode ierr;
3259c87e5d42SMatthew Knepley   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
32604e879edeSHong Zhang   PetscScalar    *x,*aa;
3261c87e5d42SMatthew Knepley 
3262c87e5d42SMatthew Knepley   PetscFunctionBegin;
3263c87e5d42SMatthew Knepley   aa = a->a;
3264c87e5d42SMatthew Knepley   ai = a->i;
3265c87e5d42SMatthew Knepley   aj = a->j;
3266c87e5d42SMatthew Knepley 
3267c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3268f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3269c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3270f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3271c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3272c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3273f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3274f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3275f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3276f07e67edSHong Zhang       x[i] = 0.0;
3277f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3278289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3279f07e67edSHong Zhang           if (aj[j] > j) {
3280f07e67edSHong Zhang             idx[i] = j;
32812205254eSKarl Rupp             break;
32822205254eSKarl Rupp           }
3283289a08f5SMatthew Knepley         }
3284f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3285f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3286f07e67edSHong Zhang       }
3287289a08f5SMatthew Knepley     }
3288c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3289f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3290c87e5d42SMatthew Knepley       aa++; aj++;
3291c87e5d42SMatthew Knepley     }
3292c87e5d42SMatthew Knepley   }
3293f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3294c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3295c87e5d42SMatthew Knepley }
3296c87e5d42SMatthew Knepley 
3297985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3298985db425SBarry Smith {
3299985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3300985db425SBarry Smith   PetscErrorCode  ierr;
3301d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3302d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3303985db425SBarry Smith   PetscScalar     *x;
3304d9ca1df4SBarry Smith   const MatScalar *aa;
3305985db425SBarry Smith 
3306985db425SBarry Smith   PetscFunctionBegin;
3307e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3308985db425SBarry Smith   aa = a->a;
3309985db425SBarry Smith   ai = a->i;
3310985db425SBarry Smith   aj = a->j;
3311985db425SBarry Smith 
3312985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3313fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3314985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3315f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3316985db425SBarry Smith   for (i=0; i<m; i++) {
3317985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3318d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3319985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3320985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3321985db425SBarry Smith       x[i] = 0.0;
3322985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3323985db425SBarry Smith         for (j=0; j<ncols; j++) {
3324985db425SBarry Smith           if (aj[j] > j) {
3325985db425SBarry Smith             idx[i] = j;
3326985db425SBarry Smith             break;
3327985db425SBarry Smith           }
3328985db425SBarry Smith         }
3329fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3330fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3331985db425SBarry Smith       }
3332985db425SBarry Smith     }
3333985db425SBarry Smith     for (j=0; j<ncols; j++) {
3334985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3335985db425SBarry Smith       aa++; aj++;
3336e34fafa9SBarry Smith     }
3337e34fafa9SBarry Smith   }
3338fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3339e34fafa9SBarry Smith   PetscFunctionReturn(0);
3340e34fafa9SBarry Smith }
3341bbead8a2SBarry Smith 
3342713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3343bbead8a2SBarry Smith {
3344bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3345bbead8a2SBarry Smith   PetscErrorCode  ierr;
334633d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3347bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33480da83c2eSBarry Smith   const PetscReal shift = 0.0;
33491a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3350bbead8a2SBarry Smith 
3351bbead8a2SBarry Smith   PetscFunctionBegin;
3352a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33534a0d0026SBarry Smith   if (a->ibdiagvalid) {
33544a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33554a0d0026SBarry Smith     PetscFunctionReturn(0);
33564a0d0026SBarry Smith   }
3357bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3358bbead8a2SBarry Smith   if (!a->ibdiag) {
3359785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
33603bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3361bbead8a2SBarry Smith   }
3362bbead8a2SBarry Smith   diag = a->ibdiag;
3363bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3364bbead8a2SBarry Smith   /* factor and invert each block */
3365bbead8a2SBarry Smith   switch (bs) {
3366bbead8a2SBarry Smith   case 1:
3367bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3368bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3369ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3370ec1892c8SHong Zhang         if (allowzeropivot) {
33717b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33727b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
33737b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
33747b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
33757b6c816cSBarry 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);
3376ec1892c8SHong Zhang       }
3377bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3378bbead8a2SBarry Smith     }
3379bbead8a2SBarry Smith     break;
3380bbead8a2SBarry Smith   case 2:
3381bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3382bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3383bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3384a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33857b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
338696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3387bbead8a2SBarry Smith       diag += 4;
3388bbead8a2SBarry Smith     }
3389bbead8a2SBarry Smith     break;
3390bbead8a2SBarry Smith   case 3:
3391bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3392bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3393bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3394a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33957b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
339696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3397bbead8a2SBarry Smith       diag += 9;
3398bbead8a2SBarry Smith     }
3399bbead8a2SBarry Smith     break;
3400bbead8a2SBarry Smith   case 4:
3401bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3402bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3403bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3404a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34057b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
340696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3407bbead8a2SBarry Smith       diag += 16;
3408bbead8a2SBarry Smith     }
3409bbead8a2SBarry Smith     break;
3410bbead8a2SBarry Smith   case 5:
3411bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3412bbead8a2SBarry 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;
3413bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3414a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34157b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
341696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3417bbead8a2SBarry Smith       diag += 25;
3418bbead8a2SBarry Smith     }
3419bbead8a2SBarry Smith     break;
3420bbead8a2SBarry Smith   case 6:
3421bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3422bbead8a2SBarry 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;
3423bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3424a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34257b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
342696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3427bbead8a2SBarry Smith       diag += 36;
3428bbead8a2SBarry Smith     }
3429bbead8a2SBarry Smith     break;
3430bbead8a2SBarry Smith   case 7:
3431bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3432bbead8a2SBarry 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;
3433bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3434a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34357b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
343696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3437bbead8a2SBarry Smith       diag += 49;
3438bbead8a2SBarry Smith     }
3439bbead8a2SBarry Smith     break;
3440bbead8a2SBarry Smith   default:
3441dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3442bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3443bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3444bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3445bbead8a2SBarry Smith       }
3446bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
34475f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34487b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
344996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3450bbead8a2SBarry Smith       diag += bs2;
3451bbead8a2SBarry Smith     }
3452bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3453bbead8a2SBarry Smith   }
3454bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3455bbead8a2SBarry Smith   PetscFunctionReturn(0);
3456bbead8a2SBarry Smith }
3457bbead8a2SBarry Smith 
345873a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
345973a71a0fSBarry Smith {
346073a71a0fSBarry Smith   PetscErrorCode ierr;
346173a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
346273a71a0fSBarry Smith   PetscScalar    a;
346373a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
346473a71a0fSBarry Smith 
346573a71a0fSBarry Smith   PetscFunctionBegin;
346673a71a0fSBarry Smith   if (!x->assembled) {
346773a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
346873a71a0fSBarry Smith     for (i=0; i<m; i++) {
346973a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
347073a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
347173a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
347273a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
347373a71a0fSBarry Smith       }
347473a71a0fSBarry Smith     }
3475e2ce353bSJunchao Zhang   } else {
3476e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3477e2ce353bSJunchao Zhang   }
347873a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
347973a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
348073a71a0fSBarry Smith   PetscFunctionReturn(0);
348173a71a0fSBarry Smith }
348273a71a0fSBarry Smith 
3483679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3484679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3485679944adSJunchao Zhang {
3486679944adSJunchao Zhang   PetscErrorCode ierr;
3487679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3488679944adSJunchao Zhang   PetscScalar    a;
3489679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3490679944adSJunchao Zhang 
3491679944adSJunchao Zhang   PetscFunctionBegin;
3492679944adSJunchao Zhang   nskip = high - low;
3493679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3494679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3495679944adSJunchao Zhang   for (i=0; i<m; i++) {
3496679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3497679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3498679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3499679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3500679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3501679944adSJunchao Zhang     }
3502e2ce353bSJunchao Zhang   }
3503679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3504679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3505679944adSJunchao Zhang   PetscFunctionReturn(0);
3506679944adSJunchao Zhang }
3507679944adSJunchao Zhang 
3508679944adSJunchao Zhang 
3509682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35100a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3511cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3512cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3513cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
351497304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35157c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35167c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3517f4259b30SLisandro Dalcin                                         NULL,
3518f4259b30SLisandro Dalcin                                         NULL,
3519f4259b30SLisandro Dalcin                                         NULL,
3520f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3521cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3522f4259b30SLisandro Dalcin                                         NULL,
352341f059aeSBarry Smith                                         MatSOR_SeqAIJ,
352491e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
352597304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3526cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3527cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3528cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3529cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3530f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3531cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3532cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3533cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3534d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3535f4259b30SLisandro Dalcin                                         NULL,
3536f4259b30SLisandro Dalcin                                         NULL,
3537f4259b30SLisandro Dalcin                                         NULL,
3538f4259b30SLisandro Dalcin                                         NULL,
35394994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3540f4259b30SLisandro Dalcin                                         NULL,
3541f4259b30SLisandro Dalcin                                         NULL,
3542f4259b30SLisandro Dalcin                                         NULL,
3543f4259b30SLisandro Dalcin                                         NULL,
3544d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3545f4259b30SLisandro Dalcin                                         NULL,
3546f4259b30SLisandro Dalcin                                         NULL,
3547cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3548f4259b30SLisandro Dalcin                                         NULL,
3549d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35507dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3551cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3552cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3553cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3554d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3555cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35567d68702bSBarry Smith                                         MatShift_SeqAIJ,
355779299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
35586e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
355973a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
35603b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
35613b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
35623b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3563a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
356493dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3565f4259b30SLisandro Dalcin                                         NULL,
3566f4259b30SLisandro Dalcin                                         NULL,
3567cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3568f4259b30SLisandro Dalcin                                         NULL,
3569f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3570b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3571b9b97703SBarry Smith                                         MatView_SeqAIJ,
3572f4259b30SLisandro Dalcin                                         NULL,
3573f4259b30SLisandro Dalcin                                         NULL,
3574f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3575321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3576f4259b30SLisandro Dalcin                                         NULL,
3577f4259b30SLisandro Dalcin                                         NULL,
3578f4259b30SLisandro Dalcin                                         NULL,
3579d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3580c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3581f4259b30SLisandro Dalcin                                         NULL,
3582f4259b30SLisandro Dalcin                                         NULL,
3583f4259b30SLisandro Dalcin                                         NULL,
3584f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
35853acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3586f4259b30SLisandro Dalcin                                         NULL,
3587f4259b30SLisandro Dalcin                                         NULL,
3588f4259b30SLisandro Dalcin                                         NULL,
35896ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3590f4259b30SLisandro Dalcin                                         NULL,
3591f4259b30SLisandro Dalcin                                         NULL,
3592f4259b30SLisandro Dalcin                                         NULL,
3593bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3594d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
35951cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3596f4259b30SLisandro Dalcin                                         NULL,
3597f4259b30SLisandro Dalcin                                         NULL,
3598f4259b30SLisandro Dalcin                                         NULL,
3599f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3600f4259b30SLisandro Dalcin                                         NULL,
360126be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3602f4259b30SLisandro Dalcin                                         NULL,
3603f4259b30SLisandro Dalcin                                         NULL,
36048fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3605f4259b30SLisandro Dalcin                                         NULL,
3606f4259b30SLisandro Dalcin                                         NULL,
36076fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3608f4259b30SLisandro Dalcin                                         NULL,
36094222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3610f4259b30SLisandro Dalcin                                         NULL,
3611f4259b30SLisandro Dalcin                                         NULL,
361287d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3613f4259b30SLisandro Dalcin                                         NULL,
3614d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
361599cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3616f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3617f4259b30SLisandro Dalcin                                         NULL,
3618f4259b30SLisandro Dalcin                                         NULL,
3619cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3620f4259b30SLisandro Dalcin                                         NULL,
36212af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3622f4259b30SLisandro Dalcin                                         NULL,
3623599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3624f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3625f4259b30SLisandro Dalcin                                         NULL,
3626f4259b30SLisandro Dalcin                                         NULL,
3627f4259b30SLisandro Dalcin                                         NULL,
3628f4259b30SLisandro Dalcin                                         NULL,
3629f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3630f4259b30SLisandro Dalcin                                         NULL,
3631f4259b30SLisandro Dalcin                                         NULL,
3632f4259b30SLisandro Dalcin                                         NULL,
3633b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36340716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3635bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
363637868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36370da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3638f4259b30SLisandro Dalcin                                         NULL,
3639f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3640f4259b30SLisandro Dalcin                                         NULL,
3641f4259b30SLisandro Dalcin                                         NULL,
364275648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3643b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3644b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36452b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3646f4259b30SLisandro Dalcin                                         NULL,
3647f4259b30SLisandro Dalcin                                         NULL,
36483964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3649f4259b30SLisandro Dalcin                                  /*139*/NULL,
3650f4259b30SLisandro Dalcin                                         NULL,
3651f4259b30SLisandro Dalcin                                         NULL,
36523a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36539c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36544222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36554222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3656f4259b30SLisandro Dalcin                                         NULL,
3657f4259b30SLisandro Dalcin                                         NULL
36589e29f15eSvictorle };
365917ab2063SBarry Smith 
36607087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3661bef8e0ddSBarry Smith {
3662bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
366397f1f81fSBarry Smith   PetscInt   i,nz,n;
3664bef8e0ddSBarry Smith 
3665bef8e0ddSBarry Smith   PetscFunctionBegin;
3666bef8e0ddSBarry Smith   nz = aij->maxnz;
3667d0f46423SBarry Smith   n  = mat->rmap->n;
3668bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3669bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3670bef8e0ddSBarry Smith   }
3671bef8e0ddSBarry Smith   aij->nz = nz;
3672bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3673bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3674bef8e0ddSBarry Smith   }
3675bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3676bef8e0ddSBarry Smith }
3677bef8e0ddSBarry Smith 
3678a3bb6f32SFande Kong /*
3679e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3680a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3681a3bb6f32SFande Kong  * */
3682a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3683a3bb6f32SFande Kong {
3684a3bb6f32SFande Kong   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
3685a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3686a3bb6f32SFande Kong   PetscTablePosition tpos;
3687a3bb6f32SFande Kong   PetscInt           gid,lid,i,j,ncols,ec;
3688a3bb6f32SFande Kong   PetscInt           *garray;
3689a3bb6f32SFande Kong   PetscErrorCode  ierr;
3690a3bb6f32SFande Kong 
3691a3bb6f32SFande Kong   PetscFunctionBegin;
3692a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3693a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3694a3bb6f32SFande Kong   /* use a table */
3695a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3696a3bb6f32SFande Kong   ec = 0;
3697a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3698a3bb6f32SFande Kong     ncols = aij->i[i+1] - aij->i[i];
3699a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3700a3bb6f32SFande Kong       PetscInt data,gid1 = aij->j[aij->i[i] + j] + 1;
3701a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3702a3bb6f32SFande Kong       if (!data) {
3703a3bb6f32SFande Kong         /* one based table */
3704a3bb6f32SFande Kong         ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3705a3bb6f32SFande Kong       }
3706a3bb6f32SFande Kong     }
3707a3bb6f32SFande Kong   }
3708a3bb6f32SFande Kong   /* form array of columns we need */
3709a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3710a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3711a3bb6f32SFande Kong   while (tpos) {
3712a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3713a3bb6f32SFande Kong     gid--;
3714a3bb6f32SFande Kong     lid--;
3715a3bb6f32SFande Kong     garray[lid] = gid;
3716a3bb6f32SFande Kong   }
3717a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3718a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3719a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3720a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3721a3bb6f32SFande Kong   }
3722a3bb6f32SFande Kong   /* compact out the extra columns in B */
3723a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3724a3bb6f32SFande Kong         ncols = aij->i[i+1] - aij->i[i];
3725a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3726a3bb6f32SFande Kong       PetscInt gid1 = aij->j[aij->i[i] + j] + 1;
3727a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3728a3bb6f32SFande Kong       lid--;
3729a3bb6f32SFande Kong       aij->j[aij->i[i] + j] = lid;
3730a3bb6f32SFande Kong     }
3731a3bb6f32SFande Kong   }
3732ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3733ca5434daSLawrence Mitchell   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3734a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
3735a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3736a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3737a3bb6f32SFande Kong   PetscFunctionReturn(0);
3738a3bb6f32SFande Kong }
3739a3bb6f32SFande Kong 
3740bef8e0ddSBarry Smith /*@
3741bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3742bef8e0ddSBarry Smith        in the matrix.
3743bef8e0ddSBarry Smith 
3744bef8e0ddSBarry Smith   Input Parameters:
3745bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3746bef8e0ddSBarry Smith -  indices - the column indices
3747bef8e0ddSBarry Smith 
374815091d37SBarry Smith   Level: advanced
374915091d37SBarry Smith 
3750bef8e0ddSBarry Smith   Notes:
3751bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3752bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3753bef8e0ddSBarry Smith   of the MatSetValues() operation.
3754bef8e0ddSBarry Smith 
3755bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3756d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3757bef8e0ddSBarry Smith 
3758bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3759bef8e0ddSBarry Smith 
3760b9617806SBarry Smith     The indices should start with zero, not one.
3761b9617806SBarry Smith 
3762bef8e0ddSBarry Smith @*/
37637087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3764bef8e0ddSBarry Smith {
37654ac538c5SBarry Smith   PetscErrorCode ierr;
3766bef8e0ddSBarry Smith 
3767bef8e0ddSBarry Smith   PetscFunctionBegin;
37680700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
37694482741eSBarry Smith   PetscValidPointer(indices,2);
37704ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3771bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3772bef8e0ddSBarry Smith }
3773bef8e0ddSBarry Smith 
3774be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3775be6bf707SBarry Smith 
37767087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3777be6bf707SBarry Smith {
3778be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
37796849ba73SBarry Smith   PetscErrorCode ierr;
3780d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3781be6bf707SBarry Smith 
3782be6bf707SBarry Smith   PetscFunctionBegin;
3783169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3784be6bf707SBarry Smith 
3785be6bf707SBarry Smith   /* allocate space for values if not already there */
3786be6bf707SBarry Smith   if (!aij->saved_values) {
3787854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
37883bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3789be6bf707SBarry Smith   }
3790be6bf707SBarry Smith 
3791be6bf707SBarry Smith   /* copy values over */
3792580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3793be6bf707SBarry Smith   PetscFunctionReturn(0);
3794be6bf707SBarry Smith }
3795be6bf707SBarry Smith 
3796be6bf707SBarry Smith /*@
3797be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3798be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3799be6bf707SBarry Smith        nonlinear portion.
3800be6bf707SBarry Smith 
3801be6bf707SBarry Smith    Collect on Mat
3802be6bf707SBarry Smith 
3803be6bf707SBarry Smith   Input Parameters:
38040e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3805be6bf707SBarry Smith 
380615091d37SBarry Smith   Level: advanced
380715091d37SBarry Smith 
3808be6bf707SBarry Smith   Common Usage, with SNESSolve():
3809be6bf707SBarry Smith $    Create Jacobian matrix
3810be6bf707SBarry Smith $    Set linear terms into matrix
3811be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3812be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3813be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3814512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3815be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3816be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3817be6bf707SBarry Smith $    In your Jacobian routine
3818be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3819be6bf707SBarry Smith $      Set nonlinear terms in matrix
3820be6bf707SBarry Smith 
3821be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3822be6bf707SBarry Smith $    // build linear portion of Jacobian
3823512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3824be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3825be6bf707SBarry Smith $    loop over nonlinear iterations
3826be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3827be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3828be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3829be6bf707SBarry Smith $       Solve linear system with Jacobian
3830be6bf707SBarry Smith $    endloop
3831be6bf707SBarry Smith 
3832be6bf707SBarry Smith   Notes:
3833be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3834512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3835be6bf707SBarry Smith     calling this routine.
3836be6bf707SBarry Smith 
38370c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38380c468ba9SBarry Smith     and does not allocated additional space.
38390c468ba9SBarry Smith 
3840be6bf707SBarry Smith .seealso: MatRetrieveValues()
3841be6bf707SBarry Smith 
3842be6bf707SBarry Smith @*/
38437087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3844be6bf707SBarry Smith {
38454ac538c5SBarry Smith   PetscErrorCode ierr;
3846be6bf707SBarry Smith 
3847be6bf707SBarry Smith   PetscFunctionBegin;
38480700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3849e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3850e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38514ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3852be6bf707SBarry Smith   PetscFunctionReturn(0);
3853be6bf707SBarry Smith }
3854be6bf707SBarry Smith 
38557087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3856be6bf707SBarry Smith {
3857be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38586849ba73SBarry Smith   PetscErrorCode ierr;
3859d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3860be6bf707SBarry Smith 
3861be6bf707SBarry Smith   PetscFunctionBegin;
3862169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3863f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3864be6bf707SBarry Smith   /* copy values over */
3865580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3866be6bf707SBarry Smith   PetscFunctionReturn(0);
3867be6bf707SBarry Smith }
3868be6bf707SBarry Smith 
3869be6bf707SBarry Smith /*@
3870be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3871be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3872be6bf707SBarry Smith        nonlinear portion.
3873be6bf707SBarry Smith 
3874be6bf707SBarry Smith    Collect on Mat
3875be6bf707SBarry Smith 
3876be6bf707SBarry Smith   Input Parameters:
3877386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3878be6bf707SBarry Smith 
387915091d37SBarry Smith   Level: advanced
388015091d37SBarry Smith 
3881be6bf707SBarry Smith .seealso: MatStoreValues()
3882be6bf707SBarry Smith 
3883be6bf707SBarry Smith @*/
38847087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3885be6bf707SBarry Smith {
38864ac538c5SBarry Smith   PetscErrorCode ierr;
3887be6bf707SBarry Smith 
3888be6bf707SBarry Smith   PetscFunctionBegin;
38890700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3890e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3891e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38924ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3893be6bf707SBarry Smith   PetscFunctionReturn(0);
3894be6bf707SBarry Smith }
3895be6bf707SBarry Smith 
3896f83d6046SBarry Smith 
3897be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
389817ab2063SBarry Smith /*@C
3899682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39000d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39016e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
390251c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39032bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
390417ab2063SBarry Smith 
3905d083f849SBarry Smith    Collective
3906db81eaa0SLois Curfman McInnes 
390717ab2063SBarry Smith    Input Parameters:
3908db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
390917ab2063SBarry Smith .  m - number of rows
391017ab2063SBarry Smith .  n - number of columns
391117ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
391251c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39130298fd71SBarry Smith          (possibly different for each row) or NULL
391417ab2063SBarry Smith 
391517ab2063SBarry Smith    Output Parameter:
3916416022c9SBarry Smith .  A - the matrix
391717ab2063SBarry Smith 
3918175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3919f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3920175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3921175b88e8SBarry Smith 
3922b259b22eSLois Curfman McInnes    Notes:
392349a6f317SBarry Smith    If nnz is given then nz is ignored
392449a6f317SBarry Smith 
392517ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
392617ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39270002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
392844cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
392917ab2063SBarry Smith 
393017ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39310298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39323d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39336da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
393417ab2063SBarry Smith 
3935682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39364fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3937682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39386c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39396c7ebb05SLois Curfman McInnes 
39406c7ebb05SLois Curfman McInnes    Options Database Keys:
3941698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39429db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
394317ab2063SBarry Smith 
3944027ccd11SLois Curfman McInnes    Level: intermediate
3945027ccd11SLois Curfman McInnes 
394669b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
394736db0b34SBarry Smith 
394817ab2063SBarry Smith @*/
39497087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
395017ab2063SBarry Smith {
3951dfbe8321SBarry Smith   PetscErrorCode ierr;
39526945ee14SBarry Smith 
39533a40ed3dSBarry Smith   PetscFunctionBegin;
3954f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3955117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3956c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3957d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3958273d9f13SBarry Smith   PetscFunctionReturn(0);
3959273d9f13SBarry Smith }
3960273d9f13SBarry Smith 
3961273d9f13SBarry Smith /*@C
3962273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3963273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3964273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3965273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3966273d9f13SBarry Smith 
3967d083f849SBarry Smith    Collective
3968273d9f13SBarry Smith 
3969273d9f13SBarry Smith    Input Parameters:
39701c4f3114SJed Brown +  B - The matrix
3971273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3972273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39730298fd71SBarry Smith          (possibly different for each row) or NULL
3974273d9f13SBarry Smith 
3975273d9f13SBarry Smith    Notes:
397649a6f317SBarry Smith      If nnz is given then nz is ignored
397749a6f317SBarry Smith 
3978273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3979273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3980273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3981273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3982273d9f13SBarry Smith 
3983273d9f13SBarry 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
3985273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3986273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3987273d9f13SBarry Smith 
3988aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3989aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3990aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3991aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3992aa95bbe8SBarry Smith 
3993a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3994a96a251dSBarry Smith    entries or columns indices
3995a96a251dSBarry Smith 
3996273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3997273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3998273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3999273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4000273d9f13SBarry Smith 
4001273d9f13SBarry Smith    Options Database Keys:
4002698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
400347b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4004273d9f13SBarry Smith 
4005273d9f13SBarry Smith    Level: intermediate
4006273d9f13SBarry Smith 
400719b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
400819b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4009273d9f13SBarry Smith 
4010273d9f13SBarry Smith @*/
40117087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4012273d9f13SBarry Smith {
40134ac538c5SBarry Smith   PetscErrorCode ierr;
4014a23d5eceSKris Buschelman 
4015a23d5eceSKris Buschelman   PetscFunctionBegin;
40166ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40176ba663aaSJed Brown   PetscValidType(B,1);
40184ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4019a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4020a23d5eceSKris Buschelman }
4021a23d5eceSKris Buschelman 
40227087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4023a23d5eceSKris Buschelman {
4024273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40252576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40266849ba73SBarry Smith   PetscErrorCode ierr;
402797f1f81fSBarry Smith   PetscInt       i;
4028273d9f13SBarry Smith 
4029273d9f13SBarry Smith   PetscFunctionBegin;
40302576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4031a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4032c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4033c461c341SBarry Smith     nz             = 0;
4034c461c341SBarry Smith   }
403526283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
403626283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4037899cda47SBarry Smith 
4038435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
403960e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4040cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4041d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
404260e0710aSBarry 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]);
404360e0710aSBarry 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);
4044b73539f3SBarry Smith     }
4045b73539f3SBarry Smith   }
4046b73539f3SBarry Smith 
4047273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
40482205254eSKarl Rupp 
4049273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4050273d9f13SBarry Smith 
4051ab93d7beSBarry Smith   if (!skipallocation) {
40522ee49352SLisandro Dalcin     if (!b->imax) {
4053071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4054071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4055071fcb05SBarry Smith     }
4056071fcb05SBarry Smith     if (!b->ilen) {
4057071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4058071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4059071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4060071fcb05SBarry Smith     } else {
4061071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
40622ee49352SLisandro Dalcin     }
4063846b4da1SFande Kong     if (!b->ipre) {
4064846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4065846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4066846b4da1SFande Kong     }
4067273d9f13SBarry Smith     if (!nnz) {
4068435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4069c62bd62aSJed Brown       else if (nz < 0) nz = 1;
40705d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4071d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4072d0f46423SBarry Smith       nz = nz*B->rmap->n;
4073273d9f13SBarry Smith     } else {
4074c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4075c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4076c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4077273d9f13SBarry Smith     }
4078ab93d7beSBarry Smith 
4079273d9f13SBarry Smith     /* allocate the matrix space */
408053dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
40812ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4082396832f4SHong Zhang     if (B->structure_only) {
40835848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
40845848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4085396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4086396832f4SHong Zhang     } else {
4087dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
40883bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4089396832f4SHong Zhang     }
4090bfeeae90SHong Zhang     b->i[0] = 0;
4091d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
40925da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
40935da197adSKris Buschelman     }
4094396832f4SHong Zhang     if (B->structure_only) {
4095396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4096396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4097396832f4SHong Zhang     } else {
4098273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4099e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4100396832f4SHong Zhang     }
4101e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4102c461c341SBarry Smith   } else {
4103e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4104e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4105c461c341SBarry Smith   }
4106273d9f13SBarry Smith 
4107846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4108846b4da1SFande Kong     /* reserve user-requested sparsity */
4109580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4110846b4da1SFande Kong   }
4111846b4da1SFande Kong 
4112846b4da1SFande Kong 
4113273d9f13SBarry Smith   b->nz               = 0;
4114273d9f13SBarry Smith   b->maxnz            = nz;
4115273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41162205254eSKarl Rupp   if (realalloc) {
41172205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41182205254eSKarl Rupp   }
4119cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4120cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4121273d9f13SBarry Smith   PetscFunctionReturn(0);
4122273d9f13SBarry Smith }
4123273d9f13SBarry Smith 
4124846b4da1SFande Kong 
4125846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4126846b4da1SFande Kong {
4127846b4da1SFande Kong   Mat_SeqAIJ     *a;
4128a5bbaf83SFande Kong   PetscInt       i;
4129846b4da1SFande Kong   PetscErrorCode ierr;
4130846b4da1SFande Kong 
4131846b4da1SFande Kong   PetscFunctionBegin;
4132846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
413314d0e64fSAlex Lindsay 
413414d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
413514d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
413614d0e64fSAlex Lindsay 
4137846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41382c814fdeSFande Kong   /* if no saved info, we error out */
4139fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
41402c814fdeSFande Kong 
4141fb4dc15dSAlex 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");
41422c814fdeSFande Kong 
4143580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4144580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4145846b4da1SFande Kong   a->i[0] = 0;
4146846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4147846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4148846b4da1SFande Kong   }
4149846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4150846b4da1SFande Kong   a->nz               = 0;
4151846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4152846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4153846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4154846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4155846b4da1SFande Kong   PetscFunctionReturn(0);
4156846b4da1SFande Kong }
4157846b4da1SFande Kong 
415858d36128SBarry Smith /*@
4159a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4160a1661176SMatthew Knepley 
4161a1661176SMatthew Knepley    Input Parameters:
4162a1661176SMatthew Knepley +  B - the matrix
4163a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4164a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4165a1661176SMatthew Knepley -  v - optional values in the matrix
4166a1661176SMatthew Knepley 
4167a1661176SMatthew Knepley    Level: developer
4168a1661176SMatthew Knepley 
41696a9b8d82SBarry Smith    Notes:
417058d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
417158d36128SBarry Smith 
41726a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
41736a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
41746a9b8d82SBarry Smith 
41756a9b8d82SBarry Smith     Developer Notes:
41766a9b8d82SBarry 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
41776a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
41786a9b8d82SBarry Smith 
41796a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
41806a9b8d82SBarry Smith 
41816a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4182a1661176SMatthew Knepley @*/
4183a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4184a1661176SMatthew Knepley {
4185a1661176SMatthew Knepley   PetscErrorCode ierr;
4186a1661176SMatthew Knepley 
4187a1661176SMatthew Knepley   PetscFunctionBegin;
41880700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
41896ba663aaSJed Brown   PetscValidType(B,1);
41904ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4191a1661176SMatthew Knepley   PetscFunctionReturn(0);
4192a1661176SMatthew Knepley }
4193a1661176SMatthew Knepley 
41947087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4195a1661176SMatthew Knepley {
4196a1661176SMatthew Knepley   PetscInt       i;
4197a1661176SMatthew Knepley   PetscInt       m,n;
4198a1661176SMatthew Knepley   PetscInt       nz;
41996a9b8d82SBarry Smith   PetscInt       *nnz;
4200a1661176SMatthew Knepley   PetscErrorCode ierr;
4201a1661176SMatthew Knepley 
4202a1661176SMatthew Knepley   PetscFunctionBegin;
420365e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4204779a8d59SSatish Balay 
4205779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4206779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4207779a8d59SSatish Balay 
4208779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4209854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4210a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4211b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
421265e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4213a1661176SMatthew Knepley     nnz[i] = nz;
4214a1661176SMatthew Knepley   }
4215a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4216a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4217a1661176SMatthew Knepley 
4218a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4219071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4220a1661176SMatthew Knepley   }
4221a1661176SMatthew Knepley 
4222a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4223a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4224a1661176SMatthew Knepley 
42257827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4226a1661176SMatthew Knepley   PetscFunctionReturn(0);
4227a1661176SMatthew Knepley }
4228a1661176SMatthew Knepley 
4229c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4230af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4231170fe5c8SBarry Smith 
4232170fe5c8SBarry Smith /*
4233170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4234170fe5c8SBarry Smith 
4235170fe5c8SBarry Smith                n                       p                          p
42362da392ccSBarry Smith         [             ]       [             ]         [                 ]
42372da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
42382da392ccSBarry Smith         [             ]       [             ]         [                 ]
4239170fe5c8SBarry Smith 
4240170fe5c8SBarry Smith */
4241170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4242170fe5c8SBarry Smith {
4243170fe5c8SBarry Smith   PetscErrorCode    ierr;
4244170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4245170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4246170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
424786214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4248170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4249170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4250170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
425186214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
425286214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4253170fe5c8SBarry Smith 
4254170fe5c8SBarry Smith   PetscFunctionBegin;
4255d0f46423SBarry Smith   m    = A->rmap->n;
4256d0f46423SBarry Smith   n    = A->cmap->n;
4257d0f46423SBarry Smith   p    = B->cmap->n;
4258170fe5c8SBarry Smith   a    = sub_a->v;
4259170fe5c8SBarry Smith   b    = sub_b->a;
4260170fe5c8SBarry Smith   c    = sub_c->v;
426186214ceeSStefano Zampini   if (clda == m) {
4262580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
426386214ceeSStefano Zampini   } else {
426486214ceeSStefano Zampini     for (j=0;j<p;j++)
426586214ceeSStefano Zampini       for (i=0;i<m;i++)
426686214ceeSStefano Zampini         c[j*clda + i] = 0.0;
426786214ceeSStefano Zampini   }
4268170fe5c8SBarry Smith   ii  = sub_b->i;
4269170fe5c8SBarry Smith   idx = sub_b->j;
4270170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4271170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4272170fe5c8SBarry Smith     while (q-->0) {
427386214ceeSStefano Zampini       c_q = c + clda*(*idx);
427486214ceeSStefano Zampini       a_q = a + alda*i;
4275854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4276170fe5c8SBarry Smith       idx++;
4277170fe5c8SBarry Smith       b++;
4278170fe5c8SBarry Smith     }
4279170fe5c8SBarry Smith   }
4280170fe5c8SBarry Smith   PetscFunctionReturn(0);
4281170fe5c8SBarry Smith }
4282170fe5c8SBarry Smith 
42834222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4284170fe5c8SBarry Smith {
4285170fe5c8SBarry Smith   PetscErrorCode ierr;
4286d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
428786214ceeSStefano Zampini   PetscBool      cisdense;
4288170fe5c8SBarry Smith 
4289170fe5c8SBarry Smith   PetscFunctionBegin;
429060e0710aSBarry 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);
42914222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
42924222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
429386214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
429486214ceeSStefano Zampini   if (!cisdense) {
429586214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
429686214ceeSStefano Zampini   }
429786214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4298d73949e8SHong Zhang 
42994222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4300170fe5c8SBarry Smith   PetscFunctionReturn(0);
4301170fe5c8SBarry Smith }
4302170fe5c8SBarry Smith 
4303170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
43040bad9183SKris Buschelman /*MC
4305fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
43060bad9183SKris Buschelman    based on compressed sparse row format.
43070bad9183SKris Buschelman 
43080bad9183SKris Buschelman    Options Database Keys:
43090bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
43100bad9183SKris Buschelman 
43110bad9183SKris Buschelman    Level: beginner
43120bad9183SKris Buschelman 
43130cd7f59aSBarry Smith    Notes:
43140cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
43150cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
43160cd7f59aSBarry Smith     in the matrix
43170cd7f59aSBarry Smith 
43180cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
43190cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
43200cd7f59aSBarry Smith 
43210cd7f59aSBarry Smith   Developer Notes:
43220cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
43230cd7f59aSBarry Smith 
4324f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
43250bad9183SKris Buschelman M*/
43260bad9183SKris Buschelman 
4327ccd284c7SBarry Smith /*MC
4328ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4329ccd284c7SBarry Smith 
4330ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4331ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
43320cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4333ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4334ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4335ccd284c7SBarry Smith 
4336ccd284c7SBarry Smith    Options Database Keys:
4337ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4338ccd284c7SBarry Smith 
433995452b02SPatrick Sanan   Developer Notes:
4340ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4341ccd284c7SBarry Smith    enough exist.
4342ccd284c7SBarry Smith 
4343ccd284c7SBarry Smith   Level: beginner
4344ccd284c7SBarry Smith 
4345ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4346ccd284c7SBarry Smith M*/
4347ccd284c7SBarry Smith 
4348ccd284c7SBarry Smith /*MC
4349ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4350ccd284c7SBarry Smith 
4351ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4352ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4353ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4354ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4355ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4356ccd284c7SBarry Smith 
4357ccd284c7SBarry Smith    Options Database Keys:
4358ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4359ccd284c7SBarry Smith 
4360ccd284c7SBarry Smith   Level: beginner
4361ccd284c7SBarry Smith 
4362ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4363ccd284c7SBarry Smith M*/
4364ccd284c7SBarry Smith 
43657906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
43667906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
43677906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
43687906f579SHong Zhang #endif
4369d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4370d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4371d24d4204SJose E. Roman #endif
43727906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
43737906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
43747906f579SHong Zhang #endif
43757906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
43767906f579SHong Zhang 
4377d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4378c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
43794222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
43807906f579SHong Zhang 
43818c778c55SBarry Smith /*@C
43828f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
43838c778c55SBarry Smith 
43848c778c55SBarry Smith    Not Collective
43858c778c55SBarry Smith 
43868c778c55SBarry Smith    Input Parameter:
4387579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
43888c778c55SBarry Smith 
43898c778c55SBarry Smith    Output Parameter:
43908c778c55SBarry Smith .   array - pointer to the data
43918c778c55SBarry Smith 
43928c778c55SBarry Smith    Level: intermediate
43938c778c55SBarry Smith 
4394774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
43958c778c55SBarry Smith @*/
43968c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
43978c778c55SBarry Smith {
43988c778c55SBarry Smith   PetscErrorCode ierr;
43998c778c55SBarry Smith 
44008c778c55SBarry Smith   PetscFunctionBegin;
44018c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
44028c778c55SBarry Smith   PetscFunctionReturn(0);
44038c778c55SBarry Smith }
44048c778c55SBarry Smith 
440521e72a00SBarry Smith /*@C
44068f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
44078f1ea47aSStefano Zampini 
44088f1ea47aSStefano Zampini    Not Collective
44098f1ea47aSStefano Zampini 
44108f1ea47aSStefano Zampini    Input Parameter:
44118f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44128f1ea47aSStefano Zampini 
44138f1ea47aSStefano Zampini    Output Parameter:
44148f1ea47aSStefano Zampini .   array - pointer to the data
44158f1ea47aSStefano Zampini 
44168f1ea47aSStefano Zampini    Level: intermediate
44178f1ea47aSStefano Zampini 
44188f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
44198f1ea47aSStefano Zampini @*/
44208f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
44218f1ea47aSStefano Zampini {
44228c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4423c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44248f1ea47aSStefano Zampini #endif
44258f1ea47aSStefano Zampini   PetscErrorCode ierr;
44268f1ea47aSStefano Zampini 
44278f1ea47aSStefano Zampini   PetscFunctionBegin;
44288c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4429c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44308f1ea47aSStefano Zampini #endif
44318f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44328c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4433c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
44348f1ea47aSStefano Zampini #endif
44358f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44368f1ea47aSStefano Zampini }
44378f1ea47aSStefano Zampini 
44388f1ea47aSStefano Zampini /*@C
44398f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
44408f1ea47aSStefano Zampini 
44418f1ea47aSStefano Zampini    Not Collective
44428f1ea47aSStefano Zampini 
44438f1ea47aSStefano Zampini    Input Parameter:
44448f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44458f1ea47aSStefano Zampini 
44468f1ea47aSStefano Zampini    Output Parameter:
44478f1ea47aSStefano Zampini .   array - pointer to the data
44488f1ea47aSStefano Zampini 
44498f1ea47aSStefano Zampini    Level: intermediate
44508f1ea47aSStefano Zampini 
44518f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
44528f1ea47aSStefano Zampini @*/
44538f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
44548f1ea47aSStefano Zampini {
44558c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4456c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44578f1ea47aSStefano Zampini #endif
44588f1ea47aSStefano Zampini   PetscErrorCode ierr;
44598f1ea47aSStefano Zampini 
44608f1ea47aSStefano Zampini   PetscFunctionBegin;
44618c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4462c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44638f1ea47aSStefano Zampini #endif
44648f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44658c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4466c70f7ee4SJunchao Zhang   A->offloadmask = oval;
44678f1ea47aSStefano Zampini #endif
44688f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44698f1ea47aSStefano Zampini }
44708f1ea47aSStefano Zampini 
44718f1ea47aSStefano Zampini /*@C
447221e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
447321e72a00SBarry Smith 
447421e72a00SBarry Smith    Not Collective
447521e72a00SBarry Smith 
447621e72a00SBarry Smith    Input Parameter:
4477579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
447821e72a00SBarry Smith 
447921e72a00SBarry Smith    Output Parameter:
448021e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
448121e72a00SBarry Smith 
448221e72a00SBarry Smith    Level: intermediate
448321e72a00SBarry Smith 
448421e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
448521e72a00SBarry Smith @*/
448621e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
448721e72a00SBarry Smith {
448821e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
448921e72a00SBarry Smith 
449021e72a00SBarry Smith   PetscFunctionBegin;
449121e72a00SBarry Smith   *nz = aij->rmax;
449221e72a00SBarry Smith   PetscFunctionReturn(0);
449321e72a00SBarry Smith }
449421e72a00SBarry Smith 
44958c778c55SBarry Smith /*@C
4496579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
44978c778c55SBarry Smith 
44988c778c55SBarry Smith    Not Collective
44998c778c55SBarry Smith 
45008c778c55SBarry Smith    Input Parameters:
4501a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4502a2b725a8SWilliam Gropp -  array - pointer to the data
45038c778c55SBarry Smith 
45048c778c55SBarry Smith    Level: intermediate
45058c778c55SBarry Smith 
4506774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
45078c778c55SBarry Smith @*/
45088c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
45098c778c55SBarry Smith {
45108c778c55SBarry Smith   PetscErrorCode ierr;
45118c778c55SBarry Smith 
45128c778c55SBarry Smith   PetscFunctionBegin;
45138c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
45148c778c55SBarry Smith   PetscFunctionReturn(0);
45158c778c55SBarry Smith }
45168c778c55SBarry Smith 
451734b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
45180ce8acdeSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
451902fe1965SBarry Smith #endif
45203d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
45213d0639e7SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat);
45223d0639e7SStefano Zampini #endif
452302fe1965SBarry Smith 
45248cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4525273d9f13SBarry Smith {
4526273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4527dfbe8321SBarry Smith   PetscErrorCode ierr;
452838baddfdSBarry Smith   PetscMPIInt    size;
4529273d9f13SBarry Smith 
4530273d9f13SBarry Smith   PetscFunctionBegin;
4531ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
4532e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4533273d9f13SBarry Smith 
4534b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
45352205254eSKarl Rupp 
4536b0a32e0cSBarry Smith   B->data = (void*)b;
45372205254eSKarl Rupp 
4538549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4539071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
45402205254eSKarl Rupp 
4541f4259b30SLisandro Dalcin   b->row                = NULL;
4542f4259b30SLisandro Dalcin   b->col                = NULL;
4543f4259b30SLisandro Dalcin   b->icol               = NULL;
4544b810aeb4SBarry Smith   b->reallocs           = 0;
454536db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4546f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4547416022c9SBarry Smith   b->nonew              = 0;
4548f4259b30SLisandro Dalcin   b->diag               = NULL;
4549f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4550f4259b30SLisandro Dalcin   B->spptr              = NULL;
4551f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4552f4259b30SLisandro Dalcin   b->idiag              = NULL;
4553f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4554f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
455571f1c65dSBarry Smith   b->omega              = 1.0;
455671f1c65dSBarry Smith   b->fshift             = 0.0;
455771f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4558bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4559a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
456017ab2063SBarry Smith 
456135d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4562bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4563bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
45648c778c55SBarry Smith 
4565b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4566bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4567bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4568b3866ffcSBarry Smith #endif
456917f1a0eaSHong Zhang 
4570bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4571bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4572bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4573bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4574bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4575bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
45764dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
45779779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
45784a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4579191b95cbSRichard Tran Mills #endif
458034b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
458102fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
45824222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
458302fe1965SBarry Smith #endif
45843d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
45853d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
45863d0639e7SStefano Zampini #endif
4587bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4588af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4589af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4590af8000cdSHong Zhang #endif
4591d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4592d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4593d24d4204SJose E. Roman #endif
459463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
459563c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
45964222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
459763c07aadSStefano Zampini #endif
4598b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4599d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4600c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4601bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4602bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4603bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4604846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4605bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4606bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
46074222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
46084222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
46094222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
46104108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
461117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
46124099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
46133a40ed3dSBarry Smith   PetscFunctionReturn(0);
461417ab2063SBarry Smith }
461517ab2063SBarry Smith 
4616b24902e0SBarry Smith /*
4617b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4618b24902e0SBarry Smith */
4619ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
462017ab2063SBarry Smith {
46212a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
46226849ba73SBarry Smith   PetscErrorCode ierr;
4623071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
462417ab2063SBarry Smith 
46253a40ed3dSBarry Smith   PetscFunctionBegin;
4626ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4627273d9f13SBarry Smith 
4628d5f3da31SBarry Smith   C->factortype = A->factortype;
4629f4259b30SLisandro Dalcin   c->row        = NULL;
4630f4259b30SLisandro Dalcin   c->col        = NULL;
4631f4259b30SLisandro Dalcin   c->icol       = NULL;
46326ad4291fSHong Zhang   c->reallocs   = 0;
463317ab2063SBarry Smith 
46346ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
463517ab2063SBarry Smith 
4636aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4637aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4638eec197d1SBarry Smith 
4639071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4640071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4641071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4642071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
46433bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
464417ab2063SBarry Smith 
464517ab2063SBarry Smith   /* allocate the matrix space */
4646f77e22a1SHong Zhang   if (mallocmatspace) {
4647dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
46483bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
46492205254eSKarl Rupp 
4650f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
46512205254eSKarl Rupp 
4652580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
465317ab2063SBarry Smith     if (m > 0) {
4654580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4655be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
4656580bdb30SBarry Smith         ierr = PetscArraycpy(c->a,a->a,a->i[m]);CHKERRQ(ierr);
4657be6bf707SBarry Smith       } else {
4658580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
465917ab2063SBarry Smith       }
466008480c60SBarry Smith     }
4661f77e22a1SHong Zhang   }
466217ab2063SBarry Smith 
46636ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4664416022c9SBarry Smith   c->roworiented       = a->roworiented;
4665416022c9SBarry Smith   c->nonew             = a->nonew;
4666416022c9SBarry Smith   if (a->diag) {
4667854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4668071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
46693bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4670071fcb05SBarry Smith   } else c->diag = NULL;
46712205254eSKarl Rupp 
4672f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4673f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4674f4259b30SLisandro Dalcin   c->idiag              = NULL;
4675f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4676a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4677e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4678e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
46796ad4291fSHong Zhang 
4680893ad86cSHong Zhang   c->rmax         = a->rmax;
4681416022c9SBarry Smith   c->nz           = a->nz;
46828ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4683273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4684754ec7b1SSatish Balay 
46856ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
46866ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4687cd6b891eSBarry Smith   if (a->compressedrow.use) {
46886ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4689dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4690580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4691580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
469227ea64f8SHong Zhang   } else {
469327ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
46940298fd71SBarry Smith     c->compressedrow.i      = NULL;
46950298fd71SBarry Smith     c->compressedrow.rindex = NULL;
46966ad4291fSHong Zhang   }
4697ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4698e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
46994846f1f5SKris Buschelman 
47002205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4701140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
47023a40ed3dSBarry Smith   PetscFunctionReturn(0);
470317ab2063SBarry Smith }
470417ab2063SBarry Smith 
4705b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4706b24902e0SBarry Smith {
4707b24902e0SBarry Smith   PetscErrorCode ierr;
4708b24902e0SBarry Smith 
4709b24902e0SBarry Smith   PetscFunctionBegin;
4710ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
47114b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4712cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
471333d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4714cfd3f464SBarry Smith   }
4715a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4716f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4717b24902e0SBarry Smith   PetscFunctionReturn(0);
4718b24902e0SBarry Smith }
4719b24902e0SBarry Smith 
4720112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4721fbdbba38SShri Abhyankar {
472252f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
472352f91c60SVaclav Hapla   PetscErrorCode ierr;
472452f91c60SVaclav Hapla 
472552f91c60SVaclav Hapla   PetscFunctionBegin;
472652f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
472752f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4728c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4729c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
473052f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
473152f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
473252f91c60SVaclav Hapla   if (isbinary) {
473352f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
473452f91c60SVaclav Hapla   } else if (ishdf5) {
473552f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
473652f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
473752f91c60SVaclav Hapla #else
473852f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
473952f91c60SVaclav Hapla #endif
474052f91c60SVaclav Hapla   } else {
474152f91c60SVaclav 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);
474252f91c60SVaclav Hapla   }
474352f91c60SVaclav Hapla   PetscFunctionReturn(0);
474452f91c60SVaclav Hapla }
474552f91c60SVaclav Hapla 
47463ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
474752f91c60SVaclav Hapla {
47483ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4749fbdbba38SShri Abhyankar   PetscErrorCode ierr;
47503ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4751fbdbba38SShri Abhyankar 
4752fbdbba38SShri Abhyankar   PetscFunctionBegin;
47533ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4754bbead8a2SBarry Smith 
47553ea6fe3dSLisandro Dalcin   /* read in matrix header */
47563ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
47573ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4758fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
47593ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
47603ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4761bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4762fbdbba38SShri Abhyankar 
47633ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
47643ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
47653ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
47663ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
47673ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
47683ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
47693ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
47703ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
47713ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
47723ea6fe3dSLisandro Dalcin 
47733ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
47743ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
47753ea6fe3dSLisandro 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);
47763ea6fe3dSLisandro Dalcin 
4777fbdbba38SShri Abhyankar   /* read in row lengths */
47783ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
47793ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
47803ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
47813ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
47823ea6fe3dSLisandro 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);
47833ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
47843ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
47853ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
478660e0710aSBarry 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);
47873ea6fe3dSLisandro Dalcin   /* store row lengths */
47883ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
47893ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4790fbdbba38SShri Abhyankar 
47913ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
47923ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
47933ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
47943ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
47953ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
47963ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4797fbdbba38SShri Abhyankar 
47983ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47993ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4800fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4801fbdbba38SShri Abhyankar }
4802fbdbba38SShri Abhyankar 
4803ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
48047264ac53SSatish Balay {
48057264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4806dfbe8321SBarry Smith   PetscErrorCode ierr;
4807eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4808eeffb40dSHong Zhang   PetscInt k;
4809eeffb40dSHong Zhang #endif
48107264ac53SSatish Balay 
48113a40ed3dSBarry Smith   PetscFunctionBegin;
4812bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4813d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4814ca44d042SBarry Smith     *flg = PETSC_FALSE;
4815ca44d042SBarry Smith     PetscFunctionReturn(0);
4816bcd2baecSBarry Smith   }
48177264ac53SSatish Balay 
48187264ac53SSatish Balay   /* if the a->i are the same */
4819580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4820abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
48217264ac53SSatish Balay 
48227264ac53SSatish Balay   /* if a->j are the same */
4823580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4824abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4825bcd2baecSBarry Smith 
4826bcd2baecSBarry Smith   /* if a->a are the same */
4827eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4828eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4829eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4830eeffb40dSHong Zhang       *flg = PETSC_FALSE;
48313a40ed3dSBarry Smith       PetscFunctionReturn(0);
4832eeffb40dSHong Zhang     }
4833eeffb40dSHong Zhang   }
4834eeffb40dSHong Zhang #else
4835580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4836eeffb40dSHong Zhang #endif
4837eeffb40dSHong Zhang   PetscFunctionReturn(0);
48387264ac53SSatish Balay }
483936db0b34SBarry Smith 
484005869f15SSatish Balay /*@
484136db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
484236db0b34SBarry Smith               provided by the user.
484336db0b34SBarry Smith 
4844d083f849SBarry Smith       Collective
484536db0b34SBarry Smith 
484636db0b34SBarry Smith    Input Parameters:
484736db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
484836db0b34SBarry Smith .   m - number of rows
484936db0b34SBarry Smith .   n - number of columns
4850483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
485136db0b34SBarry Smith .   j - column indices
485236db0b34SBarry Smith -   a - matrix values
485336db0b34SBarry Smith 
485436db0b34SBarry Smith    Output Parameter:
485536db0b34SBarry Smith .   mat - the matrix
485636db0b34SBarry Smith 
485736db0b34SBarry Smith    Level: intermediate
485836db0b34SBarry Smith 
485936db0b34SBarry Smith    Notes:
48600551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4861292fb18eSBarry Smith     once the matrix is destroyed and not before
486236db0b34SBarry Smith 
486336db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
486436db0b34SBarry Smith 
4865bfeeae90SHong Zhang        The i and j indices are 0 based
486636db0b34SBarry Smith 
4867a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4868a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
48698eef79e4SBarry Smith     as shown
4870a4552177SSatish Balay 
48718eef79e4SBarry Smith $        1 0 0
48728eef79e4SBarry Smith $        2 0 3
48738eef79e4SBarry Smith $        4 5 6
48748eef79e4SBarry Smith $
48758eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
48768eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
48778eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4878a4552177SSatish Balay 
48799985e31cSBarry Smith 
488069b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
488136db0b34SBarry Smith 
488236db0b34SBarry Smith @*/
4883c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
488436db0b34SBarry Smith {
4885dfbe8321SBarry Smith   PetscErrorCode ierr;
4886cbcfb4deSHong Zhang   PetscInt       ii;
488736db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4888cbcfb4deSHong Zhang   PetscInt jj;
488936db0b34SBarry Smith 
489036db0b34SBarry Smith   PetscFunctionBegin;
489141096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4892f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4893f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4894a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4895ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4896f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
4897ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4898071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4899071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4900ab93d7beSBarry Smith 
490136db0b34SBarry Smith   aij->i            = i;
490236db0b34SBarry Smith   aij->j            = j;
490336db0b34SBarry Smith   aij->a            = a;
490436db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
490536db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4906e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4907e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
490836db0b34SBarry Smith 
490936db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
491036db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
491176bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
491260e0710aSBarry 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]);
49139985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4914a061629eSStefano 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);
4915a061629eSStefano 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);
49169985e31cSBarry Smith       }
491736db0b34SBarry Smith     }
491876bd3646SJed Brown   }
491976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
492036db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
492160e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
492260e0710aSBarry 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]);
492336db0b34SBarry Smith     }
492476bd3646SJed Brown   }
492536db0b34SBarry Smith 
4926b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4927b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
492836db0b34SBarry Smith   PetscFunctionReturn(0);
492936db0b34SBarry Smith }
493080ef6e79SMatthew G Knepley /*@C
4931d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
49328a0b0e6bSVictor Minden               provided by the user.
49338a0b0e6bSVictor Minden 
4934d083f849SBarry Smith       Collective
49358a0b0e6bSVictor Minden 
49368a0b0e6bSVictor Minden    Input Parameters:
49378a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
49388a0b0e6bSVictor Minden .   m   - number of rows
49398a0b0e6bSVictor Minden .   n   - number of columns
49408a0b0e6bSVictor Minden .   i   - row indices
49418a0b0e6bSVictor Minden .   j   - column indices
49421230e6d1SVictor Minden .   a   - matrix values
49431230e6d1SVictor Minden .   nz  - number of nonzeros
49441230e6d1SVictor Minden -   idx - 0 or 1 based
49458a0b0e6bSVictor Minden 
49468a0b0e6bSVictor Minden    Output Parameter:
49478a0b0e6bSVictor Minden .   mat - the matrix
49488a0b0e6bSVictor Minden 
49498a0b0e6bSVictor Minden    Level: intermediate
49508a0b0e6bSVictor Minden 
49518a0b0e6bSVictor Minden    Notes:
49528a0b0e6bSVictor Minden        The i and j indices are 0 based
49538a0b0e6bSVictor Minden 
49548a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
49558a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
49568a0b0e6bSVictor Minden     as shown:
49578a0b0e6bSVictor Minden 
49588a0b0e6bSVictor Minden         1 0 0
49598a0b0e6bSVictor Minden         2 0 3
49608a0b0e6bSVictor Minden         4 5 6
49618a0b0e6bSVictor Minden 
49628a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
49638a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
49648a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
49658a0b0e6bSVictor Minden 
49668a0b0e6bSVictor Minden 
496769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
49688a0b0e6bSVictor Minden 
49698a0b0e6bSVictor Minden @*/
4970c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
49718a0b0e6bSVictor Minden {
49728a0b0e6bSVictor Minden   PetscErrorCode ierr;
4973d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
49748a0b0e6bSVictor Minden 
49758a0b0e6bSVictor Minden 
49768a0b0e6bSVictor Minden   PetscFunctionBegin;
49771795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
49781230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
4979c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
49801230e6d1SVictor Minden   }
49818a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
49828a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
49838a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
49841230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
49851230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
49861230e6d1SVictor Minden     if (idx) {
49871230e6d1SVictor Minden       row = i[ii] - 1;
49881230e6d1SVictor Minden       col = j[ii] - 1;
49891230e6d1SVictor Minden     } else {
49901230e6d1SVictor Minden       row = i[ii];
49911230e6d1SVictor Minden       col = j[ii];
49928a0b0e6bSVictor Minden     }
49931230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
49948a0b0e6bSVictor Minden   }
49958a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49968a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4997d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
49988a0b0e6bSVictor Minden   PetscFunctionReturn(0);
49998a0b0e6bSVictor Minden }
500036db0b34SBarry Smith 
5001acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5002acf2f550SJed Brown {
5003acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5004acf2f550SJed Brown   PetscErrorCode ierr;
5005acf2f550SJed Brown 
5006acf2f550SJed Brown   PetscFunctionBegin;
5007acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5008acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
50092205254eSKarl Rupp 
5010acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5011acf2f550SJed Brown   PetscFunctionReturn(0);
5012acf2f550SJed Brown }
5013acf2f550SJed Brown 
50149c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
50159c8f2541SHong Zhang {
50169c8f2541SHong Zhang   PetscErrorCode ierr;
50178761c3d6SHong Zhang   PetscMPIInt    size;
50189c8f2541SHong Zhang 
50199c8f2541SHong Zhang   PetscFunctionBegin;
50208761c3d6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
50217bbdc51dSHong Zhang   if (size == 1) {
50227bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
50237bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
50247bbdc51dSHong Zhang     } else {
50258761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
50267bbdc51dSHong Zhang     }
50278761c3d6SHong Zhang   } else {
50289c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
50298761c3d6SHong Zhang   }
50309c8f2541SHong Zhang   PetscFunctionReturn(0);
50319c8f2541SHong Zhang }
50329c8f2541SHong Zhang 
503381824310SBarry Smith /*
503453dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
503553dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
503653dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
503753dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
503853dd7562SDmitry Karpeev  */
503953dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
504053dd7562SDmitry Karpeev {
504153dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
504253dd7562SDmitry Karpeev   PetscErrorCode ierr;
504353dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
504453dd7562SDmitry Karpeev   PetscBool      seqaij;
504553dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
504653dd7562SDmitry Karpeev   PetscScalar    v;
504753dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
504853dd7562SDmitry Karpeev 
504953dd7562SDmitry Karpeev   PetscFunctionBegin;
505053dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
505153dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
50524099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
505353dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
505453dd7562SDmitry Karpeev   if (rowemb) {
505553dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
505653dd7562SDmitry 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);
505753dd7562SDmitry Karpeev   } else {
50586c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
505953dd7562SDmitry Karpeev   }
506053dd7562SDmitry Karpeev   if (colemb) {
506153dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
506253dd7562SDmitry 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);
506353dd7562SDmitry Karpeev   } else {
506453dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
506553dd7562SDmitry Karpeev   }
506653dd7562SDmitry Karpeev 
506753dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
506853dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
506953dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
507053dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
507153dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
507253dd7562SDmitry Karpeev     }
507353dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
507453dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
507553dd7562SDmitry Karpeev   }
507653dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
507753dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
507853dd7562SDmitry Karpeev   }
507953dd7562SDmitry Karpeev   count = 0;
508053dd7562SDmitry Karpeev   rowindices = NULL;
508153dd7562SDmitry Karpeev   colindices = NULL;
508253dd7562SDmitry Karpeev   if (rowemb) {
508353dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
508453dd7562SDmitry Karpeev   }
508553dd7562SDmitry Karpeev   if (colemb) {
508653dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
508753dd7562SDmitry Karpeev   }
508853dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
508953dd7562SDmitry Karpeev     PetscInt row;
509053dd7562SDmitry Karpeev     row = i;
509153dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
509253dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
509353dd7562SDmitry Karpeev       PetscInt col;
509453dd7562SDmitry Karpeev       col  = Baij->j[count];
509553dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
509653dd7562SDmitry Karpeev       v    = Baij->a[count];
509753dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
509853dd7562SDmitry Karpeev       ++count;
509953dd7562SDmitry Karpeev     }
510053dd7562SDmitry Karpeev   }
510153dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
510253dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
510353dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
510453dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
510553dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
510653dd7562SDmitry Karpeev   PetscFunctionReturn(0);
510753dd7562SDmitry Karpeev }
510853dd7562SDmitry Karpeev 
51094099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
51104099cc6bSBarry Smith 
51114099cc6bSBarry Smith /*@C
51124099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
51134099cc6bSBarry Smith 
51144099cc6bSBarry Smith    Collective on Mat
51154099cc6bSBarry Smith 
51164099cc6bSBarry Smith    Input Parameters:
51174099cc6bSBarry Smith +  mat      - the matrix object
51184099cc6bSBarry Smith -  matype   - matrix type
51194099cc6bSBarry Smith 
51204099cc6bSBarry Smith    Options Database Key:
51214099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
51224099cc6bSBarry Smith 
51234099cc6bSBarry Smith 
51244099cc6bSBarry Smith   Level: intermediate
51254099cc6bSBarry Smith 
51264099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
51274099cc6bSBarry Smith @*/
51284099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
51294099cc6bSBarry Smith {
5130fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
51314099cc6bSBarry Smith   PetscBool      sametype;
51324099cc6bSBarry Smith 
51334099cc6bSBarry Smith   PetscFunctionBegin;
51344099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
51354099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
51364099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
51374099cc6bSBarry Smith 
51384099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
51394099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
51404099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
51414099cc6bSBarry Smith   PetscFunctionReturn(0);
51424099cc6bSBarry Smith }
51434099cc6bSBarry Smith 
51444099cc6bSBarry Smith 
51454099cc6bSBarry Smith /*@C
51464099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
51474099cc6bSBarry Smith 
51484099cc6bSBarry Smith    Not Collective
51494099cc6bSBarry Smith 
51504099cc6bSBarry Smith    Input Parameters:
51514099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
51524099cc6bSBarry Smith -  function - routine to convert to subtype
51534099cc6bSBarry Smith 
51544099cc6bSBarry Smith    Notes:
51554099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
51564099cc6bSBarry Smith 
51574099cc6bSBarry Smith 
51584099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
51594099cc6bSBarry Smith $     -mat_seqaij_type my_mat
51604099cc6bSBarry Smith 
51614099cc6bSBarry Smith    Level: advanced
51624099cc6bSBarry Smith 
51634099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
51644099cc6bSBarry Smith 
51654099cc6bSBarry Smith 
51664099cc6bSBarry Smith   Level: advanced
51674099cc6bSBarry Smith @*/
5168388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
51694099cc6bSBarry Smith {
51704099cc6bSBarry Smith   PetscErrorCode ierr;
51714099cc6bSBarry Smith 
51724099cc6bSBarry Smith   PetscFunctionBegin;
51739cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
51744099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
51754099cc6bSBarry Smith   PetscFunctionReturn(0);
51764099cc6bSBarry Smith }
51774099cc6bSBarry Smith 
51784099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
51794099cc6bSBarry Smith 
51804099cc6bSBarry Smith /*@C
51814099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
51824099cc6bSBarry Smith 
51834099cc6bSBarry Smith   Not Collective
51844099cc6bSBarry Smith 
51854099cc6bSBarry Smith   Level: advanced
51864099cc6bSBarry Smith 
5187f719121fSJed Brown   Developers Note: CUSPARSE does not yet support the MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
51884099cc6bSBarry Smith 
51894099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
51904099cc6bSBarry Smith @*/
51914099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
51924099cc6bSBarry Smith {
51934099cc6bSBarry Smith   PetscErrorCode ierr;
51944099cc6bSBarry Smith 
51954099cc6bSBarry Smith   PetscFunctionBegin;
51964099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
51974099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
51984099cc6bSBarry Smith 
51994099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
52004099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
52014dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
52029779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
52036b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5204485f9817SRichard Tran Mills #endif
52054099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
52064099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
52074099cc6bSBarry Smith #endif
52084099cc6bSBarry Smith   PetscFunctionReturn(0);
52094099cc6bSBarry Smith }
521053dd7562SDmitry Karpeev 
521153dd7562SDmitry Karpeev /*
521281824310SBarry Smith     Special version for direct calls from Fortran
521381824310SBarry Smith */
5214af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
521581824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
521681824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
521781824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
521881824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
521981824310SBarry Smith #endif
522081824310SBarry Smith 
522181824310SBarry Smith /* Change these macros so can be used in void function */
522281824310SBarry Smith #undef CHKERRQ
5223ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
522481824310SBarry Smith #undef SETERRQ2
5225e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
52264994cf47SJed Brown #undef SETERRQ3
52274994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
522881824310SBarry Smith 
522919caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
523081824310SBarry Smith {
523181824310SBarry Smith   Mat            A  = *AA;
523281824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
523381824310SBarry Smith   InsertMode     is = *isis;
523481824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
523581824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
523681824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
523781824310SBarry Smith   PetscErrorCode ierr;
523881824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
523954f21887SBarry Smith   MatScalar      *ap,value,*aa;
5240ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5241ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
524281824310SBarry Smith 
524381824310SBarry Smith   PetscFunctionBegin;
52444994cf47SJed Brown   MatCheckPreallocated(A,1);
524581824310SBarry Smith   imax  = a->imax;
524681824310SBarry Smith   ai    = a->i;
524781824310SBarry Smith   ailen = a->ilen;
524881824310SBarry Smith   aj    = a->j;
524981824310SBarry Smith   aa    = a->a;
525081824310SBarry Smith 
525181824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
525281824310SBarry Smith     row = im[k];
525381824310SBarry Smith     if (row < 0) continue;
5254cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
525581824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
525681824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
525781824310SBarry Smith     low  = 0;
525881824310SBarry Smith     high = nrow;
525981824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
526081824310SBarry Smith       if (in[l] < 0) continue;
5261cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
526281824310SBarry Smith       col = in[l];
52632205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
52642205254eSKarl Rupp       else value = v[k + l*m];
52652205254eSKarl Rupp 
526681824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
526781824310SBarry Smith 
52682205254eSKarl Rupp       if (col <= lastcol) low = 0;
52692205254eSKarl Rupp       else high = nrow;
527081824310SBarry Smith       lastcol = col;
527181824310SBarry Smith       while (high-low > 5) {
527281824310SBarry Smith         t = (low+high)/2;
527381824310SBarry Smith         if (rp[t] > col) high = t;
527481824310SBarry Smith         else             low  = t;
527581824310SBarry Smith       }
527681824310SBarry Smith       for (i=low; i<high; i++) {
527781824310SBarry Smith         if (rp[i] > col) break;
527881824310SBarry Smith         if (rp[i] == col) {
527981824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
528081824310SBarry Smith           else                  ap[i] = value;
528181824310SBarry Smith           goto noinsert;
528281824310SBarry Smith         }
528381824310SBarry Smith       }
528481824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
528581824310SBarry Smith       if (nonew == 1) goto noinsert;
5286ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5287fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
528881824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
528981824310SBarry Smith       /* shift up all the later entries in this row */
529081824310SBarry Smith       for (ii=N; ii>=i; ii--) {
529181824310SBarry Smith         rp[ii+1] = rp[ii];
529281824310SBarry Smith         ap[ii+1] = ap[ii];
529381824310SBarry Smith       }
529481824310SBarry Smith       rp[i] = col;
529581824310SBarry Smith       ap[i] = value;
5296e56f5c9eSBarry Smith       A->nonzerostate++;
529781824310SBarry Smith noinsert:;
529881824310SBarry Smith       low = i + 1;
529981824310SBarry Smith     }
530081824310SBarry Smith     ailen[row] = nrow;
530181824310SBarry Smith   }
530281824310SBarry Smith   PetscFunctionReturnVoid();
530381824310SBarry Smith }
5304