xref: /petsc/src/mat/impls/aij/seq/aij.c (revision f719121f3d32fb20d5348a7033ed4c0d28fdf2dc)
1d5d45c9bSBarry Smith /*
23369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
3d5d45c9bSBarry Smith   matrix storage format.
4d5d45c9bSBarry Smith */
53369ce9aSBarry Smith 
67c4f633dSBarry Smith 
7c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
8c6db04a5SJed Brown #include <petscblaslapack.h>
9c6db04a5SJed Brown #include <petscbt.h>
10af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
110716a85fSBarry Smith 
124099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
134099cc6bSBarry Smith {
144099cc6bSBarry Smith   PetscErrorCode       ierr;
154099cc6bSBarry Smith   PetscBool            flg;
164099cc6bSBarry Smith   char                 type[256];
174099cc6bSBarry Smith 
184099cc6bSBarry Smith   PetscFunctionBegin;
194099cc6bSBarry Smith   ierr = PetscObjectOptionsBegin((PetscObject)A);
204099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
214099cc6bSBarry Smith   if (flg) {
224099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
234099cc6bSBarry Smith   }
244099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
254099cc6bSBarry Smith   PetscFunctionReturn(0);
264099cc6bSBarry Smith }
274099cc6bSBarry Smith 
280716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
290716a85fSBarry Smith {
300716a85fSBarry Smith   PetscErrorCode ierr;
310716a85fSBarry Smith   PetscInt       i,m,n;
320716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
330716a85fSBarry Smith 
340716a85fSBarry Smith   PetscFunctionBegin;
350716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
36580bdb30SBarry Smith   ierr = PetscArrayzero(norms,n);CHKERRQ(ierr);
370716a85fSBarry Smith   if (type == NORM_2) {
380716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
390716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
400716a85fSBarry Smith     }
410716a85fSBarry Smith   } else if (type == NORM_1) {
420716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
430716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
440716a85fSBarry Smith     }
450716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
460716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
470716a85fSBarry Smith       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
480716a85fSBarry Smith     }
490716a85fSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");
500716a85fSBarry Smith 
510716a85fSBarry Smith   if (type == NORM_2) {
528f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
530716a85fSBarry Smith   }
540716a85fSBarry Smith   PetscFunctionReturn(0);
550716a85fSBarry Smith }
560716a85fSBarry Smith 
573a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
583a062f41SBarry Smith {
593a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
603a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
613a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
623a062f41SBarry Smith   PetscInt        *rows;
633a062f41SBarry Smith   PetscErrorCode  ierr;
643a062f41SBarry Smith 
653a062f41SBarry Smith   PetscFunctionBegin;
663a062f41SBarry Smith   for (i=0; i<m; i++) {
673a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
683a062f41SBarry Smith       cnt++;
693a062f41SBarry Smith     }
703a062f41SBarry Smith   }
713a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
723a062f41SBarry Smith   cnt  = 0;
733a062f41SBarry Smith   for (i=0; i<m; i++) {
743a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
753a062f41SBarry Smith       rows[cnt] = i;
763a062f41SBarry Smith       cnt++;
773a062f41SBarry Smith     }
783a062f41SBarry Smith   }
793a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
803a062f41SBarry Smith   PetscFunctionReturn(0);
813a062f41SBarry Smith }
823a062f41SBarry Smith 
83f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
846ce1633cSBarry Smith {
856ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
866ce1633cSBarry Smith   const MatScalar *aa = a->a;
876ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
88b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
896ce1633cSBarry Smith   PetscInt        *rows;
906ce1633cSBarry Smith   PetscErrorCode  ierr;
916ce1633cSBarry Smith 
926ce1633cSBarry Smith   PetscFunctionBegin;
936ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
946ce1633cSBarry Smith   diag = a->diag;
956ce1633cSBarry Smith   for (i=0; i<m; i++) {
96b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
976ce1633cSBarry Smith       cnt++;
986ce1633cSBarry Smith     }
996ce1633cSBarry Smith   }
100785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1016ce1633cSBarry Smith   cnt  = 0;
1026ce1633cSBarry Smith   for (i=0; i<m; i++) {
103b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1046ce1633cSBarry Smith       rows[cnt++] = i;
1056ce1633cSBarry Smith     }
1066ce1633cSBarry Smith   }
107f1f41ecbSJed Brown   *nrows = cnt;
108f1f41ecbSJed Brown   *zrows = rows;
109f1f41ecbSJed Brown   PetscFunctionReturn(0);
110f1f41ecbSJed Brown }
111f1f41ecbSJed Brown 
112f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
113f1f41ecbSJed Brown {
114f1f41ecbSJed Brown   PetscInt       nrows,*rows;
115f1f41ecbSJed Brown   PetscErrorCode ierr;
116f1f41ecbSJed Brown 
117f1f41ecbSJed Brown   PetscFunctionBegin;
1180298fd71SBarry Smith   *zrows = NULL;
119f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
120ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1216ce1633cSBarry Smith   PetscFunctionReturn(0);
1226ce1633cSBarry Smith }
1236ce1633cSBarry Smith 
124b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
125b3a44c85SBarry Smith {
126b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
127b3a44c85SBarry Smith   const MatScalar *aa;
128b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
129b3a44c85SBarry Smith   const PetscInt  *ii;
130b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
131b3a44c85SBarry Smith   PetscErrorCode  ierr;
132b3a44c85SBarry Smith 
133b3a44c85SBarry Smith   PetscFunctionBegin;
134f4259b30SLisandro Dalcin   *keptrows = NULL;
135b3a44c85SBarry Smith   ii        = a->i;
136b3a44c85SBarry Smith   for (i=0; i<m; i++) {
137b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
138b3a44c85SBarry Smith     if (!n) {
139b3a44c85SBarry Smith       cnt++;
140b3a44c85SBarry Smith       goto ok1;
141b3a44c85SBarry Smith     }
142b3a44c85SBarry Smith     aa = a->a + ii[i];
143b3a44c85SBarry Smith     for (j=0; j<n; j++) {
144b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
145b3a44c85SBarry Smith     }
146b3a44c85SBarry Smith     cnt++;
147b3a44c85SBarry Smith ok1:;
148b3a44c85SBarry Smith   }
149b3a44c85SBarry Smith   if (!cnt) PetscFunctionReturn(0);
150854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
151b3a44c85SBarry Smith   cnt  = 0;
152b3a44c85SBarry Smith   for (i=0; i<m; i++) {
153b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
154b3a44c85SBarry Smith     if (!n) continue;
155b3a44c85SBarry Smith     aa = a->a + ii[i];
156b3a44c85SBarry Smith     for (j=0; j<n; j++) {
157b3a44c85SBarry Smith       if (aa[j] != 0.0) {
158b3a44c85SBarry Smith         rows[cnt++] = i;
159b3a44c85SBarry Smith         break;
160b3a44c85SBarry Smith       }
161b3a44c85SBarry Smith     }
162b3a44c85SBarry Smith   }
163b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
164b3a44c85SBarry Smith   PetscFunctionReturn(0);
165b3a44c85SBarry Smith }
166b3a44c85SBarry Smith 
1677087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
16879299369SBarry Smith {
16979299369SBarry Smith   PetscErrorCode    ierr;
17079299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17199e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17299e65526SBarry Smith   const PetscInt    *diag;
17354f21887SBarry Smith   MatScalar         *aa = aij->a;
17499e65526SBarry Smith   const PetscScalar *v;
175ace3abfcSBarry Smith   PetscBool         missing;
1768c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
177837a59e1SRichard Tran Mills   PetscBool         inserted = PETSC_FALSE;
178837a59e1SRichard Tran Mills #endif
17979299369SBarry Smith 
18079299369SBarry Smith   PetscFunctionBegin;
18109f38230SBarry Smith   if (Y->assembled) {
1820298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
18309f38230SBarry Smith     if (!missing) {
18479299369SBarry Smith       diag = aij->diag;
18599e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
18679299369SBarry Smith       if (is == INSERT_VALUES) {
1878c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
188837a59e1SRichard Tran Mills         inserted = PETSC_TRUE;
189837a59e1SRichard Tran Mills #endif
19079299369SBarry Smith         for (i=0; i<m; i++) {
19179299369SBarry Smith           aa[diag[i]] = v[i];
19279299369SBarry Smith         }
19379299369SBarry Smith       } else {
19479299369SBarry Smith         for (i=0; i<m; i++) {
1958c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
196837a59e1SRichard Tran Mills           if (v[i] != 0.0) inserted = PETSC_TRUE;
197837a59e1SRichard Tran Mills #endif
19879299369SBarry Smith           aa[diag[i]] += v[i];
19979299369SBarry Smith         }
20079299369SBarry Smith       }
2018c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
202837a59e1SRichard Tran Mills       if (inserted) Y->offloadmask = PETSC_OFFLOAD_CPU;
203837a59e1SRichard Tran Mills #endif
20499e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
20579299369SBarry Smith       PetscFunctionReturn(0);
20679299369SBarry Smith     }
207acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
20809f38230SBarry Smith   }
20909f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
21009f38230SBarry Smith   PetscFunctionReturn(0);
21109f38230SBarry Smith }
21279299369SBarry Smith 
2131a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21417ab2063SBarry Smith {
215416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
216dfbe8321SBarry Smith   PetscErrorCode ierr;
21797f1f81fSBarry Smith   PetscInt       i,ishift;
21817ab2063SBarry Smith 
2193a40ed3dSBarry Smith   PetscFunctionBegin;
220d0f46423SBarry Smith   *m = A->rmap->n;
2213a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
222bfeeae90SHong Zhang   ishift = 0;
22353e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2242462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
225bfeeae90SHong Zhang   } else if (oshift == 1) {
2261a83f524SJed Brown     PetscInt *tia;
227d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2283b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
229854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2301a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2311a83f524SJed Brown     *ia = tia;
232ecc77c7aSBarry Smith     if (ja) {
2331a83f524SJed Brown       PetscInt *tja;
234854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2351a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2361a83f524SJed Brown       *ja = tja;
237ecc77c7aSBarry Smith     }
2386945ee14SBarry Smith   } else {
239ecc77c7aSBarry Smith     *ia = a->i;
240ecc77c7aSBarry Smith     if (ja) *ja = a->j;
241a2ce50c7SBarry Smith   }
2423a40ed3dSBarry Smith   PetscFunctionReturn(0);
243a2744918SBarry Smith }
244a2744918SBarry Smith 
2451a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2466945ee14SBarry Smith {
247dfbe8321SBarry Smith   PetscErrorCode ierr;
2486945ee14SBarry Smith 
2493a40ed3dSBarry Smith   PetscFunctionBegin;
2503a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
251bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
252606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
253ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
254bcd2baecSBarry Smith   }
2553a40ed3dSBarry Smith   PetscFunctionReturn(0);
25617ab2063SBarry Smith }
25717ab2063SBarry Smith 
2581a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2593b2fbd54SBarry Smith {
2603b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
261dfbe8321SBarry Smith   PetscErrorCode ierr;
262d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
26397f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2643b2fbd54SBarry Smith 
2653a40ed3dSBarry Smith   PetscFunctionBegin;
266899cda47SBarry Smith   *nn = n;
2673a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2683b2fbd54SBarry Smith   if (symmetric) {
2692462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2703b2fbd54SBarry Smith   } else {
271b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
272854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
273b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2743b2fbd54SBarry Smith     jj   = a->j;
2753b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
276bfeeae90SHong Zhang       collengths[jj[i]]++;
2773b2fbd54SBarry Smith     }
2783b2fbd54SBarry Smith     cia[0] = oshift;
2793b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2803b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2813b2fbd54SBarry Smith     }
282580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2833b2fbd54SBarry Smith     jj   = a->j;
284a93ec695SBarry Smith     for (row=0; row<m; row++) {
285a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
286a93ec695SBarry Smith       for (i=0; i<mr; i++) {
287bfeeae90SHong Zhang         col = *jj++;
2882205254eSKarl Rupp 
2893b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2903b2fbd54SBarry Smith       }
2913b2fbd54SBarry Smith     }
292606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2933b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2943b2fbd54SBarry Smith   }
2953a40ed3dSBarry Smith   PetscFunctionReturn(0);
2963b2fbd54SBarry Smith }
2973b2fbd54SBarry Smith 
2981a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2993b2fbd54SBarry Smith {
300dfbe8321SBarry Smith   PetscErrorCode ierr;
301606d414cSSatish Balay 
3023a40ed3dSBarry Smith   PetscFunctionBegin;
3033a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3043b2fbd54SBarry Smith 
305606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
306606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3073a40ed3dSBarry Smith   PetscFunctionReturn(0);
3083b2fbd54SBarry Smith }
3093b2fbd54SBarry Smith 
3107cee066cSHong Zhang /*
3117cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3127cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
313040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3147cee066cSHong Zhang */
3157cee066cSHong Zhang PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3167cee066cSHong Zhang {
3177cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3187cee066cSHong Zhang   PetscErrorCode ierr;
3197cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
320071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3217cee066cSHong Zhang   PetscInt       *cspidx;
322071fcb05SBarry Smith   const PetscInt *jj;
3237cee066cSHong Zhang 
3247cee066cSHong Zhang   PetscFunctionBegin;
3257cee066cSHong Zhang   *nn = n;
3267cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
327625f6d37SHong Zhang 
328b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
329854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
330b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
331b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3327cee066cSHong Zhang   jj   = a->j;
3337cee066cSHong Zhang   for (i=0; i<nz; i++) {
3347cee066cSHong Zhang     collengths[jj[i]]++;
3357cee066cSHong Zhang   }
3367cee066cSHong Zhang   cia[0] = oshift;
3377cee066cSHong Zhang   for (i=0; i<n; i++) {
3387cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3397cee066cSHong Zhang   }
340580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3417cee066cSHong Zhang   jj   = a->j;
3427cee066cSHong Zhang   for (row=0; row<m; row++) {
3437cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3447cee066cSHong Zhang     for (i=0; i<mr; i++) {
3457cee066cSHong Zhang       col         = *jj++;
346071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
347071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
348071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3497cee066cSHong Zhang     }
3507cee066cSHong Zhang   }
3517cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
352071fcb05SBarry Smith   *ia    = cia;
353071fcb05SBarry Smith   *ja    = cja;
3547cee066cSHong Zhang   *spidx = cspidx;
3557cee066cSHong Zhang   PetscFunctionReturn(0);
3567cee066cSHong Zhang }
3577cee066cSHong Zhang 
3587cee066cSHong Zhang PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3597cee066cSHong Zhang {
3607cee066cSHong Zhang   PetscErrorCode ierr;
3617cee066cSHong Zhang 
3627cee066cSHong Zhang   PetscFunctionBegin;
3635243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3647cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3657cee066cSHong Zhang   PetscFunctionReturn(0);
3667cee066cSHong Zhang }
3677cee066cSHong Zhang 
36887d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
36987d4246cSBarry Smith {
37087d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
37187d4246cSBarry Smith   PetscInt       *ai = a->i;
37287d4246cSBarry Smith   PetscErrorCode ierr;
37387d4246cSBarry Smith 
37487d4246cSBarry Smith   PetscFunctionBegin;
375580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
3768c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
377c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
378e2cf4d64SStefano Zampini #endif
37987d4246cSBarry Smith   PetscFunctionReturn(0);
38087d4246cSBarry Smith }
38187d4246cSBarry Smith 
382bd04181cSBarry Smith /*
383bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
384bd04181cSBarry Smith 
385bd04181cSBarry Smith       -   a single row of values is set with each call
386bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
387bd04181cSBarry Smith       -   the values are always added to the matrix, not set
388bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
389bd04181cSBarry Smith 
3901f763a69SBarry Smith      This does NOT assume the global column indices are sorted
391bd04181cSBarry Smith 
3921f763a69SBarry Smith */
393bd04181cSBarry Smith 
394af0996ceSBarry Smith #include <petsc/private/isimpl.h>
395189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
396189e4007SBarry Smith {
397189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3981f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
3991f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4001f763a69SBarry Smith   PetscInt       lastcol = -1;
401189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
402189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
403189e4007SBarry Smith 
404f38dd0b8SBarry Smith   row  = ridx[im[0]];
4051f763a69SBarry Smith   rp   = aj + ai[row];
4061f763a69SBarry Smith   ap   = aa + ai[row];
4071f763a69SBarry Smith   nrow = ailen[row];
408189e4007SBarry Smith   low  = 0;
409189e4007SBarry Smith   high = nrow;
410189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
411189e4007SBarry Smith     col = cidx[in[l]];
412f38dd0b8SBarry Smith     value = v[l];
413189e4007SBarry Smith 
414189e4007SBarry Smith     if (col <= lastcol) low = 0;
415189e4007SBarry Smith     else high = nrow;
416189e4007SBarry Smith     lastcol = col;
417189e4007SBarry Smith     while (high-low > 5) {
418189e4007SBarry Smith       t = (low+high)/2;
419189e4007SBarry Smith       if (rp[t] > col) high = t;
420189e4007SBarry Smith       else low = t;
421189e4007SBarry Smith     }
422189e4007SBarry Smith     for (i=low; i<high; i++) {
423189e4007SBarry Smith       if (rp[i] == col) {
4241f763a69SBarry Smith         ap[i] += value;
425189e4007SBarry Smith         low = i + 1;
4261f763a69SBarry Smith         break;
427189e4007SBarry Smith       }
428189e4007SBarry Smith     }
429189e4007SBarry Smith   }
4308c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
431c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
432e2cf4d64SStefano Zampini #endif
433f38dd0b8SBarry Smith   return 0;
434189e4007SBarry Smith }
435189e4007SBarry Smith 
43697f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
43717ab2063SBarry Smith {
438416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
439e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
44097f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4416849ba73SBarry Smith   PetscErrorCode ierr;
442e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
443d8cdefa3SHong Zhang   MatScalar      *ap=NULL,value=0.0,*aa = a->a;
444ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
445ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
4468c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
447e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
448e2cf4d64SStefano Zampini #endif
44917ab2063SBarry Smith 
4503a40ed3dSBarry Smith   PetscFunctionBegin;
45117ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
452416022c9SBarry Smith     row = im[k];
4535ef9f2a5SBarry Smith     if (row < 0) continue;
454cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
455720833daSHong Zhang     rp   = aj + ai[row];
456876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
45717ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
458416022c9SBarry Smith     low  = 0;
459c71e6ed7SBarry Smith     high = nrow;
46017ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4615ef9f2a5SBarry Smith       if (in[l] < 0) continue;
462cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
463bfeeae90SHong Zhang       col = in[l];
464071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
465071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
46636db0b34SBarry Smith 
4672205254eSKarl Rupp       if (col <= lastcol) low = 0;
4682205254eSKarl Rupp       else high = nrow;
469e2ee6c50SBarry Smith       lastcol = col;
470416022c9SBarry Smith       while (high-low > 5) {
471416022c9SBarry Smith         t = (low+high)/2;
472416022c9SBarry Smith         if (rp[t] > col) high = t;
473416022c9SBarry Smith         else low = t;
47417ab2063SBarry Smith       }
475416022c9SBarry Smith       for (i=low; i<high; i++) {
47617ab2063SBarry Smith         if (rp[i] > col) break;
47717ab2063SBarry Smith         if (rp[i] == col) {
478876c6284SHong Zhang           if (!A->structure_only) {
4790c0d7e18SFande Kong             if (is == ADD_VALUES) {
4800c0d7e18SFande Kong               ap[i] += value;
4810c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4820c0d7e18SFande Kong             }
48317ab2063SBarry Smith             else ap[i] = value;
4848c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
485e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
486e2cf4d64SStefano Zampini #endif
487720833daSHong Zhang           }
488e44c0bd4SBarry Smith           low = i + 1;
48917ab2063SBarry Smith           goto noinsert;
49017ab2063SBarry Smith         }
49117ab2063SBarry Smith       }
492dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
493c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
494e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
495720833daSHong Zhang       if (A->structure_only) {
496876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
497720833daSHong Zhang       } else {
498fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
499720833daSHong Zhang       }
500c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
501416022c9SBarry Smith       /* shift up all the later entries in this row */
502580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
50317ab2063SBarry Smith       rp[i] = col;
504580bdb30SBarry Smith       if (!A->structure_only){
505580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
506580bdb30SBarry Smith         ap[i] = value;
507580bdb30SBarry Smith       }
508416022c9SBarry Smith       low = i + 1;
509e56f5c9eSBarry Smith       A->nonzerostate++;
5108c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
511e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
512e2cf4d64SStefano Zampini #endif
513e44c0bd4SBarry Smith noinsert:;
51417ab2063SBarry Smith     }
51517ab2063SBarry Smith     ailen[row] = nrow;
51617ab2063SBarry Smith   }
5178c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
518c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
519e2cf4d64SStefano Zampini #endif
5203a40ed3dSBarry Smith   PetscFunctionReturn(0);
52117ab2063SBarry Smith }
52217ab2063SBarry Smith 
52319b08ed1SBarry Smith 
52419b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
52519b08ed1SBarry Smith {
52619b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
52719b08ed1SBarry Smith   PetscInt       *rp,k,row;
52819b08ed1SBarry Smith   PetscInt       *ai = a->i;
52919b08ed1SBarry Smith   PetscErrorCode ierr;
53019b08ed1SBarry Smith   PetscInt       *aj = a->j;
53119b08ed1SBarry Smith   MatScalar      *aa = a->a,*ap;
53219b08ed1SBarry Smith 
53319b08ed1SBarry Smith   PetscFunctionBegin;
53419b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
53519b08ed1SBarry Smith   if (m*n+a->nz > a->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of entries in matrix will be larger than maximum nonzeros allocated for %D in MatSeqAIJSetTotalPreallocation()",a->maxnz);
53619b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
53719b08ed1SBarry Smith     row  = im[k];
53819b08ed1SBarry Smith     rp   = aj + ai[row];
53919b08ed1SBarry Smith     ap   = aa + ai[row];
54019b08ed1SBarry Smith 
54119b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
54219b08ed1SBarry Smith     if (!A->structure_only) {
54319b08ed1SBarry Smith       if (v) {
54419b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
54519b08ed1SBarry Smith         v   += n;
54619b08ed1SBarry Smith       } else {
54719b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
54819b08ed1SBarry Smith       }
54919b08ed1SBarry Smith     }
55019b08ed1SBarry Smith     a->ilen[row] = n;
55119b08ed1SBarry Smith     a->imax[row] = n;
55219b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
55319b08ed1SBarry Smith     a->nz       += n;
55419b08ed1SBarry Smith   }
5558c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
55619b08ed1SBarry Smith   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
55719b08ed1SBarry Smith #endif
55819b08ed1SBarry Smith   PetscFunctionReturn(0);
55919b08ed1SBarry Smith }
56019b08ed1SBarry Smith 
56119b08ed1SBarry Smith /*@
56219b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
56319b08ed1SBarry Smith 
56419b08ed1SBarry Smith   Input Parameters:
56519b08ed1SBarry Smith +  A - the SeqAIJ matrix
56619b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
56719b08ed1SBarry Smith 
56819b08ed1SBarry Smith   Level: advanced
56919b08ed1SBarry Smith 
57019b08ed1SBarry Smith   Notes:
57119b08ed1SBarry Smith     This can be called if you will be provided the matrix row by row (from row zero) with sorted column indices for each row.
57219b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
57319b08ed1SBarry Smith     as always with multiple matrix assemblies.
57419b08ed1SBarry Smith 
57519b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
57619b08ed1SBarry Smith @*/
57719b08ed1SBarry Smith 
57819b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
57919b08ed1SBarry Smith {
58019b08ed1SBarry Smith   PetscErrorCode ierr;
58119b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
58219b08ed1SBarry Smith 
58319b08ed1SBarry Smith   PetscFunctionBegin;
58419b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
58519b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
58619b08ed1SBarry Smith   a->maxnz  = nztotal;
58719b08ed1SBarry Smith   if (!a->imax) {
58819b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
58919b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59019b08ed1SBarry Smith   }
59119b08ed1SBarry Smith   if (!a->ilen) {
59219b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
59319b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59419b08ed1SBarry Smith   } else {
59519b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59619b08ed1SBarry Smith   }
59719b08ed1SBarry Smith 
59819b08ed1SBarry Smith   /* allocate the matrix space */
59919b08ed1SBarry Smith   if (A->structure_only) {
60019b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
60119b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
60219b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
60319b08ed1SBarry Smith   } else {
60419b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
60519b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
60619b08ed1SBarry Smith   }
60719b08ed1SBarry Smith   a->i[0] = 0;
60819b08ed1SBarry Smith   if (A->structure_only) {
60919b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
61019b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
61119b08ed1SBarry Smith   } else {
61219b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
61319b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
61419b08ed1SBarry Smith   }
61519b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
61619b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
61719b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
61819b08ed1SBarry Smith   PetscFunctionReturn(0);
61919b08ed1SBarry Smith }
62019b08ed1SBarry Smith 
621071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
622071fcb05SBarry Smith {
623071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
624071fcb05SBarry Smith   PetscInt       *rp,k,row;
625071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
626071fcb05SBarry Smith   PetscErrorCode ierr;
627071fcb05SBarry Smith   PetscInt       *aj = a->j;
628071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
629071fcb05SBarry Smith 
630071fcb05SBarry Smith   PetscFunctionBegin;
631071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
632071fcb05SBarry Smith     row  = im[k];
63319b08ed1SBarry Smith     if (PetscUnlikelyDebug(n > a->imax[row])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Preallocation for row %D does not match number of columns provided",n);
634071fcb05SBarry Smith     rp   = aj + ai[row];
635071fcb05SBarry Smith     ap   = aa + ai[row];
636071fcb05SBarry Smith     if (!A->was_assembled) {
637071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
638071fcb05SBarry Smith     }
639071fcb05SBarry Smith     if (!A->structure_only) {
640071fcb05SBarry Smith       if (v) {
641071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
642071fcb05SBarry Smith         v   += n;
643071fcb05SBarry Smith       } else {
644071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
645071fcb05SBarry Smith       }
646071fcb05SBarry Smith     }
647071fcb05SBarry Smith     ailen[row] = n;
648071fcb05SBarry Smith     a->nz      += n;
649071fcb05SBarry Smith   }
6508c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
651c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
652e2cf4d64SStefano Zampini #endif
653071fcb05SBarry Smith   PetscFunctionReturn(0);
654071fcb05SBarry Smith }
655071fcb05SBarry Smith 
65681824310SBarry Smith 
657a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6587eb43aa7SLois Curfman McInnes {
6597eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
66097f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
66197f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
66254f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
6637eb43aa7SLois Curfman McInnes 
6643a40ed3dSBarry Smith   PetscFunctionBegin;
6657eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6667eb43aa7SLois Curfman McInnes     row = im[k];
667e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
668e32f2f54SBarry Smith     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
669bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6707eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6717eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
672e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
673e32f2f54SBarry Smith       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
674bfeeae90SHong Zhang       col  = in[l];
6757eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6767eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6777eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6787eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6797eb43aa7SLois Curfman McInnes         else low = t;
6807eb43aa7SLois Curfman McInnes       }
6817eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6827eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6837eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
684b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6857eb43aa7SLois Curfman McInnes           goto finished;
6867eb43aa7SLois Curfman McInnes         }
6877eb43aa7SLois Curfman McInnes       }
68897e567efSBarry Smith       *v++ = 0.0;
6897eb43aa7SLois Curfman McInnes finished:;
6907eb43aa7SLois Curfman McInnes     }
6917eb43aa7SLois Curfman McInnes   }
6923a40ed3dSBarry Smith   PetscFunctionReturn(0);
6937eb43aa7SLois Curfman McInnes }
6947eb43aa7SLois Curfman McInnes 
6953ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
69617ab2063SBarry Smith {
6973ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *A = (Mat_SeqAIJ*)mat->data;
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);
1146b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1147b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1148b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1149b215bc84SStefano Zampini     PetscFunctionReturn(0);
1150b215bc84SStefano Zampini   }
115117ab2063SBarry Smith 
115243ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
115317ab2063SBarry Smith   for (i=1; i<m; i++) {
1154416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
115517ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
115694a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
115717ab2063SBarry Smith     if (fshift) {
1158bfeeae90SHong Zhang       ip = aj + ai[i];
1159bfeeae90SHong Zhang       ap = aa + ai[i];
116017ab2063SBarry Smith       N  = ailen[i];
1161580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1162580bdb30SBarry Smith       if (!A->structure_only) {
1163580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
116417ab2063SBarry Smith       }
116517ab2063SBarry Smith     }
116617ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
116717ab2063SBarry Smith   }
116817ab2063SBarry Smith   if (m) {
116917ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
117017ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
117117ab2063SBarry Smith   }
11727b083b7cSBarry Smith 
117317ab2063SBarry Smith   /* reset ilen and imax for each row */
11747b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1175396832f4SHong Zhang   if (A->structure_only) {
1176071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1177071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1178396832f4SHong Zhang   } else { /* !A->structure_only */
117917ab2063SBarry Smith     for (i=0; i<m; i++) {
118017ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11817b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
118217ab2063SBarry Smith     }
1183396832f4SHong Zhang   }
1184bfeeae90SHong Zhang   a->nz = ai[m];
118565e19b50SBarry 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);
118617ab2063SBarry Smith 
118709f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1188d0f46423SBarry 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);
1189ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1190ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
11912205254eSKarl Rupp 
11928e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1193dd5f02e7SSatish Balay   a->reallocs         = 0;
11946712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
119536db0b34SBarry Smith   a->rmax             = rmax;
11964e220ebcSLois Curfman McInnes 
1197396832f4SHong Zhang   if (!A->structure_only) {
119811e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1199396832f4SHong Zhang   }
12004108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12013a40ed3dSBarry Smith   PetscFunctionReturn(0);
120217ab2063SBarry Smith }
120317ab2063SBarry Smith 
120499cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
120599cafbc1SBarry Smith {
120699cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
120799cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
120854f21887SBarry Smith   MatScalar      *aa = a->a;
1209acf2f550SJed Brown   PetscErrorCode ierr;
121099cafbc1SBarry Smith 
121199cafbc1SBarry Smith   PetscFunctionBegin;
121299cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1213acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12148c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1215c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1216e2cf4d64SStefano Zampini #endif
121799cafbc1SBarry Smith   PetscFunctionReturn(0);
121899cafbc1SBarry Smith }
121999cafbc1SBarry Smith 
122099cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
122199cafbc1SBarry Smith {
122299cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
122399cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
122454f21887SBarry Smith   MatScalar      *aa = a->a;
1225acf2f550SJed Brown   PetscErrorCode ierr;
122699cafbc1SBarry Smith 
122799cafbc1SBarry Smith   PetscFunctionBegin;
122899cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1229acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12308c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1231c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1232e2cf4d64SStefano Zampini #endif
123399cafbc1SBarry Smith   PetscFunctionReturn(0);
123499cafbc1SBarry Smith }
123599cafbc1SBarry Smith 
1236dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
123717ab2063SBarry Smith {
1238416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1239dfbe8321SBarry Smith   PetscErrorCode ierr;
12403a40ed3dSBarry Smith 
12413a40ed3dSBarry Smith   PetscFunctionBegin;
1242580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1243acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12448c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1245c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1246e2cf4d64SStefano Zampini #endif
12473a40ed3dSBarry Smith   PetscFunctionReturn(0);
124817ab2063SBarry Smith }
1249416022c9SBarry Smith 
1250dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
125117ab2063SBarry Smith {
1252416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1253dfbe8321SBarry Smith   PetscErrorCode ierr;
1254d5d45c9bSBarry Smith 
12553a40ed3dSBarry Smith   PetscFunctionBegin;
1256aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1257d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
125817ab2063SBarry Smith #endif
1259e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12606bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12616bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
126205b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1263d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1264071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1265071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1266846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
126771f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
126805b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12696bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
127005b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1271cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1272a30b2313SHong Zhang 
12734108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1274bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1275901853e0SKris Buschelman 
12766718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12776718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12786718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12796718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12806718818eSStefano Zampini      due to different matrix sizes */
12816718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
12826718818eSStefano Zampini 
1283f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1284bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1285bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1286bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1287bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1288bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1289bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
12904222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12914222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1292e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
12934222ddf1SHong Zhang #endif
12943d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
12953d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
12963d0639e7SStefano Zampini #endif
12974222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1298af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1299af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1300af8000cdSHong Zhang #endif
1301d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1302d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1303d24d4204SJose E. Roman #endif
130463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
130563c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13064222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
130763c07aadSStefano Zampini #endif
1308b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1309c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1310c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1311bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1312bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1313846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1314bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1315bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13164222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13174222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13184222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
13193a40ed3dSBarry Smith   PetscFunctionReturn(0);
132017ab2063SBarry Smith }
132117ab2063SBarry Smith 
1322ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
132317ab2063SBarry Smith {
1324416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13254846f1f5SKris Buschelman   PetscErrorCode ierr;
13263a40ed3dSBarry Smith 
13273a40ed3dSBarry Smith   PetscFunctionBegin;
1328a65d3064SKris Buschelman   switch (op) {
1329a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13304e0d8c25SBarry Smith     a->roworiented = flg;
1331a65d3064SKris Buschelman     break;
1332a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1333a9817697SBarry Smith     a->keepnonzeropattern = flg;
1334a65d3064SKris Buschelman     break;
1335512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1336512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1337a65d3064SKris Buschelman     break;
1338a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13394e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1340a65d3064SKris Buschelman     break;
1341a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13424e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1343a65d3064SKris Buschelman     break;
134428b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
134528b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
134628b2fa4aSMatthew Knepley     break;
1347a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13484e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13490df259c2SBarry Smith     break;
13503d472b54SHong Zhang   case MAT_SPD:
1351b1646e73SJed Brown   case MAT_SYMMETRIC:
1352b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1353b1646e73SJed Brown   case MAT_HERMITIAN:
1354b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1355957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13565021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13575021d80fSJed Brown     break;
13584e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1359a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1360a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1361290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1362a65d3064SKris Buschelman     break;
1363b87ac2d8SJed Brown   case MAT_USE_INODES:
1364b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1365b87ac2d8SJed Brown     break;
1366c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1367c10200c1SHong Zhang     A->submat_singleis = flg;
1368c10200c1SHong Zhang     break;
1369071fcb05SBarry Smith   case MAT_SORTED_FULL:
1370071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1371071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1372071fcb05SBarry Smith     break;
1373a65d3064SKris Buschelman   default:
1374e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1375a65d3064SKris Buschelman   }
13763a40ed3dSBarry Smith   PetscFunctionReturn(0);
137717ab2063SBarry Smith }
137817ab2063SBarry Smith 
1379dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
138017ab2063SBarry Smith {
1381416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13826849ba73SBarry Smith   PetscErrorCode ierr;
1383fdc842d1SBarry Smith   PetscInt       i,j,n,*ai=a->i,*aj=a->j;
1384fdc842d1SBarry Smith   PetscScalar    *aa=a->a,*x;
138517ab2063SBarry Smith 
13863a40ed3dSBarry Smith   PetscFunctionBegin;
1387d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1388e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
138935e7444dSHong Zhang 
1390d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1391d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1392fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
13932c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1394fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
139535e7444dSHong Zhang     PetscFunctionReturn(0);
139635e7444dSHong Zhang   }
139735e7444dSHong Zhang 
1398fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
139935e7444dSHong Zhang   for (i=0; i<n; i++) {
1400fdc842d1SBarry Smith     x[i] = 0.0;
140135e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
140235e7444dSHong Zhang       if (aj[j] == i) {
140335e7444dSHong Zhang         x[i] = aa[j];
140417ab2063SBarry Smith         break;
140517ab2063SBarry Smith       }
140617ab2063SBarry Smith     }
140717ab2063SBarry Smith   }
1408fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
14093a40ed3dSBarry Smith   PetscFunctionReturn(0);
141017ab2063SBarry Smith }
141117ab2063SBarry Smith 
1412c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1413dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
141417ab2063SBarry Smith {
1415416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1416d9ca1df4SBarry Smith   PetscScalar       *y;
1417d9ca1df4SBarry Smith   const PetscScalar *x;
1418dfbe8321SBarry Smith   PetscErrorCode    ierr;
1419d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14205c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1421d9ca1df4SBarry Smith   const MatScalar   *v;
1422a77337e4SBarry Smith   PetscScalar       alpha;
1423d9ca1df4SBarry Smith   PetscInt          n,i,j;
1424d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14253447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1426ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14275c897100SBarry Smith #endif
142817ab2063SBarry Smith 
14293a40ed3dSBarry Smith   PetscFunctionBegin;
14302e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1431d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14321ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14335c897100SBarry Smith 
14345c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1435bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14365c897100SBarry Smith #else
14373447b6efSHong Zhang   if (usecprow) {
14383447b6efSHong Zhang     m    = cprow.nrows;
14393447b6efSHong Zhang     ii   = cprow.i;
14407b2bb3b9SHong Zhang     ridx = cprow.rindex;
14413447b6efSHong Zhang   } else {
14423447b6efSHong Zhang     ii = a->i;
14433447b6efSHong Zhang   }
144417ab2063SBarry Smith   for (i=0; i<m; i++) {
14453447b6efSHong Zhang     idx = a->j + ii[i];
14463447b6efSHong Zhang     v   = a->a + ii[i];
14473447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14483447b6efSHong Zhang     if (usecprow) {
14497b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14503447b6efSHong Zhang     } else {
145117ab2063SBarry Smith       alpha = x[i];
14523447b6efSHong Zhang     }
145304fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
145417ab2063SBarry Smith   }
14555c897100SBarry Smith #endif
1456dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1457d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14581ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14593a40ed3dSBarry Smith   PetscFunctionReturn(0);
146017ab2063SBarry Smith }
146117ab2063SBarry Smith 
1462dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14635c897100SBarry Smith {
1464dfbe8321SBarry Smith   PetscErrorCode ierr;
14655c897100SBarry Smith 
14665c897100SBarry Smith   PetscFunctionBegin;
1467170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14685c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14695c897100SBarry Smith   PetscFunctionReturn(0);
14705c897100SBarry Smith }
14715c897100SBarry Smith 
1472c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
147378b84d54SShri Abhyankar 
1474dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
147517ab2063SBarry Smith {
1476416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1477d9fead3dSBarry Smith   PetscScalar       *y;
147854f21887SBarry Smith   const PetscScalar *x;
147954f21887SBarry Smith   const MatScalar   *aa;
1480dfbe8321SBarry Smith   PetscErrorCode    ierr;
1481003131ecSBarry Smith   PetscInt          m=A->rmap->n;
14820298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
14837b083b7cSBarry Smith   PetscInt          n,i;
1484362ced78SSatish Balay   PetscScalar       sum;
1485ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
148617ab2063SBarry Smith 
1487b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
148897952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1489fee21e36SBarry Smith #endif
1490fee21e36SBarry Smith 
14913a40ed3dSBarry Smith   PetscFunctionBegin;
1492b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1493b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1494b215bc84SStefano Zampini     PetscFunctionReturn(0);
1495b215bc84SStefano Zampini   }
14963649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14971ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1498416022c9SBarry Smith   ii   = a->i;
14994eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1500580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
150197952fefSHong Zhang     m    = a->compressedrow.nrows;
150297952fefSHong Zhang     ii   = a->compressedrow.i;
150397952fefSHong Zhang     ridx = a->compressedrow.rindex;
150497952fefSHong Zhang     for (i=0; i<m; i++) {
150597952fefSHong Zhang       n           = ii[i+1] - ii[i];
150697952fefSHong Zhang       aj          = a->j + ii[i];
150797952fefSHong Zhang       aa          = a->a + ii[i];
150897952fefSHong Zhang       sum         = 0.0;
1509003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1510003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
151197952fefSHong Zhang       y[*ridx++] = sum;
151297952fefSHong Zhang     }
151397952fefSHong Zhang   } else { /* do not use compressed row format */
1514b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15153d3eaba7SBarry Smith     aj   = a->j;
15163d3eaba7SBarry Smith     aa   = a->a;
1517b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1518b05257ddSBarry Smith #else
151917ab2063SBarry Smith     for (i=0; i<m; i++) {
1520003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1521003131ecSBarry Smith       aj          = a->j + ii[i];
1522003131ecSBarry Smith       aa          = a->a + ii[i];
152317ab2063SBarry Smith       sum         = 0.0;
1524003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
152517ab2063SBarry Smith       y[i] = sum;
152617ab2063SBarry Smith     }
15278d195f9aSBarry Smith #endif
1528b05257ddSBarry Smith   }
15297b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15303649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15311ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15323a40ed3dSBarry Smith   PetscFunctionReturn(0);
153317ab2063SBarry Smith }
153417ab2063SBarry Smith 
1535b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1536b434eb95SMatthew G. Knepley {
1537b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1538b434eb95SMatthew G. Knepley   PetscScalar       *y;
1539b434eb95SMatthew G. Knepley   const PetscScalar *x;
1540b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1541b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1542b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1543b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1544b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1545b434eb95SMatthew G. Knepley   PetscScalar       sum;
1546b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1547b434eb95SMatthew G. Knepley 
1548b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1549b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1550b434eb95SMatthew G. Knepley #endif
1551b434eb95SMatthew G. Knepley 
1552b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1553b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1554b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1555b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1556b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1557b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1558b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1559b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1560b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1561b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1562b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1563b434eb95SMatthew G. Knepley       sum         = 0.0;
1564b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1565b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1566b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1567b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1568b434eb95SMatthew G. Knepley     }
1569b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15703d3eaba7SBarry Smith     ii = a->i;
1571b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1572b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1573b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1574b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1575b434eb95SMatthew G. Knepley       sum         = 0.0;
1576b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1577b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1578b434eb95SMatthew G. Knepley       y[i] = sum;
1579b434eb95SMatthew G. Knepley     }
1580b434eb95SMatthew G. Knepley   }
1581b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1582b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1583b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1584b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1585b434eb95SMatthew G. Knepley }
1586b434eb95SMatthew G. Knepley 
1587b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1588b434eb95SMatthew G. Knepley {
1589b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1590b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1591b434eb95SMatthew G. Knepley   const PetscScalar *x;
1592b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1593b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1594b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1595b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1596b434eb95SMatthew G. Knepley   PetscScalar       sum;
1597b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1598b434eb95SMatthew G. Knepley 
1599b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1600b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1601d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1602b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1603b434eb95SMatthew G. Knepley     if (zz != yy) {
1604580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1605b434eb95SMatthew G. Knepley     }
1606b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1607b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1608b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1609b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1610b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1611b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1612b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1613b434eb95SMatthew G. Knepley       sum = y[*ridx];
1614b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1615b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1616b434eb95SMatthew G. Knepley     }
1617b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16183d3eaba7SBarry Smith     ii = a->i;
1619b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1620b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1621b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1622b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1623b434eb95SMatthew G. Knepley       sum = y[i];
1624b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1625b434eb95SMatthew G. Knepley       z[i] = sum;
1626b434eb95SMatthew G. Knepley     }
1627b434eb95SMatthew G. Knepley   }
1628b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1629b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1630d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1631b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1632b434eb95SMatthew G. Knepley }
1633b434eb95SMatthew G. Knepley 
1634c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1635dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
163617ab2063SBarry Smith {
1637416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1638f15663dcSBarry Smith   PetscScalar       *y,*z;
1639f15663dcSBarry Smith   const PetscScalar *x;
164054f21887SBarry Smith   const MatScalar   *aa;
1641dfbe8321SBarry Smith   PetscErrorCode    ierr;
1642d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1643d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1644362ced78SSatish Balay   PetscScalar       sum;
1645ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16469ea0dfa2SSatish Balay 
16473a40ed3dSBarry Smith   PetscFunctionBegin;
1648b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1649b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1650b215bc84SStefano Zampini     PetscFunctionReturn(0);
1651b215bc84SStefano Zampini   }
1652f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1653d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16544eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16554eb6d288SHong Zhang     if (zz != yy) {
1656580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16574eb6d288SHong Zhang     }
165897952fefSHong Zhang     m    = a->compressedrow.nrows;
165997952fefSHong Zhang     ii   = a->compressedrow.i;
166097952fefSHong Zhang     ridx = a->compressedrow.rindex;
166197952fefSHong Zhang     for (i=0; i<m; i++) {
166297952fefSHong Zhang       n   = ii[i+1] - ii[i];
166397952fefSHong Zhang       aj  = a->j + ii[i];
166497952fefSHong Zhang       aa  = a->a + ii[i];
166597952fefSHong Zhang       sum = y[*ridx];
1666f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
166797952fefSHong Zhang       z[*ridx++] = sum;
166897952fefSHong Zhang     }
166997952fefSHong Zhang   } else { /* do not use compressed row format */
16703d3eaba7SBarry Smith     ii = a->i;
1671f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16723d3eaba7SBarry Smith     aj = a->j;
16733d3eaba7SBarry Smith     aa = a->a;
1674f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1675f15663dcSBarry Smith #else
167617ab2063SBarry Smith     for (i=0; i<m; i++) {
1677f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1678f15663dcSBarry Smith       aj  = a->j + ii[i];
1679f15663dcSBarry Smith       aa  = a->a + ii[i];
168017ab2063SBarry Smith       sum = y[i];
1681f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
168217ab2063SBarry Smith       z[i] = sum;
168317ab2063SBarry Smith     }
168402ab625aSSatish Balay #endif
1685f15663dcSBarry Smith   }
1686dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1687f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1688d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16893a40ed3dSBarry Smith   PetscFunctionReturn(0);
169017ab2063SBarry Smith }
169117ab2063SBarry Smith 
169217ab2063SBarry Smith /*
169317ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
169417ab2063SBarry Smith */
1695dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
169617ab2063SBarry Smith {
1697416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
16986849ba73SBarry Smith   PetscErrorCode ierr;
1699d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
170017ab2063SBarry Smith 
17013a40ed3dSBarry Smith   PetscFunctionBegin;
170209f38230SBarry Smith   if (!a->diag) {
1703785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17043bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
170509f38230SBarry Smith   }
1706d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
170709f38230SBarry Smith     a->diag[i] = a->i[i+1];
1708bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1709bfeeae90SHong Zhang       if (a->j[j] == i) {
171009f38230SBarry Smith         a->diag[i] = j;
171117ab2063SBarry Smith         break;
171217ab2063SBarry Smith       }
171317ab2063SBarry Smith     }
171417ab2063SBarry Smith   }
17153a40ed3dSBarry Smith   PetscFunctionReturn(0);
171617ab2063SBarry Smith }
171717ab2063SBarry Smith 
171861ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
171961ecd0c6SBarry Smith {
172061ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
172161ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
172261ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
172361ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
172461ecd0c6SBarry Smith   PetscErrorCode    ierr;
172561ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
172661ecd0c6SBarry Smith 
172761ecd0c6SBarry Smith   PetscFunctionBegin;
172861ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
172961ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
173061ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
173161ecd0c6SBarry Smith     PetscFunctionReturn(0);
173261ecd0c6SBarry Smith   }
173361ecd0c6SBarry Smith 
173461ecd0c6SBarry Smith   if (a->diagonaldense) {
173561ecd0c6SBarry Smith     cnt = 0;
173661ecd0c6SBarry Smith   } else {
173761ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
173861ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
173961ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
174061ecd0c6SBarry Smith         cnt++;
174161ecd0c6SBarry Smith         mdiag[i] = 1;
174261ecd0c6SBarry Smith       }
174361ecd0c6SBarry Smith     }
174461ecd0c6SBarry Smith   }
174561ecd0c6SBarry Smith   if (!cnt) {
174661ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
174761ecd0c6SBarry Smith   } else {
1748b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1749b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
175061ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
175161ecd0c6SBarry Smith 
175261ecd0c6SBarry Smith     a->a = NULL;
175361ecd0c6SBarry Smith     a->j = NULL;
175461ecd0c6SBarry Smith     a->i = NULL;
175561ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
175661ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
175761ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1758447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
175961ecd0c6SBarry Smith     }
176061ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
176161ecd0c6SBarry Smith 
176261ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
176361ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
176461ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1765447d62f5SStefano Zampini       if (i < A->cmap->n) {
176661ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
176761ecd0c6SBarry Smith       }
1768447d62f5SStefano Zampini     }
176961ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
177061ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
177161ecd0c6SBarry Smith     if (singlemalloc) {
177261ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
177361ecd0c6SBarry Smith     } else {
177461ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
177561ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
177661ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
177761ecd0c6SBarry Smith     }
177861ecd0c6SBarry Smith   }
177961ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
178061ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
178161ecd0c6SBarry Smith   PetscFunctionReturn(0);
178261ecd0c6SBarry Smith }
178361ecd0c6SBarry Smith 
1784be5855fcSBarry Smith /*
1785be5855fcSBarry Smith      Checks for missing diagonals
1786be5855fcSBarry Smith */
1787ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1788be5855fcSBarry Smith {
1789be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17907734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1791994fe344SLisandro Dalcin   PetscErrorCode ierr;
1792be5855fcSBarry Smith 
1793be5855fcSBarry Smith   PetscFunctionBegin;
179409f38230SBarry Smith   *missing = PETSC_FALSE;
17957734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
179609f38230SBarry Smith     *missing = PETSC_TRUE;
179709f38230SBarry Smith     if (d) *d = 0;
1798994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
179909f38230SBarry Smith   } else {
180001445905SHong Zhang     PetscInt n;
180101445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1802f1e2ffcdSBarry Smith     diag = a->diag;
180301445905SHong Zhang     for (i=0; i<n; i++) {
18047734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
180509f38230SBarry Smith         *missing = PETSC_TRUE;
180609f38230SBarry Smith         if (d) *d = i;
1807994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1808358d2f5dSShri Abhyankar         break;
180909f38230SBarry Smith       }
1810be5855fcSBarry Smith     }
1811be5855fcSBarry Smith   }
1812be5855fcSBarry Smith   PetscFunctionReturn(0);
1813be5855fcSBarry Smith }
1814be5855fcSBarry Smith 
18150da83c2eSBarry Smith #include <petscblaslapack.h>
18160da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18170da83c2eSBarry Smith 
18180da83c2eSBarry Smith /*
18190da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18200da83c2eSBarry Smith */
18210da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18220da83c2eSBarry Smith {
18230da83c2eSBarry Smith   PetscErrorCode  ierr;
18240da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18250da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18260da83c2eSBarry Smith   const PetscReal shift = 0.0;
18270da83c2eSBarry Smith   PetscInt        ipvt[5];
18280da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18290da83c2eSBarry Smith 
18300da83c2eSBarry Smith   PetscFunctionBegin;
18310da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18320da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18330da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18340da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18350da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18360da83c2eSBarry Smith   }
18370da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18380da83c2eSBarry Smith   if (bsizemax > 7) {
18390da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18400da83c2eSBarry Smith   }
18410da83c2eSBarry Smith   ncnt = 0;
18420da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18430da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18440da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18450da83c2eSBarry Smith     switch (bsizes[i]) {
18460da83c2eSBarry Smith     case 1:
18470da83c2eSBarry Smith       *diag = 1.0/(*diag);
18480da83c2eSBarry Smith       break;
18490da83c2eSBarry Smith     case 2:
18500da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18510da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18520da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18530da83c2eSBarry Smith       break;
18540da83c2eSBarry Smith     case 3:
18550da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18560da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18570da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18580da83c2eSBarry Smith       break;
18590da83c2eSBarry Smith     case 4:
18600da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18610da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18620da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18630da83c2eSBarry Smith       break;
18640da83c2eSBarry Smith     case 5:
18650da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18660da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18670da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18680da83c2eSBarry Smith       break;
18690da83c2eSBarry Smith     case 6:
18700da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18710da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18720da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
18730da83c2eSBarry Smith       break;
18740da83c2eSBarry Smith     case 7:
18750da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18760da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18770da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
18780da83c2eSBarry Smith       break;
18790da83c2eSBarry Smith     default:
18800da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18810da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18820da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
18830da83c2eSBarry Smith     }
18840da83c2eSBarry Smith     ncnt   += bsizes[i];
18850da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
18860da83c2eSBarry Smith   }
18870da83c2eSBarry Smith   if (bsizemax > 7) {
18880da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
18890da83c2eSBarry Smith   }
18900da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
18910da83c2eSBarry Smith   PetscFunctionReturn(0);
18920da83c2eSBarry Smith }
18930da83c2eSBarry Smith 
1894422a814eSBarry Smith /*
1895422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1896422a814eSBarry Smith */
18977087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
189871f1c65dSBarry Smith {
189971f1c65dSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
190071f1c65dSBarry Smith   PetscErrorCode ierr;
1901d0f46423SBarry Smith   PetscInt       i,*diag,m = A->rmap->n;
190254f21887SBarry Smith   MatScalar      *v = a->a;
190354f21887SBarry Smith   PetscScalar    *idiag,*mdiag;
190471f1c65dSBarry Smith 
190571f1c65dSBarry Smith   PetscFunctionBegin;
190671f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
190771f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
190871f1c65dSBarry Smith   diag = a->diag;
190971f1c65dSBarry Smith   if (!a->idiag) {
1910dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19113bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
191271f1c65dSBarry Smith     v    = a->a;
191371f1c65dSBarry Smith   }
191471f1c65dSBarry Smith   mdiag = a->mdiag;
191571f1c65dSBarry Smith   idiag = a->idiag;
191671f1c65dSBarry Smith 
1917422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
191871f1c65dSBarry Smith     for (i=0; i<m; i++) {
191971f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1920899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1921899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1922899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19237b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19247b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19257b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1926a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1927899639b0SHong Zhang       }
192871f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
192971f1c65dSBarry Smith     }
193071f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
193171f1c65dSBarry Smith   } else {
193271f1c65dSBarry Smith     for (i=0; i<m; i++) {
193371f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
193471f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
193571f1c65dSBarry Smith     }
1936dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
193771f1c65dSBarry Smith   }
193871f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
193971f1c65dSBarry Smith   PetscFunctionReturn(0);
194071f1c65dSBarry Smith }
194171f1c65dSBarry Smith 
1942c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
194341f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
194417ab2063SBarry Smith {
1945416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1946e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
1947f4259b30SLisandro Dalcin   const MatScalar   *v,*idiag=NULL,*mdiag;
194854f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1949dfbe8321SBarry Smith   PetscErrorCode    ierr;
19503d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
195197f1f81fSBarry Smith   const PetscInt    *idx,*diag;
195217ab2063SBarry Smith 
19533a40ed3dSBarry Smith   PetscFunctionBegin;
1954b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1955b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1956b215bc84SStefano Zampini     PetscFunctionReturn(0);
1957b215bc84SStefano Zampini   }
1958b965ef7fSBarry Smith   its = its*lits;
195991723122SBarry Smith 
196071f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
196171f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
196271f1c65dSBarry Smith   a->fshift = fshift;
196371f1c65dSBarry Smith   a->omega  = omega;
1964ed480e8bSBarry Smith 
196571f1c65dSBarry Smith   diag  = a->diag;
196671f1c65dSBarry Smith   t     = a->ssor_work;
1967ed480e8bSBarry Smith   idiag = a->idiag;
196871f1c65dSBarry Smith   mdiag = a->mdiag;
1969ed480e8bSBarry Smith 
19701ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
19713649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1972ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
197317ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
197417ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1975ed480e8bSBarry Smith     bs = b;
197617ab2063SBarry Smith     for (i=0; i<m; i++) {
197771f1c65dSBarry Smith       d   = fshift + mdiag[i];
1978416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1979ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1980ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
198117ab2063SBarry Smith       sum = b[i]*d/omega;
1982003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
198317ab2063SBarry Smith       x[i] = sum;
198417ab2063SBarry Smith     }
19851ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
19863649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1987efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
19883a40ed3dSBarry Smith     PetscFunctionReturn(0);
198917ab2063SBarry Smith   }
1990c783ea89SBarry Smith 
19912205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
19922205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
19934c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1994887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
199517ab2063SBarry Smith 
199617ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
199717ab2063SBarry Smith 
1998887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
199917ab2063SBarry Smith     */
200017ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
200117ab2063SBarry Smith 
200217ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
200317ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2004416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2005ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
2006ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
200717ab2063SBarry Smith       sum = b[i];
2008e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2009ed480e8bSBarry Smith       x[i] = sum*idiag[i];
201017ab2063SBarry Smith     }
201117ab2063SBarry Smith 
201217ab2063SBarry Smith     /*  t = b - (2*E - D)x */
2013416022c9SBarry Smith     v = a->a;
20142205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
201517ab2063SBarry Smith 
201617ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2017ed480e8bSBarry Smith     ts   = t;
2018416022c9SBarry Smith     diag = a->diag;
201917ab2063SBarry Smith     for (i=0; i<m; i++) {
2020416022c9SBarry Smith       n   = diag[i] - a->i[i];
2021ed480e8bSBarry Smith       idx = a->j + a->i[i];
2022ed480e8bSBarry Smith       v   = a->a + a->i[i];
202317ab2063SBarry Smith       sum = t[i];
2024003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2025ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2026733d66baSBarry Smith       /*  x = x + t */
2027733d66baSBarry Smith       x[i] += t[i];
202817ab2063SBarry Smith     }
202917ab2063SBarry Smith 
2030dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20311ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20323649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20333a40ed3dSBarry Smith     PetscFunctionReturn(0);
203417ab2063SBarry Smith   }
203517ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
203617ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
203717ab2063SBarry Smith       for (i=0; i<m; i++) {
2038416022c9SBarry Smith         n   = diag[i] - a->i[i];
2039ed480e8bSBarry Smith         idx = a->j + a->i[i];
2040ed480e8bSBarry Smith         v   = a->a + a->i[i];
204117ab2063SBarry Smith         sum = b[i];
2042e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20435c99c7daSBarry Smith         t[i] = sum;
2044ed480e8bSBarry Smith         x[i] = sum*idiag[i];
204517ab2063SBarry Smith       }
20465c99c7daSBarry Smith       xb   = t;
2047efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20483a40ed3dSBarry Smith     } else xb = b;
204917ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
205017ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2051416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2052ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
2053ed480e8bSBarry Smith         v   = a->a + diag[i] + 1;
205417ab2063SBarry Smith         sum = xb[i];
2055e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20565c99c7daSBarry Smith         if (xb == b) {
2057ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20585c99c7daSBarry Smith         } else {
2059b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
206017ab2063SBarry Smith         }
20615c99c7daSBarry Smith       }
2062b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
206317ab2063SBarry Smith     }
206417ab2063SBarry Smith     its--;
206517ab2063SBarry Smith   }
206617ab2063SBarry Smith   while (its--) {
206717ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
206817ab2063SBarry Smith       for (i=0; i<m; i++) {
2069b19a5dc2SMark Adams         /* lower */
2070b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2071ed480e8bSBarry Smith         idx = a->j + a->i[i];
2072ed480e8bSBarry Smith         v   = a->a + a->i[i];
207317ab2063SBarry Smith         sum = b[i];
2074e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2075b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2076b19a5dc2SMark Adams         /* upper */
2077b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2078b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
2079b19a5dc2SMark Adams         v   = a->a + diag[i] + 1;
2080b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2081b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
208217ab2063SBarry Smith       }
2083b19a5dc2SMark Adams       xb   = t;
20849f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2085b19a5dc2SMark Adams     } else xb = b;
208617ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
208717ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2088b19a5dc2SMark Adams         sum = xb[i];
2089b19a5dc2SMark Adams         if (xb == b) {
2090b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2091416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2092ed480e8bSBarry Smith           idx = a->j + a->i[i];
2093ed480e8bSBarry Smith           v   = a->a + a->i[i];
2094e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2095ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2096b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2097b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2098b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
2099b19a5dc2SMark Adams           v   = a->a + diag[i] + 1;
2100b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2101b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
210217ab2063SBarry Smith         }
2103b19a5dc2SMark Adams       }
2104b19a5dc2SMark Adams       if (xb == b) {
21059f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2106b19a5dc2SMark Adams       } else {
2107b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2108b19a5dc2SMark Adams       }
210917ab2063SBarry Smith     }
211017ab2063SBarry Smith   }
21111ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21123649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2113365a8a9eSBarry Smith   PetscFunctionReturn(0);
211417ab2063SBarry Smith }
211517ab2063SBarry Smith 
21162af78befSBarry Smith 
2117dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
211817ab2063SBarry Smith {
2119416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21204e220ebcSLois Curfman McInnes 
21213a40ed3dSBarry Smith   PetscFunctionBegin;
21224e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21233966268fSBarry Smith   info->nz_allocated = a->maxnz;
21243966268fSBarry Smith   info->nz_used      = a->nz;
21253966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21263966268fSBarry Smith   info->assemblies   = A->num_ass;
21273966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21287adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2129d5f3da31SBarry Smith   if (A->factortype) {
21304e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21314e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21324e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21334e220ebcSLois Curfman McInnes   } else {
21344e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21354e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21364e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21374e220ebcSLois Curfman McInnes   }
21383a40ed3dSBarry Smith   PetscFunctionReturn(0);
213917ab2063SBarry Smith }
214017ab2063SBarry Smith 
21412b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
214217ab2063SBarry Smith {
2143416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2144c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21456849ba73SBarry Smith   PetscErrorCode    ierr;
214697b48c8fSBarry Smith   const PetscScalar *xx;
214797b48c8fSBarry Smith   PetscScalar       *bb;
2148c7da8527SEric Chamberland   PetscInt          d = 0;
214917ab2063SBarry Smith 
21503a40ed3dSBarry Smith   PetscFunctionBegin;
215197b48c8fSBarry Smith   if (x && b) {
215297b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
215397b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
215497b48c8fSBarry Smith     for (i=0; i<N; i++) {
215597b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2156447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
215797b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
215897b48c8fSBarry Smith     }
215997b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
216097b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
216197b48c8fSBarry Smith   }
216297b48c8fSBarry Smith 
2163a9817697SBarry Smith   if (a->keepnonzeropattern) {
2164f1e2ffcdSBarry 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]);
2166580bdb30SBarry Smith       ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2167f1e2ffcdSBarry Smith     }
2168f4df32b1SMatthew Knepley     if (diag != 0.0) {
2169c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2170c7da8527SEric Chamberland         d = rows[i];
2171447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2172c7da8527SEric 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);
2173c7da8527SEric Chamberland       }
2174f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2175447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2176f4df32b1SMatthew Knepley         a->a[a->diag[rows[i]]] = diag;
2177f1e2ffcdSBarry Smith       }
2178f1e2ffcdSBarry Smith     }
2179f1e2ffcdSBarry Smith   } else {
2180f4df32b1SMatthew Knepley     if (diag != 0.0) {
218117ab2063SBarry Smith       for (i=0; i<N; i++) {
2182e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
21837ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2184447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2185447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2186447d62f5SStefano Zampini           } else {
2187416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
2188f4df32b1SMatthew Knepley             a->a[a->i[rows[i]]] = diag;
2189bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2190447d62f5SStefano Zampini           }
2191447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2192f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
219317ab2063SBarry Smith         }
219417ab2063SBarry Smith       }
21953a40ed3dSBarry Smith     } else {
219617ab2063SBarry Smith       for (i=0; i<N; i++) {
2197e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2198416022c9SBarry Smith         a->ilen[rows[i]] = 0;
219917ab2063SBarry Smith       }
220017ab2063SBarry Smith     }
2201e56f5c9eSBarry Smith     A->nonzerostate++;
2202f1e2ffcdSBarry Smith   }
22038c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2204c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2205e2cf4d64SStefano Zampini #endif
22064099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22073a40ed3dSBarry Smith   PetscFunctionReturn(0);
220817ab2063SBarry Smith }
220917ab2063SBarry Smith 
22106e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22116e169961SBarry Smith {
22126e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22136e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22146e169961SBarry Smith   PetscErrorCode    ierr;
22152b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22166e169961SBarry Smith   const PetscScalar *xx;
22176e169961SBarry Smith   PetscScalar       *bb;
22186e169961SBarry Smith 
22196e169961SBarry Smith   PetscFunctionBegin;
22206e169961SBarry Smith   if (x && b) {
22216e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22226e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22232b40b63fSBarry Smith     vecs = PETSC_TRUE;
22246e169961SBarry Smith   }
22251795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22266e169961SBarry Smith   for (i=0; i<N; i++) {
22276e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2228580bdb30SBarry Smith     ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22292205254eSKarl Rupp 
22306e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22316e169961SBarry Smith   }
22326e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22336e169961SBarry Smith     if (!zeroed[i]) {
22346e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22354cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22362b40b63fSBarry Smith           if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
22376e169961SBarry Smith           a->a[j] = 0.0;
22386e169961SBarry Smith         }
22396e169961SBarry Smith       }
22404cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22416e169961SBarry Smith   }
22426e169961SBarry Smith   if (x && b) {
22436e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22446e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22456e169961SBarry Smith   }
22466e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22476e169961SBarry Smith   if (diag != 0.0) {
22486e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22491d5a398dSstefano_zampini     if (missing) {
22501d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22514cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22524cf107fdSStefano 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]);
22531d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22541d5a398dSstefano_zampini       }
22551d5a398dSstefano_zampini     } else {
22566e169961SBarry Smith       for (i=0; i<N; i++) {
22576e169961SBarry Smith         a->a[a->diag[rows[i]]] = diag;
22586e169961SBarry Smith       }
22596e169961SBarry Smith     }
22601d5a398dSstefano_zampini   }
22618c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2262c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2263e2cf4d64SStefano Zampini #endif
22644099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22656e169961SBarry Smith   PetscFunctionReturn(0);
22666e169961SBarry Smith }
22676e169961SBarry Smith 
2268a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
226917ab2063SBarry Smith {
2270416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
227197f1f81fSBarry Smith   PetscInt   *itmp;
227217ab2063SBarry Smith 
22733a40ed3dSBarry Smith   PetscFunctionBegin;
2274e32f2f54SBarry Smith   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
227517ab2063SBarry Smith 
2276416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
2277bfeeae90SHong Zhang   if (v) *v = a->a + a->i[row];
227817ab2063SBarry Smith   if (idx) {
2279bfeeae90SHong Zhang     itmp = a->j + a->i[row];
228026fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2281f4259b30SLisandro Dalcin     else *idx = NULL;
228217ab2063SBarry Smith   }
22833a40ed3dSBarry Smith   PetscFunctionReturn(0);
228417ab2063SBarry Smith }
228517ab2063SBarry Smith 
2286bfeeae90SHong Zhang /* remove this function? */
2287a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
228817ab2063SBarry Smith {
22893a40ed3dSBarry Smith   PetscFunctionBegin;
22903a40ed3dSBarry Smith   PetscFunctionReturn(0);
229117ab2063SBarry Smith }
229217ab2063SBarry Smith 
2293dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
229417ab2063SBarry Smith {
2295416022c9SBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
229654f21887SBarry Smith   MatScalar      *v  = a->a;
229736db0b34SBarry Smith   PetscReal      sum = 0.0;
22986849ba73SBarry Smith   PetscErrorCode ierr;
229997f1f81fSBarry Smith   PetscInt       i,j;
230017ab2063SBarry Smith 
23013a40ed3dSBarry Smith   PetscFunctionBegin;
230217ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2303570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2304570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
2305570b7f6dSBarry Smith     *nrm = BLASnrm2_(&nz,v,&one);
2306570b7f6dSBarry Smith #else
2307416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
230836db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
230917ab2063SBarry Smith     }
23108f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2311570b7f6dSBarry Smith #endif
2312ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23133a40ed3dSBarry Smith   } else if (type == NORM_1) {
231436db0b34SBarry Smith     PetscReal *tmp;
231597f1f81fSBarry Smith     PetscInt  *jj = a->j;
23161795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2317064f8208SBarry Smith     *nrm = 0.0;
2318416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2319bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
232017ab2063SBarry Smith     }
2321d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2322064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
232317ab2063SBarry Smith     }
2324606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
232551f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23263a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2327064f8208SBarry Smith     *nrm = 0.0;
2328d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
2329bfeeae90SHong Zhang       v   = a->a + a->i[j];
233017ab2063SBarry Smith       sum = 0.0;
2331416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
2332cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
233317ab2063SBarry Smith       }
2334064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
233517ab2063SBarry Smith     }
233651f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2337f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23383a40ed3dSBarry Smith   PetscFunctionReturn(0);
233917ab2063SBarry Smith }
234017ab2063SBarry Smith 
23414e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23424e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23434e938277SHong Zhang {
23444e938277SHong Zhang   PetscErrorCode ierr;
23454e938277SHong Zhang   PetscInt       i,j,anzj;
23464e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23474e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23484e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23494e938277SHong Zhang 
23504e938277SHong Zhang   PetscFunctionBegin;
23514e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2352854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2353785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2354785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
23554e938277SHong Zhang 
23564e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23574e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
235826fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
23594e938277SHong Zhang   /* Form ati for csr format of A^T. */
236026fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
23614e938277SHong Zhang 
23624e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2363580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
23644e938277SHong Zhang 
23654e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
23664e938277SHong Zhang   for (i=0;i<am;i++) {
23674e938277SHong Zhang     anzj = ai[i+1] - ai[i];
23684e938277SHong Zhang     for (j=0;j<anzj;j++) {
23694e938277SHong Zhang       atj[atfill[*aj]] = i;
23704e938277SHong Zhang       atfill[*aj++]   += 1;
23714e938277SHong Zhang     }
23724e938277SHong Zhang   }
23734e938277SHong Zhang 
23744e938277SHong Zhang   /* Clean up temporary space and complete requests. */
23754e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2376ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
237733d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2378b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2379a2f3521dSMark F. Adams 
23804e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
23814e938277SHong Zhang   b->free_a  = PETSC_FALSE;
23824e938277SHong Zhang   b->free_ij = PETSC_TRUE;
23834e938277SHong Zhang   b->nonew   = 0;
23844e938277SHong Zhang   PetscFunctionReturn(0);
23854e938277SHong Zhang }
23864e938277SHong Zhang 
23877087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2388cd0d46ebSvictorle {
23893d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
239054f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
239154f21887SBarry Smith   MatScalar      *va,*vb;
23926849ba73SBarry Smith   PetscErrorCode ierr;
239397f1f81fSBarry Smith   PetscInt       ma,na,mb,nb, i;
2394cd0d46ebSvictorle 
2395cd0d46ebSvictorle   PetscFunctionBegin;
2396cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2397cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
23985485867bSBarry Smith   if (ma!=nb || na!=mb) {
23995485867bSBarry Smith     *f = PETSC_FALSE;
24005485867bSBarry Smith     PetscFunctionReturn(0);
24015485867bSBarry Smith   }
2402cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2403cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2404cd0d46ebSvictorle   va   = aij->a; vb = bij->a;
2405785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2406785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2407cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2408cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2409cd0d46ebSvictorle 
2410cd0d46ebSvictorle   *f = PETSC_TRUE;
2411cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2412cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
241397f1f81fSBarry Smith       PetscInt    idc,idr;
24145485867bSBarry Smith       PetscScalar vc,vr;
2415cd0d46ebSvictorle       /* column/row index/value */
24165485867bSBarry Smith       idc = adx[aptr[i]];
24175485867bSBarry Smith       idr = bdx[bptr[idc]];
24185485867bSBarry Smith       vc  = va[aptr[i]];
24195485867bSBarry Smith       vr  = vb[bptr[idc]];
24205485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24215485867bSBarry Smith         *f = PETSC_FALSE;
24225485867bSBarry Smith         goto done;
2423cd0d46ebSvictorle       } else {
24245485867bSBarry Smith         aptr[i]++;
24255485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2426cd0d46ebSvictorle       }
2427cd0d46ebSvictorle     }
2428cd0d46ebSvictorle   }
2429cd0d46ebSvictorle done:
2430cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24313aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
2432cd0d46ebSvictorle   PetscFunctionReturn(0);
2433cd0d46ebSvictorle }
2434cd0d46ebSvictorle 
24357087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24361cbb95d3SBarry Smith {
24373d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
243854f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
243954f21887SBarry Smith   MatScalar      *va,*vb;
24401cbb95d3SBarry Smith   PetscErrorCode ierr;
24411cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24421cbb95d3SBarry Smith 
24431cbb95d3SBarry Smith   PetscFunctionBegin;
24441cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
24451cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24461cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24471cbb95d3SBarry Smith     *f = PETSC_FALSE;
24481cbb95d3SBarry Smith     PetscFunctionReturn(0);
24491cbb95d3SBarry Smith   }
24501cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24511cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24521cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2453785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2454785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
24551cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
24561cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
24571cbb95d3SBarry Smith 
24581cbb95d3SBarry Smith   *f = PETSC_TRUE;
24591cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
24601cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
24611cbb95d3SBarry Smith       PetscInt    idc,idr;
24621cbb95d3SBarry Smith       PetscScalar vc,vr;
24631cbb95d3SBarry Smith       /* column/row index/value */
24641cbb95d3SBarry Smith       idc = adx[aptr[i]];
24651cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
24661cbb95d3SBarry Smith       vc  = va[aptr[i]];
24671cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
24681cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
24691cbb95d3SBarry Smith         *f = PETSC_FALSE;
24701cbb95d3SBarry Smith         goto done;
24711cbb95d3SBarry Smith       } else {
24721cbb95d3SBarry Smith         aptr[i]++;
24731cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
24741cbb95d3SBarry Smith       }
24751cbb95d3SBarry Smith     }
24761cbb95d3SBarry Smith   }
24771cbb95d3SBarry Smith done:
24781cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
24791cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
24801cbb95d3SBarry Smith   PetscFunctionReturn(0);
24811cbb95d3SBarry Smith }
24821cbb95d3SBarry Smith 
2483ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24849e29f15eSvictorle {
2485dfbe8321SBarry Smith   PetscErrorCode ierr;
24866e111a19SKarl Rupp 
24879e29f15eSvictorle   PetscFunctionBegin;
24885485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
24899e29f15eSvictorle   PetscFunctionReturn(0);
24909e29f15eSvictorle }
24919e29f15eSvictorle 
2492ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24931cbb95d3SBarry Smith {
24941cbb95d3SBarry Smith   PetscErrorCode ierr;
24956e111a19SKarl Rupp 
24961cbb95d3SBarry Smith   PetscFunctionBegin;
24971cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
24981cbb95d3SBarry Smith   PetscFunctionReturn(0);
24991cbb95d3SBarry Smith }
25001cbb95d3SBarry Smith 
2501dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
250217ab2063SBarry Smith {
2503416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2504fff8e43fSBarry Smith   const PetscScalar *l,*r;
2505fff8e43fSBarry Smith   PetscScalar       x;
250654f21887SBarry Smith   MatScalar         *v;
2507dfbe8321SBarry Smith   PetscErrorCode    ierr;
2508fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2509fff8e43fSBarry Smith   const PetscInt    *jj;
251017ab2063SBarry Smith 
25113a40ed3dSBarry Smith   PetscFunctionBegin;
251217ab2063SBarry Smith   if (ll) {
25133ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25143ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2515e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2516e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2517fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
2518416022c9SBarry Smith     v    = a->a;
251917ab2063SBarry Smith     for (i=0; i<m; i++) {
252017ab2063SBarry Smith       x = l[i];
2521416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25222205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
252317ab2063SBarry Smith     }
2524fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2525efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
252617ab2063SBarry Smith   }
252717ab2063SBarry Smith   if (rr) {
2528e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2529e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2530fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
2531416022c9SBarry Smith     v    = a->a; jj = a->j;
25322205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
2533fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2534efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
253517ab2063SBarry Smith   }
2536acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
25378c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2538c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2539e2cf4d64SStefano Zampini #endif
25403a40ed3dSBarry Smith   PetscFunctionReturn(0);
254117ab2063SBarry Smith }
254217ab2063SBarry Smith 
25437dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
254417ab2063SBarry Smith {
2545db02288aSLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
25466849ba73SBarry Smith   PetscErrorCode ierr;
2547d0f46423SBarry Smith   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
254897f1f81fSBarry Smith   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25495d0c19d7SBarry Smith   const PetscInt *irow,*icol;
25505d0c19d7SBarry Smith   PetscInt       nrows,ncols;
255197f1f81fSBarry Smith   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
255254f21887SBarry Smith   MatScalar      *a_new,*mat_a;
2553416022c9SBarry Smith   Mat            C;
2554cdc6f3adSToby Isaac   PetscBool      stride;
255517ab2063SBarry Smith 
25563a40ed3dSBarry Smith   PetscFunctionBegin;
255799141d43SSatish Balay 
255817ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2559b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2560b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
256117ab2063SBarry Smith 
2562251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2563ff718158SBarry Smith   if (stride) {
2564ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2565ff718158SBarry Smith   } else {
2566ff718158SBarry Smith     first = 0;
2567ff718158SBarry Smith     step  = 0;
2568ff718158SBarry Smith   }
2569fee21e36SBarry Smith   if (stride && step == 1) {
257002834360SBarry Smith     /* special case of contiguous rows */
2571dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
257202834360SBarry Smith     /* loop over new rows determining lens and starting points */
257302834360SBarry Smith     for (i=0; i<nrows; i++) {
2574bfeeae90SHong Zhang       kstart = ai[irow[i]];
2575a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2576a91a9bebSLisandro Dalcin       starts[i] = kstart;
257702834360SBarry Smith       for (k=kstart; k<kend; k++) {
2578bfeeae90SHong Zhang         if (aj[k] >= first) {
257902834360SBarry Smith           starts[i] = k;
258002834360SBarry Smith           break;
258102834360SBarry Smith         }
258202834360SBarry Smith       }
2583a2744918SBarry Smith       sum = 0;
258402834360SBarry Smith       while (k < kend) {
2585bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2586a2744918SBarry Smith         sum++;
258702834360SBarry Smith       }
2588a2744918SBarry Smith       lens[i] = sum;
258902834360SBarry Smith     }
259002834360SBarry Smith     /* create submatrix */
2591cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
259297f1f81fSBarry Smith       PetscInt n_cols,n_rows;
259308480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2594e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2595d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
259608480c60SBarry Smith       C    = *B;
25973a40ed3dSBarry Smith     } else {
25983bef6203SJed Brown       PetscInt rbs,cbs;
2599ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2600f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26013bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26023bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26033bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26047adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2605ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
260608480c60SBarry Smith     }
2607db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2608db02288aSLois Curfman McInnes 
260902834360SBarry Smith     /* loop over rows inserting into submatrix */
2610db02288aSLois Curfman McInnes     a_new = c->a;
2611db02288aSLois Curfman McInnes     j_new = c->j;
2612db02288aSLois Curfman McInnes     i_new = c->i;
2613bfeeae90SHong Zhang 
261402834360SBarry Smith     for (i=0; i<nrows; i++) {
2615a2744918SBarry Smith       ii    = starts[i];
2616a2744918SBarry Smith       lensi = lens[i];
2617a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2618a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
261902834360SBarry Smith       }
2620580bdb30SBarry Smith       ierr       = PetscArraycpy(a_new,a->a + starts[i],lensi);CHKERRQ(ierr);
2621a2744918SBarry Smith       a_new     += lensi;
2622a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2623a2744918SBarry Smith       c->ilen[i] = lensi;
262402834360SBarry Smith     }
26250e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26263a40ed3dSBarry Smith   } else {
262702834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26281795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2629854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26304dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2631d9ef940eSSatish 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);
26324dcab191SBarry Smith       smap[icol[i]] = i+1;
26334dcab191SBarry Smith     }
26344dcab191SBarry Smith 
263502834360SBarry Smith     /* determine lens of each row */
263602834360SBarry Smith     for (i=0; i<nrows; i++) {
2637bfeeae90SHong Zhang       kstart  = ai[irow[i]];
263802834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
263902834360SBarry Smith       lens[i] = 0;
264002834360SBarry Smith       for (k=kstart; k<kend; k++) {
2641bfeeae90SHong Zhang         if (smap[aj[k]]) {
264202834360SBarry Smith           lens[i]++;
264302834360SBarry Smith         }
264402834360SBarry Smith       }
264502834360SBarry Smith     }
264617ab2063SBarry Smith     /* Create and fill new matrix */
2647a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2648ace3abfcSBarry Smith       PetscBool equal;
26490f5bd95cSBarry Smith 
265099141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2651e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2652580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2653f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2654580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
265508480c60SBarry Smith       C    = *B;
26563a40ed3dSBarry Smith     } else {
26573bef6203SJed Brown       PetscInt rbs,cbs;
2658ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2659f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26603bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26613bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26623bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26637adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2664ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
266508480c60SBarry Smith     }
266699141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
266717ab2063SBarry Smith     for (i=0; i<nrows; i++) {
266899141d43SSatish Balay       row      = irow[i];
2669bfeeae90SHong Zhang       kstart   = ai[row];
267099141d43SSatish Balay       kend     = kstart + a->ilen[row];
2671bfeeae90SHong Zhang       mat_i    = c->i[i];
267299141d43SSatish Balay       mat_j    = c->j + mat_i;
267399141d43SSatish Balay       mat_a    = c->a + mat_i;
267499141d43SSatish Balay       mat_ilen = c->ilen + i;
267517ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2676bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2677ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
267899141d43SSatish Balay           *mat_a++ = a->a[k];
267999141d43SSatish Balay           (*mat_ilen)++;
268099141d43SSatish Balay 
268117ab2063SBarry Smith         }
268217ab2063SBarry Smith       }
268317ab2063SBarry Smith     }
268402834360SBarry Smith     /* Free work space */
268502834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2686606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2687606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2688cdc6f3adSToby Isaac     /* sort */
2689cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2690cdc6f3adSToby Isaac       PetscInt ilen;
2691cdc6f3adSToby Isaac 
2692cdc6f3adSToby Isaac       mat_i = c->i[i];
2693cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2694cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2695cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2696390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2697cdc6f3adSToby Isaac     }
269802834360SBarry Smith   }
26998c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2700b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2701305c6ccfSStefano Zampini #endif
27026d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27036d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
270417ab2063SBarry Smith 
270517ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2706416022c9SBarry Smith   *B   = C;
27073a40ed3dSBarry Smith   PetscFunctionReturn(0);
270817ab2063SBarry Smith }
270917ab2063SBarry Smith 
2710fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
271182d44351SHong Zhang {
271282d44351SHong Zhang   PetscErrorCode ierr;
271382d44351SHong Zhang   Mat            B;
271482d44351SHong Zhang 
271582d44351SHong Zhang   PetscFunctionBegin;
2716c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
271782d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
271882d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
271933d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
272082d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
272182d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
272282d44351SHong Zhang     *subMat = B;
2723c2d650bdSHong Zhang   } else {
2724c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2725c2d650bdSHong Zhang   }
272682d44351SHong Zhang   PetscFunctionReturn(0);
272782d44351SHong Zhang }
272882d44351SHong Zhang 
27299a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2730a871dcd8SBarry Smith {
273163b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2732dfbe8321SBarry Smith   PetscErrorCode ierr;
273363b91edcSBarry Smith   Mat            outA;
2734ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
273563b91edcSBarry Smith 
27363a40ed3dSBarry Smith   PetscFunctionBegin;
2737e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27381df811f5SHong Zhang 
2739b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2740b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2741a871dcd8SBarry Smith 
274263b91edcSBarry Smith   outA             = inA;
2743d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2744f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2745f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
27462205254eSKarl Rupp 
2747c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
27486bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
27492205254eSKarl Rupp 
2750c3122656SLisandro Dalcin   a->row = row;
27512205254eSKarl Rupp 
2752c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
27536bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
27542205254eSKarl Rupp 
2755c3122656SLisandro Dalcin   a->col = col;
275663b91edcSBarry Smith 
275736db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
27586bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
27594c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
27603bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2761f0ec6fceSSatish Balay 
276294a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2763854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
27643bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
276594a9d846SBarry Smith   }
276663b91edcSBarry Smith 
2767f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2768137fb511SHong Zhang   if (row_identity && col_identity) {
2769ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2770137fb511SHong Zhang   } else {
2771719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2772137fb511SHong Zhang   }
27733a40ed3dSBarry Smith   PetscFunctionReturn(0);
2774a871dcd8SBarry Smith }
2775a871dcd8SBarry Smith 
2776f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2777f0b747eeSBarry Smith {
2778f0b747eeSBarry Smith   Mat_SeqAIJ     *a     = (Mat_SeqAIJ*)inA->data;
2779f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
2780efee365bSSatish Balay   PetscErrorCode ierr;
2781c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
27823a40ed3dSBarry Smith 
27833a40ed3dSBarry Smith   PetscFunctionBegin;
2784c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
27858b83055fSJed Brown   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one));
2786efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2787acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
27888c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2789c70f7ee4SJunchao Zhang   if (inA->offloadmask != PETSC_OFFLOAD_UNALLOCATED) inA->offloadmask = PETSC_OFFLOAD_CPU;
2790e2cf4d64SStefano Zampini #endif
27913a40ed3dSBarry Smith   PetscFunctionReturn(0);
2792f0b747eeSBarry Smith }
2793f0b747eeSBarry Smith 
2794f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
279516b64355SHong Zhang {
279616b64355SHong Zhang   PetscErrorCode ierr;
279716b64355SHong Zhang   PetscInt       i;
279816b64355SHong Zhang 
279916b64355SHong Zhang   PetscFunctionBegin;
280016b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
280116b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
280216b64355SHong Zhang 
280316b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
280416b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
280516b64355SHong Zhang     }
280616b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
280716b64355SHong Zhang 
280816b64355SHong Zhang     if (submatj->rbuf1) {
280916b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
281016b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
281116b64355SHong Zhang     }
281216b64355SHong Zhang 
281316b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
281416b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
281516b64355SHong Zhang     }
281616b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
281716b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
281816b64355SHong Zhang   }
281916b64355SHong Zhang 
282016b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
282116b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
282216b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
282316b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
282416b64355SHong Zhang #else
282516b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
282616b64355SHong Zhang #endif
282716b64355SHong Zhang 
282816b64355SHong Zhang   if (!submatj->allcolumns) {
282916b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
283016b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
283116b64355SHong Zhang #else
283216b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
283316b64355SHong Zhang #endif
283416b64355SHong Zhang   }
283516b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
283616b64355SHong Zhang 
283716b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
283816b64355SHong Zhang   PetscFunctionReturn(0);
283916b64355SHong Zhang }
284016b64355SHong Zhang 
28410fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
284216b64355SHong Zhang {
284316b64355SHong Zhang   PetscErrorCode ierr;
284416b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28455c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
284616b64355SHong Zhang 
284716b64355SHong Zhang   PetscFunctionBegin;
284834136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2849f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
285016b64355SHong Zhang   PetscFunctionReturn(0);
285116b64355SHong Zhang }
285216b64355SHong Zhang 
28532d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
28542d033e1fSHong Zhang {
28552d033e1fSHong Zhang   PetscErrorCode ierr;
28562d033e1fSHong Zhang   PetscInt       i;
28570fb991dcSHong Zhang   Mat            C;
28580fb991dcSHong Zhang   Mat_SeqAIJ     *c;
28590fb991dcSHong Zhang   Mat_SubSppt    *submatj;
28602d033e1fSHong Zhang 
28612d033e1fSHong Zhang   PetscFunctionBegin;
28622d033e1fSHong Zhang   for (i=0; i<n; i++) {
28630fb991dcSHong Zhang     C       = (*mat)[i];
28640fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
28650fb991dcSHong Zhang     submatj = c->submatis1;
28662d033e1fSHong Zhang     if (submatj) {
2867682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
286834136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2869f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
287034136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
28712d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
28722d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
28732d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2874682e4c99SStefano Zampini       }
28752d033e1fSHong Zhang     } else {
28762d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
28772d033e1fSHong Zhang     }
28782d033e1fSHong Zhang   }
287986e85357SHong Zhang 
288063a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
288163a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
288263a75b2aSHong Zhang 
28832d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
28842d033e1fSHong Zhang   PetscFunctionReturn(0);
28852d033e1fSHong Zhang }
28862d033e1fSHong Zhang 
28877dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2888cddf8d76SBarry Smith {
2889dfbe8321SBarry Smith   PetscErrorCode ierr;
289097f1f81fSBarry Smith   PetscInt       i;
2891cddf8d76SBarry Smith 
28923a40ed3dSBarry Smith   PetscFunctionBegin;
2893cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2894df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2895cddf8d76SBarry Smith   }
2896cddf8d76SBarry Smith 
2897cddf8d76SBarry Smith   for (i=0; i<n; i++) {
28987dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2899cddf8d76SBarry Smith   }
29003a40ed3dSBarry Smith   PetscFunctionReturn(0);
2901cddf8d76SBarry Smith }
2902cddf8d76SBarry Smith 
290397f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29044dcbc457SBarry Smith {
2905e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29066849ba73SBarry Smith   PetscErrorCode ierr;
29075d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29085d0c19d7SBarry Smith   const PetscInt *idx;
290997f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2910f1af5d2fSBarry Smith   PetscBT        table;
2911bbd702dbSSatish Balay 
29123a40ed3dSBarry Smith   PetscFunctionBegin;
2913d0f46423SBarry Smith   m  = A->rmap->n;
2914e4d965acSSatish Balay   ai = a->i;
2915bfeeae90SHong Zhang   aj = a->j;
29168a047759SSatish Balay 
2917e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
291806763907SSatish Balay 
2919854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
292053b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
292106763907SSatish Balay 
2922e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2923b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2924e4d965acSSatish Balay     isz  = 0;
29256831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2926e4d965acSSatish Balay 
2927e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29284dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2929b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2930e4d965acSSatish Balay 
2931dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2932e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29332205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29344dcbc457SBarry Smith     }
293506763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
29366bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2937e4d965acSSatish Balay 
293804a348a9SBarry Smith     k = 0;
293904a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
294004a348a9SBarry Smith       n = isz;
294106763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2942e4d965acSSatish Balay         row   = nidx[k];
2943e4d965acSSatish Balay         start = ai[row];
2944e4d965acSSatish Balay         end   = ai[row+1];
294504a348a9SBarry Smith         for (l = start; l<end; l++) {
2946efb16452SHong Zhang           val = aj[l];
29472205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2948e4d965acSSatish Balay         }
2949e4d965acSSatish Balay       }
2950e4d965acSSatish Balay     }
295170b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2952e4d965acSSatish Balay   }
295394bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2954606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
29553a40ed3dSBarry Smith   PetscFunctionReturn(0);
29564dcbc457SBarry Smith }
295717ab2063SBarry Smith 
29580513a670SBarry Smith /* -------------------------------------------------------------- */
2959dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
29600513a670SBarry Smith {
29610513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29626849ba73SBarry Smith   PetscErrorCode ierr;
29633b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
29645d0c19d7SBarry Smith   const PetscInt *row,*col;
29655d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
296656cd22aeSBarry Smith   IS             icolp,irowp;
29670298fd71SBarry Smith   PetscInt       *cwork = NULL;
29680298fd71SBarry Smith   PetscScalar    *vwork = NULL;
29690513a670SBarry Smith 
29703a40ed3dSBarry Smith   PetscFunctionBegin;
29714c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
297256cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
29734c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
297456cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
29750513a670SBarry Smith 
29760513a670SBarry Smith   /* determine lengths of permuted rows */
2977854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
29782205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
2979ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
2980f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
298133d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
29827adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2983ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2984606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
29850513a670SBarry Smith 
2986785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
29870513a670SBarry Smith   for (i=0; i<m; i++) {
298832ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
29892205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
2990cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
299132ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
29920513a670SBarry Smith   }
2993606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
29942205254eSKarl Rupp 
29953c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
29962205254eSKarl Rupp 
29978c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2998b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
29999fe5e383SStefano Zampini #endif
30000513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30010513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
300256cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
300356cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30046bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30056bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30066768869dSprj-   if (rowp == colp) {
30076768869dSprj-     if (A->symmetric) {
30086768869dSprj-       ierr = MatSetOption(*B,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
30096768869dSprj-     }
30106768869dSprj-     if (A->hermitian) {
30116768869dSprj-       ierr = MatSetOption(*B,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
30126768869dSprj-     }
30136768869dSprj-   }
30143a40ed3dSBarry Smith   PetscFunctionReturn(0);
30150513a670SBarry Smith }
30160513a670SBarry Smith 
3017dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3018cb5b572fSBarry Smith {
3019dfbe8321SBarry Smith   PetscErrorCode ierr;
3020cb5b572fSBarry Smith 
3021cb5b572fSBarry Smith   PetscFunctionBegin;
302233f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
302333f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3024be6bf707SBarry Smith     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
3025be6bf707SBarry Smith     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
3026be6bf707SBarry Smith 
30274d805d7cSStefano 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]);
3028580bdb30SBarry Smith     ierr = PetscArraycpy(b->a,a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
3029cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
3030cb5b572fSBarry Smith   } else {
3031cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3032cb5b572fSBarry Smith   }
3033cb5b572fSBarry Smith   PetscFunctionReturn(0);
3034cb5b572fSBarry Smith }
3035cb5b572fSBarry Smith 
30364994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3037273d9f13SBarry Smith {
3038dfbe8321SBarry Smith   PetscErrorCode ierr;
3039273d9f13SBarry Smith 
3040273d9f13SBarry Smith   PetscFunctionBegin;
3041f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3042273d9f13SBarry Smith   PetscFunctionReturn(0);
3043273d9f13SBarry Smith }
3044273d9f13SBarry Smith 
3045f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30466c0721eeSBarry Smith {
30476c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30486e111a19SKarl Rupp 
30496c0721eeSBarry Smith   PetscFunctionBegin;
30506c0721eeSBarry Smith   *array = a->a;
30516c0721eeSBarry Smith   PetscFunctionReturn(0);
30526c0721eeSBarry Smith }
30536c0721eeSBarry Smith 
3054f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
30556c0721eeSBarry Smith {
30566c0721eeSBarry Smith   PetscFunctionBegin;
3057f38c1e66SStefano Zampini   *array = NULL;
30586c0721eeSBarry Smith   PetscFunctionReturn(0);
30596c0721eeSBarry Smith }
3060273d9f13SBarry Smith 
30618229c054SShri Abhyankar /*
30628229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
30638229c054SShri Abhyankar    have different nonzero structure.
30648229c054SShri Abhyankar */
3065b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3066ec7775f6SShri Abhyankar {
3067b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3068ec7775f6SShri Abhyankar 
3069ec7775f6SShri Abhyankar   PetscFunctionBegin;
3070ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3071ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3072b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3073b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3074b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
30758af7cee1SJed Brown     nnz[i] = 0;
30768af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3077b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3078b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
30798af7cee1SJed Brown       nnz[i]++;
30808af7cee1SJed Brown     }
30818af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3082ec7775f6SShri Abhyankar   }
3083ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3084ec7775f6SShri Abhyankar }
3085ec7775f6SShri Abhyankar 
3086b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3087b264fe52SHong Zhang {
3088b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3089b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3090b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3091b264fe52SHong Zhang   PetscErrorCode ierr;
3092b264fe52SHong Zhang 
3093b264fe52SHong Zhang   PetscFunctionBegin;
3094b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3095b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3096b264fe52SHong Zhang   PetscFunctionReturn(0);
3097b264fe52SHong Zhang }
3098b264fe52SHong Zhang 
3099f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3100ac90fabeSBarry Smith {
3101dfbe8321SBarry Smith   PetscErrorCode ierr;
3102ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3103ac90fabeSBarry Smith 
3104ac90fabeSBarry Smith   PetscFunctionBegin;
310581fa06acSBarry Smith   if (str == DIFFERENT_NONZERO_PATTERN) {
310681fa06acSBarry Smith     if (x->nz == y->nz) {
310781fa06acSBarry Smith       PetscBool e;
310881fa06acSBarry Smith       ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
310981fa06acSBarry Smith       if (e) {
311081fa06acSBarry Smith         ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
311181fa06acSBarry Smith         if (e) {
311281fa06acSBarry Smith           str = SAME_NONZERO_PATTERN;
311381fa06acSBarry Smith         }
311481fa06acSBarry Smith       }
311581fa06acSBarry Smith     }
311681fa06acSBarry Smith   }
3117ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
3118f4df32b1SMatthew Knepley     PetscScalar  alpha = a;
311981fa06acSBarry Smith     PetscBLASInt one = 1,bnz;
312081fa06acSBarry Smith 
312181fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31228b83055fSJed Brown     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one));
3123acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3124a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
312581fa06acSBarry Smith     /* the MatAXPY_Basic* subroutines calls MatAssembly, so the matrix on the GPU will be updated */
31268c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3127c70f7ee4SJunchao Zhang     if (Y->offloadmask != PETSC_OFFLOAD_UNALLOCATED) {
3128c70f7ee4SJunchao Zhang       Y->offloadmask = PETSC_OFFLOAD_CPU;
3129e2cf4d64SStefano Zampini     }
3130e2cf4d64SStefano Zampini #endif
3131ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3132ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3133ac90fabeSBarry Smith   } else {
31348229c054SShri Abhyankar     Mat      B;
31358229c054SShri Abhyankar     PetscInt *nnz;
3136785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3137ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3138bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
313981fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
3140176df525SBarry Smith     ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr);
31418229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3142ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3143ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
314428be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
31458229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3146ac90fabeSBarry Smith   }
3147ac90fabeSBarry Smith   PetscFunctionReturn(0);
3148ac90fabeSBarry Smith }
3149ac90fabeSBarry Smith 
31507087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
3151354c94deSBarry Smith {
3152354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3153354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3154354c94deSBarry Smith   PetscInt    i,nz;
3155354c94deSBarry Smith   PetscScalar *a;
3156354c94deSBarry Smith 
3157354c94deSBarry Smith   PetscFunctionBegin;
3158354c94deSBarry Smith   nz = aij->nz;
3159354c94deSBarry Smith   a  = aij->a;
31602205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
31618c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3162c70f7ee4SJunchao Zhang   if (mat->offloadmask != PETSC_OFFLOAD_UNALLOCATED) mat->offloadmask = PETSC_OFFLOAD_CPU;
3163e2cf4d64SStefano Zampini #endif
3164354c94deSBarry Smith #else
3165354c94deSBarry Smith   PetscFunctionBegin;
3166354c94deSBarry Smith #endif
3167354c94deSBarry Smith   PetscFunctionReturn(0);
3168354c94deSBarry Smith }
3169354c94deSBarry Smith 
3170985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3171e34fafa9SBarry Smith {
3172e34fafa9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3173e34fafa9SBarry Smith   PetscErrorCode ierr;
3174d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3175e34fafa9SBarry Smith   PetscReal      atmp;
3176985db425SBarry Smith   PetscScalar    *x;
3177e34fafa9SBarry Smith   MatScalar      *aa;
3178e34fafa9SBarry Smith 
3179e34fafa9SBarry Smith   PetscFunctionBegin;
3180e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3181e34fafa9SBarry Smith   aa = a->a;
3182e34fafa9SBarry Smith   ai = a->i;
3183e34fafa9SBarry Smith   aj = a->j;
3184e34fafa9SBarry Smith 
3185985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3186475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3187e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3188e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3189e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3190e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3191e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3192985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3193985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3194985db425SBarry Smith       aa++; aj++;
3195985db425SBarry Smith     }
3196985db425SBarry Smith   }
3197475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3198985db425SBarry Smith   PetscFunctionReturn(0);
3199985db425SBarry Smith }
3200985db425SBarry Smith 
3201985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3202985db425SBarry Smith {
3203985db425SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3204985db425SBarry Smith   PetscErrorCode ierr;
3205d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3206985db425SBarry Smith   PetscScalar    *x;
3207985db425SBarry Smith   MatScalar      *aa;
3208985db425SBarry Smith 
3209985db425SBarry Smith   PetscFunctionBegin;
3210e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3211985db425SBarry Smith   aa = a->a;
3212985db425SBarry Smith   ai = a->i;
3213985db425SBarry Smith   aj = a->j;
3214985db425SBarry Smith 
3215985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3216fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3217985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3218e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3219985db425SBarry Smith   for (i=0; i<m; i++) {
3220985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3221d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3222985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3223985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3224985db425SBarry Smith       x[i] = 0.0;
3225985db425SBarry Smith       if (idx) {
3226985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3227985db425SBarry Smith           if (aj[j] > j) {
3228985db425SBarry Smith             idx[i] = j;
3229985db425SBarry Smith             break;
3230985db425SBarry Smith           }
3231985db425SBarry Smith         }
32321a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32331a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3234985db425SBarry Smith       }
3235985db425SBarry Smith     }
3236985db425SBarry Smith     for (j=0; j<ncols; j++) {
3237985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3238985db425SBarry Smith       aa++; aj++;
3239985db425SBarry Smith     }
3240985db425SBarry Smith   }
3241fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3242985db425SBarry Smith   PetscFunctionReturn(0);
3243985db425SBarry Smith }
3244985db425SBarry Smith 
3245c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3246c87e5d42SMatthew Knepley {
3247c87e5d42SMatthew Knepley   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3248c87e5d42SMatthew Knepley   PetscErrorCode ierr;
3249c87e5d42SMatthew Knepley   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
32504e879edeSHong Zhang   PetscScalar    *x,*aa;
3251c87e5d42SMatthew Knepley 
3252c87e5d42SMatthew Knepley   PetscFunctionBegin;
3253c87e5d42SMatthew Knepley   aa = a->a;
3254c87e5d42SMatthew Knepley   ai = a->i;
3255c87e5d42SMatthew Knepley   aj = a->j;
3256c87e5d42SMatthew Knepley 
3257c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3258f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3259c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3260f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3261c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3262c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3263f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3264f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3265f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3266f07e67edSHong Zhang       x[i] = 0.0;
3267f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3268289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3269f07e67edSHong Zhang           if (aj[j] > j) {
3270f07e67edSHong Zhang             idx[i] = j;
32712205254eSKarl Rupp             break;
32722205254eSKarl Rupp           }
3273289a08f5SMatthew Knepley         }
3274f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3275f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3276f07e67edSHong Zhang       }
3277289a08f5SMatthew Knepley     }
3278c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3279f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3280c87e5d42SMatthew Knepley       aa++; aj++;
3281c87e5d42SMatthew Knepley     }
3282c87e5d42SMatthew Knepley   }
3283f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3284c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3285c87e5d42SMatthew Knepley }
3286c87e5d42SMatthew Knepley 
3287985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3288985db425SBarry Smith {
3289985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3290985db425SBarry Smith   PetscErrorCode  ierr;
3291d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3292d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3293985db425SBarry Smith   PetscScalar     *x;
3294d9ca1df4SBarry Smith   const MatScalar *aa;
3295985db425SBarry Smith 
3296985db425SBarry Smith   PetscFunctionBegin;
3297e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3298985db425SBarry Smith   aa = a->a;
3299985db425SBarry Smith   ai = a->i;
3300985db425SBarry Smith   aj = a->j;
3301985db425SBarry Smith 
3302985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3303fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3304985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3305f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3306985db425SBarry Smith   for (i=0; i<m; i++) {
3307985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3308d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3309985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3310985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3311985db425SBarry Smith       x[i] = 0.0;
3312985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3313985db425SBarry Smith         for (j=0; j<ncols; j++) {
3314985db425SBarry Smith           if (aj[j] > j) {
3315985db425SBarry Smith             idx[i] = j;
3316985db425SBarry Smith             break;
3317985db425SBarry Smith           }
3318985db425SBarry Smith         }
3319fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3320fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3321985db425SBarry Smith       }
3322985db425SBarry Smith     }
3323985db425SBarry Smith     for (j=0; j<ncols; j++) {
3324985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3325985db425SBarry Smith       aa++; aj++;
3326e34fafa9SBarry Smith     }
3327e34fafa9SBarry Smith   }
3328fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3329e34fafa9SBarry Smith   PetscFunctionReturn(0);
3330e34fafa9SBarry Smith }
3331bbead8a2SBarry Smith 
3332713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3333bbead8a2SBarry Smith {
3334bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3335bbead8a2SBarry Smith   PetscErrorCode  ierr;
333633d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3337bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33380da83c2eSBarry Smith   const PetscReal shift = 0.0;
33391a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3340bbead8a2SBarry Smith 
3341bbead8a2SBarry Smith   PetscFunctionBegin;
3342a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33434a0d0026SBarry Smith   if (a->ibdiagvalid) {
33444a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33454a0d0026SBarry Smith     PetscFunctionReturn(0);
33464a0d0026SBarry Smith   }
3347bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3348bbead8a2SBarry Smith   if (!a->ibdiag) {
3349785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
33503bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3351bbead8a2SBarry Smith   }
3352bbead8a2SBarry Smith   diag = a->ibdiag;
3353bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3354bbead8a2SBarry Smith   /* factor and invert each block */
3355bbead8a2SBarry Smith   switch (bs) {
3356bbead8a2SBarry Smith   case 1:
3357bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3358bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3359ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3360ec1892c8SHong Zhang         if (allowzeropivot) {
33617b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33627b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
33637b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
33647b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
33657b6c816cSBarry 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);
3366ec1892c8SHong Zhang       }
3367bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3368bbead8a2SBarry Smith     }
3369bbead8a2SBarry Smith     break;
3370bbead8a2SBarry Smith   case 2:
3371bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3372bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3373bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3374a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33757b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
337696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3377bbead8a2SBarry Smith       diag += 4;
3378bbead8a2SBarry Smith     }
3379bbead8a2SBarry Smith     break;
3380bbead8a2SBarry Smith   case 3:
3381bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3382bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3383bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3384a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33857b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
338696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3387bbead8a2SBarry Smith       diag += 9;
3388bbead8a2SBarry Smith     }
3389bbead8a2SBarry Smith     break;
3390bbead8a2SBarry Smith   case 4:
3391bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3392bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3393bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3394a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
33957b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
339696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3397bbead8a2SBarry Smith       diag += 16;
3398bbead8a2SBarry Smith     }
3399bbead8a2SBarry Smith     break;
3400bbead8a2SBarry Smith   case 5:
3401bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3402bbead8a2SBarry 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;
3403bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3404a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34057b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
340696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3407bbead8a2SBarry Smith       diag += 25;
3408bbead8a2SBarry Smith     }
3409bbead8a2SBarry Smith     break;
3410bbead8a2SBarry Smith   case 6:
3411bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3412bbead8a2SBarry 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;
3413bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3414a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34157b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
341696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3417bbead8a2SBarry Smith       diag += 36;
3418bbead8a2SBarry Smith     }
3419bbead8a2SBarry Smith     break;
3420bbead8a2SBarry Smith   case 7:
3421bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3422bbead8a2SBarry 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;
3423bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3424a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34257b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
342696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3427bbead8a2SBarry Smith       diag += 49;
3428bbead8a2SBarry Smith     }
3429bbead8a2SBarry Smith     break;
3430bbead8a2SBarry Smith   default:
3431dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3432bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3433bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3434bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3435bbead8a2SBarry Smith       }
3436bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
34375f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34387b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
343996b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3440bbead8a2SBarry Smith       diag += bs2;
3441bbead8a2SBarry Smith     }
3442bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3443bbead8a2SBarry Smith   }
3444bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3445bbead8a2SBarry Smith   PetscFunctionReturn(0);
3446bbead8a2SBarry Smith }
3447bbead8a2SBarry Smith 
344873a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
344973a71a0fSBarry Smith {
345073a71a0fSBarry Smith   PetscErrorCode ierr;
345173a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
345273a71a0fSBarry Smith   PetscScalar    a;
345373a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
345473a71a0fSBarry Smith 
345573a71a0fSBarry Smith   PetscFunctionBegin;
345673a71a0fSBarry Smith   if (!x->assembled) {
345773a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
345873a71a0fSBarry Smith     for (i=0; i<m; i++) {
345973a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
346073a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
346173a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
346273a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
346373a71a0fSBarry Smith       }
346473a71a0fSBarry Smith     }
3465e2ce353bSJunchao Zhang   } else {
3466e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3467e2ce353bSJunchao Zhang   }
346873a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
346973a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
347073a71a0fSBarry Smith   PetscFunctionReturn(0);
347173a71a0fSBarry Smith }
347273a71a0fSBarry Smith 
3473679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3474679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3475679944adSJunchao Zhang {
3476679944adSJunchao Zhang   PetscErrorCode ierr;
3477679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3478679944adSJunchao Zhang   PetscScalar    a;
3479679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3480679944adSJunchao Zhang 
3481679944adSJunchao Zhang   PetscFunctionBegin;
3482679944adSJunchao Zhang   nskip = high - low;
3483679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3484679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3485679944adSJunchao Zhang   for (i=0; i<m; i++) {
3486679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3487679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3488679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3489679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3490679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3491679944adSJunchao Zhang     }
3492e2ce353bSJunchao Zhang   }
3493679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3494679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3495679944adSJunchao Zhang   PetscFunctionReturn(0);
3496679944adSJunchao Zhang }
3497679944adSJunchao Zhang 
3498679944adSJunchao Zhang 
3499682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35000a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3501cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3502cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3503cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
350497304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35057c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35067c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3507f4259b30SLisandro Dalcin                                         NULL,
3508f4259b30SLisandro Dalcin                                         NULL,
3509f4259b30SLisandro Dalcin                                         NULL,
3510f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3511cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3512f4259b30SLisandro Dalcin                                         NULL,
351341f059aeSBarry Smith                                         MatSOR_SeqAIJ,
351491e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
351597304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3516cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3517cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3518cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3519cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3520f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3521cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3522cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3523cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3524d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3525f4259b30SLisandro Dalcin                                         NULL,
3526f4259b30SLisandro Dalcin                                         NULL,
3527f4259b30SLisandro Dalcin                                         NULL,
3528f4259b30SLisandro Dalcin                                         NULL,
35294994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3530f4259b30SLisandro Dalcin                                         NULL,
3531f4259b30SLisandro Dalcin                                         NULL,
3532f4259b30SLisandro Dalcin                                         NULL,
3533f4259b30SLisandro Dalcin                                         NULL,
3534d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3535f4259b30SLisandro Dalcin                                         NULL,
3536f4259b30SLisandro Dalcin                                         NULL,
3537cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3538f4259b30SLisandro Dalcin                                         NULL,
3539d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35407dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3541cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3542cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3543cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3544d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3545cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35467d68702bSBarry Smith                                         MatShift_SeqAIJ,
354779299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
35486e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
354973a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
35503b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
35513b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
35523b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3553a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
355493dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3555f4259b30SLisandro Dalcin                                         NULL,
3556f4259b30SLisandro Dalcin                                         NULL,
3557cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3558f4259b30SLisandro Dalcin                                         NULL,
3559f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3560b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3561b9b97703SBarry Smith                                         MatView_SeqAIJ,
3562f4259b30SLisandro Dalcin                                         NULL,
3563f4259b30SLisandro Dalcin                                         NULL,
3564f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3565321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3566f4259b30SLisandro Dalcin                                         NULL,
3567f4259b30SLisandro Dalcin                                         NULL,
3568f4259b30SLisandro Dalcin                                         NULL,
3569d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3570c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3571f4259b30SLisandro Dalcin                                         NULL,
3572f4259b30SLisandro Dalcin                                         NULL,
3573f4259b30SLisandro Dalcin                                         NULL,
3574f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
35753acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3576f4259b30SLisandro Dalcin                                         NULL,
3577f4259b30SLisandro Dalcin                                         NULL,
3578f4259b30SLisandro Dalcin                                         NULL,
35796ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3580f4259b30SLisandro Dalcin                                         NULL,
3581f4259b30SLisandro Dalcin                                         NULL,
3582f4259b30SLisandro Dalcin                                         NULL,
3583bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3584d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
35851cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3586f4259b30SLisandro Dalcin                                         NULL,
3587f4259b30SLisandro Dalcin                                         NULL,
3588f4259b30SLisandro Dalcin                                         NULL,
3589f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3590f4259b30SLisandro Dalcin                                         NULL,
359126be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3592f4259b30SLisandro Dalcin                                         NULL,
3593f4259b30SLisandro Dalcin                                         NULL,
35948fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3595f4259b30SLisandro Dalcin                                         NULL,
3596f4259b30SLisandro Dalcin                                         NULL,
35976fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3598f4259b30SLisandro Dalcin                                         NULL,
35994222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3600f4259b30SLisandro Dalcin                                         NULL,
3601f4259b30SLisandro Dalcin                                         NULL,
360287d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3603f4259b30SLisandro Dalcin                                         NULL,
3604d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
360599cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3606f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3607f4259b30SLisandro Dalcin                                         NULL,
3608f4259b30SLisandro Dalcin                                         NULL,
3609cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3610f4259b30SLisandro Dalcin                                         NULL,
36112af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3612f4259b30SLisandro Dalcin                                         NULL,
3613599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3614f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3615f4259b30SLisandro Dalcin                                         NULL,
3616f4259b30SLisandro Dalcin                                         NULL,
3617f4259b30SLisandro Dalcin                                         NULL,
3618f4259b30SLisandro Dalcin                                         NULL,
3619f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3620f4259b30SLisandro Dalcin                                         NULL,
3621f4259b30SLisandro Dalcin                                         NULL,
3622f4259b30SLisandro Dalcin                                         NULL,
3623b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36240716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3625bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
362637868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36270da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3628f4259b30SLisandro Dalcin                                         NULL,
3629f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3630f4259b30SLisandro Dalcin                                         NULL,
3631f4259b30SLisandro Dalcin                                         NULL,
363275648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3633b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3634b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36352b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3636f4259b30SLisandro Dalcin                                         NULL,
3637f4259b30SLisandro Dalcin                                         NULL,
36383964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3639f4259b30SLisandro Dalcin                                  /*139*/NULL,
3640f4259b30SLisandro Dalcin                                         NULL,
3641f4259b30SLisandro Dalcin                                         NULL,
36423a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36439c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36444222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36454222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3646f4259b30SLisandro Dalcin                                         NULL,
3647f4259b30SLisandro Dalcin                                         NULL
36489e29f15eSvictorle };
364917ab2063SBarry Smith 
36507087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3651bef8e0ddSBarry Smith {
3652bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
365397f1f81fSBarry Smith   PetscInt   i,nz,n;
3654bef8e0ddSBarry Smith 
3655bef8e0ddSBarry Smith   PetscFunctionBegin;
3656bef8e0ddSBarry Smith   nz = aij->maxnz;
3657d0f46423SBarry Smith   n  = mat->rmap->n;
3658bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3659bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3660bef8e0ddSBarry Smith   }
3661bef8e0ddSBarry Smith   aij->nz = nz;
3662bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3663bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3664bef8e0ddSBarry Smith   }
3665bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3666bef8e0ddSBarry Smith }
3667bef8e0ddSBarry Smith 
3668a3bb6f32SFande Kong /*
3669e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3670a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3671a3bb6f32SFande Kong  * */
3672a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3673a3bb6f32SFande Kong {
3674a3bb6f32SFande Kong   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
3675a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3676a3bb6f32SFande Kong   PetscTablePosition tpos;
3677a3bb6f32SFande Kong   PetscInt           gid,lid,i,j,ncols,ec;
3678a3bb6f32SFande Kong   PetscInt           *garray;
3679a3bb6f32SFande Kong   PetscErrorCode  ierr;
3680a3bb6f32SFande Kong 
3681a3bb6f32SFande Kong   PetscFunctionBegin;
3682a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3683a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3684a3bb6f32SFande Kong   /* use a table */
3685a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3686a3bb6f32SFande Kong   ec = 0;
3687a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3688a3bb6f32SFande Kong     ncols = aij->i[i+1] - aij->i[i];
3689a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3690a3bb6f32SFande Kong       PetscInt data,gid1 = aij->j[aij->i[i] + j] + 1;
3691a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3692a3bb6f32SFande Kong       if (!data) {
3693a3bb6f32SFande Kong         /* one based table */
3694a3bb6f32SFande Kong         ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3695a3bb6f32SFande Kong       }
3696a3bb6f32SFande Kong     }
3697a3bb6f32SFande Kong   }
3698a3bb6f32SFande Kong   /* form array of columns we need */
3699a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3700a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3701a3bb6f32SFande Kong   while (tpos) {
3702a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3703a3bb6f32SFande Kong     gid--;
3704a3bb6f32SFande Kong     lid--;
3705a3bb6f32SFande Kong     garray[lid] = gid;
3706a3bb6f32SFande Kong   }
3707a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3708a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3709a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3710a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3711a3bb6f32SFande Kong   }
3712a3bb6f32SFande Kong   /* compact out the extra columns in B */
3713a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3714a3bb6f32SFande Kong         ncols = aij->i[i+1] - aij->i[i];
3715a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3716a3bb6f32SFande Kong       PetscInt gid1 = aij->j[aij->i[i] + j] + 1;
3717a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3718a3bb6f32SFande Kong       lid--;
3719a3bb6f32SFande Kong       aij->j[aij->i[i] + j] = lid;
3720a3bb6f32SFande Kong     }
3721a3bb6f32SFande Kong   }
3722ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3723ca5434daSLawrence Mitchell   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3724a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
3725a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3726a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3727a3bb6f32SFande Kong   PetscFunctionReturn(0);
3728a3bb6f32SFande Kong }
3729a3bb6f32SFande Kong 
3730bef8e0ddSBarry Smith /*@
3731bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3732bef8e0ddSBarry Smith        in the matrix.
3733bef8e0ddSBarry Smith 
3734bef8e0ddSBarry Smith   Input Parameters:
3735bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3736bef8e0ddSBarry Smith -  indices - the column indices
3737bef8e0ddSBarry Smith 
373815091d37SBarry Smith   Level: advanced
373915091d37SBarry Smith 
3740bef8e0ddSBarry Smith   Notes:
3741bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3742bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3743bef8e0ddSBarry Smith   of the MatSetValues() operation.
3744bef8e0ddSBarry Smith 
3745bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3746d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3747bef8e0ddSBarry Smith 
3748bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3749bef8e0ddSBarry Smith 
3750b9617806SBarry Smith     The indices should start with zero, not one.
3751b9617806SBarry Smith 
3752bef8e0ddSBarry Smith @*/
37537087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3754bef8e0ddSBarry Smith {
37554ac538c5SBarry Smith   PetscErrorCode ierr;
3756bef8e0ddSBarry Smith 
3757bef8e0ddSBarry Smith   PetscFunctionBegin;
37580700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
37594482741eSBarry Smith   PetscValidPointer(indices,2);
37604ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3761bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3762bef8e0ddSBarry Smith }
3763bef8e0ddSBarry Smith 
3764be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3765be6bf707SBarry Smith 
37667087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3767be6bf707SBarry Smith {
3768be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
37696849ba73SBarry Smith   PetscErrorCode ierr;
3770d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3771be6bf707SBarry Smith 
3772be6bf707SBarry Smith   PetscFunctionBegin;
3773169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3774be6bf707SBarry Smith 
3775be6bf707SBarry Smith   /* allocate space for values if not already there */
3776be6bf707SBarry Smith   if (!aij->saved_values) {
3777854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
37783bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3779be6bf707SBarry Smith   }
3780be6bf707SBarry Smith 
3781be6bf707SBarry Smith   /* copy values over */
3782580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3783be6bf707SBarry Smith   PetscFunctionReturn(0);
3784be6bf707SBarry Smith }
3785be6bf707SBarry Smith 
3786be6bf707SBarry Smith /*@
3787be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3788be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3789be6bf707SBarry Smith        nonlinear portion.
3790be6bf707SBarry Smith 
3791be6bf707SBarry Smith    Collect on Mat
3792be6bf707SBarry Smith 
3793be6bf707SBarry Smith   Input Parameters:
37940e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3795be6bf707SBarry Smith 
379615091d37SBarry Smith   Level: advanced
379715091d37SBarry Smith 
3798be6bf707SBarry Smith   Common Usage, with SNESSolve():
3799be6bf707SBarry Smith $    Create Jacobian matrix
3800be6bf707SBarry Smith $    Set linear terms into matrix
3801be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3802be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3803be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3804512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3805be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3806be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3807be6bf707SBarry Smith $    In your Jacobian routine
3808be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3809be6bf707SBarry Smith $      Set nonlinear terms in matrix
3810be6bf707SBarry Smith 
3811be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3812be6bf707SBarry Smith $    // build linear portion of Jacobian
3813512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3814be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3815be6bf707SBarry Smith $    loop over nonlinear iterations
3816be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3817be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3818be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3819be6bf707SBarry Smith $       Solve linear system with Jacobian
3820be6bf707SBarry Smith $    endloop
3821be6bf707SBarry Smith 
3822be6bf707SBarry Smith   Notes:
3823be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3824512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3825be6bf707SBarry Smith     calling this routine.
3826be6bf707SBarry Smith 
38270c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38280c468ba9SBarry Smith     and does not allocated additional space.
38290c468ba9SBarry Smith 
3830be6bf707SBarry Smith .seealso: MatRetrieveValues()
3831be6bf707SBarry Smith 
3832be6bf707SBarry Smith @*/
38337087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3834be6bf707SBarry Smith {
38354ac538c5SBarry Smith   PetscErrorCode ierr;
3836be6bf707SBarry Smith 
3837be6bf707SBarry Smith   PetscFunctionBegin;
38380700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3839e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3840e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38414ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3842be6bf707SBarry Smith   PetscFunctionReturn(0);
3843be6bf707SBarry Smith }
3844be6bf707SBarry Smith 
38457087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3846be6bf707SBarry Smith {
3847be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38486849ba73SBarry Smith   PetscErrorCode ierr;
3849d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3850be6bf707SBarry Smith 
3851be6bf707SBarry Smith   PetscFunctionBegin;
3852169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3853f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3854be6bf707SBarry Smith   /* copy values over */
3855580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3856be6bf707SBarry Smith   PetscFunctionReturn(0);
3857be6bf707SBarry Smith }
3858be6bf707SBarry Smith 
3859be6bf707SBarry Smith /*@
3860be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3861be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3862be6bf707SBarry Smith        nonlinear portion.
3863be6bf707SBarry Smith 
3864be6bf707SBarry Smith    Collect on Mat
3865be6bf707SBarry Smith 
3866be6bf707SBarry Smith   Input Parameters:
3867386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3868be6bf707SBarry Smith 
386915091d37SBarry Smith   Level: advanced
387015091d37SBarry Smith 
3871be6bf707SBarry Smith .seealso: MatStoreValues()
3872be6bf707SBarry Smith 
3873be6bf707SBarry Smith @*/
38747087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3875be6bf707SBarry Smith {
38764ac538c5SBarry Smith   PetscErrorCode ierr;
3877be6bf707SBarry Smith 
3878be6bf707SBarry Smith   PetscFunctionBegin;
38790700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3880e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3881e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38824ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3883be6bf707SBarry Smith   PetscFunctionReturn(0);
3884be6bf707SBarry Smith }
3885be6bf707SBarry Smith 
3886f83d6046SBarry Smith 
3887be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
388817ab2063SBarry Smith /*@C
3889682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
38900d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
38916e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
389251c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
38932bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
389417ab2063SBarry Smith 
3895d083f849SBarry Smith    Collective
3896db81eaa0SLois Curfman McInnes 
389717ab2063SBarry Smith    Input Parameters:
3898db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
389917ab2063SBarry Smith .  m - number of rows
390017ab2063SBarry Smith .  n - number of columns
390117ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
390251c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39030298fd71SBarry Smith          (possibly different for each row) or NULL
390417ab2063SBarry Smith 
390517ab2063SBarry Smith    Output Parameter:
3906416022c9SBarry Smith .  A - the matrix
390717ab2063SBarry Smith 
3908175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3909f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3910175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3911175b88e8SBarry Smith 
3912b259b22eSLois Curfman McInnes    Notes:
391349a6f317SBarry Smith    If nnz is given then nz is ignored
391449a6f317SBarry Smith 
391517ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
391617ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39170002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
391844cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
391917ab2063SBarry Smith 
392017ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39210298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39223d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39236da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
392417ab2063SBarry Smith 
3925682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39264fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3927682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39286c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39296c7ebb05SLois Curfman McInnes 
39306c7ebb05SLois Curfman McInnes    Options Database Keys:
3931698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39329db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
393317ab2063SBarry Smith 
3934027ccd11SLois Curfman McInnes    Level: intermediate
3935027ccd11SLois Curfman McInnes 
393669b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
393736db0b34SBarry Smith 
393817ab2063SBarry Smith @*/
39397087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
394017ab2063SBarry Smith {
3941dfbe8321SBarry Smith   PetscErrorCode ierr;
39426945ee14SBarry Smith 
39433a40ed3dSBarry Smith   PetscFunctionBegin;
3944f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3945117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3946c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3947d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3948273d9f13SBarry Smith   PetscFunctionReturn(0);
3949273d9f13SBarry Smith }
3950273d9f13SBarry Smith 
3951273d9f13SBarry Smith /*@C
3952273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3953273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3954273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3955273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3956273d9f13SBarry Smith 
3957d083f849SBarry Smith    Collective
3958273d9f13SBarry Smith 
3959273d9f13SBarry Smith    Input Parameters:
39601c4f3114SJed Brown +  B - The matrix
3961273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3962273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39630298fd71SBarry Smith          (possibly different for each row) or NULL
3964273d9f13SBarry Smith 
3965273d9f13SBarry Smith    Notes:
396649a6f317SBarry Smith      If nnz is given then nz is ignored
396749a6f317SBarry Smith 
3968273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3969273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3970273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3971273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3972273d9f13SBarry Smith 
3973273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39740298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3975273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3976273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3977273d9f13SBarry Smith 
3978aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3979aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3980aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3981aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3982aa95bbe8SBarry Smith 
3983a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3984a96a251dSBarry Smith    entries or columns indices
3985a96a251dSBarry Smith 
3986273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3987273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3988273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3989273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3990273d9f13SBarry Smith 
3991273d9f13SBarry Smith    Options Database Keys:
3992698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
399347b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3994273d9f13SBarry Smith 
3995273d9f13SBarry Smith    Level: intermediate
3996273d9f13SBarry Smith 
399719b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
399819b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
3999273d9f13SBarry Smith 
4000273d9f13SBarry Smith @*/
40017087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4002273d9f13SBarry Smith {
40034ac538c5SBarry Smith   PetscErrorCode ierr;
4004a23d5eceSKris Buschelman 
4005a23d5eceSKris Buschelman   PetscFunctionBegin;
40066ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40076ba663aaSJed Brown   PetscValidType(B,1);
40084ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4009a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4010a23d5eceSKris Buschelman }
4011a23d5eceSKris Buschelman 
40127087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4013a23d5eceSKris Buschelman {
4014273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40152576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40166849ba73SBarry Smith   PetscErrorCode ierr;
401797f1f81fSBarry Smith   PetscInt       i;
4018273d9f13SBarry Smith 
4019273d9f13SBarry Smith   PetscFunctionBegin;
40202576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4021a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4022c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4023c461c341SBarry Smith     nz             = 0;
4024c461c341SBarry Smith   }
402526283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
402626283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4027899cda47SBarry Smith 
4028435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
402960e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4030cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4031d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
403260e0710aSBarry 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]);
403360e0710aSBarry 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);
4034b73539f3SBarry Smith     }
4035b73539f3SBarry Smith   }
4036b73539f3SBarry Smith 
4037273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
40382205254eSKarl Rupp 
4039273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4040273d9f13SBarry Smith 
4041ab93d7beSBarry Smith   if (!skipallocation) {
40422ee49352SLisandro Dalcin     if (!b->imax) {
4043071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4044071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4045071fcb05SBarry Smith     }
4046071fcb05SBarry Smith     if (!b->ilen) {
4047071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4048071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4049071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4050071fcb05SBarry Smith     } else {
4051071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
40522ee49352SLisandro Dalcin     }
4053846b4da1SFande Kong     if (!b->ipre) {
4054846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4055846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4056846b4da1SFande Kong     }
4057273d9f13SBarry Smith     if (!nnz) {
4058435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4059c62bd62aSJed Brown       else if (nz < 0) nz = 1;
40605d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4061d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4062d0f46423SBarry Smith       nz = nz*B->rmap->n;
4063273d9f13SBarry Smith     } else {
4064c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4065c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4066c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4067273d9f13SBarry Smith     }
4068ab93d7beSBarry Smith 
4069273d9f13SBarry Smith     /* allocate the matrix space */
407053dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
40712ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4072396832f4SHong Zhang     if (B->structure_only) {
40735848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
40745848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4075396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4076396832f4SHong Zhang     } else {
4077dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
40783bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4079396832f4SHong Zhang     }
4080bfeeae90SHong Zhang     b->i[0] = 0;
4081d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
40825da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
40835da197adSKris Buschelman     }
4084396832f4SHong Zhang     if (B->structure_only) {
4085396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4086396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4087396832f4SHong Zhang     } else {
4088273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4089e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4090396832f4SHong Zhang     }
4091e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4092c461c341SBarry Smith   } else {
4093e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4094e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4095c461c341SBarry Smith   }
4096273d9f13SBarry Smith 
4097846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4098846b4da1SFande Kong     /* reserve user-requested sparsity */
4099580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4100846b4da1SFande Kong   }
4101846b4da1SFande Kong 
4102846b4da1SFande Kong 
4103273d9f13SBarry Smith   b->nz               = 0;
4104273d9f13SBarry Smith   b->maxnz            = nz;
4105273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41062205254eSKarl Rupp   if (realalloc) {
41072205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41082205254eSKarl Rupp   }
4109cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4110cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4111273d9f13SBarry Smith   PetscFunctionReturn(0);
4112273d9f13SBarry Smith }
4113273d9f13SBarry Smith 
4114846b4da1SFande Kong 
4115846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4116846b4da1SFande Kong {
4117846b4da1SFande Kong   Mat_SeqAIJ     *a;
4118a5bbaf83SFande Kong   PetscInt       i;
4119846b4da1SFande Kong   PetscErrorCode ierr;
4120846b4da1SFande Kong 
4121846b4da1SFande Kong   PetscFunctionBegin;
4122846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
412314d0e64fSAlex Lindsay 
412414d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
412514d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
412614d0e64fSAlex Lindsay 
4127846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41282c814fdeSFande Kong   /* if no saved info, we error out */
4129fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
41302c814fdeSFande Kong 
4131fb4dc15dSAlex 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");
41322c814fdeSFande Kong 
4133580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4134580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4135846b4da1SFande Kong   a->i[0] = 0;
4136846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4137846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4138846b4da1SFande Kong   }
4139846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4140846b4da1SFande Kong   a->nz               = 0;
4141846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4142846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4143846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4144846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4145846b4da1SFande Kong   PetscFunctionReturn(0);
4146846b4da1SFande Kong }
4147846b4da1SFande Kong 
414858d36128SBarry Smith /*@
4149a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4150a1661176SMatthew Knepley 
4151a1661176SMatthew Knepley    Input Parameters:
4152a1661176SMatthew Knepley +  B - the matrix
4153a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4154a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4155a1661176SMatthew Knepley -  v - optional values in the matrix
4156a1661176SMatthew Knepley 
4157a1661176SMatthew Knepley    Level: developer
4158a1661176SMatthew Knepley 
41596a9b8d82SBarry Smith    Notes:
416058d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
416158d36128SBarry Smith 
41626a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
41636a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
41646a9b8d82SBarry Smith 
41656a9b8d82SBarry Smith     Developer Notes:
41666a9b8d82SBarry 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
41676a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
41686a9b8d82SBarry Smith 
41696a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
41706a9b8d82SBarry Smith 
41716a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4172a1661176SMatthew Knepley @*/
4173a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4174a1661176SMatthew Knepley {
4175a1661176SMatthew Knepley   PetscErrorCode ierr;
4176a1661176SMatthew Knepley 
4177a1661176SMatthew Knepley   PetscFunctionBegin;
41780700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
41796ba663aaSJed Brown   PetscValidType(B,1);
41804ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4181a1661176SMatthew Knepley   PetscFunctionReturn(0);
4182a1661176SMatthew Knepley }
4183a1661176SMatthew Knepley 
41847087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4185a1661176SMatthew Knepley {
4186a1661176SMatthew Knepley   PetscInt       i;
4187a1661176SMatthew Knepley   PetscInt       m,n;
4188a1661176SMatthew Knepley   PetscInt       nz;
41896a9b8d82SBarry Smith   PetscInt       *nnz;
4190a1661176SMatthew Knepley   PetscErrorCode ierr;
4191a1661176SMatthew Knepley 
4192a1661176SMatthew Knepley   PetscFunctionBegin;
419365e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4194779a8d59SSatish Balay 
4195779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4196779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4197779a8d59SSatish Balay 
4198779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4199854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4200a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4201b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
420265e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4203a1661176SMatthew Knepley     nnz[i] = nz;
4204a1661176SMatthew Knepley   }
4205a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4206a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4207a1661176SMatthew Knepley 
4208a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4209071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4210a1661176SMatthew Knepley   }
4211a1661176SMatthew Knepley 
4212a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4213a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4214a1661176SMatthew Knepley 
42157827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4216a1661176SMatthew Knepley   PetscFunctionReturn(0);
4217a1661176SMatthew Knepley }
4218a1661176SMatthew Knepley 
4219c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4220af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4221170fe5c8SBarry Smith 
4222170fe5c8SBarry Smith /*
4223170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4224170fe5c8SBarry Smith 
4225170fe5c8SBarry Smith                n                       p                          p
42262da392ccSBarry Smith         [             ]       [             ]         [                 ]
42272da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
42282da392ccSBarry Smith         [             ]       [             ]         [                 ]
4229170fe5c8SBarry Smith 
4230170fe5c8SBarry Smith */
4231170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4232170fe5c8SBarry Smith {
4233170fe5c8SBarry Smith   PetscErrorCode    ierr;
4234170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4235170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4236170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
423786214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4238170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4239170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4240170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
424186214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
424286214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4243170fe5c8SBarry Smith 
4244170fe5c8SBarry Smith   PetscFunctionBegin;
4245d0f46423SBarry Smith   m    = A->rmap->n;
4246d0f46423SBarry Smith   n    = A->cmap->n;
4247d0f46423SBarry Smith   p    = B->cmap->n;
4248170fe5c8SBarry Smith   a    = sub_a->v;
4249170fe5c8SBarry Smith   b    = sub_b->a;
4250170fe5c8SBarry Smith   c    = sub_c->v;
425186214ceeSStefano Zampini   if (clda == m) {
4252580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
425386214ceeSStefano Zampini   } else {
425486214ceeSStefano Zampini     for (j=0;j<p;j++)
425586214ceeSStefano Zampini       for (i=0;i<m;i++)
425686214ceeSStefano Zampini         c[j*clda + i] = 0.0;
425786214ceeSStefano Zampini   }
4258170fe5c8SBarry Smith   ii  = sub_b->i;
4259170fe5c8SBarry Smith   idx = sub_b->j;
4260170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4261170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4262170fe5c8SBarry Smith     while (q-->0) {
426386214ceeSStefano Zampini       c_q = c + clda*(*idx);
426486214ceeSStefano Zampini       a_q = a + alda*i;
4265854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4266170fe5c8SBarry Smith       idx++;
4267170fe5c8SBarry Smith       b++;
4268170fe5c8SBarry Smith     }
4269170fe5c8SBarry Smith   }
4270170fe5c8SBarry Smith   PetscFunctionReturn(0);
4271170fe5c8SBarry Smith }
4272170fe5c8SBarry Smith 
42734222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4274170fe5c8SBarry Smith {
4275170fe5c8SBarry Smith   PetscErrorCode ierr;
4276d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
427786214ceeSStefano Zampini   PetscBool      cisdense;
4278170fe5c8SBarry Smith 
4279170fe5c8SBarry Smith   PetscFunctionBegin;
428060e0710aSBarry 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);
42814222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
42824222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
428386214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
428486214ceeSStefano Zampini   if (!cisdense) {
428586214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
428686214ceeSStefano Zampini   }
428786214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4288d73949e8SHong Zhang 
42894222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4290170fe5c8SBarry Smith   PetscFunctionReturn(0);
4291170fe5c8SBarry Smith }
4292170fe5c8SBarry Smith 
4293170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
42940bad9183SKris Buschelman /*MC
4295fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
42960bad9183SKris Buschelman    based on compressed sparse row format.
42970bad9183SKris Buschelman 
42980bad9183SKris Buschelman    Options Database Keys:
42990bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
43000bad9183SKris Buschelman 
43010bad9183SKris Buschelman    Level: beginner
43020bad9183SKris Buschelman 
43030cd7f59aSBarry Smith    Notes:
43040cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
43050cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
43060cd7f59aSBarry Smith     in the matrix
43070cd7f59aSBarry Smith 
43080cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
43090cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
43100cd7f59aSBarry Smith 
43110cd7f59aSBarry Smith   Developer Notes:
43120cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
43130cd7f59aSBarry Smith 
4314f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
43150bad9183SKris Buschelman M*/
43160bad9183SKris Buschelman 
4317ccd284c7SBarry Smith /*MC
4318ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4319ccd284c7SBarry Smith 
4320ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4321ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
43220cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4323ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4324ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4325ccd284c7SBarry Smith 
4326ccd284c7SBarry Smith    Options Database Keys:
4327ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4328ccd284c7SBarry Smith 
432995452b02SPatrick Sanan   Developer Notes:
4330ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4331ccd284c7SBarry Smith    enough exist.
4332ccd284c7SBarry Smith 
4333ccd284c7SBarry Smith   Level: beginner
4334ccd284c7SBarry Smith 
4335ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4336ccd284c7SBarry Smith M*/
4337ccd284c7SBarry Smith 
4338ccd284c7SBarry Smith /*MC
4339ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4340ccd284c7SBarry Smith 
4341ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4342ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4343ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4344ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4345ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4346ccd284c7SBarry Smith 
4347ccd284c7SBarry Smith    Options Database Keys:
4348ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4349ccd284c7SBarry Smith 
4350ccd284c7SBarry Smith   Level: beginner
4351ccd284c7SBarry Smith 
4352ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4353ccd284c7SBarry Smith M*/
4354ccd284c7SBarry Smith 
43557906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
43567906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
43577906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
43587906f579SHong Zhang #endif
4359d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4360d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4361d24d4204SJose E. Roman #endif
43627906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
43637906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
43647906f579SHong Zhang #endif
43657906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
43667906f579SHong Zhang 
4367d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4368c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
43694222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
43707906f579SHong Zhang 
43718c778c55SBarry Smith /*@C
43728f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
43738c778c55SBarry Smith 
43748c778c55SBarry Smith    Not Collective
43758c778c55SBarry Smith 
43768c778c55SBarry Smith    Input Parameter:
4377579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
43788c778c55SBarry Smith 
43798c778c55SBarry Smith    Output Parameter:
43808c778c55SBarry Smith .   array - pointer to the data
43818c778c55SBarry Smith 
43828c778c55SBarry Smith    Level: intermediate
43838c778c55SBarry Smith 
4384774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
43858c778c55SBarry Smith @*/
43868c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
43878c778c55SBarry Smith {
43888c778c55SBarry Smith   PetscErrorCode ierr;
43898c778c55SBarry Smith 
43908c778c55SBarry Smith   PetscFunctionBegin;
43918c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
43928c778c55SBarry Smith   PetscFunctionReturn(0);
43938c778c55SBarry Smith }
43948c778c55SBarry Smith 
439521e72a00SBarry Smith /*@C
43968f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
43978f1ea47aSStefano Zampini 
43988f1ea47aSStefano Zampini    Not Collective
43998f1ea47aSStefano Zampini 
44008f1ea47aSStefano Zampini    Input Parameter:
44018f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44028f1ea47aSStefano Zampini 
44038f1ea47aSStefano Zampini    Output Parameter:
44048f1ea47aSStefano Zampini .   array - pointer to the data
44058f1ea47aSStefano Zampini 
44068f1ea47aSStefano Zampini    Level: intermediate
44078f1ea47aSStefano Zampini 
44088f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
44098f1ea47aSStefano Zampini @*/
44108f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
44118f1ea47aSStefano Zampini {
44128c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4413c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44148f1ea47aSStefano Zampini #endif
44158f1ea47aSStefano Zampini   PetscErrorCode ierr;
44168f1ea47aSStefano Zampini 
44178f1ea47aSStefano Zampini   PetscFunctionBegin;
44188c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4419c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44208f1ea47aSStefano Zampini #endif
44218f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44228c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4423c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
44248f1ea47aSStefano Zampini #endif
44258f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44268f1ea47aSStefano Zampini }
44278f1ea47aSStefano Zampini 
44288f1ea47aSStefano Zampini /*@C
44298f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
44308f1ea47aSStefano Zampini 
44318f1ea47aSStefano Zampini    Not Collective
44328f1ea47aSStefano Zampini 
44338f1ea47aSStefano Zampini    Input Parameter:
44348f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44358f1ea47aSStefano Zampini 
44368f1ea47aSStefano Zampini    Output Parameter:
44378f1ea47aSStefano Zampini .   array - pointer to the data
44388f1ea47aSStefano Zampini 
44398f1ea47aSStefano Zampini    Level: intermediate
44408f1ea47aSStefano Zampini 
44418f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
44428f1ea47aSStefano Zampini @*/
44438f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
44448f1ea47aSStefano Zampini {
44458c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4446c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
44478f1ea47aSStefano Zampini #endif
44488f1ea47aSStefano Zampini   PetscErrorCode ierr;
44498f1ea47aSStefano Zampini 
44508f1ea47aSStefano Zampini   PetscFunctionBegin;
44518c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4452c70f7ee4SJunchao Zhang   oval = A->offloadmask;
44538f1ea47aSStefano Zampini #endif
44548f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
44558c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4456c70f7ee4SJunchao Zhang   A->offloadmask = oval;
44578f1ea47aSStefano Zampini #endif
44588f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44598f1ea47aSStefano Zampini }
44608f1ea47aSStefano Zampini 
44618f1ea47aSStefano Zampini /*@C
446221e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
446321e72a00SBarry Smith 
446421e72a00SBarry Smith    Not Collective
446521e72a00SBarry Smith 
446621e72a00SBarry Smith    Input Parameter:
4467579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
446821e72a00SBarry Smith 
446921e72a00SBarry Smith    Output Parameter:
447021e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
447121e72a00SBarry Smith 
447221e72a00SBarry Smith    Level: intermediate
447321e72a00SBarry Smith 
447421e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
447521e72a00SBarry Smith @*/
447621e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
447721e72a00SBarry Smith {
447821e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
447921e72a00SBarry Smith 
448021e72a00SBarry Smith   PetscFunctionBegin;
448121e72a00SBarry Smith   *nz = aij->rmax;
448221e72a00SBarry Smith   PetscFunctionReturn(0);
448321e72a00SBarry Smith }
448421e72a00SBarry Smith 
44858c778c55SBarry Smith /*@C
4486579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
44878c778c55SBarry Smith 
44888c778c55SBarry Smith    Not Collective
44898c778c55SBarry Smith 
44908c778c55SBarry Smith    Input Parameters:
4491a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4492a2b725a8SWilliam Gropp -  array - pointer to the data
44938c778c55SBarry Smith 
44948c778c55SBarry Smith    Level: intermediate
44958c778c55SBarry Smith 
4496774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
44978c778c55SBarry Smith @*/
44988c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
44998c778c55SBarry Smith {
45008c778c55SBarry Smith   PetscErrorCode ierr;
45018c778c55SBarry Smith 
45028c778c55SBarry Smith   PetscFunctionBegin;
45038c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
45048c778c55SBarry Smith   PetscFunctionReturn(0);
45058c778c55SBarry Smith }
45068c778c55SBarry Smith 
450734b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
45080ce8acdeSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
450902fe1965SBarry Smith #endif
45103d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
45113d0639e7SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat);
45123d0639e7SStefano Zampini #endif
451302fe1965SBarry Smith 
45148cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4515273d9f13SBarry Smith {
4516273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4517dfbe8321SBarry Smith   PetscErrorCode ierr;
451838baddfdSBarry Smith   PetscMPIInt    size;
4519273d9f13SBarry Smith 
4520273d9f13SBarry Smith   PetscFunctionBegin;
4521ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
4522e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4523273d9f13SBarry Smith 
4524b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
45252205254eSKarl Rupp 
4526b0a32e0cSBarry Smith   B->data = (void*)b;
45272205254eSKarl Rupp 
4528549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4529071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
45302205254eSKarl Rupp 
4531f4259b30SLisandro Dalcin   b->row                = NULL;
4532f4259b30SLisandro Dalcin   b->col                = NULL;
4533f4259b30SLisandro Dalcin   b->icol               = NULL;
4534b810aeb4SBarry Smith   b->reallocs           = 0;
453536db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4536f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4537416022c9SBarry Smith   b->nonew              = 0;
4538f4259b30SLisandro Dalcin   b->diag               = NULL;
4539f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4540f4259b30SLisandro Dalcin   B->spptr              = NULL;
4541f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4542f4259b30SLisandro Dalcin   b->idiag              = NULL;
4543f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4544f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
454571f1c65dSBarry Smith   b->omega              = 1.0;
454671f1c65dSBarry Smith   b->fshift             = 0.0;
454771f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4548bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4549a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
455017ab2063SBarry Smith 
455135d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4552bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4553bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
45548c778c55SBarry Smith 
4555b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4556bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4557bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4558b3866ffcSBarry Smith #endif
455917f1a0eaSHong Zhang 
4560bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4561bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4562bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4563bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4564bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4565bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
45664dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
45679779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
45684a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4569191b95cbSRichard Tran Mills #endif
457034b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
457102fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
45724222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
457302fe1965SBarry Smith #endif
45743d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
45753d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
45763d0639e7SStefano Zampini #endif
4577bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4578af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4579af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4580af8000cdSHong Zhang #endif
4581d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4582d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4583d24d4204SJose E. Roman #endif
458463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
458563c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
45864222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
458763c07aadSStefano Zampini #endif
4588b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4589d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4590c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4591bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4592bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4593bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4594846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4595bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4596bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
45974222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
45984222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
45994222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
46004108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
460117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
46024099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
46033a40ed3dSBarry Smith   PetscFunctionReturn(0);
460417ab2063SBarry Smith }
460517ab2063SBarry Smith 
4606b24902e0SBarry Smith /*
4607b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4608b24902e0SBarry Smith */
4609ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
461017ab2063SBarry Smith {
46112a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
46126849ba73SBarry Smith   PetscErrorCode ierr;
4613071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
461417ab2063SBarry Smith 
46153a40ed3dSBarry Smith   PetscFunctionBegin;
4616ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4617273d9f13SBarry Smith 
4618d5f3da31SBarry Smith   C->factortype = A->factortype;
4619f4259b30SLisandro Dalcin   c->row        = NULL;
4620f4259b30SLisandro Dalcin   c->col        = NULL;
4621f4259b30SLisandro Dalcin   c->icol       = NULL;
46226ad4291fSHong Zhang   c->reallocs   = 0;
462317ab2063SBarry Smith 
46246ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
462517ab2063SBarry Smith 
4626aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4627aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4628eec197d1SBarry Smith 
4629071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4630071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4631071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4632071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
46333bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
463417ab2063SBarry Smith 
463517ab2063SBarry Smith   /* allocate the matrix space */
4636f77e22a1SHong Zhang   if (mallocmatspace) {
4637dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
46383bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
46392205254eSKarl Rupp 
4640f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
46412205254eSKarl Rupp 
4642580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
464317ab2063SBarry Smith     if (m > 0) {
4644580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4645be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
4646580bdb30SBarry Smith         ierr = PetscArraycpy(c->a,a->a,a->i[m]);CHKERRQ(ierr);
4647be6bf707SBarry Smith       } else {
4648580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
464917ab2063SBarry Smith       }
465008480c60SBarry Smith     }
4651f77e22a1SHong Zhang   }
465217ab2063SBarry Smith 
46536ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4654416022c9SBarry Smith   c->roworiented       = a->roworiented;
4655416022c9SBarry Smith   c->nonew             = a->nonew;
4656416022c9SBarry Smith   if (a->diag) {
4657854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4658071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
46593bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4660071fcb05SBarry Smith   } else c->diag = NULL;
46612205254eSKarl Rupp 
4662f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4663f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4664f4259b30SLisandro Dalcin   c->idiag              = NULL;
4665f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4666a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4667e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4668e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
46696ad4291fSHong Zhang 
4670893ad86cSHong Zhang   c->rmax         = a->rmax;
4671416022c9SBarry Smith   c->nz           = a->nz;
46728ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4673273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4674754ec7b1SSatish Balay 
46756ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
46766ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4677cd6b891eSBarry Smith   if (a->compressedrow.use) {
46786ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4679dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4680580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4681580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
468227ea64f8SHong Zhang   } else {
468327ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
46840298fd71SBarry Smith     c->compressedrow.i      = NULL;
46850298fd71SBarry Smith     c->compressedrow.rindex = NULL;
46866ad4291fSHong Zhang   }
4687ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4688e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
46894846f1f5SKris Buschelman 
46902205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4691140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
46923a40ed3dSBarry Smith   PetscFunctionReturn(0);
469317ab2063SBarry Smith }
469417ab2063SBarry Smith 
4695b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4696b24902e0SBarry Smith {
4697b24902e0SBarry Smith   PetscErrorCode ierr;
4698b24902e0SBarry Smith 
4699b24902e0SBarry Smith   PetscFunctionBegin;
4700ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
47014b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4702cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
470333d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4704cfd3f464SBarry Smith   }
4705a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4706f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4707b24902e0SBarry Smith   PetscFunctionReturn(0);
4708b24902e0SBarry Smith }
4709b24902e0SBarry Smith 
4710112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4711fbdbba38SShri Abhyankar {
471252f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
471352f91c60SVaclav Hapla   PetscErrorCode ierr;
471452f91c60SVaclav Hapla 
471552f91c60SVaclav Hapla   PetscFunctionBegin;
471652f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
471752f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4718c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4719c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
472052f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
472152f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
472252f91c60SVaclav Hapla   if (isbinary) {
472352f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
472452f91c60SVaclav Hapla   } else if (ishdf5) {
472552f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
472652f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
472752f91c60SVaclav Hapla #else
472852f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
472952f91c60SVaclav Hapla #endif
473052f91c60SVaclav Hapla   } else {
473152f91c60SVaclav 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);
473252f91c60SVaclav Hapla   }
473352f91c60SVaclav Hapla   PetscFunctionReturn(0);
473452f91c60SVaclav Hapla }
473552f91c60SVaclav Hapla 
47363ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
473752f91c60SVaclav Hapla {
47383ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4739fbdbba38SShri Abhyankar   PetscErrorCode ierr;
47403ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4741fbdbba38SShri Abhyankar 
4742fbdbba38SShri Abhyankar   PetscFunctionBegin;
47433ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4744bbead8a2SBarry Smith 
47453ea6fe3dSLisandro Dalcin   /* read in matrix header */
47463ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
47473ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4748fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
47493ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
47503ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4751bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4752fbdbba38SShri Abhyankar 
47533ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
47543ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
47553ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
47563ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
47573ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
47583ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
47593ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
47603ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
47613ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
47623ea6fe3dSLisandro Dalcin 
47633ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
47643ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
47653ea6fe3dSLisandro 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);
47663ea6fe3dSLisandro Dalcin 
4767fbdbba38SShri Abhyankar   /* read in row lengths */
47683ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
47693ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
47703ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
47713ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
47723ea6fe3dSLisandro 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);
47733ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
47743ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
47753ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
477660e0710aSBarry 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);
47773ea6fe3dSLisandro Dalcin   /* store row lengths */
47783ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
47793ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4780fbdbba38SShri Abhyankar 
47813ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
47823ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
47833ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
47843ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
47853ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
47863ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4787fbdbba38SShri Abhyankar 
47883ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
47893ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4790fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4791fbdbba38SShri Abhyankar }
4792fbdbba38SShri Abhyankar 
4793ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
47947264ac53SSatish Balay {
47957264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4796dfbe8321SBarry Smith   PetscErrorCode ierr;
4797eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4798eeffb40dSHong Zhang   PetscInt k;
4799eeffb40dSHong Zhang #endif
48007264ac53SSatish Balay 
48013a40ed3dSBarry Smith   PetscFunctionBegin;
4802bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4803d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4804ca44d042SBarry Smith     *flg = PETSC_FALSE;
4805ca44d042SBarry Smith     PetscFunctionReturn(0);
4806bcd2baecSBarry Smith   }
48077264ac53SSatish Balay 
48087264ac53SSatish Balay   /* if the a->i are the same */
4809580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4810abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
48117264ac53SSatish Balay 
48127264ac53SSatish Balay   /* if a->j are the same */
4813580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4814abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4815bcd2baecSBarry Smith 
4816bcd2baecSBarry Smith   /* if a->a are the same */
4817eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4818eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4819eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4820eeffb40dSHong Zhang       *flg = PETSC_FALSE;
48213a40ed3dSBarry Smith       PetscFunctionReturn(0);
4822eeffb40dSHong Zhang     }
4823eeffb40dSHong Zhang   }
4824eeffb40dSHong Zhang #else
4825580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4826eeffb40dSHong Zhang #endif
4827eeffb40dSHong Zhang   PetscFunctionReturn(0);
48287264ac53SSatish Balay }
482936db0b34SBarry Smith 
483005869f15SSatish Balay /*@
483136db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
483236db0b34SBarry Smith               provided by the user.
483336db0b34SBarry Smith 
4834d083f849SBarry Smith       Collective
483536db0b34SBarry Smith 
483636db0b34SBarry Smith    Input Parameters:
483736db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
483836db0b34SBarry Smith .   m - number of rows
483936db0b34SBarry Smith .   n - number of columns
4840483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
484136db0b34SBarry Smith .   j - column indices
484236db0b34SBarry Smith -   a - matrix values
484336db0b34SBarry Smith 
484436db0b34SBarry Smith    Output Parameter:
484536db0b34SBarry Smith .   mat - the matrix
484636db0b34SBarry Smith 
484736db0b34SBarry Smith    Level: intermediate
484836db0b34SBarry Smith 
484936db0b34SBarry Smith    Notes:
48500551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4851292fb18eSBarry Smith     once the matrix is destroyed and not before
485236db0b34SBarry Smith 
485336db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
485436db0b34SBarry Smith 
4855bfeeae90SHong Zhang        The i and j indices are 0 based
485636db0b34SBarry Smith 
4857a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4858a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
48598eef79e4SBarry Smith     as shown
4860a4552177SSatish Balay 
48618eef79e4SBarry Smith $        1 0 0
48628eef79e4SBarry Smith $        2 0 3
48638eef79e4SBarry Smith $        4 5 6
48648eef79e4SBarry Smith $
48658eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
48668eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
48678eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4868a4552177SSatish Balay 
48699985e31cSBarry Smith 
487069b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
487136db0b34SBarry Smith 
487236db0b34SBarry Smith @*/
4873c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
487436db0b34SBarry Smith {
4875dfbe8321SBarry Smith   PetscErrorCode ierr;
4876cbcfb4deSHong Zhang   PetscInt       ii;
487736db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4878cbcfb4deSHong Zhang   PetscInt jj;
487936db0b34SBarry Smith 
488036db0b34SBarry Smith   PetscFunctionBegin;
488141096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4882f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4883f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4884a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4885ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4886f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
4887ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4888071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4889071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4890ab93d7beSBarry Smith 
489136db0b34SBarry Smith   aij->i            = i;
489236db0b34SBarry Smith   aij->j            = j;
489336db0b34SBarry Smith   aij->a            = a;
489436db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
489536db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4896e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4897e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
489836db0b34SBarry Smith 
489936db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
490036db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
490176bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
490260e0710aSBarry 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]);
49039985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4904a061629eSStefano 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);
4905a061629eSStefano 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);
49069985e31cSBarry Smith       }
490736db0b34SBarry Smith     }
490876bd3646SJed Brown   }
490976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
491036db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
491160e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
491260e0710aSBarry 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]);
491336db0b34SBarry Smith     }
491476bd3646SJed Brown   }
491536db0b34SBarry Smith 
4916b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4917b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
491836db0b34SBarry Smith   PetscFunctionReturn(0);
491936db0b34SBarry Smith }
492080ef6e79SMatthew G Knepley /*@C
4921d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
49228a0b0e6bSVictor Minden               provided by the user.
49238a0b0e6bSVictor Minden 
4924d083f849SBarry Smith       Collective
49258a0b0e6bSVictor Minden 
49268a0b0e6bSVictor Minden    Input Parameters:
49278a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
49288a0b0e6bSVictor Minden .   m   - number of rows
49298a0b0e6bSVictor Minden .   n   - number of columns
49308a0b0e6bSVictor Minden .   i   - row indices
49318a0b0e6bSVictor Minden .   j   - column indices
49321230e6d1SVictor Minden .   a   - matrix values
49331230e6d1SVictor Minden .   nz  - number of nonzeros
49341230e6d1SVictor Minden -   idx - 0 or 1 based
49358a0b0e6bSVictor Minden 
49368a0b0e6bSVictor Minden    Output Parameter:
49378a0b0e6bSVictor Minden .   mat - the matrix
49388a0b0e6bSVictor Minden 
49398a0b0e6bSVictor Minden    Level: intermediate
49408a0b0e6bSVictor Minden 
49418a0b0e6bSVictor Minden    Notes:
49428a0b0e6bSVictor Minden        The i and j indices are 0 based
49438a0b0e6bSVictor Minden 
49448a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
49458a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
49468a0b0e6bSVictor Minden     as shown:
49478a0b0e6bSVictor Minden 
49488a0b0e6bSVictor Minden         1 0 0
49498a0b0e6bSVictor Minden         2 0 3
49508a0b0e6bSVictor Minden         4 5 6
49518a0b0e6bSVictor Minden 
49528a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
49538a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
49548a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
49558a0b0e6bSVictor Minden 
49568a0b0e6bSVictor Minden 
495769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
49588a0b0e6bSVictor Minden 
49598a0b0e6bSVictor Minden @*/
4960c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
49618a0b0e6bSVictor Minden {
49628a0b0e6bSVictor Minden   PetscErrorCode ierr;
4963d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
49648a0b0e6bSVictor Minden 
49658a0b0e6bSVictor Minden 
49668a0b0e6bSVictor Minden   PetscFunctionBegin;
49671795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
49681230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
4969c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
49701230e6d1SVictor Minden   }
49718a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
49728a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
49738a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
49741230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
49751230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
49761230e6d1SVictor Minden     if (idx) {
49771230e6d1SVictor Minden       row = i[ii] - 1;
49781230e6d1SVictor Minden       col = j[ii] - 1;
49791230e6d1SVictor Minden     } else {
49801230e6d1SVictor Minden       row = i[ii];
49811230e6d1SVictor Minden       col = j[ii];
49828a0b0e6bSVictor Minden     }
49831230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
49848a0b0e6bSVictor Minden   }
49858a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49868a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4987d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
49888a0b0e6bSVictor Minden   PetscFunctionReturn(0);
49898a0b0e6bSVictor Minden }
499036db0b34SBarry Smith 
4991acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
4992acf2f550SJed Brown {
4993acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
4994acf2f550SJed Brown   PetscErrorCode ierr;
4995acf2f550SJed Brown 
4996acf2f550SJed Brown   PetscFunctionBegin;
4997acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
4998acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
49992205254eSKarl Rupp 
5000acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5001acf2f550SJed Brown   PetscFunctionReturn(0);
5002acf2f550SJed Brown }
5003acf2f550SJed Brown 
50049c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
50059c8f2541SHong Zhang {
50069c8f2541SHong Zhang   PetscErrorCode ierr;
50078761c3d6SHong Zhang   PetscMPIInt    size;
50089c8f2541SHong Zhang 
50099c8f2541SHong Zhang   PetscFunctionBegin;
50108761c3d6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
50117bbdc51dSHong Zhang   if (size == 1) {
50127bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
50137bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
50147bbdc51dSHong Zhang     } else {
50158761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
50167bbdc51dSHong Zhang     }
50178761c3d6SHong Zhang   } else {
50189c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
50198761c3d6SHong Zhang   }
50209c8f2541SHong Zhang   PetscFunctionReturn(0);
50219c8f2541SHong Zhang }
50229c8f2541SHong Zhang 
502381824310SBarry Smith /*
502453dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
502553dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
502653dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
502753dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
502853dd7562SDmitry Karpeev  */
502953dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
503053dd7562SDmitry Karpeev {
503153dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
503253dd7562SDmitry Karpeev   PetscErrorCode ierr;
503353dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
503453dd7562SDmitry Karpeev   PetscBool      seqaij;
503553dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
503653dd7562SDmitry Karpeev   PetscScalar    v;
503753dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
503853dd7562SDmitry Karpeev 
503953dd7562SDmitry Karpeev   PetscFunctionBegin;
504053dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
504153dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
50424099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
504353dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
504453dd7562SDmitry Karpeev   if (rowemb) {
504553dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
504653dd7562SDmitry 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);
504753dd7562SDmitry Karpeev   } else {
50486c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
504953dd7562SDmitry Karpeev   }
505053dd7562SDmitry Karpeev   if (colemb) {
505153dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
505253dd7562SDmitry 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);
505353dd7562SDmitry Karpeev   } else {
505453dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
505553dd7562SDmitry Karpeev   }
505653dd7562SDmitry Karpeev 
505753dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
505853dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
505953dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
506053dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
506153dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
506253dd7562SDmitry Karpeev     }
506353dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
506453dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
506553dd7562SDmitry Karpeev   }
506653dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
506753dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
506853dd7562SDmitry Karpeev   }
506953dd7562SDmitry Karpeev   count = 0;
507053dd7562SDmitry Karpeev   rowindices = NULL;
507153dd7562SDmitry Karpeev   colindices = NULL;
507253dd7562SDmitry Karpeev   if (rowemb) {
507353dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
507453dd7562SDmitry Karpeev   }
507553dd7562SDmitry Karpeev   if (colemb) {
507653dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
507753dd7562SDmitry Karpeev   }
507853dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
507953dd7562SDmitry Karpeev     PetscInt row;
508053dd7562SDmitry Karpeev     row = i;
508153dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
508253dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
508353dd7562SDmitry Karpeev       PetscInt col;
508453dd7562SDmitry Karpeev       col  = Baij->j[count];
508553dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
508653dd7562SDmitry Karpeev       v    = Baij->a[count];
508753dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
508853dd7562SDmitry Karpeev       ++count;
508953dd7562SDmitry Karpeev     }
509053dd7562SDmitry Karpeev   }
509153dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
509253dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
509353dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
509453dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
509553dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
509653dd7562SDmitry Karpeev   PetscFunctionReturn(0);
509753dd7562SDmitry Karpeev }
509853dd7562SDmitry Karpeev 
50994099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
51004099cc6bSBarry Smith 
51014099cc6bSBarry Smith /*@C
51024099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
51034099cc6bSBarry Smith 
51044099cc6bSBarry Smith    Collective on Mat
51054099cc6bSBarry Smith 
51064099cc6bSBarry Smith    Input Parameters:
51074099cc6bSBarry Smith +  mat      - the matrix object
51084099cc6bSBarry Smith -  matype   - matrix type
51094099cc6bSBarry Smith 
51104099cc6bSBarry Smith    Options Database Key:
51114099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
51124099cc6bSBarry Smith 
51134099cc6bSBarry Smith 
51144099cc6bSBarry Smith   Level: intermediate
51154099cc6bSBarry Smith 
51164099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
51174099cc6bSBarry Smith @*/
51184099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
51194099cc6bSBarry Smith {
5120fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
51214099cc6bSBarry Smith   PetscBool      sametype;
51224099cc6bSBarry Smith 
51234099cc6bSBarry Smith   PetscFunctionBegin;
51244099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
51254099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
51264099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
51274099cc6bSBarry Smith 
51284099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
51294099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
51304099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
51314099cc6bSBarry Smith   PetscFunctionReturn(0);
51324099cc6bSBarry Smith }
51334099cc6bSBarry Smith 
51344099cc6bSBarry Smith 
51354099cc6bSBarry Smith /*@C
51364099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
51374099cc6bSBarry Smith 
51384099cc6bSBarry Smith    Not Collective
51394099cc6bSBarry Smith 
51404099cc6bSBarry Smith    Input Parameters:
51414099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
51424099cc6bSBarry Smith -  function - routine to convert to subtype
51434099cc6bSBarry Smith 
51444099cc6bSBarry Smith    Notes:
51454099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
51464099cc6bSBarry Smith 
51474099cc6bSBarry Smith 
51484099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
51494099cc6bSBarry Smith $     -mat_seqaij_type my_mat
51504099cc6bSBarry Smith 
51514099cc6bSBarry Smith    Level: advanced
51524099cc6bSBarry Smith 
51534099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
51544099cc6bSBarry Smith 
51554099cc6bSBarry Smith 
51564099cc6bSBarry Smith   Level: advanced
51574099cc6bSBarry Smith @*/
5158388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
51594099cc6bSBarry Smith {
51604099cc6bSBarry Smith   PetscErrorCode ierr;
51614099cc6bSBarry Smith 
51624099cc6bSBarry Smith   PetscFunctionBegin;
51639cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
51644099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
51654099cc6bSBarry Smith   PetscFunctionReturn(0);
51664099cc6bSBarry Smith }
51674099cc6bSBarry Smith 
51684099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
51694099cc6bSBarry Smith 
51704099cc6bSBarry Smith /*@C
51714099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
51724099cc6bSBarry Smith 
51734099cc6bSBarry Smith   Not Collective
51744099cc6bSBarry Smith 
51754099cc6bSBarry Smith   Level: advanced
51764099cc6bSBarry Smith 
5177*f719121fSJed Brown   Developers Note: CUSPARSE does not yet support the MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
51784099cc6bSBarry Smith 
51794099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
51804099cc6bSBarry Smith @*/
51814099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
51824099cc6bSBarry Smith {
51834099cc6bSBarry Smith   PetscErrorCode ierr;
51844099cc6bSBarry Smith 
51854099cc6bSBarry Smith   PetscFunctionBegin;
51864099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
51874099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
51884099cc6bSBarry Smith 
51894099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
51904099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
51914dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
51929779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
51936b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5194485f9817SRichard Tran Mills #endif
51954099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
51964099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
51974099cc6bSBarry Smith #endif
51984099cc6bSBarry Smith   PetscFunctionReturn(0);
51994099cc6bSBarry Smith }
520053dd7562SDmitry Karpeev 
520153dd7562SDmitry Karpeev /*
520281824310SBarry Smith     Special version for direct calls from Fortran
520381824310SBarry Smith */
5204af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
520581824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
520681824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
520781824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
520881824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
520981824310SBarry Smith #endif
521081824310SBarry Smith 
521181824310SBarry Smith /* Change these macros so can be used in void function */
521281824310SBarry Smith #undef CHKERRQ
5213ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
521481824310SBarry Smith #undef SETERRQ2
5215e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
52164994cf47SJed Brown #undef SETERRQ3
52174994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
521881824310SBarry Smith 
521919caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
522081824310SBarry Smith {
522181824310SBarry Smith   Mat            A  = *AA;
522281824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
522381824310SBarry Smith   InsertMode     is = *isis;
522481824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
522581824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
522681824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
522781824310SBarry Smith   PetscErrorCode ierr;
522881824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
522954f21887SBarry Smith   MatScalar      *ap,value,*aa;
5230ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5231ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
523281824310SBarry Smith 
523381824310SBarry Smith   PetscFunctionBegin;
52344994cf47SJed Brown   MatCheckPreallocated(A,1);
523581824310SBarry Smith   imax  = a->imax;
523681824310SBarry Smith   ai    = a->i;
523781824310SBarry Smith   ailen = a->ilen;
523881824310SBarry Smith   aj    = a->j;
523981824310SBarry Smith   aa    = a->a;
524081824310SBarry Smith 
524181824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
524281824310SBarry Smith     row = im[k];
524381824310SBarry Smith     if (row < 0) continue;
5244cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
524581824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
524681824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
524781824310SBarry Smith     low  = 0;
524881824310SBarry Smith     high = nrow;
524981824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
525081824310SBarry Smith       if (in[l] < 0) continue;
5251cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
525281824310SBarry Smith       col = in[l];
52532205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
52542205254eSKarl Rupp       else value = v[k + l*m];
52552205254eSKarl Rupp 
525681824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
525781824310SBarry Smith 
52582205254eSKarl Rupp       if (col <= lastcol) low = 0;
52592205254eSKarl Rupp       else high = nrow;
526081824310SBarry Smith       lastcol = col;
526181824310SBarry Smith       while (high-low > 5) {
526281824310SBarry Smith         t = (low+high)/2;
526381824310SBarry Smith         if (rp[t] > col) high = t;
526481824310SBarry Smith         else             low  = t;
526581824310SBarry Smith       }
526681824310SBarry Smith       for (i=low; i<high; i++) {
526781824310SBarry Smith         if (rp[i] > col) break;
526881824310SBarry Smith         if (rp[i] == col) {
526981824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
527081824310SBarry Smith           else                  ap[i] = value;
527181824310SBarry Smith           goto noinsert;
527281824310SBarry Smith         }
527381824310SBarry Smith       }
527481824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
527581824310SBarry Smith       if (nonew == 1) goto noinsert;
5276ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5277fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
527881824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
527981824310SBarry Smith       /* shift up all the later entries in this row */
528081824310SBarry Smith       for (ii=N; ii>=i; ii--) {
528181824310SBarry Smith         rp[ii+1] = rp[ii];
528281824310SBarry Smith         ap[ii+1] = ap[ii];
528381824310SBarry Smith       }
528481824310SBarry Smith       rp[i] = col;
528581824310SBarry Smith       ap[i] = value;
5286e56f5c9eSBarry Smith       A->nonzerostate++;
528781824310SBarry Smith noinsert:;
528881824310SBarry Smith       low = i + 1;
528981824310SBarry Smith     }
529081824310SBarry Smith     ailen[row] = nrow;
529181824310SBarry Smith   }
529281824310SBarry Smith   PetscFunctionReturnVoid();
529381824310SBarry Smith }
5294