xref: /petsc/src/mat/impls/aij/seq/aij.c (revision fa213d2f42a2adff90447074182cc202ca0ebb7c)
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;
176837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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) {
187837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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++) {
195837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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       }
201837a59e1SRichard Tran Mills #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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);
376e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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   }
430e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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;
446e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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;
484e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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++;
510e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
511e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
512e2cf4d64SStefano Zampini #endif
513e44c0bd4SBarry Smith noinsert:;
51417ab2063SBarry Smith     }
51517ab2063SBarry Smith     ailen[row] = nrow;
51617ab2063SBarry Smith   }
517e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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   }
55519b08ed1SBarry Smith #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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   }
650e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
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;
6983ea6fe3dSLisandro Dalcin   PetscInt       header[4],M,N,m,nz,i;
6993ea6fe3dSLisandro Dalcin   PetscInt       *rowlens;
7006849ba73SBarry Smith   PetscErrorCode ierr;
70117ab2063SBarry Smith 
7023a40ed3dSBarry Smith   PetscFunctionBegin;
7033ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7042205254eSKarl Rupp 
7053ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7063ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7073ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7083ea6fe3dSLisandro Dalcin   nz = A->nz;
709416022c9SBarry Smith 
7103ea6fe3dSLisandro Dalcin   /* write matrix header */
7113ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7123ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7133ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
714416022c9SBarry Smith 
7153ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7163ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7173ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7183ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7193ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7203ea6fe3dSLisandro Dalcin   /* store column indices */
7213ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
722416022c9SBarry Smith   /* store nonzero values */
7233ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->a,nz,PETSC_SCALAR);CHKERRQ(ierr);
724b37d52dbSMark F. Adams 
7253ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7263ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7273a40ed3dSBarry Smith   PetscFunctionReturn(0);
72817ab2063SBarry Smith }
729416022c9SBarry Smith 
7307dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7317dc0baabSHong Zhang {
7327dc0baabSHong Zhang   PetscErrorCode ierr;
7337dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7347dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7357dc0baabSHong Zhang 
7367dc0baabSHong Zhang   PetscFunctionBegin;
7377dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7387dc0baabSHong Zhang   for (i=0; i<m; i++) {
7397dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7407dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7417dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7427dc0baabSHong Zhang     }
7437dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7447dc0baabSHong Zhang   }
7457dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7467dc0baabSHong Zhang   PetscFunctionReturn(0);
7477dc0baabSHong Zhang }
7487dc0baabSHong Zhang 
74909573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
750cd155464SBarry Smith 
751dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
752416022c9SBarry Smith {
753416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
754dfbe8321SBarry Smith   PetscErrorCode    ierr;
75560e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
756e060cb09SBarry Smith   const char        *name;
757f3ef73ceSBarry Smith   PetscViewerFormat format;
75817ab2063SBarry Smith 
7593a40ed3dSBarry Smith   PetscFunctionBegin;
7607dc0baabSHong Zhang   if (A->structure_only) {
7617dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7627dc0baabSHong Zhang     PetscFunctionReturn(0);
7637dc0baabSHong Zhang   }
76443e49210SHong Zhang 
765b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
76671c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
76797f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
76860e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
769c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
770d00d2cf4SBarry Smith       nofinalvalue = 1;
771d00d2cf4SBarry Smith     }
772d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
773d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
77477431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
775fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
776fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
777fbfe6fa7SJed Brown #else
77877431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
779fbfe6fa7SJed Brown #endif
780b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
78117ab2063SBarry Smith 
78217ab2063SBarry Smith     for (i=0; i<m; i++) {
78360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
784aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
785a9bf72d8SJed 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);
78617ab2063SBarry Smith #else
78760e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
78817ab2063SBarry Smith #endif
78917ab2063SBarry Smith       }
79017ab2063SBarry Smith     }
791d00d2cf4SBarry Smith     if (nofinalvalue) {
792c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
793c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
794c337ccceSJed Brown #else
795d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
796c337ccceSJed Brown #endif
797d00d2cf4SBarry Smith     }
798317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
799fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
800d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
8012950ac48SStefano Zampini   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
802cd155464SBarry Smith     PetscFunctionReturn(0);
803fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
804d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
80544cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
80677431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
80760e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
808aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
80936db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
81060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81136db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
81260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81336db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
81460e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8156831982aSBarry Smith         }
81644cd7ae7SLois Curfman McInnes #else
81760e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
81844cd7ae7SLois Curfman McInnes #endif
81944cd7ae7SLois Curfman McInnes       }
820b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
82144cd7ae7SLois Curfman McInnes     }
822d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
823fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
82497f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
825d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
826854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
827496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
828496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
82960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
830496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
831aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
83236db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
833496be53dSLois Curfman McInnes #else
834496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
835496be53dSLois Curfman McInnes #endif
836496be53dSLois Curfman McInnes         }
837496be53dSLois Curfman McInnes       }
838496be53dSLois Curfman McInnes     }
8392e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
84077431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8412e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8422205254eSKarl Rupp       if (i+4<m) {
8432205254eSKarl 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);
8442205254eSKarl Rupp       } else if (i+3<m) {
8452205254eSKarl 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);
8462205254eSKarl Rupp       } else if (i+2<m) {
8472205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8482205254eSKarl Rupp       } else if (i+1<m) {
8492205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8502205254eSKarl Rupp       } else if (i<m) {
8512205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8522205254eSKarl Rupp       } else {
8532205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8542205254eSKarl Rupp       }
855496be53dSLois Curfman McInnes     }
856b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
857606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
858496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
85960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
86077431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
861496be53dSLois Curfman McInnes       }
862b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
863496be53dSLois Curfman McInnes     }
864b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
865496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
86660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
867496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
868aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
86936db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
87060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8716831982aSBarry Smith           }
872496be53dSLois Curfman McInnes #else
87360e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
874496be53dSLois Curfman McInnes #endif
875496be53dSLois Curfman McInnes         }
876496be53dSLois Curfman McInnes       }
877b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
878496be53dSLois Curfman McInnes     }
879d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
880fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
88197f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
88287828ca2SBarry Smith     PetscScalar value;
88368f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
88468f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
88568f1ed48SBarry Smith 
88668f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
88768f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
88868f1ed48SBarry Smith         realonly = PETSC_FALSE;
88968f1ed48SBarry Smith         break;
89068f1ed48SBarry Smith       }
89168f1ed48SBarry Smith     }
89268f1ed48SBarry Smith #endif
89302594712SBarry Smith 
894d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
89502594712SBarry Smith     for (i=0; i<m; i++) {
89602594712SBarry Smith       jcnt = 0;
897d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
898e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
89902594712SBarry Smith           value = a->a[cnt++];
900e24b481bSBarry Smith           jcnt++;
90102594712SBarry Smith         } else {
90202594712SBarry Smith           value = 0.0;
90302594712SBarry Smith         }
904aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
90568f1ed48SBarry Smith         if (realonly) {
90660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
90768f1ed48SBarry Smith         } else {
90860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
90968f1ed48SBarry Smith         }
91002594712SBarry Smith #else
91160e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
91202594712SBarry Smith #endif
91302594712SBarry Smith       }
914b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
91502594712SBarry Smith     }
916d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9173c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
918150b93efSMatthew G. Knepley     PetscInt fshift=1;
919d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9203c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
92119303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9223c215bfdSMatthew Knepley #else
92319303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9243c215bfdSMatthew Knepley #endif
925d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9263c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
92760e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9283c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
929a9a0e077SKarl 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);
9303c215bfdSMatthew Knepley #else
931150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9323c215bfdSMatthew Knepley #endif
9333c215bfdSMatthew Knepley       }
9343c215bfdSMatthew Knepley     }
935d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9363a40ed3dSBarry Smith   } else {
937d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
938d5f3da31SBarry Smith     if (A->factortype) {
93916cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
94016cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
94116cd7e1dSShri Abhyankar         /* L part */
94260e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
94316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
94416cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
94560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
94616cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9476712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
94816cd7e1dSShri Abhyankar           } else {
94960e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
95016cd7e1dSShri Abhyankar           }
95116cd7e1dSShri Abhyankar #else
95260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
95316cd7e1dSShri Abhyankar #endif
95416cd7e1dSShri Abhyankar         }
95516cd7e1dSShri Abhyankar         /* diagonal */
95616cd7e1dSShri Abhyankar         j = a->diag[i];
95716cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
95816cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
95960e0710aSBarry 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);
96016cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9616712e2f1SBarry 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);
96216cd7e1dSShri Abhyankar         } else {
96360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
96416cd7e1dSShri Abhyankar         }
96516cd7e1dSShri Abhyankar #else
96660e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
96716cd7e1dSShri Abhyankar #endif
96816cd7e1dSShri Abhyankar 
96916cd7e1dSShri Abhyankar         /* U part */
97060e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
97116cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97216cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
97360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
97416cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
97522ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
97616cd7e1dSShri Abhyankar           } else {
97760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
97816cd7e1dSShri Abhyankar           }
97916cd7e1dSShri Abhyankar #else
98060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
98116cd7e1dSShri Abhyankar #endif
98216cd7e1dSShri Abhyankar         }
98316cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
98416cd7e1dSShri Abhyankar       }
98516cd7e1dSShri Abhyankar     } else {
98617ab2063SBarry Smith       for (i=0; i<m; i++) {
98777431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
98860e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
989aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
99036db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
99160e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
99236db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
99360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9943a40ed3dSBarry Smith           } else {
99560e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
99617ab2063SBarry Smith           }
99717ab2063SBarry Smith #else
99860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
99917ab2063SBarry Smith #endif
100017ab2063SBarry Smith         }
1001b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
100217ab2063SBarry Smith       }
100316cd7e1dSShri Abhyankar     }
1004d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
100517ab2063SBarry Smith   }
1006b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10073a40ed3dSBarry Smith   PetscFunctionReturn(0);
1008416022c9SBarry Smith }
1009416022c9SBarry Smith 
10109804daf3SBarry Smith #include <petscdraw.h>
1011dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1012416022c9SBarry Smith {
1013480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1014416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1015dfbe8321SBarry Smith   PetscErrorCode    ierr;
1016383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1017383922c3SLisandro Dalcin   int               color;
1018b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1019b0a32e0cSBarry Smith   PetscViewer       viewer;
1020f3ef73ceSBarry Smith   PetscViewerFormat format;
1021cddf8d76SBarry Smith 
10223a40ed3dSBarry Smith   PetscFunctionBegin;
1023480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1024b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1025b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1026383922c3SLisandro Dalcin 
1027416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10280513a670SBarry Smith 
1029fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1030383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10310513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1032b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1033416022c9SBarry Smith     for (i=0; i<m; i++) {
1034cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1035bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1036bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
103736db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
1038b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1039cddf8d76SBarry Smith       }
1040cddf8d76SBarry Smith     }
1041b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1042cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1043cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1044bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1045bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1046cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
1047b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1048cddf8d76SBarry Smith       }
1049cddf8d76SBarry Smith     }
1050b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1051cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1052cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1053bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1054bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
105536db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
1056b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1057416022c9SBarry Smith       }
1058416022c9SBarry Smith     }
1059383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10600513a670SBarry Smith   } else {
10610513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10620513a670SBarry Smith     /* first determine max of all nonzero values */
1063b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1064383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1065b0a32e0cSBarry Smith     PetscDraw popup;
10660513a670SBarry Smith 
10670513a670SBarry Smith     for (i=0; i<nz; i++) {
10680513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
10690513a670SBarry Smith     }
1070383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1071b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
107245f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1073383922c3SLisandro Dalcin 
1074383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10750513a670SBarry Smith     for (i=0; i<m; i++) {
1076383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1077383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1078bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1079383922c3SLisandro Dalcin         x_l = a->j[j];
1080383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1081b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
1082b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
10830513a670SBarry Smith         count++;
10840513a670SBarry Smith       }
10850513a670SBarry Smith     }
1086383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10870513a670SBarry Smith   }
1088480ef9eaSBarry Smith   PetscFunctionReturn(0);
1089480ef9eaSBarry Smith }
1090cddf8d76SBarry Smith 
10919804daf3SBarry Smith #include <petscdraw.h>
1092dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1093480ef9eaSBarry Smith {
1094dfbe8321SBarry Smith   PetscErrorCode ierr;
1095b0a32e0cSBarry Smith   PetscDraw      draw;
109636db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1097ace3abfcSBarry Smith   PetscBool      isnull;
1098480ef9eaSBarry Smith 
1099480ef9eaSBarry Smith   PetscFunctionBegin;
1100b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1101b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1102480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1103480ef9eaSBarry Smith 
1104d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1105480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1106b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1107832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1108b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11090298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1110832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11113a40ed3dSBarry Smith   PetscFunctionReturn(0);
1112416022c9SBarry Smith }
1113416022c9SBarry Smith 
1114dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1115416022c9SBarry Smith {
1116dfbe8321SBarry Smith   PetscErrorCode ierr;
1117ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1118416022c9SBarry Smith 
11193a40ed3dSBarry Smith   PetscFunctionBegin;
1120251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1121251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1122251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1123c45a1595SBarry Smith   if (iascii) {
11243a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11250f5bd95cSBarry Smith   } else if (isbinary) {
11263a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11270f5bd95cSBarry Smith   } else if (isdraw) {
11283a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
112911aeaf0aSBarry Smith   }
11304108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11313a40ed3dSBarry Smith   PetscFunctionReturn(0);
113217ab2063SBarry Smith }
113319bcc07fSBarry Smith 
1134dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
113517ab2063SBarry Smith {
1136416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11376849ba73SBarry Smith   PetscErrorCode ierr;
1138580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1139d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
114054f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11413447b6efSHong Zhang   PetscReal      ratio  = 0.6;
114217ab2063SBarry Smith 
11433a40ed3dSBarry Smith   PetscFunctionBegin;
11443a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1145071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1146071fcb05SBarry Smith   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) PetscFunctionReturn(0);
114717ab2063SBarry Smith 
114843ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
114917ab2063SBarry Smith   for (i=1; i<m; i++) {
1150416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
115117ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
115294a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
115317ab2063SBarry Smith     if (fshift) {
1154bfeeae90SHong Zhang       ip = aj + ai[i];
1155bfeeae90SHong Zhang       ap = aa + ai[i];
115617ab2063SBarry Smith       N  = ailen[i];
1157580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1158580bdb30SBarry Smith       if (!A->structure_only) {
1159580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
116017ab2063SBarry Smith       }
116117ab2063SBarry Smith     }
116217ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
116317ab2063SBarry Smith   }
116417ab2063SBarry Smith   if (m) {
116517ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
116617ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
116717ab2063SBarry Smith   }
11687b083b7cSBarry Smith 
116917ab2063SBarry Smith   /* reset ilen and imax for each row */
11707b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1171396832f4SHong Zhang   if (A->structure_only) {
1172071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1173071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1174396832f4SHong Zhang   } else { /* !A->structure_only */
117517ab2063SBarry Smith     for (i=0; i<m; i++) {
117617ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11777b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
117817ab2063SBarry Smith     }
1179396832f4SHong Zhang   }
1180bfeeae90SHong Zhang   a->nz = ai[m];
118165e19b50SBarry 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);
118217ab2063SBarry Smith 
118309f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1184d0f46423SBarry 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);
1185ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1186ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
11872205254eSKarl Rupp 
11888e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1189dd5f02e7SSatish Balay   a->reallocs         = 0;
11906712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
119136db0b34SBarry Smith   a->rmax             = rmax;
11924e220ebcSLois Curfman McInnes 
1193396832f4SHong Zhang   if (!A->structure_only) {
119411e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1195396832f4SHong Zhang   }
11964108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
11973a40ed3dSBarry Smith   PetscFunctionReturn(0);
119817ab2063SBarry Smith }
119917ab2063SBarry Smith 
120099cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
120199cafbc1SBarry Smith {
120299cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
120399cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
120454f21887SBarry Smith   MatScalar      *aa = a->a;
1205acf2f550SJed Brown   PetscErrorCode ierr;
120699cafbc1SBarry Smith 
120799cafbc1SBarry Smith   PetscFunctionBegin;
120899cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1209acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1210e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1211c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1212e2cf4d64SStefano Zampini #endif
121399cafbc1SBarry Smith   PetscFunctionReturn(0);
121499cafbc1SBarry Smith }
121599cafbc1SBarry Smith 
121699cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
121799cafbc1SBarry Smith {
121899cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
121999cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
122054f21887SBarry Smith   MatScalar      *aa = a->a;
1221acf2f550SJed Brown   PetscErrorCode ierr;
122299cafbc1SBarry Smith 
122399cafbc1SBarry Smith   PetscFunctionBegin;
122499cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1225acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1226e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1227c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1228e2cf4d64SStefano Zampini #endif
122999cafbc1SBarry Smith   PetscFunctionReturn(0);
123099cafbc1SBarry Smith }
123199cafbc1SBarry Smith 
1232dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
123317ab2063SBarry Smith {
1234416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1235dfbe8321SBarry Smith   PetscErrorCode ierr;
12363a40ed3dSBarry Smith 
12373a40ed3dSBarry Smith   PetscFunctionBegin;
1238580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1239acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1240e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1241c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1242e2cf4d64SStefano Zampini #endif
12433a40ed3dSBarry Smith   PetscFunctionReturn(0);
124417ab2063SBarry Smith }
1245416022c9SBarry Smith 
1246dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
124717ab2063SBarry Smith {
1248416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1249dfbe8321SBarry Smith   PetscErrorCode ierr;
1250d5d45c9bSBarry Smith 
12513a40ed3dSBarry Smith   PetscFunctionBegin;
1252aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1253d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
125417ab2063SBarry Smith #endif
1255e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12566bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12576bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
125805b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1259d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1260071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1261071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1262846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
126371f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
126405b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12656bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
126605b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1267cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1268a30b2313SHong Zhang 
12694108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1270bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1271901853e0SKris Buschelman 
12726718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12736718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12746718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12756718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12766718818eSStefano Zampini      due to different matrix sizes */
12776718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
12786718818eSStefano Zampini 
1279f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1280bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1281bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1282bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1283bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1284bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1285bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
12864222ddf1SHong Zhang 
12874222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12884222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1289e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
12904222ddf1SHong Zhang #endif
12914222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1292af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1293af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1294af8000cdSHong Zhang #endif
1295d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1296d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1297d24d4204SJose E. Roman #endif
129863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
129963c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13004222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
130163c07aadSStefano Zampini #endif
1302b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1303c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1304c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1305bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1306bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1307846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1308bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1309bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13104222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13114222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13124222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
13133a40ed3dSBarry Smith   PetscFunctionReturn(0);
131417ab2063SBarry Smith }
131517ab2063SBarry Smith 
1316ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
131717ab2063SBarry Smith {
1318416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13194846f1f5SKris Buschelman   PetscErrorCode ierr;
13203a40ed3dSBarry Smith 
13213a40ed3dSBarry Smith   PetscFunctionBegin;
1322a65d3064SKris Buschelman   switch (op) {
1323a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13244e0d8c25SBarry Smith     a->roworiented = flg;
1325a65d3064SKris Buschelman     break;
1326a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1327a9817697SBarry Smith     a->keepnonzeropattern = flg;
1328a65d3064SKris Buschelman     break;
1329512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1330512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1331a65d3064SKris Buschelman     break;
1332a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13334e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1334a65d3064SKris Buschelman     break;
1335a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13364e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1337a65d3064SKris Buschelman     break;
133828b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
133928b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
134028b2fa4aSMatthew Knepley     break;
1341a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13424e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13430df259c2SBarry Smith     break;
13443d472b54SHong Zhang   case MAT_SPD:
1345b1646e73SJed Brown   case MAT_SYMMETRIC:
1346b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1347b1646e73SJed Brown   case MAT_HERMITIAN:
1348b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1349957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13505021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13515021d80fSJed Brown     break;
13524e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1353a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1354a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1355290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1356a65d3064SKris Buschelman     break;
1357b87ac2d8SJed Brown   case MAT_USE_INODES:
1358b87ac2d8SJed Brown     /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
1359b87ac2d8SJed Brown     break;
1360c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1361c10200c1SHong Zhang     A->submat_singleis = flg;
1362c10200c1SHong Zhang     break;
1363071fcb05SBarry Smith   case MAT_SORTED_FULL:
1364071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1365071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1366071fcb05SBarry Smith     break;
1367a65d3064SKris Buschelman   default:
1368e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1369a65d3064SKris Buschelman   }
13704108e4d5SBarry Smith   ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr);
13713a40ed3dSBarry Smith   PetscFunctionReturn(0);
137217ab2063SBarry Smith }
137317ab2063SBarry Smith 
1374dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
137517ab2063SBarry Smith {
1376416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13776849ba73SBarry Smith   PetscErrorCode ierr;
1378fdc842d1SBarry Smith   PetscInt       i,j,n,*ai=a->i,*aj=a->j;
1379fdc842d1SBarry Smith   PetscScalar    *aa=a->a,*x;
138017ab2063SBarry Smith 
13813a40ed3dSBarry Smith   PetscFunctionBegin;
1382d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1383e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
138435e7444dSHong Zhang 
1385d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1386d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1387fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
13882c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1389fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
139035e7444dSHong Zhang     PetscFunctionReturn(0);
139135e7444dSHong Zhang   }
139235e7444dSHong Zhang 
1393fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
139435e7444dSHong Zhang   for (i=0; i<n; i++) {
1395fdc842d1SBarry Smith     x[i] = 0.0;
139635e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
139735e7444dSHong Zhang       if (aj[j] == i) {
139835e7444dSHong Zhang         x[i] = aa[j];
139917ab2063SBarry Smith         break;
140017ab2063SBarry Smith       }
140117ab2063SBarry Smith     }
140217ab2063SBarry Smith   }
1403fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
14043a40ed3dSBarry Smith   PetscFunctionReturn(0);
140517ab2063SBarry Smith }
140617ab2063SBarry Smith 
1407c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1408dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
140917ab2063SBarry Smith {
1410416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1411d9ca1df4SBarry Smith   PetscScalar       *y;
1412d9ca1df4SBarry Smith   const PetscScalar *x;
1413dfbe8321SBarry Smith   PetscErrorCode    ierr;
1414d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14155c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1416d9ca1df4SBarry Smith   const MatScalar   *v;
1417a77337e4SBarry Smith   PetscScalar       alpha;
1418d9ca1df4SBarry Smith   PetscInt          n,i,j;
1419d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14203447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1421ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14225c897100SBarry Smith #endif
142317ab2063SBarry Smith 
14243a40ed3dSBarry Smith   PetscFunctionBegin;
14252e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1426d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14271ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14285c897100SBarry Smith 
14295c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1430bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14315c897100SBarry Smith #else
14323447b6efSHong Zhang   if (usecprow) {
14333447b6efSHong Zhang     m    = cprow.nrows;
14343447b6efSHong Zhang     ii   = cprow.i;
14357b2bb3b9SHong Zhang     ridx = cprow.rindex;
14363447b6efSHong Zhang   } else {
14373447b6efSHong Zhang     ii = a->i;
14383447b6efSHong Zhang   }
143917ab2063SBarry Smith   for (i=0; i<m; i++) {
14403447b6efSHong Zhang     idx = a->j + ii[i];
14413447b6efSHong Zhang     v   = a->a + ii[i];
14423447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14433447b6efSHong Zhang     if (usecprow) {
14447b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14453447b6efSHong Zhang     } else {
144617ab2063SBarry Smith       alpha = x[i];
14473447b6efSHong Zhang     }
144804fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
144917ab2063SBarry Smith   }
14505c897100SBarry Smith #endif
1451dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1452d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14531ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14543a40ed3dSBarry Smith   PetscFunctionReturn(0);
145517ab2063SBarry Smith }
145617ab2063SBarry Smith 
1457dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14585c897100SBarry Smith {
1459dfbe8321SBarry Smith   PetscErrorCode ierr;
14605c897100SBarry Smith 
14615c897100SBarry Smith   PetscFunctionBegin;
1462170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14635c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14645c897100SBarry Smith   PetscFunctionReturn(0);
14655c897100SBarry Smith }
14665c897100SBarry Smith 
1467c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
146878b84d54SShri Abhyankar 
1469dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
147017ab2063SBarry Smith {
1471416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1472d9fead3dSBarry Smith   PetscScalar       *y;
147354f21887SBarry Smith   const PetscScalar *x;
147454f21887SBarry Smith   const MatScalar   *aa;
1475dfbe8321SBarry Smith   PetscErrorCode    ierr;
1476003131ecSBarry Smith   PetscInt          m=A->rmap->n;
14770298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
14787b083b7cSBarry Smith   PetscInt          n,i;
1479362ced78SSatish Balay   PetscScalar       sum;
1480ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
148117ab2063SBarry Smith 
1482b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
148397952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1484fee21e36SBarry Smith #endif
1485fee21e36SBarry Smith 
14863a40ed3dSBarry Smith   PetscFunctionBegin;
14873649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14881ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1489416022c9SBarry Smith   ii   = a->i;
14904eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1491580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
149297952fefSHong Zhang     m    = a->compressedrow.nrows;
149397952fefSHong Zhang     ii   = a->compressedrow.i;
149497952fefSHong Zhang     ridx = a->compressedrow.rindex;
149597952fefSHong Zhang     for (i=0; i<m; i++) {
149697952fefSHong Zhang       n           = ii[i+1] - ii[i];
149797952fefSHong Zhang       aj          = a->j + ii[i];
149897952fefSHong Zhang       aa          = a->a + ii[i];
149997952fefSHong Zhang       sum         = 0.0;
1500003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1501003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
150297952fefSHong Zhang       y[*ridx++] = sum;
150397952fefSHong Zhang     }
150497952fefSHong Zhang   } else { /* do not use compressed row format */
1505b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15063d3eaba7SBarry Smith     aj   = a->j;
15073d3eaba7SBarry Smith     aa   = a->a;
1508b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1509b05257ddSBarry Smith #else
151017ab2063SBarry Smith     for (i=0; i<m; i++) {
1511003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1512003131ecSBarry Smith       aj          = a->j + ii[i];
1513003131ecSBarry Smith       aa          = a->a + ii[i];
151417ab2063SBarry Smith       sum         = 0.0;
1515003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
151617ab2063SBarry Smith       y[i] = sum;
151717ab2063SBarry Smith     }
15188d195f9aSBarry Smith #endif
1519b05257ddSBarry Smith   }
15207b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15213649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15221ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15233a40ed3dSBarry Smith   PetscFunctionReturn(0);
152417ab2063SBarry Smith }
152517ab2063SBarry Smith 
1526b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1527b434eb95SMatthew G. Knepley {
1528b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1529b434eb95SMatthew G. Knepley   PetscScalar       *y;
1530b434eb95SMatthew G. Knepley   const PetscScalar *x;
1531b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1532b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1533b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1534b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1535b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1536b434eb95SMatthew G. Knepley   PetscScalar       sum;
1537b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1538b434eb95SMatthew G. Knepley 
1539b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1540b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1541b434eb95SMatthew G. Knepley #endif
1542b434eb95SMatthew G. Knepley 
1543b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1544b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1545b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1546b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1547b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1548b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1549b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1550b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1551b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1552b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1553b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1554b434eb95SMatthew G. Knepley       sum         = 0.0;
1555b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1556b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1557b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1558b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1559b434eb95SMatthew G. Knepley     }
1560b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15613d3eaba7SBarry Smith     ii = a->i;
1562b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1563b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1564b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1565b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1566b434eb95SMatthew G. Knepley       sum         = 0.0;
1567b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1568b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1569b434eb95SMatthew G. Knepley       y[i] = sum;
1570b434eb95SMatthew G. Knepley     }
1571b434eb95SMatthew G. Knepley   }
1572b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1573b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1574b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1575b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1576b434eb95SMatthew G. Knepley }
1577b434eb95SMatthew G. Knepley 
1578b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1579b434eb95SMatthew G. Knepley {
1580b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1581b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1582b434eb95SMatthew G. Knepley   const PetscScalar *x;
1583b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1584b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1585b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1586b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1587b434eb95SMatthew G. Knepley   PetscScalar       sum;
1588b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1589b434eb95SMatthew G. Knepley 
1590b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1591b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1592d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1593b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1594b434eb95SMatthew G. Knepley     if (zz != yy) {
1595580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1596b434eb95SMatthew G. Knepley     }
1597b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1598b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1599b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1600b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1601b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1602b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1603b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1604b434eb95SMatthew G. Knepley       sum = y[*ridx];
1605b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1606b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1607b434eb95SMatthew G. Knepley     }
1608b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16093d3eaba7SBarry Smith     ii = a->i;
1610b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1611b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1612b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1613b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1614b434eb95SMatthew G. Knepley       sum = y[i];
1615b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1616b434eb95SMatthew G. Knepley       z[i] = sum;
1617b434eb95SMatthew G. Knepley     }
1618b434eb95SMatthew G. Knepley   }
1619b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1620b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1621d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1622b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1623b434eb95SMatthew G. Knepley }
1624b434eb95SMatthew G. Knepley 
1625c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1626dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
162717ab2063SBarry Smith {
1628416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1629f15663dcSBarry Smith   PetscScalar       *y,*z;
1630f15663dcSBarry Smith   const PetscScalar *x;
163154f21887SBarry Smith   const MatScalar   *aa;
1632dfbe8321SBarry Smith   PetscErrorCode    ierr;
1633d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1634d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1635362ced78SSatish Balay   PetscScalar       sum;
1636ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16379ea0dfa2SSatish Balay 
16383a40ed3dSBarry Smith   PetscFunctionBegin;
1639f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1640d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16414eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16424eb6d288SHong Zhang     if (zz != yy) {
1643580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16444eb6d288SHong Zhang     }
164597952fefSHong Zhang     m    = a->compressedrow.nrows;
164697952fefSHong Zhang     ii   = a->compressedrow.i;
164797952fefSHong Zhang     ridx = a->compressedrow.rindex;
164897952fefSHong Zhang     for (i=0; i<m; i++) {
164997952fefSHong Zhang       n   = ii[i+1] - ii[i];
165097952fefSHong Zhang       aj  = a->j + ii[i];
165197952fefSHong Zhang       aa  = a->a + ii[i];
165297952fefSHong Zhang       sum = y[*ridx];
1653f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
165497952fefSHong Zhang       z[*ridx++] = sum;
165597952fefSHong Zhang     }
165697952fefSHong Zhang   } else { /* do not use compressed row format */
16573d3eaba7SBarry Smith     ii = a->i;
1658f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16593d3eaba7SBarry Smith     aj = a->j;
16603d3eaba7SBarry Smith     aa = a->a;
1661f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1662f15663dcSBarry Smith #else
166317ab2063SBarry Smith     for (i=0; i<m; i++) {
1664f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1665f15663dcSBarry Smith       aj  = a->j + ii[i];
1666f15663dcSBarry Smith       aa  = a->a + ii[i];
166717ab2063SBarry Smith       sum = y[i];
1668f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
166917ab2063SBarry Smith       z[i] = sum;
167017ab2063SBarry Smith     }
167102ab625aSSatish Balay #endif
1672f15663dcSBarry Smith   }
1673dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1674f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1675d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16763a40ed3dSBarry Smith   PetscFunctionReturn(0);
167717ab2063SBarry Smith }
167817ab2063SBarry Smith 
167917ab2063SBarry Smith /*
168017ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
168117ab2063SBarry Smith */
1682dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
168317ab2063SBarry Smith {
1684416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
16856849ba73SBarry Smith   PetscErrorCode ierr;
1686d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
168717ab2063SBarry Smith 
16883a40ed3dSBarry Smith   PetscFunctionBegin;
168909f38230SBarry Smith   if (!a->diag) {
1690785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
16913bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
169209f38230SBarry Smith   }
1693d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
169409f38230SBarry Smith     a->diag[i] = a->i[i+1];
1695bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1696bfeeae90SHong Zhang       if (a->j[j] == i) {
169709f38230SBarry Smith         a->diag[i] = j;
169817ab2063SBarry Smith         break;
169917ab2063SBarry Smith       }
170017ab2063SBarry Smith     }
170117ab2063SBarry Smith   }
17023a40ed3dSBarry Smith   PetscFunctionReturn(0);
170317ab2063SBarry Smith }
170417ab2063SBarry Smith 
170561ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
170661ecd0c6SBarry Smith {
170761ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
170861ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
170961ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
171061ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
171161ecd0c6SBarry Smith   PetscErrorCode    ierr;
171261ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
171361ecd0c6SBarry Smith 
171461ecd0c6SBarry Smith   PetscFunctionBegin;
171561ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
171661ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
171761ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
171861ecd0c6SBarry Smith     PetscFunctionReturn(0);
171961ecd0c6SBarry Smith   }
172061ecd0c6SBarry Smith 
172161ecd0c6SBarry Smith   if (a->diagonaldense) {
172261ecd0c6SBarry Smith     cnt = 0;
172361ecd0c6SBarry Smith   } else {
172461ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
172561ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
172661ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
172761ecd0c6SBarry Smith         cnt++;
172861ecd0c6SBarry Smith         mdiag[i] = 1;
172961ecd0c6SBarry Smith       }
173061ecd0c6SBarry Smith     }
173161ecd0c6SBarry Smith   }
173261ecd0c6SBarry Smith   if (!cnt) {
173361ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
173461ecd0c6SBarry Smith   } else {
1735b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1736b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
173761ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
173861ecd0c6SBarry Smith 
173961ecd0c6SBarry Smith     a->a = NULL;
174061ecd0c6SBarry Smith     a->j = NULL;
174161ecd0c6SBarry Smith     a->i = NULL;
174261ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
174361ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
174461ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1745447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
174661ecd0c6SBarry Smith     }
174761ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
174861ecd0c6SBarry Smith 
174961ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
175061ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
175161ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1752447d62f5SStefano Zampini       if (i < A->cmap->n) {
175361ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
175461ecd0c6SBarry Smith       }
1755447d62f5SStefano Zampini     }
175661ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
175761ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
175861ecd0c6SBarry Smith     if (singlemalloc) {
175961ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
176061ecd0c6SBarry Smith     } else {
176161ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
176261ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
176361ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
176461ecd0c6SBarry Smith     }
176561ecd0c6SBarry Smith   }
176661ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
176761ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
176861ecd0c6SBarry Smith   PetscFunctionReturn(0);
176961ecd0c6SBarry Smith }
177061ecd0c6SBarry Smith 
1771be5855fcSBarry Smith /*
1772be5855fcSBarry Smith      Checks for missing diagonals
1773be5855fcSBarry Smith */
1774ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1775be5855fcSBarry Smith {
1776be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17777734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1778994fe344SLisandro Dalcin   PetscErrorCode ierr;
1779be5855fcSBarry Smith 
1780be5855fcSBarry Smith   PetscFunctionBegin;
178109f38230SBarry Smith   *missing = PETSC_FALSE;
17827734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
178309f38230SBarry Smith     *missing = PETSC_TRUE;
178409f38230SBarry Smith     if (d) *d = 0;
1785994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
178609f38230SBarry Smith   } else {
178701445905SHong Zhang     PetscInt n;
178801445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1789f1e2ffcdSBarry Smith     diag = a->diag;
179001445905SHong Zhang     for (i=0; i<n; i++) {
17917734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
179209f38230SBarry Smith         *missing = PETSC_TRUE;
179309f38230SBarry Smith         if (d) *d = i;
1794994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1795358d2f5dSShri Abhyankar         break;
179609f38230SBarry Smith       }
1797be5855fcSBarry Smith     }
1798be5855fcSBarry Smith   }
1799be5855fcSBarry Smith   PetscFunctionReturn(0);
1800be5855fcSBarry Smith }
1801be5855fcSBarry Smith 
18020da83c2eSBarry Smith #include <petscblaslapack.h>
18030da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18040da83c2eSBarry Smith 
18050da83c2eSBarry Smith /*
18060da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18070da83c2eSBarry Smith */
18080da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18090da83c2eSBarry Smith {
18100da83c2eSBarry Smith   PetscErrorCode  ierr;
18110da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18120da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18130da83c2eSBarry Smith   const PetscReal shift = 0.0;
18140da83c2eSBarry Smith   PetscInt        ipvt[5];
18150da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18160da83c2eSBarry Smith 
18170da83c2eSBarry Smith   PetscFunctionBegin;
18180da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18190da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18200da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18210da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18220da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18230da83c2eSBarry Smith   }
18240da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18250da83c2eSBarry Smith   if (bsizemax > 7) {
18260da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18270da83c2eSBarry Smith   }
18280da83c2eSBarry Smith   ncnt = 0;
18290da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18300da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18310da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18320da83c2eSBarry Smith     switch (bsizes[i]) {
18330da83c2eSBarry Smith     case 1:
18340da83c2eSBarry Smith       *diag = 1.0/(*diag);
18350da83c2eSBarry Smith       break;
18360da83c2eSBarry Smith     case 2:
18370da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18380da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18390da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18400da83c2eSBarry Smith       break;
18410da83c2eSBarry Smith     case 3:
18420da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18430da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18440da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18450da83c2eSBarry Smith       break;
18460da83c2eSBarry Smith     case 4:
18470da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18480da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18490da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18500da83c2eSBarry Smith       break;
18510da83c2eSBarry Smith     case 5:
18520da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18530da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18540da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18550da83c2eSBarry Smith       break;
18560da83c2eSBarry Smith     case 6:
18570da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18580da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18590da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
18600da83c2eSBarry Smith       break;
18610da83c2eSBarry Smith     case 7:
18620da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18630da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18640da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
18650da83c2eSBarry Smith       break;
18660da83c2eSBarry Smith     default:
18670da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18680da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18690da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
18700da83c2eSBarry Smith     }
18710da83c2eSBarry Smith     ncnt   += bsizes[i];
18720da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
18730da83c2eSBarry Smith   }
18740da83c2eSBarry Smith   if (bsizemax > 7) {
18750da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
18760da83c2eSBarry Smith   }
18770da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
18780da83c2eSBarry Smith   PetscFunctionReturn(0);
18790da83c2eSBarry Smith }
18800da83c2eSBarry Smith 
1881422a814eSBarry Smith /*
1882422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1883422a814eSBarry Smith */
18847087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
188571f1c65dSBarry Smith {
188671f1c65dSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
188771f1c65dSBarry Smith   PetscErrorCode ierr;
1888d0f46423SBarry Smith   PetscInt       i,*diag,m = A->rmap->n;
188954f21887SBarry Smith   MatScalar      *v = a->a;
189054f21887SBarry Smith   PetscScalar    *idiag,*mdiag;
189171f1c65dSBarry Smith 
189271f1c65dSBarry Smith   PetscFunctionBegin;
189371f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
189471f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
189571f1c65dSBarry Smith   diag = a->diag;
189671f1c65dSBarry Smith   if (!a->idiag) {
1897dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
18983bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
189971f1c65dSBarry Smith     v    = a->a;
190071f1c65dSBarry Smith   }
190171f1c65dSBarry Smith   mdiag = a->mdiag;
190271f1c65dSBarry Smith   idiag = a->idiag;
190371f1c65dSBarry Smith 
1904422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
190571f1c65dSBarry Smith     for (i=0; i<m; i++) {
190671f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1907899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1908899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1909899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19107b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19117b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19127b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1913a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1914899639b0SHong Zhang       }
191571f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
191671f1c65dSBarry Smith     }
191771f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
191871f1c65dSBarry Smith   } else {
191971f1c65dSBarry Smith     for (i=0; i<m; i++) {
192071f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
192171f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
192271f1c65dSBarry Smith     }
1923dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
192471f1c65dSBarry Smith   }
192571f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
192671f1c65dSBarry Smith   PetscFunctionReturn(0);
192771f1c65dSBarry Smith }
192871f1c65dSBarry Smith 
1929c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
193041f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
193117ab2063SBarry Smith {
1932416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1933e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
1934f4259b30SLisandro Dalcin   const MatScalar   *v,*idiag=NULL,*mdiag;
193554f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1936dfbe8321SBarry Smith   PetscErrorCode    ierr;
19373d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
193897f1f81fSBarry Smith   const PetscInt    *idx,*diag;
193917ab2063SBarry Smith 
19403a40ed3dSBarry Smith   PetscFunctionBegin;
1941b965ef7fSBarry Smith   its = its*lits;
194291723122SBarry Smith 
194371f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
194471f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
194571f1c65dSBarry Smith   a->fshift = fshift;
194671f1c65dSBarry Smith   a->omega  = omega;
1947ed480e8bSBarry Smith 
194871f1c65dSBarry Smith   diag  = a->diag;
194971f1c65dSBarry Smith   t     = a->ssor_work;
1950ed480e8bSBarry Smith   idiag = a->idiag;
195171f1c65dSBarry Smith   mdiag = a->mdiag;
1952ed480e8bSBarry Smith 
19531ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
19543649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1955ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
195617ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
195717ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1958ed480e8bSBarry Smith     bs = b;
195917ab2063SBarry Smith     for (i=0; i<m; i++) {
196071f1c65dSBarry Smith       d   = fshift + mdiag[i];
1961416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1962ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1963ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
196417ab2063SBarry Smith       sum = b[i]*d/omega;
1965003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
196617ab2063SBarry Smith       x[i] = sum;
196717ab2063SBarry Smith     }
19681ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
19693649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1970efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
19713a40ed3dSBarry Smith     PetscFunctionReturn(0);
197217ab2063SBarry Smith   }
1973c783ea89SBarry Smith 
19742205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
19752205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
19764c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1977887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
197817ab2063SBarry Smith 
197917ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
198017ab2063SBarry Smith 
1981887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
198217ab2063SBarry Smith     */
198317ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
198417ab2063SBarry Smith 
198517ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
198617ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
1987416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1988ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1989ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
199017ab2063SBarry Smith       sum = b[i];
1991e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1992ed480e8bSBarry Smith       x[i] = sum*idiag[i];
199317ab2063SBarry Smith     }
199417ab2063SBarry Smith 
199517ab2063SBarry Smith     /*  t = b - (2*E - D)x */
1996416022c9SBarry Smith     v = a->a;
19972205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
199817ab2063SBarry Smith 
199917ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2000ed480e8bSBarry Smith     ts   = t;
2001416022c9SBarry Smith     diag = a->diag;
200217ab2063SBarry Smith     for (i=0; i<m; i++) {
2003416022c9SBarry Smith       n   = diag[i] - a->i[i];
2004ed480e8bSBarry Smith       idx = a->j + a->i[i];
2005ed480e8bSBarry Smith       v   = a->a + a->i[i];
200617ab2063SBarry Smith       sum = t[i];
2007003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2008ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2009733d66baSBarry Smith       /*  x = x + t */
2010733d66baSBarry Smith       x[i] += t[i];
201117ab2063SBarry Smith     }
201217ab2063SBarry Smith 
2013dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20141ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20153649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20163a40ed3dSBarry Smith     PetscFunctionReturn(0);
201717ab2063SBarry Smith   }
201817ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
201917ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
202017ab2063SBarry Smith       for (i=0; i<m; i++) {
2021416022c9SBarry Smith         n   = diag[i] - a->i[i];
2022ed480e8bSBarry Smith         idx = a->j + a->i[i];
2023ed480e8bSBarry Smith         v   = a->a + a->i[i];
202417ab2063SBarry Smith         sum = b[i];
2025e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20265c99c7daSBarry Smith         t[i] = sum;
2027ed480e8bSBarry Smith         x[i] = sum*idiag[i];
202817ab2063SBarry Smith       }
20295c99c7daSBarry Smith       xb   = t;
2030efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20313a40ed3dSBarry Smith     } else xb = b;
203217ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
203317ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2034416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2035ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
2036ed480e8bSBarry Smith         v   = a->a + diag[i] + 1;
203717ab2063SBarry Smith         sum = xb[i];
2038e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20395c99c7daSBarry Smith         if (xb == b) {
2040ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20415c99c7daSBarry Smith         } else {
2042b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
204317ab2063SBarry Smith         }
20445c99c7daSBarry Smith       }
2045b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
204617ab2063SBarry Smith     }
204717ab2063SBarry Smith     its--;
204817ab2063SBarry Smith   }
204917ab2063SBarry Smith   while (its--) {
205017ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
205117ab2063SBarry Smith       for (i=0; i<m; i++) {
2052b19a5dc2SMark Adams         /* lower */
2053b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2054ed480e8bSBarry Smith         idx = a->j + a->i[i];
2055ed480e8bSBarry Smith         v   = a->a + a->i[i];
205617ab2063SBarry Smith         sum = b[i];
2057e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2058b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2059b19a5dc2SMark Adams         /* upper */
2060b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2061b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
2062b19a5dc2SMark Adams         v   = a->a + diag[i] + 1;
2063b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2064b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
206517ab2063SBarry Smith       }
2066b19a5dc2SMark Adams       xb   = t;
20679f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2068b19a5dc2SMark Adams     } else xb = b;
206917ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
207017ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2071b19a5dc2SMark Adams         sum = xb[i];
2072b19a5dc2SMark Adams         if (xb == b) {
2073b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2074416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2075ed480e8bSBarry Smith           idx = a->j + a->i[i];
2076ed480e8bSBarry Smith           v   = a->a + a->i[i];
2077e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2078ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2079b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2080b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2081b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
2082b19a5dc2SMark Adams           v   = a->a + diag[i] + 1;
2083b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2084b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
208517ab2063SBarry Smith         }
2086b19a5dc2SMark Adams       }
2087b19a5dc2SMark Adams       if (xb == b) {
20889f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2089b19a5dc2SMark Adams       } else {
2090b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2091b19a5dc2SMark Adams       }
209217ab2063SBarry Smith     }
209317ab2063SBarry Smith   }
20941ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20953649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2096365a8a9eSBarry Smith   PetscFunctionReturn(0);
209717ab2063SBarry Smith }
209817ab2063SBarry Smith 
20992af78befSBarry Smith 
2100dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
210117ab2063SBarry Smith {
2102416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21034e220ebcSLois Curfman McInnes 
21043a40ed3dSBarry Smith   PetscFunctionBegin;
21054e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21063966268fSBarry Smith   info->nz_allocated = a->maxnz;
21073966268fSBarry Smith   info->nz_used      = a->nz;
21083966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21093966268fSBarry Smith   info->assemblies   = A->num_ass;
21103966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21117adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2112d5f3da31SBarry Smith   if (A->factortype) {
21134e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21144e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21154e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21164e220ebcSLois Curfman McInnes   } else {
21174e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21184e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21194e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21204e220ebcSLois Curfman McInnes   }
21213a40ed3dSBarry Smith   PetscFunctionReturn(0);
212217ab2063SBarry Smith }
212317ab2063SBarry Smith 
21242b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
212517ab2063SBarry Smith {
2126416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2127c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21286849ba73SBarry Smith   PetscErrorCode    ierr;
212997b48c8fSBarry Smith   const PetscScalar *xx;
213097b48c8fSBarry Smith   PetscScalar       *bb;
2131c7da8527SEric Chamberland   PetscInt          d = 0;
213217ab2063SBarry Smith 
21333a40ed3dSBarry Smith   PetscFunctionBegin;
213497b48c8fSBarry Smith   if (x && b) {
213597b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
213697b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
213797b48c8fSBarry Smith     for (i=0; i<N; i++) {
213897b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2139447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
214097b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
214197b48c8fSBarry Smith     }
214297b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
214397b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
214497b48c8fSBarry Smith   }
214597b48c8fSBarry Smith 
2146a9817697SBarry Smith   if (a->keepnonzeropattern) {
2147f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2148e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2149580bdb30SBarry Smith       ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2150f1e2ffcdSBarry Smith     }
2151f4df32b1SMatthew Knepley     if (diag != 0.0) {
2152c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2153c7da8527SEric Chamberland         d = rows[i];
2154447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2155c7da8527SEric 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);
2156c7da8527SEric Chamberland       }
2157f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2158447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2159f4df32b1SMatthew Knepley         a->a[a->diag[rows[i]]] = diag;
2160f1e2ffcdSBarry Smith       }
2161f1e2ffcdSBarry Smith     }
2162f1e2ffcdSBarry Smith   } else {
2163f4df32b1SMatthew Knepley     if (diag != 0.0) {
216417ab2063SBarry Smith       for (i=0; i<N; i++) {
2165e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
21667ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2167447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2168447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2169447d62f5SStefano Zampini           } else {
2170416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
2171f4df32b1SMatthew Knepley             a->a[a->i[rows[i]]] = diag;
2172bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2173447d62f5SStefano Zampini           }
2174447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2175f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
217617ab2063SBarry Smith         }
217717ab2063SBarry Smith       }
21783a40ed3dSBarry Smith     } else {
217917ab2063SBarry Smith       for (i=0; i<N; i++) {
2180e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2181416022c9SBarry Smith         a->ilen[rows[i]] = 0;
218217ab2063SBarry Smith       }
218317ab2063SBarry Smith     }
2184e56f5c9eSBarry Smith     A->nonzerostate++;
2185f1e2ffcdSBarry Smith   }
2186e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2187c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2188e2cf4d64SStefano Zampini #endif
21894099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21903a40ed3dSBarry Smith   PetscFunctionReturn(0);
219117ab2063SBarry Smith }
219217ab2063SBarry Smith 
21936e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
21946e169961SBarry Smith {
21956e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
21966e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
21976e169961SBarry Smith   PetscErrorCode    ierr;
21982b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
21996e169961SBarry Smith   const PetscScalar *xx;
22006e169961SBarry Smith   PetscScalar       *bb;
22016e169961SBarry Smith 
22026e169961SBarry Smith   PetscFunctionBegin;
22036e169961SBarry Smith   if (x && b) {
22046e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22056e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22062b40b63fSBarry Smith     vecs = PETSC_TRUE;
22076e169961SBarry Smith   }
22081795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22096e169961SBarry Smith   for (i=0; i<N; i++) {
22106e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2211580bdb30SBarry Smith     ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22122205254eSKarl Rupp 
22136e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22146e169961SBarry Smith   }
22156e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22166e169961SBarry Smith     if (!zeroed[i]) {
22176e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22184cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22192b40b63fSBarry Smith           if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
22206e169961SBarry Smith           a->a[j] = 0.0;
22216e169961SBarry Smith         }
22226e169961SBarry Smith       }
22234cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22246e169961SBarry Smith   }
22256e169961SBarry Smith   if (x && b) {
22266e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22276e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22286e169961SBarry Smith   }
22296e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22306e169961SBarry Smith   if (diag != 0.0) {
22316e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22321d5a398dSstefano_zampini     if (missing) {
22331d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22344cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22354cf107fdSStefano 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]);
22361d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22371d5a398dSstefano_zampini       }
22381d5a398dSstefano_zampini     } else {
22396e169961SBarry Smith       for (i=0; i<N; i++) {
22406e169961SBarry Smith         a->a[a->diag[rows[i]]] = diag;
22416e169961SBarry Smith       }
22426e169961SBarry Smith     }
22431d5a398dSstefano_zampini   }
2244e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2245c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2246e2cf4d64SStefano Zampini #endif
22474099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22486e169961SBarry Smith   PetscFunctionReturn(0);
22496e169961SBarry Smith }
22506e169961SBarry Smith 
2251a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
225217ab2063SBarry Smith {
2253416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
225497f1f81fSBarry Smith   PetscInt   *itmp;
225517ab2063SBarry Smith 
22563a40ed3dSBarry Smith   PetscFunctionBegin;
2257e32f2f54SBarry Smith   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
225817ab2063SBarry Smith 
2259416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
2260bfeeae90SHong Zhang   if (v) *v = a->a + a->i[row];
226117ab2063SBarry Smith   if (idx) {
2262bfeeae90SHong Zhang     itmp = a->j + a->i[row];
226326fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2264f4259b30SLisandro Dalcin     else *idx = NULL;
226517ab2063SBarry Smith   }
22663a40ed3dSBarry Smith   PetscFunctionReturn(0);
226717ab2063SBarry Smith }
226817ab2063SBarry Smith 
2269bfeeae90SHong Zhang /* remove this function? */
2270a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
227117ab2063SBarry Smith {
22723a40ed3dSBarry Smith   PetscFunctionBegin;
22733a40ed3dSBarry Smith   PetscFunctionReturn(0);
227417ab2063SBarry Smith }
227517ab2063SBarry Smith 
2276dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
227717ab2063SBarry Smith {
2278416022c9SBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
227954f21887SBarry Smith   MatScalar      *v  = a->a;
228036db0b34SBarry Smith   PetscReal      sum = 0.0;
22816849ba73SBarry Smith   PetscErrorCode ierr;
228297f1f81fSBarry Smith   PetscInt       i,j;
228317ab2063SBarry Smith 
22843a40ed3dSBarry Smith   PetscFunctionBegin;
228517ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2286570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2287570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
2288570b7f6dSBarry Smith     *nrm = BLASnrm2_(&nz,v,&one);
2289570b7f6dSBarry Smith #else
2290416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
229136db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
229217ab2063SBarry Smith     }
22938f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2294570b7f6dSBarry Smith #endif
2295ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
22963a40ed3dSBarry Smith   } else if (type == NORM_1) {
229736db0b34SBarry Smith     PetscReal *tmp;
229897f1f81fSBarry Smith     PetscInt  *jj = a->j;
22991795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2300064f8208SBarry Smith     *nrm = 0.0;
2301416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2302bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
230317ab2063SBarry Smith     }
2304d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2305064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
230617ab2063SBarry Smith     }
2307606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
230851f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23093a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2310064f8208SBarry Smith     *nrm = 0.0;
2311d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
2312bfeeae90SHong Zhang       v   = a->a + a->i[j];
231317ab2063SBarry Smith       sum = 0.0;
2314416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
2315cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
231617ab2063SBarry Smith       }
2317064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
231817ab2063SBarry Smith     }
231951f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2320f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23213a40ed3dSBarry Smith   PetscFunctionReturn(0);
232217ab2063SBarry Smith }
232317ab2063SBarry Smith 
23244e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23254e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23264e938277SHong Zhang {
23274e938277SHong Zhang   PetscErrorCode ierr;
23284e938277SHong Zhang   PetscInt       i,j,anzj;
23294e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23304e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23314e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23324e938277SHong Zhang 
23334e938277SHong Zhang   PetscFunctionBegin;
23344e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2335854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2336785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2337785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
23384e938277SHong Zhang 
23394e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23404e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
234126fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
23424e938277SHong Zhang   /* Form ati for csr format of A^T. */
234326fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
23444e938277SHong Zhang 
23454e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2346580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
23474e938277SHong Zhang 
23484e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
23494e938277SHong Zhang   for (i=0;i<am;i++) {
23504e938277SHong Zhang     anzj = ai[i+1] - ai[i];
23514e938277SHong Zhang     for (j=0;j<anzj;j++) {
23524e938277SHong Zhang       atj[atfill[*aj]] = i;
23534e938277SHong Zhang       atfill[*aj++]   += 1;
23544e938277SHong Zhang     }
23554e938277SHong Zhang   }
23564e938277SHong Zhang 
23574e938277SHong Zhang   /* Clean up temporary space and complete requests. */
23584e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2359ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
236033d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2361b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2362a2f3521dSMark F. Adams 
23634e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
23644e938277SHong Zhang   b->free_a  = PETSC_FALSE;
23654e938277SHong Zhang   b->free_ij = PETSC_TRUE;
23664e938277SHong Zhang   b->nonew   = 0;
23674e938277SHong Zhang   PetscFunctionReturn(0);
23684e938277SHong Zhang }
23694e938277SHong Zhang 
23707087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2371cd0d46ebSvictorle {
23723d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
237354f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
237454f21887SBarry Smith   MatScalar      *va,*vb;
23756849ba73SBarry Smith   PetscErrorCode ierr;
237697f1f81fSBarry Smith   PetscInt       ma,na,mb,nb, i;
2377cd0d46ebSvictorle 
2378cd0d46ebSvictorle   PetscFunctionBegin;
2379cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2380cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
23815485867bSBarry Smith   if (ma!=nb || na!=mb) {
23825485867bSBarry Smith     *f = PETSC_FALSE;
23835485867bSBarry Smith     PetscFunctionReturn(0);
23845485867bSBarry Smith   }
2385cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2386cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2387cd0d46ebSvictorle   va   = aij->a; vb = bij->a;
2388785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2389785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2390cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2391cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2392cd0d46ebSvictorle 
2393cd0d46ebSvictorle   *f = PETSC_TRUE;
2394cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2395cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
239697f1f81fSBarry Smith       PetscInt    idc,idr;
23975485867bSBarry Smith       PetscScalar vc,vr;
2398cd0d46ebSvictorle       /* column/row index/value */
23995485867bSBarry Smith       idc = adx[aptr[i]];
24005485867bSBarry Smith       idr = bdx[bptr[idc]];
24015485867bSBarry Smith       vc  = va[aptr[i]];
24025485867bSBarry Smith       vr  = vb[bptr[idc]];
24035485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24045485867bSBarry Smith         *f = PETSC_FALSE;
24055485867bSBarry Smith         goto done;
2406cd0d46ebSvictorle       } else {
24075485867bSBarry Smith         aptr[i]++;
24085485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2409cd0d46ebSvictorle       }
2410cd0d46ebSvictorle     }
2411cd0d46ebSvictorle   }
2412cd0d46ebSvictorle done:
2413cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24143aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
2415cd0d46ebSvictorle   PetscFunctionReturn(0);
2416cd0d46ebSvictorle }
2417cd0d46ebSvictorle 
24187087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24191cbb95d3SBarry Smith {
24203d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
242154f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
242254f21887SBarry Smith   MatScalar      *va,*vb;
24231cbb95d3SBarry Smith   PetscErrorCode ierr;
24241cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24251cbb95d3SBarry Smith 
24261cbb95d3SBarry Smith   PetscFunctionBegin;
24271cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
24281cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24291cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24301cbb95d3SBarry Smith     *f = PETSC_FALSE;
24311cbb95d3SBarry Smith     PetscFunctionReturn(0);
24321cbb95d3SBarry Smith   }
24331cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24341cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24351cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2436785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2437785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
24381cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
24391cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
24401cbb95d3SBarry Smith 
24411cbb95d3SBarry Smith   *f = PETSC_TRUE;
24421cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
24431cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
24441cbb95d3SBarry Smith       PetscInt    idc,idr;
24451cbb95d3SBarry Smith       PetscScalar vc,vr;
24461cbb95d3SBarry Smith       /* column/row index/value */
24471cbb95d3SBarry Smith       idc = adx[aptr[i]];
24481cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
24491cbb95d3SBarry Smith       vc  = va[aptr[i]];
24501cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
24511cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
24521cbb95d3SBarry Smith         *f = PETSC_FALSE;
24531cbb95d3SBarry Smith         goto done;
24541cbb95d3SBarry Smith       } else {
24551cbb95d3SBarry Smith         aptr[i]++;
24561cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
24571cbb95d3SBarry Smith       }
24581cbb95d3SBarry Smith     }
24591cbb95d3SBarry Smith   }
24601cbb95d3SBarry Smith done:
24611cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
24621cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
24631cbb95d3SBarry Smith   PetscFunctionReturn(0);
24641cbb95d3SBarry Smith }
24651cbb95d3SBarry Smith 
2466ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24679e29f15eSvictorle {
2468dfbe8321SBarry Smith   PetscErrorCode ierr;
24696e111a19SKarl Rupp 
24709e29f15eSvictorle   PetscFunctionBegin;
24715485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
24729e29f15eSvictorle   PetscFunctionReturn(0);
24739e29f15eSvictorle }
24749e29f15eSvictorle 
2475ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24761cbb95d3SBarry Smith {
24771cbb95d3SBarry Smith   PetscErrorCode ierr;
24786e111a19SKarl Rupp 
24791cbb95d3SBarry Smith   PetscFunctionBegin;
24801cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
24811cbb95d3SBarry Smith   PetscFunctionReturn(0);
24821cbb95d3SBarry Smith }
24831cbb95d3SBarry Smith 
2484dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
248517ab2063SBarry Smith {
2486416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2487fff8e43fSBarry Smith   const PetscScalar *l,*r;
2488fff8e43fSBarry Smith   PetscScalar       x;
248954f21887SBarry Smith   MatScalar         *v;
2490dfbe8321SBarry Smith   PetscErrorCode    ierr;
2491fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2492fff8e43fSBarry Smith   const PetscInt    *jj;
249317ab2063SBarry Smith 
24943a40ed3dSBarry Smith   PetscFunctionBegin;
249517ab2063SBarry Smith   if (ll) {
24963ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
24973ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2498e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2499e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2500fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
2501416022c9SBarry Smith     v    = a->a;
250217ab2063SBarry Smith     for (i=0; i<m; i++) {
250317ab2063SBarry Smith       x = l[i];
2504416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25052205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
250617ab2063SBarry Smith     }
2507fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2508efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
250917ab2063SBarry Smith   }
251017ab2063SBarry Smith   if (rr) {
2511e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2512e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2513fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
2514416022c9SBarry Smith     v    = a->a; jj = a->j;
25152205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
2516fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2517efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
251817ab2063SBarry Smith   }
2519acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
2520e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2521c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2522e2cf4d64SStefano Zampini #endif
25233a40ed3dSBarry Smith   PetscFunctionReturn(0);
252417ab2063SBarry Smith }
252517ab2063SBarry Smith 
25267dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
252717ab2063SBarry Smith {
2528db02288aSLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
25296849ba73SBarry Smith   PetscErrorCode ierr;
2530d0f46423SBarry Smith   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
253197f1f81fSBarry Smith   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25325d0c19d7SBarry Smith   const PetscInt *irow,*icol;
25335d0c19d7SBarry Smith   PetscInt       nrows,ncols;
253497f1f81fSBarry Smith   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
253554f21887SBarry Smith   MatScalar      *a_new,*mat_a;
2536416022c9SBarry Smith   Mat            C;
2537cdc6f3adSToby Isaac   PetscBool      stride;
253817ab2063SBarry Smith 
25393a40ed3dSBarry Smith   PetscFunctionBegin;
254099141d43SSatish Balay 
254117ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2542b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2543b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
254417ab2063SBarry Smith 
2545251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2546ff718158SBarry Smith   if (stride) {
2547ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2548ff718158SBarry Smith   } else {
2549ff718158SBarry Smith     first = 0;
2550ff718158SBarry Smith     step  = 0;
2551ff718158SBarry Smith   }
2552fee21e36SBarry Smith   if (stride && step == 1) {
255302834360SBarry Smith     /* special case of contiguous rows */
2554dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
255502834360SBarry Smith     /* loop over new rows determining lens and starting points */
255602834360SBarry Smith     for (i=0; i<nrows; i++) {
2557bfeeae90SHong Zhang       kstart = ai[irow[i]];
2558a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2559a91a9bebSLisandro Dalcin       starts[i] = kstart;
256002834360SBarry Smith       for (k=kstart; k<kend; k++) {
2561bfeeae90SHong Zhang         if (aj[k] >= first) {
256202834360SBarry Smith           starts[i] = k;
256302834360SBarry Smith           break;
256402834360SBarry Smith         }
256502834360SBarry Smith       }
2566a2744918SBarry Smith       sum = 0;
256702834360SBarry Smith       while (k < kend) {
2568bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2569a2744918SBarry Smith         sum++;
257002834360SBarry Smith       }
2571a2744918SBarry Smith       lens[i] = sum;
257202834360SBarry Smith     }
257302834360SBarry Smith     /* create submatrix */
2574cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
257597f1f81fSBarry Smith       PetscInt n_cols,n_rows;
257608480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2577e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2578d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
257908480c60SBarry Smith       C    = *B;
25803a40ed3dSBarry Smith     } else {
25813bef6203SJed Brown       PetscInt rbs,cbs;
2582ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2583f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
25843bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
25853bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
25863bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
25877adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2588ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
258908480c60SBarry Smith     }
2590db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2591db02288aSLois Curfman McInnes 
259202834360SBarry Smith     /* loop over rows inserting into submatrix */
2593db02288aSLois Curfman McInnes     a_new = c->a;
2594db02288aSLois Curfman McInnes     j_new = c->j;
2595db02288aSLois Curfman McInnes     i_new = c->i;
2596bfeeae90SHong Zhang 
259702834360SBarry Smith     for (i=0; i<nrows; i++) {
2598a2744918SBarry Smith       ii    = starts[i];
2599a2744918SBarry Smith       lensi = lens[i];
2600a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2601a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
260202834360SBarry Smith       }
2603580bdb30SBarry Smith       ierr       = PetscArraycpy(a_new,a->a + starts[i],lensi);CHKERRQ(ierr);
2604a2744918SBarry Smith       a_new     += lensi;
2605a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2606a2744918SBarry Smith       c->ilen[i] = lensi;
260702834360SBarry Smith     }
26080e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26093a40ed3dSBarry Smith   } else {
261002834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26111795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2612854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26134dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2614d9ef940eSSatish 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);
26154dcab191SBarry Smith       smap[icol[i]] = i+1;
26164dcab191SBarry Smith     }
26174dcab191SBarry Smith 
261802834360SBarry Smith     /* determine lens of each row */
261902834360SBarry Smith     for (i=0; i<nrows; i++) {
2620bfeeae90SHong Zhang       kstart  = ai[irow[i]];
262102834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
262202834360SBarry Smith       lens[i] = 0;
262302834360SBarry Smith       for (k=kstart; k<kend; k++) {
2624bfeeae90SHong Zhang         if (smap[aj[k]]) {
262502834360SBarry Smith           lens[i]++;
262602834360SBarry Smith         }
262702834360SBarry Smith       }
262802834360SBarry Smith     }
262917ab2063SBarry Smith     /* Create and fill new matrix */
2630a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2631ace3abfcSBarry Smith       PetscBool equal;
26320f5bd95cSBarry Smith 
263399141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2634e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2635580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2636f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2637580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
263808480c60SBarry Smith       C    = *B;
26393a40ed3dSBarry Smith     } else {
26403bef6203SJed Brown       PetscInt rbs,cbs;
2641ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2642f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26433bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26443bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26453bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26467adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2647ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
264808480c60SBarry Smith     }
264999141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
265017ab2063SBarry Smith     for (i=0; i<nrows; i++) {
265199141d43SSatish Balay       row      = irow[i];
2652bfeeae90SHong Zhang       kstart   = ai[row];
265399141d43SSatish Balay       kend     = kstart + a->ilen[row];
2654bfeeae90SHong Zhang       mat_i    = c->i[i];
265599141d43SSatish Balay       mat_j    = c->j + mat_i;
265699141d43SSatish Balay       mat_a    = c->a + mat_i;
265799141d43SSatish Balay       mat_ilen = c->ilen + i;
265817ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2659bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2660ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
266199141d43SSatish Balay           *mat_a++ = a->a[k];
266299141d43SSatish Balay           (*mat_ilen)++;
266399141d43SSatish Balay 
266417ab2063SBarry Smith         }
266517ab2063SBarry Smith       }
266617ab2063SBarry Smith     }
266702834360SBarry Smith     /* Free work space */
266802834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2669606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2670606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2671cdc6f3adSToby Isaac     /* sort */
2672cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2673cdc6f3adSToby Isaac       PetscInt ilen;
2674cdc6f3adSToby Isaac 
2675cdc6f3adSToby Isaac       mat_i = c->i[i];
2676cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2677cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2678cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2679390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2680cdc6f3adSToby Isaac     }
268102834360SBarry Smith   }
2682305c6ccfSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2683b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2684305c6ccfSStefano Zampini #endif
26856d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
26866d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
268717ab2063SBarry Smith 
268817ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2689416022c9SBarry Smith   *B   = C;
26903a40ed3dSBarry Smith   PetscFunctionReturn(0);
269117ab2063SBarry Smith }
269217ab2063SBarry Smith 
2693fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
269482d44351SHong Zhang {
269582d44351SHong Zhang   PetscErrorCode ierr;
269682d44351SHong Zhang   Mat            B;
269782d44351SHong Zhang 
269882d44351SHong Zhang   PetscFunctionBegin;
2699c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
270082d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
270182d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
270233d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
270382d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
270482d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
270582d44351SHong Zhang     *subMat = B;
2706c2d650bdSHong Zhang   } else {
2707c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2708c2d650bdSHong Zhang   }
270982d44351SHong Zhang   PetscFunctionReturn(0);
271082d44351SHong Zhang }
271182d44351SHong Zhang 
27129a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2713a871dcd8SBarry Smith {
271463b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2715dfbe8321SBarry Smith   PetscErrorCode ierr;
271663b91edcSBarry Smith   Mat            outA;
2717ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
271863b91edcSBarry Smith 
27193a40ed3dSBarry Smith   PetscFunctionBegin;
2720e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27211df811f5SHong Zhang 
2722b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2723b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2724a871dcd8SBarry Smith 
272563b91edcSBarry Smith   outA             = inA;
2726d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2727f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2728f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
27292205254eSKarl Rupp 
2730c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
27316bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
27322205254eSKarl Rupp 
2733c3122656SLisandro Dalcin   a->row = row;
27342205254eSKarl Rupp 
2735c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
27366bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
27372205254eSKarl Rupp 
2738c3122656SLisandro Dalcin   a->col = col;
273963b91edcSBarry Smith 
274036db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
27416bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
27424c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
27433bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2744f0ec6fceSSatish Balay 
274594a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2746854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
27473bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
274894a9d846SBarry Smith   }
274963b91edcSBarry Smith 
2750f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2751137fb511SHong Zhang   if (row_identity && col_identity) {
2752ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2753137fb511SHong Zhang   } else {
2754719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2755137fb511SHong Zhang   }
27563a40ed3dSBarry Smith   PetscFunctionReturn(0);
2757a871dcd8SBarry Smith }
2758a871dcd8SBarry Smith 
2759f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2760f0b747eeSBarry Smith {
2761f0b747eeSBarry Smith   Mat_SeqAIJ     *a     = (Mat_SeqAIJ*)inA->data;
2762f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
2763efee365bSSatish Balay   PetscErrorCode ierr;
2764c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
27653a40ed3dSBarry Smith 
27663a40ed3dSBarry Smith   PetscFunctionBegin;
2767c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
27688b83055fSJed Brown   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one));
2769efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2770acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
2771e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2772c70f7ee4SJunchao Zhang   if (inA->offloadmask != PETSC_OFFLOAD_UNALLOCATED) inA->offloadmask = PETSC_OFFLOAD_CPU;
2773e2cf4d64SStefano Zampini #endif
27743a40ed3dSBarry Smith   PetscFunctionReturn(0);
2775f0b747eeSBarry Smith }
2776f0b747eeSBarry Smith 
2777f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
277816b64355SHong Zhang {
277916b64355SHong Zhang   PetscErrorCode ierr;
278016b64355SHong Zhang   PetscInt       i;
278116b64355SHong Zhang 
278216b64355SHong Zhang   PetscFunctionBegin;
278316b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
278416b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
278516b64355SHong Zhang 
278616b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
278716b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
278816b64355SHong Zhang     }
278916b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
279016b64355SHong Zhang 
279116b64355SHong Zhang     if (submatj->rbuf1) {
279216b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
279316b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
279416b64355SHong Zhang     }
279516b64355SHong Zhang 
279616b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
279716b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
279816b64355SHong Zhang     }
279916b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
280016b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
280116b64355SHong Zhang   }
280216b64355SHong Zhang 
280316b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
280416b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
280516b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
280616b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
280716b64355SHong Zhang #else
280816b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
280916b64355SHong Zhang #endif
281016b64355SHong Zhang 
281116b64355SHong Zhang   if (!submatj->allcolumns) {
281216b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
281316b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
281416b64355SHong Zhang #else
281516b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
281616b64355SHong Zhang #endif
281716b64355SHong Zhang   }
281816b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
281916b64355SHong Zhang 
282016b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
282116b64355SHong Zhang   PetscFunctionReturn(0);
282216b64355SHong Zhang }
282316b64355SHong Zhang 
28240fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
282516b64355SHong Zhang {
282616b64355SHong Zhang   PetscErrorCode ierr;
282716b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28285c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
282916b64355SHong Zhang 
283016b64355SHong Zhang   PetscFunctionBegin;
283134136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2832f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
283316b64355SHong Zhang   PetscFunctionReturn(0);
283416b64355SHong Zhang }
283516b64355SHong Zhang 
28362d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
28372d033e1fSHong Zhang {
28382d033e1fSHong Zhang   PetscErrorCode ierr;
28392d033e1fSHong Zhang   PetscInt       i;
28400fb991dcSHong Zhang   Mat            C;
28410fb991dcSHong Zhang   Mat_SeqAIJ     *c;
28420fb991dcSHong Zhang   Mat_SubSppt    *submatj;
28432d033e1fSHong Zhang 
28442d033e1fSHong Zhang   PetscFunctionBegin;
28452d033e1fSHong Zhang   for (i=0; i<n; i++) {
28460fb991dcSHong Zhang     C       = (*mat)[i];
28470fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
28480fb991dcSHong Zhang     submatj = c->submatis1;
28492d033e1fSHong Zhang     if (submatj) {
2850682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
285134136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2852f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
285334136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
28542d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
28552d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
28562d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2857682e4c99SStefano Zampini       }
28582d033e1fSHong Zhang     } else {
28592d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
28602d033e1fSHong Zhang     }
28612d033e1fSHong Zhang   }
286286e85357SHong Zhang 
286363a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
286463a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
286563a75b2aSHong Zhang 
28662d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
28672d033e1fSHong Zhang   PetscFunctionReturn(0);
28682d033e1fSHong Zhang }
28692d033e1fSHong Zhang 
28707dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2871cddf8d76SBarry Smith {
2872dfbe8321SBarry Smith   PetscErrorCode ierr;
287397f1f81fSBarry Smith   PetscInt       i;
2874cddf8d76SBarry Smith 
28753a40ed3dSBarry Smith   PetscFunctionBegin;
2876cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2877df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2878cddf8d76SBarry Smith   }
2879cddf8d76SBarry Smith 
2880cddf8d76SBarry Smith   for (i=0; i<n; i++) {
28817dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2882cddf8d76SBarry Smith   }
28833a40ed3dSBarry Smith   PetscFunctionReturn(0);
2884cddf8d76SBarry Smith }
2885cddf8d76SBarry Smith 
288697f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
28874dcbc457SBarry Smith {
2888e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
28896849ba73SBarry Smith   PetscErrorCode ierr;
28905d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
28915d0c19d7SBarry Smith   const PetscInt *idx;
289297f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2893f1af5d2fSBarry Smith   PetscBT        table;
2894bbd702dbSSatish Balay 
28953a40ed3dSBarry Smith   PetscFunctionBegin;
2896d0f46423SBarry Smith   m  = A->rmap->n;
2897e4d965acSSatish Balay   ai = a->i;
2898bfeeae90SHong Zhang   aj = a->j;
28998a047759SSatish Balay 
2900e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
290106763907SSatish Balay 
2902854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
290353b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
290406763907SSatish Balay 
2905e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2906b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2907e4d965acSSatish Balay     isz  = 0;
29086831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2909e4d965acSSatish Balay 
2910e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29114dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2912b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2913e4d965acSSatish Balay 
2914dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2915e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29162205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29174dcbc457SBarry Smith     }
291806763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
29196bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2920e4d965acSSatish Balay 
292104a348a9SBarry Smith     k = 0;
292204a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
292304a348a9SBarry Smith       n = isz;
292406763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2925e4d965acSSatish Balay         row   = nidx[k];
2926e4d965acSSatish Balay         start = ai[row];
2927e4d965acSSatish Balay         end   = ai[row+1];
292804a348a9SBarry Smith         for (l = start; l<end; l++) {
2929efb16452SHong Zhang           val = aj[l];
29302205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2931e4d965acSSatish Balay         }
2932e4d965acSSatish Balay       }
2933e4d965acSSatish Balay     }
293470b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2935e4d965acSSatish Balay   }
293694bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2937606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
29383a40ed3dSBarry Smith   PetscFunctionReturn(0);
29394dcbc457SBarry Smith }
294017ab2063SBarry Smith 
29410513a670SBarry Smith /* -------------------------------------------------------------- */
2942dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
29430513a670SBarry Smith {
29440513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29456849ba73SBarry Smith   PetscErrorCode ierr;
29463b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
29475d0c19d7SBarry Smith   const PetscInt *row,*col;
29485d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
294956cd22aeSBarry Smith   IS             icolp,irowp;
29500298fd71SBarry Smith   PetscInt       *cwork = NULL;
29510298fd71SBarry Smith   PetscScalar    *vwork = NULL;
29520513a670SBarry Smith 
29533a40ed3dSBarry Smith   PetscFunctionBegin;
29544c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
295556cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
29564c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
295756cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
29580513a670SBarry Smith 
29590513a670SBarry Smith   /* determine lengths of permuted rows */
2960854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
29612205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
2962ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
2963f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
296433d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
29657adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2966ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2967606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
29680513a670SBarry Smith 
2969785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
29700513a670SBarry Smith   for (i=0; i<m; i++) {
297132ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
29722205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
2973cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
297432ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
29750513a670SBarry Smith   }
2976606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
29772205254eSKarl Rupp 
29783c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
29792205254eSKarl Rupp 
29809fe5e383SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2981b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
29829fe5e383SStefano Zampini #endif
29830513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29840513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
298556cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
298656cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
29876bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
29886bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
29896768869dSprj-   if (rowp == colp) {
29906768869dSprj-     if (A->symmetric) {
29916768869dSprj-       ierr = MatSetOption(*B,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
29926768869dSprj-     }
29936768869dSprj-     if (A->hermitian) {
29946768869dSprj-       ierr = MatSetOption(*B,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
29956768869dSprj-     }
29966768869dSprj-   }
29973a40ed3dSBarry Smith   PetscFunctionReturn(0);
29980513a670SBarry Smith }
29990513a670SBarry Smith 
3000dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3001cb5b572fSBarry Smith {
3002dfbe8321SBarry Smith   PetscErrorCode ierr;
3003cb5b572fSBarry Smith 
3004cb5b572fSBarry Smith   PetscFunctionBegin;
300533f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
300633f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3007be6bf707SBarry Smith     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
3008be6bf707SBarry Smith     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
3009be6bf707SBarry Smith 
30104d805d7cSStefano 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]);
3011580bdb30SBarry Smith     ierr = PetscArraycpy(b->a,a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
3012cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
3013cb5b572fSBarry Smith   } else {
3014cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3015cb5b572fSBarry Smith   }
3016cb5b572fSBarry Smith   PetscFunctionReturn(0);
3017cb5b572fSBarry Smith }
3018cb5b572fSBarry Smith 
30194994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3020273d9f13SBarry Smith {
3021dfbe8321SBarry Smith   PetscErrorCode ierr;
3022273d9f13SBarry Smith 
3023273d9f13SBarry Smith   PetscFunctionBegin;
3024f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3025273d9f13SBarry Smith   PetscFunctionReturn(0);
3026273d9f13SBarry Smith }
3027273d9f13SBarry Smith 
3028f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30296c0721eeSBarry Smith {
30306c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30316e111a19SKarl Rupp 
30326c0721eeSBarry Smith   PetscFunctionBegin;
30336c0721eeSBarry Smith   *array = a->a;
30346c0721eeSBarry Smith   PetscFunctionReturn(0);
30356c0721eeSBarry Smith }
30366c0721eeSBarry Smith 
3037f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
30386c0721eeSBarry Smith {
30396c0721eeSBarry Smith   PetscFunctionBegin;
3040f38c1e66SStefano Zampini   *array = NULL;
30416c0721eeSBarry Smith   PetscFunctionReturn(0);
30426c0721eeSBarry Smith }
3043273d9f13SBarry Smith 
30448229c054SShri Abhyankar /*
30458229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
30468229c054SShri Abhyankar    have different nonzero structure.
30478229c054SShri Abhyankar */
3048b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3049ec7775f6SShri Abhyankar {
3050b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3051ec7775f6SShri Abhyankar 
3052ec7775f6SShri Abhyankar   PetscFunctionBegin;
3053ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3054ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3055b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3056b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3057b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
30588af7cee1SJed Brown     nnz[i] = 0;
30598af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3060b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3061b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
30628af7cee1SJed Brown       nnz[i]++;
30638af7cee1SJed Brown     }
30648af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3065ec7775f6SShri Abhyankar   }
3066ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3067ec7775f6SShri Abhyankar }
3068ec7775f6SShri Abhyankar 
3069b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3070b264fe52SHong Zhang {
3071b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3072b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3073b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3074b264fe52SHong Zhang   PetscErrorCode ierr;
3075b264fe52SHong Zhang 
3076b264fe52SHong Zhang   PetscFunctionBegin;
3077b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3078b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3079b264fe52SHong Zhang   PetscFunctionReturn(0);
3080b264fe52SHong Zhang }
3081b264fe52SHong Zhang 
3082f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3083ac90fabeSBarry Smith {
3084dfbe8321SBarry Smith   PetscErrorCode ierr;
3085ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3086ac90fabeSBarry Smith 
3087ac90fabeSBarry Smith   PetscFunctionBegin;
308881fa06acSBarry Smith   if (str == DIFFERENT_NONZERO_PATTERN) {
308981fa06acSBarry Smith     if (x->nz == y->nz) {
309081fa06acSBarry Smith       PetscBool e;
309181fa06acSBarry Smith       ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
309281fa06acSBarry Smith       if (e) {
309381fa06acSBarry Smith         ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
309481fa06acSBarry Smith         if (e) {
309581fa06acSBarry Smith           str = SAME_NONZERO_PATTERN;
309681fa06acSBarry Smith         }
309781fa06acSBarry Smith       }
309881fa06acSBarry Smith     }
309981fa06acSBarry Smith   }
3100ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
3101f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
310281fa06acSBarry Smith     PetscBLASInt one = 1,bnz;
310381fa06acSBarry Smith 
310481fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31058b83055fSJed Brown     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one));
3106acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3107a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
310881fa06acSBarry Smith     /* the MatAXPY_Basic* subroutines calls MatAssembly, so the matrix on the GPU will be updated */
3109e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
3110c70f7ee4SJunchao Zhang     if (Y->offloadmask != PETSC_OFFLOAD_UNALLOCATED) {
3111c70f7ee4SJunchao Zhang       Y->offloadmask = PETSC_OFFLOAD_CPU;
3112e2cf4d64SStefano Zampini     }
3113e2cf4d64SStefano Zampini #endif
3114ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3115ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3116ac90fabeSBarry Smith   } else {
31178229c054SShri Abhyankar     Mat      B;
31188229c054SShri Abhyankar     PetscInt *nnz;
3119785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3120ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3121bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
312281fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
3123176df525SBarry Smith     ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr);
31248229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3125ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3126ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
312728be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
31288229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3129ac90fabeSBarry Smith   }
3130ac90fabeSBarry Smith   PetscFunctionReturn(0);
3131ac90fabeSBarry Smith }
3132ac90fabeSBarry Smith 
31337087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
3134354c94deSBarry Smith {
3135354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3136354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3137354c94deSBarry Smith   PetscInt    i,nz;
3138354c94deSBarry Smith   PetscScalar *a;
3139354c94deSBarry Smith 
3140354c94deSBarry Smith   PetscFunctionBegin;
3141354c94deSBarry Smith   nz = aij->nz;
3142354c94deSBarry Smith   a  = aij->a;
31432205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3144e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
3145c70f7ee4SJunchao Zhang   if (mat->offloadmask != PETSC_OFFLOAD_UNALLOCATED) mat->offloadmask = PETSC_OFFLOAD_CPU;
3146e2cf4d64SStefano Zampini #endif
3147354c94deSBarry Smith #else
3148354c94deSBarry Smith   PetscFunctionBegin;
3149354c94deSBarry Smith #endif
3150354c94deSBarry Smith   PetscFunctionReturn(0);
3151354c94deSBarry Smith }
3152354c94deSBarry Smith 
3153985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3154e34fafa9SBarry Smith {
3155e34fafa9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3156e34fafa9SBarry Smith   PetscErrorCode ierr;
3157d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3158e34fafa9SBarry Smith   PetscReal      atmp;
3159985db425SBarry Smith   PetscScalar    *x;
3160e34fafa9SBarry Smith   MatScalar      *aa;
3161e34fafa9SBarry Smith 
3162e34fafa9SBarry Smith   PetscFunctionBegin;
3163e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3164e34fafa9SBarry Smith   aa = a->a;
3165e34fafa9SBarry Smith   ai = a->i;
3166e34fafa9SBarry Smith   aj = a->j;
3167e34fafa9SBarry Smith 
3168985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3169e34fafa9SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3170e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3171e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3172e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3173e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
31749189402eSHong Zhang     x[i]  = 0.0;
3175e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3176985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3177985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3178985db425SBarry Smith       aa++; aj++;
3179985db425SBarry Smith     }
3180985db425SBarry Smith   }
3181985db425SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3182985db425SBarry Smith   PetscFunctionReturn(0);
3183985db425SBarry Smith }
3184985db425SBarry Smith 
3185985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3186985db425SBarry Smith {
3187985db425SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3188985db425SBarry Smith   PetscErrorCode ierr;
3189d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3190985db425SBarry Smith   PetscScalar    *x;
3191985db425SBarry Smith   MatScalar      *aa;
3192985db425SBarry Smith 
3193985db425SBarry Smith   PetscFunctionBegin;
3194e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3195985db425SBarry Smith   aa = a->a;
3196985db425SBarry Smith   ai = a->i;
3197985db425SBarry Smith   aj = a->j;
3198985db425SBarry Smith 
3199985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3200*fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3201985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3202e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3203985db425SBarry Smith   for (i=0; i<m; i++) {
3204985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3205d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3206985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3207985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3208985db425SBarry Smith       x[i] = 0.0;
3209985db425SBarry Smith       if (idx) {
3210985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3211985db425SBarry Smith           if (aj[j] > j) {
3212985db425SBarry Smith             idx[i] = j;
3213985db425SBarry Smith             break;
3214985db425SBarry Smith           }
3215985db425SBarry Smith         }
32161a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32171a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3218985db425SBarry Smith       }
3219985db425SBarry Smith     }
3220985db425SBarry Smith     for (j=0; j<ncols; j++) {
3221985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3222985db425SBarry Smith       aa++; aj++;
3223985db425SBarry Smith     }
3224985db425SBarry Smith   }
3225*fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3226985db425SBarry Smith   PetscFunctionReturn(0);
3227985db425SBarry Smith }
3228985db425SBarry Smith 
3229c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3230c87e5d42SMatthew Knepley {
3231c87e5d42SMatthew Knepley   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3232c87e5d42SMatthew Knepley   PetscErrorCode ierr;
3233c87e5d42SMatthew Knepley   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3234c87e5d42SMatthew Knepley   PetscReal      atmp;
3235c87e5d42SMatthew Knepley   PetscScalar    *x;
3236c87e5d42SMatthew Knepley   MatScalar      *aa;
3237c87e5d42SMatthew Knepley 
3238c87e5d42SMatthew Knepley   PetscFunctionBegin;
3239e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3240c87e5d42SMatthew Knepley   aa = a->a;
3241c87e5d42SMatthew Knepley   ai = a->i;
3242c87e5d42SMatthew Knepley   aj = a->j;
3243c87e5d42SMatthew Knepley 
3244c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3245c87e5d42SMatthew Knepley   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3246c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
324760e0710aSBarry Smith   if (n != A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", A->rmap->n, n);
3248c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3249c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3250289a08f5SMatthew Knepley     if (ncols) {
3251289a08f5SMatthew Knepley       /* Get first nonzero */
3252289a08f5SMatthew Knepley       for (j = 0; j < ncols; j++) {
3253289a08f5SMatthew Knepley         atmp = PetscAbsScalar(aa[j]);
32542205254eSKarl Rupp         if (atmp > 1.0e-12) {
32552205254eSKarl Rupp           x[i] = atmp;
32562205254eSKarl Rupp           if (idx) idx[i] = aj[j];
32572205254eSKarl Rupp           break;
32582205254eSKarl Rupp         }
3259289a08f5SMatthew Knepley       }
326012431cb0SMatthew G Knepley       if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;}
3261289a08f5SMatthew Knepley     } else {
3262289a08f5SMatthew Knepley       x[i] = 0.0; if (idx) idx[i] = 0;
3263289a08f5SMatthew Knepley     }
3264c87e5d42SMatthew Knepley     for (j = 0; j < ncols; j++) {
3265c87e5d42SMatthew Knepley       atmp = PetscAbsScalar(*aa);
3266289a08f5SMatthew Knepley       if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3267c87e5d42SMatthew Knepley       aa++; aj++;
3268c87e5d42SMatthew Knepley     }
3269c87e5d42SMatthew Knepley   }
3270c87e5d42SMatthew Knepley   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3271c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3272c87e5d42SMatthew Knepley }
3273c87e5d42SMatthew Knepley 
3274985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3275985db425SBarry Smith {
3276985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3277985db425SBarry Smith   PetscErrorCode  ierr;
3278d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3279d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3280985db425SBarry Smith   PetscScalar     *x;
3281d9ca1df4SBarry Smith   const MatScalar *aa;
3282985db425SBarry Smith 
3283985db425SBarry Smith   PetscFunctionBegin;
3284e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3285985db425SBarry Smith   aa = a->a;
3286985db425SBarry Smith   ai = a->i;
3287985db425SBarry Smith   aj = a->j;
3288985db425SBarry Smith 
3289985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3290*fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3291985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3292e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3293985db425SBarry Smith   for (i=0; i<m; i++) {
3294985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3295d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3296985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3297985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3298985db425SBarry Smith       x[i] = 0.0;
3299985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3300985db425SBarry Smith         for (j=0; j<ncols; j++) {
3301985db425SBarry Smith           if (aj[j] > j) {
3302985db425SBarry Smith             idx[i] = j;
3303985db425SBarry Smith             break;
3304985db425SBarry Smith           }
3305985db425SBarry Smith         }
3306*fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3307*fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3308985db425SBarry Smith       }
3309985db425SBarry Smith     }
3310985db425SBarry Smith     for (j=0; j<ncols; j++) {
3311985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3312985db425SBarry Smith       aa++; aj++;
3313e34fafa9SBarry Smith     }
3314e34fafa9SBarry Smith   }
3315*fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3316e34fafa9SBarry Smith   PetscFunctionReturn(0);
3317e34fafa9SBarry Smith }
3318bbead8a2SBarry Smith 
3319713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3320bbead8a2SBarry Smith {
3321bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3322bbead8a2SBarry Smith   PetscErrorCode  ierr;
332333d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3324bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33250da83c2eSBarry Smith   const PetscReal shift = 0.0;
33261a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3327bbead8a2SBarry Smith 
3328bbead8a2SBarry Smith   PetscFunctionBegin;
3329a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33304a0d0026SBarry Smith   if (a->ibdiagvalid) {
33314a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33324a0d0026SBarry Smith     PetscFunctionReturn(0);
33334a0d0026SBarry Smith   }
3334bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3335bbead8a2SBarry Smith   if (!a->ibdiag) {
3336785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
33373bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3338bbead8a2SBarry Smith   }
3339bbead8a2SBarry Smith   diag = a->ibdiag;
3340bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3341bbead8a2SBarry Smith   /* factor and invert each block */
3342bbead8a2SBarry Smith   switch (bs) {
3343bbead8a2SBarry Smith   case 1:
3344bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3345bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3346ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3347ec1892c8SHong Zhang         if (allowzeropivot) {
33487b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33497b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
33507b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
33517b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
33527b6c816cSBarry 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);
3353ec1892c8SHong Zhang       }
3354bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3355bbead8a2SBarry Smith     }
3356bbead8a2SBarry Smith     break;
3357bbead8a2SBarry Smith   case 2:
3358bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3359bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3360bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3361a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33627b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
336396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3364bbead8a2SBarry Smith       diag += 4;
3365bbead8a2SBarry Smith     }
3366bbead8a2SBarry Smith     break;
3367bbead8a2SBarry Smith   case 3:
3368bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3369bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3370bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3371a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33727b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
337396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3374bbead8a2SBarry Smith       diag += 9;
3375bbead8a2SBarry Smith     }
3376bbead8a2SBarry Smith     break;
3377bbead8a2SBarry Smith   case 4:
3378bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3379bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3380bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3381a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33827b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
338396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3384bbead8a2SBarry Smith       diag += 16;
3385bbead8a2SBarry Smith     }
3386bbead8a2SBarry Smith     break;
3387bbead8a2SBarry Smith   case 5:
3388bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3389bbead8a2SBarry 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;
3390bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3391a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33927b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
339396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3394bbead8a2SBarry Smith       diag += 25;
3395bbead8a2SBarry Smith     }
3396bbead8a2SBarry Smith     break;
3397bbead8a2SBarry Smith   case 6:
3398bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3399bbead8a2SBarry 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;
3400bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3401a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34027b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
340396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3404bbead8a2SBarry Smith       diag += 36;
3405bbead8a2SBarry Smith     }
3406bbead8a2SBarry Smith     break;
3407bbead8a2SBarry Smith   case 7:
3408bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3409bbead8a2SBarry 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;
3410bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3411a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34127b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
341396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3414bbead8a2SBarry Smith       diag += 49;
3415bbead8a2SBarry Smith     }
3416bbead8a2SBarry Smith     break;
3417bbead8a2SBarry Smith   default:
3418dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3419bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3420bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3421bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3422bbead8a2SBarry Smith       }
3423bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
34245f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34257b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
342696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3427bbead8a2SBarry Smith       diag += bs2;
3428bbead8a2SBarry Smith     }
3429bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3430bbead8a2SBarry Smith   }
3431bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3432bbead8a2SBarry Smith   PetscFunctionReturn(0);
3433bbead8a2SBarry Smith }
3434bbead8a2SBarry Smith 
343573a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
343673a71a0fSBarry Smith {
343773a71a0fSBarry Smith   PetscErrorCode ierr;
343873a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
343973a71a0fSBarry Smith   PetscScalar    a;
344073a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
344173a71a0fSBarry Smith 
344273a71a0fSBarry Smith   PetscFunctionBegin;
344373a71a0fSBarry Smith   if (!x->assembled) {
344473a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
344573a71a0fSBarry Smith     for (i=0; i<m; i++) {
344673a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
344773a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
344873a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
344973a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
345073a71a0fSBarry Smith       }
345173a71a0fSBarry Smith     }
3452e2ce353bSJunchao Zhang   } else {
3453e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3454e2ce353bSJunchao Zhang   }
345573a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
345673a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
345773a71a0fSBarry Smith   PetscFunctionReturn(0);
345873a71a0fSBarry Smith }
345973a71a0fSBarry Smith 
3460679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3461679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3462679944adSJunchao Zhang {
3463679944adSJunchao Zhang   PetscErrorCode ierr;
3464679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3465679944adSJunchao Zhang   PetscScalar    a;
3466679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3467679944adSJunchao Zhang 
3468679944adSJunchao Zhang   PetscFunctionBegin;
3469679944adSJunchao Zhang   nskip = high - low;
3470679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3471679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3472679944adSJunchao Zhang   for (i=0; i<m; i++) {
3473679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3474679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3475679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3476679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3477679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3478679944adSJunchao Zhang     }
3479e2ce353bSJunchao Zhang   }
3480679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3481679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3482679944adSJunchao Zhang   PetscFunctionReturn(0);
3483679944adSJunchao Zhang }
3484679944adSJunchao Zhang 
3485679944adSJunchao Zhang 
3486682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
34870a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3488cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3489cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3490cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
349197304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
34927c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
34937c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3494f4259b30SLisandro Dalcin                                         NULL,
3495f4259b30SLisandro Dalcin                                         NULL,
3496f4259b30SLisandro Dalcin                                         NULL,
3497f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3498cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3499f4259b30SLisandro Dalcin                                         NULL,
350041f059aeSBarry Smith                                         MatSOR_SeqAIJ,
350191e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
350297304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3503cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3504cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3505cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3506cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3507f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3508cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3509cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3510cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3511d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3512f4259b30SLisandro Dalcin                                         NULL,
3513f4259b30SLisandro Dalcin                                         NULL,
3514f4259b30SLisandro Dalcin                                         NULL,
3515f4259b30SLisandro Dalcin                                         NULL,
35164994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3517f4259b30SLisandro Dalcin                                         NULL,
3518f4259b30SLisandro Dalcin                                         NULL,
3519f4259b30SLisandro Dalcin                                         NULL,
3520f4259b30SLisandro Dalcin                                         NULL,
3521d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3522f4259b30SLisandro Dalcin                                         NULL,
3523f4259b30SLisandro Dalcin                                         NULL,
3524cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3525f4259b30SLisandro Dalcin                                         NULL,
3526d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35277dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3528cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3529cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3530cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3531d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3532cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35337d68702bSBarry Smith                                         MatShift_SeqAIJ,
353479299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
35356e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
353673a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
35373b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
35383b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
35393b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3540a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
354193dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3542f4259b30SLisandro Dalcin                                         NULL,
3543f4259b30SLisandro Dalcin                                         NULL,
3544cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3545f4259b30SLisandro Dalcin                                         NULL,
3546f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3547b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3548b9b97703SBarry Smith                                         MatView_SeqAIJ,
3549f4259b30SLisandro Dalcin                                         NULL,
3550f4259b30SLisandro Dalcin                                         NULL,
3551f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3552321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3553f4259b30SLisandro Dalcin                                         NULL,
3554f4259b30SLisandro Dalcin                                         NULL,
3555f4259b30SLisandro Dalcin                                         NULL,
3556d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3557c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3558f4259b30SLisandro Dalcin                                         NULL,
3559f4259b30SLisandro Dalcin                                         NULL,
3560f4259b30SLisandro Dalcin                                         NULL,
3561f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
35623acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3563f4259b30SLisandro Dalcin                                         NULL,
3564f4259b30SLisandro Dalcin                                         NULL,
3565f4259b30SLisandro Dalcin                                         NULL,
35666ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3567f4259b30SLisandro Dalcin                                         NULL,
3568f4259b30SLisandro Dalcin                                         NULL,
3569f4259b30SLisandro Dalcin                                         NULL,
3570bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3571d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
35721cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3573f4259b30SLisandro Dalcin                                         NULL,
3574f4259b30SLisandro Dalcin                                         NULL,
3575f4259b30SLisandro Dalcin                                         NULL,
3576f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3577f4259b30SLisandro Dalcin                                         NULL,
357826be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3579f4259b30SLisandro Dalcin                                         NULL,
3580f4259b30SLisandro Dalcin                                         NULL,
35818fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3582f4259b30SLisandro Dalcin                                         NULL,
3583f4259b30SLisandro Dalcin                                         NULL,
35846fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3585f4259b30SLisandro Dalcin                                         NULL,
35864222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3587f4259b30SLisandro Dalcin                                         NULL,
3588f4259b30SLisandro Dalcin                                         NULL,
358987d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3590f4259b30SLisandro Dalcin                                         NULL,
3591d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
359299cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3593f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3594f4259b30SLisandro Dalcin                                         NULL,
3595f4259b30SLisandro Dalcin                                         NULL,
3596cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3597f4259b30SLisandro Dalcin                                         NULL,
35982af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3599f4259b30SLisandro Dalcin                                         NULL,
3600599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3601f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3602f4259b30SLisandro Dalcin                                         NULL,
3603f4259b30SLisandro Dalcin                                         NULL,
3604f4259b30SLisandro Dalcin                                         NULL,
3605f4259b30SLisandro Dalcin                                         NULL,
3606f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3607f4259b30SLisandro Dalcin                                         NULL,
3608f4259b30SLisandro Dalcin                                         NULL,
3609f4259b30SLisandro Dalcin                                         NULL,
3610b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36110716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3612bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
361337868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36140da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3615f4259b30SLisandro Dalcin                                         NULL,
3616f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3617f4259b30SLisandro Dalcin                                         NULL,
3618f4259b30SLisandro Dalcin                                         NULL,
361975648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3620b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3621b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36222b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3623f4259b30SLisandro Dalcin                                         NULL,
3624f4259b30SLisandro Dalcin                                         NULL,
36253964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3626f4259b30SLisandro Dalcin                                  /*139*/NULL,
3627f4259b30SLisandro Dalcin                                         NULL,
3628f4259b30SLisandro Dalcin                                         NULL,
36293a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36309c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36314222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36324222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3633f4259b30SLisandro Dalcin                                         NULL,
3634f4259b30SLisandro Dalcin                                         NULL
36359e29f15eSvictorle };
363617ab2063SBarry Smith 
36377087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3638bef8e0ddSBarry Smith {
3639bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
364097f1f81fSBarry Smith   PetscInt   i,nz,n;
3641bef8e0ddSBarry Smith 
3642bef8e0ddSBarry Smith   PetscFunctionBegin;
3643bef8e0ddSBarry Smith   nz = aij->maxnz;
3644d0f46423SBarry Smith   n  = mat->rmap->n;
3645bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3646bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3647bef8e0ddSBarry Smith   }
3648bef8e0ddSBarry Smith   aij->nz = nz;
3649bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3650bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3651bef8e0ddSBarry Smith   }
3652bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3653bef8e0ddSBarry Smith }
3654bef8e0ddSBarry Smith 
3655a3bb6f32SFande Kong /*
3656e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3657a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3658a3bb6f32SFande Kong  * */
3659a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3660a3bb6f32SFande Kong {
3661a3bb6f32SFande Kong   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
3662a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3663a3bb6f32SFande Kong   PetscTablePosition tpos;
3664a3bb6f32SFande Kong   PetscInt           gid,lid,i,j,ncols,ec;
3665a3bb6f32SFande Kong   PetscInt           *garray;
3666a3bb6f32SFande Kong   PetscErrorCode  ierr;
3667a3bb6f32SFande Kong 
3668a3bb6f32SFande Kong   PetscFunctionBegin;
3669a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3670a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3671a3bb6f32SFande Kong   /* use a table */
3672a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3673a3bb6f32SFande Kong   ec = 0;
3674a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3675a3bb6f32SFande Kong     ncols = aij->i[i+1] - aij->i[i];
3676a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3677a3bb6f32SFande Kong       PetscInt data,gid1 = aij->j[aij->i[i] + j] + 1;
3678a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3679a3bb6f32SFande Kong       if (!data) {
3680a3bb6f32SFande Kong         /* one based table */
3681a3bb6f32SFande Kong         ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3682a3bb6f32SFande Kong       }
3683a3bb6f32SFande Kong     }
3684a3bb6f32SFande Kong   }
3685a3bb6f32SFande Kong   /* form array of columns we need */
3686a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3687a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3688a3bb6f32SFande Kong   while (tpos) {
3689a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3690a3bb6f32SFande Kong     gid--;
3691a3bb6f32SFande Kong     lid--;
3692a3bb6f32SFande Kong     garray[lid] = gid;
3693a3bb6f32SFande Kong   }
3694a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3695a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3696a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3697a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3698a3bb6f32SFande Kong   }
3699a3bb6f32SFande Kong   /* compact out the extra columns in B */
3700a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3701a3bb6f32SFande Kong         ncols = aij->i[i+1] - aij->i[i];
3702a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3703a3bb6f32SFande Kong       PetscInt gid1 = aij->j[aij->i[i] + j] + 1;
3704a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3705a3bb6f32SFande Kong       lid--;
3706a3bb6f32SFande Kong       aij->j[aij->i[i] + j] = lid;
3707a3bb6f32SFande Kong     }
3708a3bb6f32SFande Kong   }
3709ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3710ca5434daSLawrence Mitchell   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3711a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
3712a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3713a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3714a3bb6f32SFande Kong   PetscFunctionReturn(0);
3715a3bb6f32SFande Kong }
3716a3bb6f32SFande Kong 
3717bef8e0ddSBarry Smith /*@
3718bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3719bef8e0ddSBarry Smith        in the matrix.
3720bef8e0ddSBarry Smith 
3721bef8e0ddSBarry Smith   Input Parameters:
3722bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3723bef8e0ddSBarry Smith -  indices - the column indices
3724bef8e0ddSBarry Smith 
372515091d37SBarry Smith   Level: advanced
372615091d37SBarry Smith 
3727bef8e0ddSBarry Smith   Notes:
3728bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3729bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3730bef8e0ddSBarry Smith   of the MatSetValues() operation.
3731bef8e0ddSBarry Smith 
3732bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3733d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3734bef8e0ddSBarry Smith 
3735bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3736bef8e0ddSBarry Smith 
3737b9617806SBarry Smith     The indices should start with zero, not one.
3738b9617806SBarry Smith 
3739bef8e0ddSBarry Smith @*/
37407087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3741bef8e0ddSBarry Smith {
37424ac538c5SBarry Smith   PetscErrorCode ierr;
3743bef8e0ddSBarry Smith 
3744bef8e0ddSBarry Smith   PetscFunctionBegin;
37450700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
37464482741eSBarry Smith   PetscValidPointer(indices,2);
37474ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3748bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3749bef8e0ddSBarry Smith }
3750bef8e0ddSBarry Smith 
3751be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3752be6bf707SBarry Smith 
37537087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3754be6bf707SBarry Smith {
3755be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
37566849ba73SBarry Smith   PetscErrorCode ierr;
3757d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3758be6bf707SBarry Smith 
3759be6bf707SBarry Smith   PetscFunctionBegin;
3760169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3761be6bf707SBarry Smith 
3762be6bf707SBarry Smith   /* allocate space for values if not already there */
3763be6bf707SBarry Smith   if (!aij->saved_values) {
3764854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
37653bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3766be6bf707SBarry Smith   }
3767be6bf707SBarry Smith 
3768be6bf707SBarry Smith   /* copy values over */
3769580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3770be6bf707SBarry Smith   PetscFunctionReturn(0);
3771be6bf707SBarry Smith }
3772be6bf707SBarry Smith 
3773be6bf707SBarry Smith /*@
3774be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3775be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3776be6bf707SBarry Smith        nonlinear portion.
3777be6bf707SBarry Smith 
3778be6bf707SBarry Smith    Collect on Mat
3779be6bf707SBarry Smith 
3780be6bf707SBarry Smith   Input Parameters:
37810e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3782be6bf707SBarry Smith 
378315091d37SBarry Smith   Level: advanced
378415091d37SBarry Smith 
3785be6bf707SBarry Smith   Common Usage, with SNESSolve():
3786be6bf707SBarry Smith $    Create Jacobian matrix
3787be6bf707SBarry Smith $    Set linear terms into matrix
3788be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3789be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3790be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3791512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3792be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3793be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3794be6bf707SBarry Smith $    In your Jacobian routine
3795be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3796be6bf707SBarry Smith $      Set nonlinear terms in matrix
3797be6bf707SBarry Smith 
3798be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3799be6bf707SBarry Smith $    // build linear portion of Jacobian
3800512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3801be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3802be6bf707SBarry Smith $    loop over nonlinear iterations
3803be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3804be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3805be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3806be6bf707SBarry Smith $       Solve linear system with Jacobian
3807be6bf707SBarry Smith $    endloop
3808be6bf707SBarry Smith 
3809be6bf707SBarry Smith   Notes:
3810be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3811512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3812be6bf707SBarry Smith     calling this routine.
3813be6bf707SBarry Smith 
38140c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38150c468ba9SBarry Smith     and does not allocated additional space.
38160c468ba9SBarry Smith 
3817be6bf707SBarry Smith .seealso: MatRetrieveValues()
3818be6bf707SBarry Smith 
3819be6bf707SBarry Smith @*/
38207087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3821be6bf707SBarry Smith {
38224ac538c5SBarry Smith   PetscErrorCode ierr;
3823be6bf707SBarry Smith 
3824be6bf707SBarry Smith   PetscFunctionBegin;
38250700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3826e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3827e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38284ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3829be6bf707SBarry Smith   PetscFunctionReturn(0);
3830be6bf707SBarry Smith }
3831be6bf707SBarry Smith 
38327087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3833be6bf707SBarry Smith {
3834be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38356849ba73SBarry Smith   PetscErrorCode ierr;
3836d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3837be6bf707SBarry Smith 
3838be6bf707SBarry Smith   PetscFunctionBegin;
3839169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3840f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3841be6bf707SBarry Smith   /* copy values over */
3842580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3843be6bf707SBarry Smith   PetscFunctionReturn(0);
3844be6bf707SBarry Smith }
3845be6bf707SBarry Smith 
3846be6bf707SBarry Smith /*@
3847be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3848be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3849be6bf707SBarry Smith        nonlinear portion.
3850be6bf707SBarry Smith 
3851be6bf707SBarry Smith    Collect on Mat
3852be6bf707SBarry Smith 
3853be6bf707SBarry Smith   Input Parameters:
3854386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3855be6bf707SBarry Smith 
385615091d37SBarry Smith   Level: advanced
385715091d37SBarry Smith 
3858be6bf707SBarry Smith .seealso: MatStoreValues()
3859be6bf707SBarry Smith 
3860be6bf707SBarry Smith @*/
38617087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3862be6bf707SBarry Smith {
38634ac538c5SBarry Smith   PetscErrorCode ierr;
3864be6bf707SBarry Smith 
3865be6bf707SBarry Smith   PetscFunctionBegin;
38660700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3867e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3868e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38694ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3870be6bf707SBarry Smith   PetscFunctionReturn(0);
3871be6bf707SBarry Smith }
3872be6bf707SBarry Smith 
3873f83d6046SBarry Smith 
3874be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
387517ab2063SBarry Smith /*@C
3876682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
38770d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
38786e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
387951c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
38802bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
388117ab2063SBarry Smith 
3882d083f849SBarry Smith    Collective
3883db81eaa0SLois Curfman McInnes 
388417ab2063SBarry Smith    Input Parameters:
3885db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
388617ab2063SBarry Smith .  m - number of rows
388717ab2063SBarry Smith .  n - number of columns
388817ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
388951c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
38900298fd71SBarry Smith          (possibly different for each row) or NULL
389117ab2063SBarry Smith 
389217ab2063SBarry Smith    Output Parameter:
3893416022c9SBarry Smith .  A - the matrix
389417ab2063SBarry Smith 
3895175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3896f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3897175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3898175b88e8SBarry Smith 
3899b259b22eSLois Curfman McInnes    Notes:
390049a6f317SBarry Smith    If nnz is given then nz is ignored
390149a6f317SBarry Smith 
390217ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
390317ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39040002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
390544cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
390617ab2063SBarry Smith 
390717ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39080298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39093d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39106da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
391117ab2063SBarry Smith 
3912682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39134fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3914682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39156c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39166c7ebb05SLois Curfman McInnes 
39176c7ebb05SLois Curfman McInnes    Options Database Keys:
3918698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39199db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
392017ab2063SBarry Smith 
3921027ccd11SLois Curfman McInnes    Level: intermediate
3922027ccd11SLois Curfman McInnes 
392369b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
392436db0b34SBarry Smith 
392517ab2063SBarry Smith @*/
39267087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
392717ab2063SBarry Smith {
3928dfbe8321SBarry Smith   PetscErrorCode ierr;
39296945ee14SBarry Smith 
39303a40ed3dSBarry Smith   PetscFunctionBegin;
3931f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3932117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3933c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3934d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3935273d9f13SBarry Smith   PetscFunctionReturn(0);
3936273d9f13SBarry Smith }
3937273d9f13SBarry Smith 
3938273d9f13SBarry Smith /*@C
3939273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3940273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3941273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3942273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3943273d9f13SBarry Smith 
3944d083f849SBarry Smith    Collective
3945273d9f13SBarry Smith 
3946273d9f13SBarry Smith    Input Parameters:
39471c4f3114SJed Brown +  B - The matrix
3948273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3949273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39500298fd71SBarry Smith          (possibly different for each row) or NULL
3951273d9f13SBarry Smith 
3952273d9f13SBarry Smith    Notes:
395349a6f317SBarry Smith      If nnz is given then nz is ignored
395449a6f317SBarry Smith 
3955273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3956273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3957273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3958273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3959273d9f13SBarry Smith 
3960273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39610298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3962273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3963273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3964273d9f13SBarry Smith 
3965aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3966aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3967aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3968aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3969aa95bbe8SBarry Smith 
3970a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3971a96a251dSBarry Smith    entries or columns indices
3972a96a251dSBarry Smith 
3973273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3974273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3975273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3976273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3977273d9f13SBarry Smith 
3978273d9f13SBarry Smith    Options Database Keys:
3979698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
398047b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3981273d9f13SBarry Smith 
3982273d9f13SBarry Smith    Level: intermediate
3983273d9f13SBarry Smith 
398419b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
398519b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
3986273d9f13SBarry Smith 
3987273d9f13SBarry Smith @*/
39887087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3989273d9f13SBarry Smith {
39904ac538c5SBarry Smith   PetscErrorCode ierr;
3991a23d5eceSKris Buschelman 
3992a23d5eceSKris Buschelman   PetscFunctionBegin;
39936ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
39946ba663aaSJed Brown   PetscValidType(B,1);
39954ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
3996a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3997a23d5eceSKris Buschelman }
3998a23d5eceSKris Buschelman 
39997087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4000a23d5eceSKris Buschelman {
4001273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40022576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40036849ba73SBarry Smith   PetscErrorCode ierr;
400497f1f81fSBarry Smith   PetscInt       i;
4005273d9f13SBarry Smith 
4006273d9f13SBarry Smith   PetscFunctionBegin;
40072576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4008a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4009c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4010c461c341SBarry Smith     nz             = 0;
4011c461c341SBarry Smith   }
401226283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
401326283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4014899cda47SBarry Smith 
4015435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
401660e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4017cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4018d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
401960e0710aSBarry 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]);
402060e0710aSBarry 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);
4021b73539f3SBarry Smith     }
4022b73539f3SBarry Smith   }
4023b73539f3SBarry Smith 
4024273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
40252205254eSKarl Rupp 
4026273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4027273d9f13SBarry Smith 
4028ab93d7beSBarry Smith   if (!skipallocation) {
40292ee49352SLisandro Dalcin     if (!b->imax) {
4030071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4031071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4032071fcb05SBarry Smith     }
4033071fcb05SBarry Smith     if (!b->ilen) {
4034071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4035071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4036071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4037071fcb05SBarry Smith     } else {
4038071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
40392ee49352SLisandro Dalcin     }
4040846b4da1SFande Kong     if (!b->ipre) {
4041846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4042846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4043846b4da1SFande Kong     }
4044273d9f13SBarry Smith     if (!nnz) {
4045435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4046c62bd62aSJed Brown       else if (nz < 0) nz = 1;
40475d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4048d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4049d0f46423SBarry Smith       nz = nz*B->rmap->n;
4050273d9f13SBarry Smith     } else {
4051c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4052c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4053c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4054273d9f13SBarry Smith     }
4055ab93d7beSBarry Smith 
4056273d9f13SBarry Smith     /* allocate the matrix space */
405753dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
40582ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4059396832f4SHong Zhang     if (B->structure_only) {
40605848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
40615848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4062396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4063396832f4SHong Zhang     } else {
4064dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
40653bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4066396832f4SHong Zhang     }
4067bfeeae90SHong Zhang     b->i[0] = 0;
4068d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
40695da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
40705da197adSKris Buschelman     }
4071396832f4SHong Zhang     if (B->structure_only) {
4072396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4073396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4074396832f4SHong Zhang     } else {
4075273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4076e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4077396832f4SHong Zhang     }
4078e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4079c461c341SBarry Smith   } else {
4080e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4081e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4082c461c341SBarry Smith   }
4083273d9f13SBarry Smith 
4084846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4085846b4da1SFande Kong     /* reserve user-requested sparsity */
4086580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4087846b4da1SFande Kong   }
4088846b4da1SFande Kong 
4089846b4da1SFande Kong 
4090273d9f13SBarry Smith   b->nz               = 0;
4091273d9f13SBarry Smith   b->maxnz            = nz;
4092273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
40932205254eSKarl Rupp   if (realalloc) {
40942205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
40952205254eSKarl Rupp   }
4096cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4097cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4098273d9f13SBarry Smith   PetscFunctionReturn(0);
4099273d9f13SBarry Smith }
4100273d9f13SBarry Smith 
4101846b4da1SFande Kong 
4102846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4103846b4da1SFande Kong {
4104846b4da1SFande Kong   Mat_SeqAIJ     *a;
4105a5bbaf83SFande Kong   PetscInt       i;
4106846b4da1SFande Kong   PetscErrorCode ierr;
4107846b4da1SFande Kong 
4108846b4da1SFande Kong   PetscFunctionBegin;
4109846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
411014d0e64fSAlex Lindsay 
411114d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
411214d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
411314d0e64fSAlex Lindsay 
4114846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41152c814fdeSFande Kong   /* if no saved info, we error out */
4116fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
41172c814fdeSFande Kong 
4118fb4dc15dSAlex 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");
41192c814fdeSFande Kong 
4120580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4121580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4122846b4da1SFande Kong   a->i[0] = 0;
4123846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4124846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4125846b4da1SFande Kong   }
4126846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4127846b4da1SFande Kong   a->nz               = 0;
4128846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4129846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4130846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4131846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4132846b4da1SFande Kong   PetscFunctionReturn(0);
4133846b4da1SFande Kong }
4134846b4da1SFande Kong 
413558d36128SBarry Smith /*@
4136a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4137a1661176SMatthew Knepley 
4138a1661176SMatthew Knepley    Input Parameters:
4139a1661176SMatthew Knepley +  B - the matrix
4140a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4141a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4142a1661176SMatthew Knepley -  v - optional values in the matrix
4143a1661176SMatthew Knepley 
4144a1661176SMatthew Knepley    Level: developer
4145a1661176SMatthew Knepley 
41466a9b8d82SBarry Smith    Notes:
414758d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
414858d36128SBarry Smith 
41496a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
41506a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
41516a9b8d82SBarry Smith 
41526a9b8d82SBarry Smith     Developer Notes:
41536a9b8d82SBarry 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
41546a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
41556a9b8d82SBarry Smith 
41566a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
41576a9b8d82SBarry Smith 
41586a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4159a1661176SMatthew Knepley @*/
4160a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4161a1661176SMatthew Knepley {
4162a1661176SMatthew Knepley   PetscErrorCode ierr;
4163a1661176SMatthew Knepley 
4164a1661176SMatthew Knepley   PetscFunctionBegin;
41650700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
41666ba663aaSJed Brown   PetscValidType(B,1);
41674ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4168a1661176SMatthew Knepley   PetscFunctionReturn(0);
4169a1661176SMatthew Knepley }
4170a1661176SMatthew Knepley 
41717087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4172a1661176SMatthew Knepley {
4173a1661176SMatthew Knepley   PetscInt       i;
4174a1661176SMatthew Knepley   PetscInt       m,n;
4175a1661176SMatthew Knepley   PetscInt       nz;
41766a9b8d82SBarry Smith   PetscInt       *nnz;
4177a1661176SMatthew Knepley   PetscErrorCode ierr;
4178a1661176SMatthew Knepley 
4179a1661176SMatthew Knepley   PetscFunctionBegin;
418065e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4181779a8d59SSatish Balay 
4182779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4183779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4184779a8d59SSatish Balay 
4185779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4186854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4187a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4188b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
418965e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4190a1661176SMatthew Knepley     nnz[i] = nz;
4191a1661176SMatthew Knepley   }
4192a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4193a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4194a1661176SMatthew Knepley 
4195a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4196071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4197a1661176SMatthew Knepley   }
4198a1661176SMatthew Knepley 
4199a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4200a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4201a1661176SMatthew Knepley 
42027827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4203a1661176SMatthew Knepley   PetscFunctionReturn(0);
4204a1661176SMatthew Knepley }
4205a1661176SMatthew Knepley 
4206c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4207af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4208170fe5c8SBarry Smith 
4209170fe5c8SBarry Smith /*
4210170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4211170fe5c8SBarry Smith 
4212170fe5c8SBarry Smith                n                       p                          p
42132da392ccSBarry Smith         [             ]       [             ]         [                 ]
42142da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
42152da392ccSBarry Smith         [             ]       [             ]         [                 ]
4216170fe5c8SBarry Smith 
4217170fe5c8SBarry Smith */
4218170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4219170fe5c8SBarry Smith {
4220170fe5c8SBarry Smith   PetscErrorCode    ierr;
4221170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4222170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4223170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
422486214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4225170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4226170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4227170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
422886214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
422986214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4230170fe5c8SBarry Smith 
4231170fe5c8SBarry Smith   PetscFunctionBegin;
4232d0f46423SBarry Smith   m    = A->rmap->n;
4233d0f46423SBarry Smith   n    = A->cmap->n;
4234d0f46423SBarry Smith   p    = B->cmap->n;
4235170fe5c8SBarry Smith   a    = sub_a->v;
4236170fe5c8SBarry Smith   b    = sub_b->a;
4237170fe5c8SBarry Smith   c    = sub_c->v;
423886214ceeSStefano Zampini   if (clda == m) {
4239580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
424086214ceeSStefano Zampini   } else {
424186214ceeSStefano Zampini     for (j=0;j<p;j++)
424286214ceeSStefano Zampini       for (i=0;i<m;i++)
424386214ceeSStefano Zampini         c[j*clda + i] = 0.0;
424486214ceeSStefano Zampini   }
4245170fe5c8SBarry Smith   ii  = sub_b->i;
4246170fe5c8SBarry Smith   idx = sub_b->j;
4247170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4248170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4249170fe5c8SBarry Smith     while (q-->0) {
425086214ceeSStefano Zampini       c_q = c + clda*(*idx);
425186214ceeSStefano Zampini       a_q = a + alda*i;
4252854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4253170fe5c8SBarry Smith       idx++;
4254170fe5c8SBarry Smith       b++;
4255170fe5c8SBarry Smith     }
4256170fe5c8SBarry Smith   }
4257170fe5c8SBarry Smith   PetscFunctionReturn(0);
4258170fe5c8SBarry Smith }
4259170fe5c8SBarry Smith 
42604222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4261170fe5c8SBarry Smith {
4262170fe5c8SBarry Smith   PetscErrorCode ierr;
4263d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
426486214ceeSStefano Zampini   PetscBool      cisdense;
4265170fe5c8SBarry Smith 
4266170fe5c8SBarry Smith   PetscFunctionBegin;
426760e0710aSBarry 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);
42684222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
42694222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
427086214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
427186214ceeSStefano Zampini   if (!cisdense) {
427286214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
427386214ceeSStefano Zampini   }
427486214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4275d73949e8SHong Zhang 
42764222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4277170fe5c8SBarry Smith   PetscFunctionReturn(0);
4278170fe5c8SBarry Smith }
4279170fe5c8SBarry Smith 
4280170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
42810bad9183SKris Buschelman /*MC
4282fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
42830bad9183SKris Buschelman    based on compressed sparse row format.
42840bad9183SKris Buschelman 
42850bad9183SKris Buschelman    Options Database Keys:
42860bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
42870bad9183SKris Buschelman 
42880bad9183SKris Buschelman    Level: beginner
42890bad9183SKris Buschelman 
42900cd7f59aSBarry Smith    Notes:
42910cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
42920cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
42930cd7f59aSBarry Smith     in the matrix
42940cd7f59aSBarry Smith 
42950cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
42960cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
42970cd7f59aSBarry Smith 
42980cd7f59aSBarry Smith   Developer Notes:
42990cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
43000cd7f59aSBarry Smith 
4301f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
43020bad9183SKris Buschelman M*/
43030bad9183SKris Buschelman 
4304ccd284c7SBarry Smith /*MC
4305ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4306ccd284c7SBarry Smith 
4307ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4308ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
43090cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4310ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4311ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4312ccd284c7SBarry Smith 
4313ccd284c7SBarry Smith    Options Database Keys:
4314ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4315ccd284c7SBarry Smith 
431695452b02SPatrick Sanan   Developer Notes:
4317ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4318ccd284c7SBarry Smith    enough exist.
4319ccd284c7SBarry Smith 
4320ccd284c7SBarry Smith   Level: beginner
4321ccd284c7SBarry Smith 
4322ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4323ccd284c7SBarry Smith M*/
4324ccd284c7SBarry Smith 
4325ccd284c7SBarry Smith /*MC
4326ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4327ccd284c7SBarry Smith 
4328ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4329ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4330ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4331ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4332ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4333ccd284c7SBarry Smith 
4334ccd284c7SBarry Smith    Options Database Keys:
4335ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4336ccd284c7SBarry Smith 
4337ccd284c7SBarry Smith   Level: beginner
4338ccd284c7SBarry Smith 
4339ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4340ccd284c7SBarry Smith M*/
4341ccd284c7SBarry Smith 
43427906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
43437906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
43447906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
43457906f579SHong Zhang #endif
4346d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4347d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4348d24d4204SJose E. Roman #endif
43497906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
43507906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
43517906f579SHong Zhang #endif
43527906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
43537906f579SHong Zhang 
4354d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4355c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
43564222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
43577906f579SHong Zhang 
43588c778c55SBarry Smith /*@C
43598f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
43608c778c55SBarry Smith 
43618c778c55SBarry Smith    Not Collective
43628c778c55SBarry Smith 
43638c778c55SBarry Smith    Input Parameter:
4364579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
43658c778c55SBarry Smith 
43668c778c55SBarry Smith    Output Parameter:
43678c778c55SBarry Smith .   array - pointer to the data
43688c778c55SBarry Smith 
43698c778c55SBarry Smith    Level: intermediate
43708c778c55SBarry Smith 
4371774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
43728c778c55SBarry Smith @*/
43738c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
43748c778c55SBarry Smith {
43758c778c55SBarry Smith   PetscErrorCode ierr;
43768c778c55SBarry Smith 
43778c778c55SBarry Smith   PetscFunctionBegin;
43788c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
43798c778c55SBarry Smith   PetscFunctionReturn(0);
43808c778c55SBarry Smith }
43818c778c55SBarry Smith 
438221e72a00SBarry Smith /*@C
43838f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
43848f1ea47aSStefano Zampini 
43858f1ea47aSStefano Zampini    Not Collective
43868f1ea47aSStefano Zampini 
43878f1ea47aSStefano Zampini    Input Parameter:
43888f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
43898f1ea47aSStefano Zampini 
43908f1ea47aSStefano Zampini    Output Parameter:
43918f1ea47aSStefano Zampini .   array - pointer to the data
43928f1ea47aSStefano Zampini 
43938f1ea47aSStefano Zampini    Level: intermediate
43948f1ea47aSStefano Zampini 
43958f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
43968f1ea47aSStefano Zampini @*/
43978f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
43988f1ea47aSStefano Zampini {
43998f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4400c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44018f1ea47aSStefano Zampini #endif
44028f1ea47aSStefano Zampini   PetscErrorCode ierr;
44038f1ea47aSStefano Zampini 
44048f1ea47aSStefano Zampini   PetscFunctionBegin;
44058f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4406c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44078f1ea47aSStefano Zampini #endif
44088f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44098f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4410c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
44118f1ea47aSStefano Zampini #endif
44128f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44138f1ea47aSStefano Zampini }
44148f1ea47aSStefano Zampini 
44158f1ea47aSStefano Zampini /*@C
44168f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
44178f1ea47aSStefano Zampini 
44188f1ea47aSStefano Zampini    Not Collective
44198f1ea47aSStefano Zampini 
44208f1ea47aSStefano Zampini    Input Parameter:
44218f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44228f1ea47aSStefano Zampini 
44238f1ea47aSStefano Zampini    Output Parameter:
44248f1ea47aSStefano Zampini .   array - pointer to the data
44258f1ea47aSStefano Zampini 
44268f1ea47aSStefano Zampini    Level: intermediate
44278f1ea47aSStefano Zampini 
44288f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
44298f1ea47aSStefano Zampini @*/
44308f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
44318f1ea47aSStefano Zampini {
44328f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4433c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44348f1ea47aSStefano Zampini #endif
44358f1ea47aSStefano Zampini   PetscErrorCode ierr;
44368f1ea47aSStefano Zampini 
44378f1ea47aSStefano Zampini   PetscFunctionBegin;
44388f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4439c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44408f1ea47aSStefano Zampini #endif
44418f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44428f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4443c70f7ee4SJunchao Zhang   A->offloadmask = oval;
44448f1ea47aSStefano Zampini #endif
44458f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44468f1ea47aSStefano Zampini }
44478f1ea47aSStefano Zampini 
44488f1ea47aSStefano Zampini /*@C
444921e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
445021e72a00SBarry Smith 
445121e72a00SBarry Smith    Not Collective
445221e72a00SBarry Smith 
445321e72a00SBarry Smith    Input Parameter:
4454579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
445521e72a00SBarry Smith 
445621e72a00SBarry Smith    Output Parameter:
445721e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
445821e72a00SBarry Smith 
445921e72a00SBarry Smith    Level: intermediate
446021e72a00SBarry Smith 
446121e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
446221e72a00SBarry Smith @*/
446321e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
446421e72a00SBarry Smith {
446521e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
446621e72a00SBarry Smith 
446721e72a00SBarry Smith   PetscFunctionBegin;
446821e72a00SBarry Smith   *nz = aij->rmax;
446921e72a00SBarry Smith   PetscFunctionReturn(0);
447021e72a00SBarry Smith }
447121e72a00SBarry Smith 
44728c778c55SBarry Smith /*@C
4473579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
44748c778c55SBarry Smith 
44758c778c55SBarry Smith    Not Collective
44768c778c55SBarry Smith 
44778c778c55SBarry Smith    Input Parameters:
4478a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4479a2b725a8SWilliam Gropp -  array - pointer to the data
44808c778c55SBarry Smith 
44818c778c55SBarry Smith    Level: intermediate
44828c778c55SBarry Smith 
4483774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
44848c778c55SBarry Smith @*/
44858c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
44868c778c55SBarry Smith {
44878c778c55SBarry Smith   PetscErrorCode ierr;
44888c778c55SBarry Smith 
44898c778c55SBarry Smith   PetscFunctionBegin;
44908c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
44918c778c55SBarry Smith   PetscFunctionReturn(0);
44928c778c55SBarry Smith }
44938c778c55SBarry Smith 
449434b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
44950ce8acdeSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
449602fe1965SBarry Smith #endif
449702fe1965SBarry Smith 
44988cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4499273d9f13SBarry Smith {
4500273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4501dfbe8321SBarry Smith   PetscErrorCode ierr;
450238baddfdSBarry Smith   PetscMPIInt    size;
4503273d9f13SBarry Smith 
4504273d9f13SBarry Smith   PetscFunctionBegin;
4505ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
4506e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4507273d9f13SBarry Smith 
4508b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
45092205254eSKarl Rupp 
4510b0a32e0cSBarry Smith   B->data = (void*)b;
45112205254eSKarl Rupp 
4512549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4513071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
45142205254eSKarl Rupp 
4515f4259b30SLisandro Dalcin   b->row                = NULL;
4516f4259b30SLisandro Dalcin   b->col                = NULL;
4517f4259b30SLisandro Dalcin   b->icol               = NULL;
4518b810aeb4SBarry Smith   b->reallocs           = 0;
451936db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4520f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4521416022c9SBarry Smith   b->nonew              = 0;
4522f4259b30SLisandro Dalcin   b->diag               = NULL;
4523f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4524f4259b30SLisandro Dalcin   B->spptr              = NULL;
4525f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4526f4259b30SLisandro Dalcin   b->idiag              = NULL;
4527f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4528f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
452971f1c65dSBarry Smith   b->omega              = 1.0;
453071f1c65dSBarry Smith   b->fshift             = 0.0;
453171f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4532bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4533a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
453417ab2063SBarry Smith 
453535d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4536bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4537bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
45388c778c55SBarry Smith 
4539b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4540bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4541bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4542b3866ffcSBarry Smith #endif
454317f1a0eaSHong Zhang 
4544bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4545bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4546bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4547bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4548bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4549bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
45504dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
45519779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
45524a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4553191b95cbSRichard Tran Mills #endif
455434b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
455502fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
45564222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
455702fe1965SBarry Smith #endif
4558bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4559af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4560af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4561af8000cdSHong Zhang #endif
4562d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4563d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4564d24d4204SJose E. Roman #endif
456563c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
456663c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
45674222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
456863c07aadSStefano Zampini #endif
4569b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4570d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4571c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4572bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4573bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4574bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4575846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4576bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4577bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
45784222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
45794222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
45804222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
45814108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
458217667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
45834099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
45843a40ed3dSBarry Smith   PetscFunctionReturn(0);
458517ab2063SBarry Smith }
458617ab2063SBarry Smith 
4587b24902e0SBarry Smith /*
4588b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4589b24902e0SBarry Smith */
4590ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
459117ab2063SBarry Smith {
45922a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
45936849ba73SBarry Smith   PetscErrorCode ierr;
4594071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
459517ab2063SBarry Smith 
45963a40ed3dSBarry Smith   PetscFunctionBegin;
4597ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4598273d9f13SBarry Smith 
4599d5f3da31SBarry Smith   C->factortype = A->factortype;
4600f4259b30SLisandro Dalcin   c->row        = NULL;
4601f4259b30SLisandro Dalcin   c->col        = NULL;
4602f4259b30SLisandro Dalcin   c->icol       = NULL;
46036ad4291fSHong Zhang   c->reallocs   = 0;
460417ab2063SBarry Smith 
46056ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
460617ab2063SBarry Smith 
4607aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4608aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4609eec197d1SBarry Smith 
4610071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4611071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4612071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4613071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
46143bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
461517ab2063SBarry Smith 
461617ab2063SBarry Smith   /* allocate the matrix space */
4617f77e22a1SHong Zhang   if (mallocmatspace) {
4618dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
46193bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
46202205254eSKarl Rupp 
4621f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
46222205254eSKarl Rupp 
4623580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
462417ab2063SBarry Smith     if (m > 0) {
4625580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4626be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
4627580bdb30SBarry Smith         ierr = PetscArraycpy(c->a,a->a,a->i[m]);CHKERRQ(ierr);
4628be6bf707SBarry Smith       } else {
4629580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
463017ab2063SBarry Smith       }
463108480c60SBarry Smith     }
4632f77e22a1SHong Zhang   }
463317ab2063SBarry Smith 
46346ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4635416022c9SBarry Smith   c->roworiented       = a->roworiented;
4636416022c9SBarry Smith   c->nonew             = a->nonew;
4637416022c9SBarry Smith   if (a->diag) {
4638854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4639071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
46403bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4641071fcb05SBarry Smith   } else c->diag = NULL;
46422205254eSKarl Rupp 
4643f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4644f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4645f4259b30SLisandro Dalcin   c->idiag              = NULL;
4646f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4647a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4648e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4649e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
46506ad4291fSHong Zhang 
4651893ad86cSHong Zhang   c->rmax         = a->rmax;
4652416022c9SBarry Smith   c->nz           = a->nz;
46538ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4654273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4655754ec7b1SSatish Balay 
46566ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
46576ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4658cd6b891eSBarry Smith   if (a->compressedrow.use) {
46596ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4660dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4661580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4662580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
466327ea64f8SHong Zhang   } else {
466427ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
46650298fd71SBarry Smith     c->compressedrow.i      = NULL;
46660298fd71SBarry Smith     c->compressedrow.rindex = NULL;
46676ad4291fSHong Zhang   }
4668ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4669e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
46704846f1f5SKris Buschelman 
46712205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4672140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
46733a40ed3dSBarry Smith   PetscFunctionReturn(0);
467417ab2063SBarry Smith }
467517ab2063SBarry Smith 
4676b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4677b24902e0SBarry Smith {
4678b24902e0SBarry Smith   PetscErrorCode ierr;
4679b24902e0SBarry Smith 
4680b24902e0SBarry Smith   PetscFunctionBegin;
4681ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
46824b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4683cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
468433d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4685cfd3f464SBarry Smith   }
4686a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4687f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4688b24902e0SBarry Smith   PetscFunctionReturn(0);
4689b24902e0SBarry Smith }
4690b24902e0SBarry Smith 
4691112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4692fbdbba38SShri Abhyankar {
469352f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
469452f91c60SVaclav Hapla   PetscErrorCode ierr;
469552f91c60SVaclav Hapla 
469652f91c60SVaclav Hapla   PetscFunctionBegin;
469752f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
469852f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4699c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4700c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
470152f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
470252f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
470352f91c60SVaclav Hapla   if (isbinary) {
470452f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
470552f91c60SVaclav Hapla   } else if (ishdf5) {
470652f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
470752f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
470852f91c60SVaclav Hapla #else
470952f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
471052f91c60SVaclav Hapla #endif
471152f91c60SVaclav Hapla   } else {
471252f91c60SVaclav 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);
471352f91c60SVaclav Hapla   }
471452f91c60SVaclav Hapla   PetscFunctionReturn(0);
471552f91c60SVaclav Hapla }
471652f91c60SVaclav Hapla 
47173ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
471852f91c60SVaclav Hapla {
47193ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4720fbdbba38SShri Abhyankar   PetscErrorCode ierr;
47213ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4722fbdbba38SShri Abhyankar 
4723fbdbba38SShri Abhyankar   PetscFunctionBegin;
47243ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4725bbead8a2SBarry Smith 
47263ea6fe3dSLisandro Dalcin   /* read in matrix header */
47273ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
47283ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4729fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
47303ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
47313ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4732bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4733fbdbba38SShri Abhyankar 
47343ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
47353ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
47363ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
47373ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
47383ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
47393ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
47403ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
47413ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
47423ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
47433ea6fe3dSLisandro Dalcin 
47443ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
47453ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
47463ea6fe3dSLisandro 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);
47473ea6fe3dSLisandro Dalcin 
4748fbdbba38SShri Abhyankar   /* read in row lengths */
47493ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
47503ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
47513ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
47523ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
47533ea6fe3dSLisandro 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);
47543ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
47553ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
47563ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
475760e0710aSBarry 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);
47583ea6fe3dSLisandro Dalcin   /* store row lengths */
47593ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
47603ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4761fbdbba38SShri Abhyankar 
47623ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
47633ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
47643ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
47653ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
47663ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
47673ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4768fbdbba38SShri Abhyankar 
47693ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47703ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4771fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4772fbdbba38SShri Abhyankar }
4773fbdbba38SShri Abhyankar 
4774ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
47757264ac53SSatish Balay {
47767264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4777dfbe8321SBarry Smith   PetscErrorCode ierr;
4778eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4779eeffb40dSHong Zhang   PetscInt k;
4780eeffb40dSHong Zhang #endif
47817264ac53SSatish Balay 
47823a40ed3dSBarry Smith   PetscFunctionBegin;
4783bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4784d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4785ca44d042SBarry Smith     *flg = PETSC_FALSE;
4786ca44d042SBarry Smith     PetscFunctionReturn(0);
4787bcd2baecSBarry Smith   }
47887264ac53SSatish Balay 
47897264ac53SSatish Balay   /* if the a->i are the same */
4790580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4791abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
47927264ac53SSatish Balay 
47937264ac53SSatish Balay   /* if a->j are the same */
4794580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4795abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4796bcd2baecSBarry Smith 
4797bcd2baecSBarry Smith   /* if a->a are the same */
4798eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4799eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4800eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4801eeffb40dSHong Zhang       *flg = PETSC_FALSE;
48023a40ed3dSBarry Smith       PetscFunctionReturn(0);
4803eeffb40dSHong Zhang     }
4804eeffb40dSHong Zhang   }
4805eeffb40dSHong Zhang #else
4806580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4807eeffb40dSHong Zhang #endif
4808eeffb40dSHong Zhang   PetscFunctionReturn(0);
48097264ac53SSatish Balay }
481036db0b34SBarry Smith 
481105869f15SSatish Balay /*@
481236db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
481336db0b34SBarry Smith               provided by the user.
481436db0b34SBarry Smith 
4815d083f849SBarry Smith       Collective
481636db0b34SBarry Smith 
481736db0b34SBarry Smith    Input Parameters:
481836db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
481936db0b34SBarry Smith .   m - number of rows
482036db0b34SBarry Smith .   n - number of columns
4821483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
482236db0b34SBarry Smith .   j - column indices
482336db0b34SBarry Smith -   a - matrix values
482436db0b34SBarry Smith 
482536db0b34SBarry Smith    Output Parameter:
482636db0b34SBarry Smith .   mat - the matrix
482736db0b34SBarry Smith 
482836db0b34SBarry Smith    Level: intermediate
482936db0b34SBarry Smith 
483036db0b34SBarry Smith    Notes:
48310551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4832292fb18eSBarry Smith     once the matrix is destroyed and not before
483336db0b34SBarry Smith 
483436db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
483536db0b34SBarry Smith 
4836bfeeae90SHong Zhang        The i and j indices are 0 based
483736db0b34SBarry Smith 
4838a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4839a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
48408eef79e4SBarry Smith     as shown
4841a4552177SSatish Balay 
48428eef79e4SBarry Smith $        1 0 0
48438eef79e4SBarry Smith $        2 0 3
48448eef79e4SBarry Smith $        4 5 6
48458eef79e4SBarry Smith $
48468eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
48478eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
48488eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4849a4552177SSatish Balay 
48509985e31cSBarry Smith 
485169b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
485236db0b34SBarry Smith 
485336db0b34SBarry Smith @*/
4854c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
485536db0b34SBarry Smith {
4856dfbe8321SBarry Smith   PetscErrorCode ierr;
4857cbcfb4deSHong Zhang   PetscInt       ii;
485836db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4859cbcfb4deSHong Zhang   PetscInt jj;
486036db0b34SBarry Smith 
486136db0b34SBarry Smith   PetscFunctionBegin;
486241096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4863f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4864f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4865a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4866ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4867f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
4868ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4869071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4870071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4871ab93d7beSBarry Smith 
487236db0b34SBarry Smith   aij->i            = i;
487336db0b34SBarry Smith   aij->j            = j;
487436db0b34SBarry Smith   aij->a            = a;
487536db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
487636db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4877e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4878e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
487936db0b34SBarry Smith 
488036db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
488136db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
488276bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
488360e0710aSBarry 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]);
48849985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4885a061629eSStefano 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);
4886a061629eSStefano 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);
48879985e31cSBarry Smith       }
488836db0b34SBarry Smith     }
488976bd3646SJed Brown   }
489076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
489136db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
489260e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
489360e0710aSBarry 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]);
489436db0b34SBarry Smith     }
489576bd3646SJed Brown   }
489636db0b34SBarry Smith 
4897b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4898b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
489936db0b34SBarry Smith   PetscFunctionReturn(0);
490036db0b34SBarry Smith }
490180ef6e79SMatthew G Knepley /*@C
4902d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
49038a0b0e6bSVictor Minden               provided by the user.
49048a0b0e6bSVictor Minden 
4905d083f849SBarry Smith       Collective
49068a0b0e6bSVictor Minden 
49078a0b0e6bSVictor Minden    Input Parameters:
49088a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
49098a0b0e6bSVictor Minden .   m   - number of rows
49108a0b0e6bSVictor Minden .   n   - number of columns
49118a0b0e6bSVictor Minden .   i   - row indices
49128a0b0e6bSVictor Minden .   j   - column indices
49131230e6d1SVictor Minden .   a   - matrix values
49141230e6d1SVictor Minden .   nz  - number of nonzeros
49151230e6d1SVictor Minden -   idx - 0 or 1 based
49168a0b0e6bSVictor Minden 
49178a0b0e6bSVictor Minden    Output Parameter:
49188a0b0e6bSVictor Minden .   mat - the matrix
49198a0b0e6bSVictor Minden 
49208a0b0e6bSVictor Minden    Level: intermediate
49218a0b0e6bSVictor Minden 
49228a0b0e6bSVictor Minden    Notes:
49238a0b0e6bSVictor Minden        The i and j indices are 0 based
49248a0b0e6bSVictor Minden 
49258a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
49268a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
49278a0b0e6bSVictor Minden     as shown:
49288a0b0e6bSVictor Minden 
49298a0b0e6bSVictor Minden         1 0 0
49308a0b0e6bSVictor Minden         2 0 3
49318a0b0e6bSVictor Minden         4 5 6
49328a0b0e6bSVictor Minden 
49338a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
49348a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
49358a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
49368a0b0e6bSVictor Minden 
49378a0b0e6bSVictor Minden 
493869b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
49398a0b0e6bSVictor Minden 
49408a0b0e6bSVictor Minden @*/
4941c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
49428a0b0e6bSVictor Minden {
49438a0b0e6bSVictor Minden   PetscErrorCode ierr;
4944d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
49458a0b0e6bSVictor Minden 
49468a0b0e6bSVictor Minden 
49478a0b0e6bSVictor Minden   PetscFunctionBegin;
49481795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
49491230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
4950c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
49511230e6d1SVictor Minden   }
49528a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
49538a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
49548a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
49551230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
49561230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
49571230e6d1SVictor Minden     if (idx) {
49581230e6d1SVictor Minden       row = i[ii] - 1;
49591230e6d1SVictor Minden       col = j[ii] - 1;
49601230e6d1SVictor Minden     } else {
49611230e6d1SVictor Minden       row = i[ii];
49621230e6d1SVictor Minden       col = j[ii];
49638a0b0e6bSVictor Minden     }
49641230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
49658a0b0e6bSVictor Minden   }
49668a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49678a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4968d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
49698a0b0e6bSVictor Minden   PetscFunctionReturn(0);
49708a0b0e6bSVictor Minden }
497136db0b34SBarry Smith 
4972acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
4973acf2f550SJed Brown {
4974acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
4975acf2f550SJed Brown   PetscErrorCode ierr;
4976acf2f550SJed Brown 
4977acf2f550SJed Brown   PetscFunctionBegin;
4978acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
4979acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
49802205254eSKarl Rupp 
4981acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
4982acf2f550SJed Brown   PetscFunctionReturn(0);
4983acf2f550SJed Brown }
4984acf2f550SJed Brown 
49859c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
49869c8f2541SHong Zhang {
49879c8f2541SHong Zhang   PetscErrorCode ierr;
49888761c3d6SHong Zhang   PetscMPIInt    size;
49899c8f2541SHong Zhang 
49909c8f2541SHong Zhang   PetscFunctionBegin;
49918761c3d6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
49927bbdc51dSHong Zhang   if (size == 1) {
49937bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
49947bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
49957bbdc51dSHong Zhang     } else {
49968761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
49977bbdc51dSHong Zhang     }
49988761c3d6SHong Zhang   } else {
49999c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
50008761c3d6SHong Zhang   }
50019c8f2541SHong Zhang   PetscFunctionReturn(0);
50029c8f2541SHong Zhang }
50039c8f2541SHong Zhang 
500481824310SBarry Smith /*
500553dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
500653dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
500753dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
500853dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
500953dd7562SDmitry Karpeev  */
501053dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
501153dd7562SDmitry Karpeev {
501253dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
501353dd7562SDmitry Karpeev   PetscErrorCode ierr;
501453dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
501553dd7562SDmitry Karpeev   PetscBool      seqaij;
501653dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
501753dd7562SDmitry Karpeev   PetscScalar    v;
501853dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
501953dd7562SDmitry Karpeev 
502053dd7562SDmitry Karpeev   PetscFunctionBegin;
502153dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
502253dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
50234099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
502453dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
502553dd7562SDmitry Karpeev   if (rowemb) {
502653dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
502753dd7562SDmitry 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);
502853dd7562SDmitry Karpeev   } else {
50296c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
503053dd7562SDmitry Karpeev   }
503153dd7562SDmitry Karpeev   if (colemb) {
503253dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
503353dd7562SDmitry 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);
503453dd7562SDmitry Karpeev   } else {
503553dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
503653dd7562SDmitry Karpeev   }
503753dd7562SDmitry Karpeev 
503853dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
503953dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
504053dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
504153dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
504253dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
504353dd7562SDmitry Karpeev     }
504453dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
504553dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
504653dd7562SDmitry Karpeev   }
504753dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
504853dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
504953dd7562SDmitry Karpeev   }
505053dd7562SDmitry Karpeev   count = 0;
505153dd7562SDmitry Karpeev   rowindices = NULL;
505253dd7562SDmitry Karpeev   colindices = NULL;
505353dd7562SDmitry Karpeev   if (rowemb) {
505453dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
505553dd7562SDmitry Karpeev   }
505653dd7562SDmitry Karpeev   if (colemb) {
505753dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
505853dd7562SDmitry Karpeev   }
505953dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
506053dd7562SDmitry Karpeev     PetscInt row;
506153dd7562SDmitry Karpeev     row = i;
506253dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
506353dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
506453dd7562SDmitry Karpeev       PetscInt col;
506553dd7562SDmitry Karpeev       col  = Baij->j[count];
506653dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
506753dd7562SDmitry Karpeev       v    = Baij->a[count];
506853dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
506953dd7562SDmitry Karpeev       ++count;
507053dd7562SDmitry Karpeev     }
507153dd7562SDmitry Karpeev   }
507253dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
507353dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
507453dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
507553dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
507653dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
507753dd7562SDmitry Karpeev   PetscFunctionReturn(0);
507853dd7562SDmitry Karpeev }
507953dd7562SDmitry Karpeev 
50804099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
50814099cc6bSBarry Smith 
50824099cc6bSBarry Smith /*@C
50834099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
50844099cc6bSBarry Smith 
50854099cc6bSBarry Smith    Collective on Mat
50864099cc6bSBarry Smith 
50874099cc6bSBarry Smith    Input Parameters:
50884099cc6bSBarry Smith +  mat      - the matrix object
50894099cc6bSBarry Smith -  matype   - matrix type
50904099cc6bSBarry Smith 
50914099cc6bSBarry Smith    Options Database Key:
50924099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
50934099cc6bSBarry Smith 
50944099cc6bSBarry Smith 
50954099cc6bSBarry Smith   Level: intermediate
50964099cc6bSBarry Smith 
50974099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
50984099cc6bSBarry Smith @*/
50994099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
51004099cc6bSBarry Smith {
5101fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
51024099cc6bSBarry Smith   PetscBool      sametype;
51034099cc6bSBarry Smith 
51044099cc6bSBarry Smith   PetscFunctionBegin;
51054099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
51064099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
51074099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
51084099cc6bSBarry Smith 
51094099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
51104099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
51114099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
51124099cc6bSBarry Smith   PetscFunctionReturn(0);
51134099cc6bSBarry Smith }
51144099cc6bSBarry Smith 
51154099cc6bSBarry Smith 
51164099cc6bSBarry Smith /*@C
51174099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
51184099cc6bSBarry Smith 
51194099cc6bSBarry Smith    Not Collective
51204099cc6bSBarry Smith 
51214099cc6bSBarry Smith    Input Parameters:
51224099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
51234099cc6bSBarry Smith -  function - routine to convert to subtype
51244099cc6bSBarry Smith 
51254099cc6bSBarry Smith    Notes:
51264099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
51274099cc6bSBarry Smith 
51284099cc6bSBarry Smith 
51294099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
51304099cc6bSBarry Smith $     -mat_seqaij_type my_mat
51314099cc6bSBarry Smith 
51324099cc6bSBarry Smith    Level: advanced
51334099cc6bSBarry Smith 
51344099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
51354099cc6bSBarry Smith 
51364099cc6bSBarry Smith 
51374099cc6bSBarry Smith   Level: advanced
51384099cc6bSBarry Smith @*/
5139388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
51404099cc6bSBarry Smith {
51414099cc6bSBarry Smith   PetscErrorCode ierr;
51424099cc6bSBarry Smith 
51434099cc6bSBarry Smith   PetscFunctionBegin;
51449cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
51454099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
51464099cc6bSBarry Smith   PetscFunctionReturn(0);
51474099cc6bSBarry Smith }
51484099cc6bSBarry Smith 
51494099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
51504099cc6bSBarry Smith 
51514099cc6bSBarry Smith /*@C
51524099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
51534099cc6bSBarry Smith 
51544099cc6bSBarry Smith   Not Collective
51554099cc6bSBarry Smith 
51564099cc6bSBarry Smith   Level: advanced
51574099cc6bSBarry Smith 
51584099cc6bSBarry Smith   Developers Note: CUSP and CUSPARSE do not yet support the  MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
51594099cc6bSBarry Smith 
51604099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
51614099cc6bSBarry Smith @*/
51624099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
51634099cc6bSBarry Smith {
51644099cc6bSBarry Smith   PetscErrorCode ierr;
51654099cc6bSBarry Smith 
51664099cc6bSBarry Smith   PetscFunctionBegin;
51674099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
51684099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
51694099cc6bSBarry Smith 
51704099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
51714099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
51724dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
51739779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
51746b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5175485f9817SRichard Tran Mills #endif
51764099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
51774099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
51784099cc6bSBarry Smith #endif
51794099cc6bSBarry Smith   PetscFunctionReturn(0);
51804099cc6bSBarry Smith }
518153dd7562SDmitry Karpeev 
518253dd7562SDmitry Karpeev /*
518381824310SBarry Smith     Special version for direct calls from Fortran
518481824310SBarry Smith */
5185af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
518681824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
518781824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
518881824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
518981824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
519081824310SBarry Smith #endif
519181824310SBarry Smith 
519281824310SBarry Smith /* Change these macros so can be used in void function */
519381824310SBarry Smith #undef CHKERRQ
5194ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
519581824310SBarry Smith #undef SETERRQ2
5196e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
51974994cf47SJed Brown #undef SETERRQ3
51984994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
519981824310SBarry Smith 
520019caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
520181824310SBarry Smith {
520281824310SBarry Smith   Mat            A  = *AA;
520381824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
520481824310SBarry Smith   InsertMode     is = *isis;
520581824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
520681824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
520781824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
520881824310SBarry Smith   PetscErrorCode ierr;
520981824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
521054f21887SBarry Smith   MatScalar      *ap,value,*aa;
5211ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5212ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
521381824310SBarry Smith 
521481824310SBarry Smith   PetscFunctionBegin;
52154994cf47SJed Brown   MatCheckPreallocated(A,1);
521681824310SBarry Smith   imax  = a->imax;
521781824310SBarry Smith   ai    = a->i;
521881824310SBarry Smith   ailen = a->ilen;
521981824310SBarry Smith   aj    = a->j;
522081824310SBarry Smith   aa    = a->a;
522181824310SBarry Smith 
522281824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
522381824310SBarry Smith     row = im[k];
522481824310SBarry Smith     if (row < 0) continue;
5225cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
522681824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
522781824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
522881824310SBarry Smith     low  = 0;
522981824310SBarry Smith     high = nrow;
523081824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
523181824310SBarry Smith       if (in[l] < 0) continue;
5232cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
523381824310SBarry Smith       col = in[l];
52342205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
52352205254eSKarl Rupp       else value = v[k + l*m];
52362205254eSKarl Rupp 
523781824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
523881824310SBarry Smith 
52392205254eSKarl Rupp       if (col <= lastcol) low = 0;
52402205254eSKarl Rupp       else high = nrow;
524181824310SBarry Smith       lastcol = col;
524281824310SBarry Smith       while (high-low > 5) {
524381824310SBarry Smith         t = (low+high)/2;
524481824310SBarry Smith         if (rp[t] > col) high = t;
524581824310SBarry Smith         else             low  = t;
524681824310SBarry Smith       }
524781824310SBarry Smith       for (i=low; i<high; i++) {
524881824310SBarry Smith         if (rp[i] > col) break;
524981824310SBarry Smith         if (rp[i] == col) {
525081824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
525181824310SBarry Smith           else                  ap[i] = value;
525281824310SBarry Smith           goto noinsert;
525381824310SBarry Smith         }
525481824310SBarry Smith       }
525581824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
525681824310SBarry Smith       if (nonew == 1) goto noinsert;
5257ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5258fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
525981824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
526081824310SBarry Smith       /* shift up all the later entries in this row */
526181824310SBarry Smith       for (ii=N; ii>=i; ii--) {
526281824310SBarry Smith         rp[ii+1] = rp[ii];
526381824310SBarry Smith         ap[ii+1] = ap[ii];
526481824310SBarry Smith       }
526581824310SBarry Smith       rp[i] = col;
526681824310SBarry Smith       ap[i] = value;
5267e56f5c9eSBarry Smith       A->nonzerostate++;
526881824310SBarry Smith noinsert:;
526981824310SBarry Smith       low = i + 1;
527081824310SBarry Smith     }
527181824310SBarry Smith     ailen[row] = nrow;
527281824310SBarry Smith   }
527381824310SBarry Smith   PetscFunctionReturnVoid();
527481824310SBarry Smith }
5275