xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 6768869d7801acedb92b9f43bd82866d66477bf2)
1b377110cSBarry Smith 
2d5d45c9bSBarry Smith /*
33369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
4d5d45c9bSBarry Smith   matrix storage format.
5d5d45c9bSBarry Smith */
63369ce9aSBarry Smith 
77c4f633dSBarry Smith 
8c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
9c6db04a5SJed Brown #include <petscblaslapack.h>
10c6db04a5SJed Brown #include <petscbt.h>
11af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
120716a85fSBarry Smith 
134099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
144099cc6bSBarry Smith {
154099cc6bSBarry Smith   PetscErrorCode       ierr;
164099cc6bSBarry Smith   PetscBool            flg;
174099cc6bSBarry Smith   char                 type[256];
184099cc6bSBarry Smith 
194099cc6bSBarry Smith   PetscFunctionBegin;
204099cc6bSBarry Smith   ierr = PetscObjectOptionsBegin((PetscObject)A);
214099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
224099cc6bSBarry Smith   if (flg) {
234099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
244099cc6bSBarry Smith   }
254099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
264099cc6bSBarry Smith   PetscFunctionReturn(0);
274099cc6bSBarry Smith }
284099cc6bSBarry Smith 
290716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_SeqAIJ(Mat A,NormType type,PetscReal *norms)
300716a85fSBarry Smith {
310716a85fSBarry Smith   PetscErrorCode ierr;
320716a85fSBarry Smith   PetscInt       i,m,n;
330716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
340716a85fSBarry Smith 
350716a85fSBarry Smith   PetscFunctionBegin;
360716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
37580bdb30SBarry Smith   ierr = PetscArrayzero(norms,n);CHKERRQ(ierr);
380716a85fSBarry Smith   if (type == NORM_2) {
390716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
400716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
410716a85fSBarry Smith     }
420716a85fSBarry Smith   } else if (type == NORM_1) {
430716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
440716a85fSBarry Smith       norms[aij->j[i]] += PetscAbsScalar(aij->a[i]);
450716a85fSBarry Smith     }
460716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
470716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
480716a85fSBarry Smith       norms[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),norms[aij->j[i]]);
490716a85fSBarry Smith     }
500716a85fSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown NormType");
510716a85fSBarry Smith 
520716a85fSBarry Smith   if (type == NORM_2) {
538f1a2a5eSBarry Smith     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
540716a85fSBarry Smith   }
550716a85fSBarry Smith   PetscFunctionReturn(0);
560716a85fSBarry Smith }
570716a85fSBarry Smith 
583a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
593a062f41SBarry Smith {
603a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
613a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
623a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
633a062f41SBarry Smith   PetscInt        *rows;
643a062f41SBarry Smith   PetscErrorCode  ierr;
653a062f41SBarry Smith 
663a062f41SBarry Smith   PetscFunctionBegin;
673a062f41SBarry Smith   for (i=0; i<m; i++) {
683a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
693a062f41SBarry Smith       cnt++;
703a062f41SBarry Smith     }
713a062f41SBarry Smith   }
723a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
733a062f41SBarry Smith   cnt  = 0;
743a062f41SBarry Smith   for (i=0; i<m; i++) {
753a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
763a062f41SBarry Smith       rows[cnt] = i;
773a062f41SBarry Smith       cnt++;
783a062f41SBarry Smith     }
793a062f41SBarry Smith   }
803a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
813a062f41SBarry Smith   PetscFunctionReturn(0);
823a062f41SBarry Smith }
833a062f41SBarry Smith 
84f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
856ce1633cSBarry Smith {
866ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
876ce1633cSBarry Smith   const MatScalar *aa = a->a;
886ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
89b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
906ce1633cSBarry Smith   PetscInt        *rows;
916ce1633cSBarry Smith   PetscErrorCode  ierr;
926ce1633cSBarry Smith 
936ce1633cSBarry Smith   PetscFunctionBegin;
946ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
956ce1633cSBarry Smith   diag = a->diag;
966ce1633cSBarry Smith   for (i=0; i<m; i++) {
97b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
986ce1633cSBarry Smith       cnt++;
996ce1633cSBarry Smith     }
1006ce1633cSBarry Smith   }
101785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1026ce1633cSBarry Smith   cnt  = 0;
1036ce1633cSBarry Smith   for (i=0; i<m; i++) {
104b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1056ce1633cSBarry Smith       rows[cnt++] = i;
1066ce1633cSBarry Smith     }
1076ce1633cSBarry Smith   }
108f1f41ecbSJed Brown   *nrows = cnt;
109f1f41ecbSJed Brown   *zrows = rows;
110f1f41ecbSJed Brown   PetscFunctionReturn(0);
111f1f41ecbSJed Brown }
112f1f41ecbSJed Brown 
113f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
114f1f41ecbSJed Brown {
115f1f41ecbSJed Brown   PetscInt       nrows,*rows;
116f1f41ecbSJed Brown   PetscErrorCode ierr;
117f1f41ecbSJed Brown 
118f1f41ecbSJed Brown   PetscFunctionBegin;
1190298fd71SBarry Smith   *zrows = NULL;
120f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
121ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1226ce1633cSBarry Smith   PetscFunctionReturn(0);
1236ce1633cSBarry Smith }
1246ce1633cSBarry Smith 
125b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
126b3a44c85SBarry Smith {
127b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
128b3a44c85SBarry Smith   const MatScalar *aa;
129b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
130b3a44c85SBarry Smith   const PetscInt  *ii;
131b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
132b3a44c85SBarry Smith   PetscErrorCode  ierr;
133b3a44c85SBarry Smith 
134b3a44c85SBarry Smith   PetscFunctionBegin;
135b3a44c85SBarry Smith   *keptrows = 0;
136b3a44c85SBarry Smith   ii        = a->i;
137b3a44c85SBarry Smith   for (i=0; i<m; i++) {
138b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
139b3a44c85SBarry Smith     if (!n) {
140b3a44c85SBarry Smith       cnt++;
141b3a44c85SBarry Smith       goto ok1;
142b3a44c85SBarry Smith     }
143b3a44c85SBarry Smith     aa = a->a + ii[i];
144b3a44c85SBarry Smith     for (j=0; j<n; j++) {
145b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
146b3a44c85SBarry Smith     }
147b3a44c85SBarry Smith     cnt++;
148b3a44c85SBarry Smith ok1:;
149b3a44c85SBarry Smith   }
150b3a44c85SBarry Smith   if (!cnt) PetscFunctionReturn(0);
151854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
152b3a44c85SBarry Smith   cnt  = 0;
153b3a44c85SBarry Smith   for (i=0; i<m; i++) {
154b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
155b3a44c85SBarry Smith     if (!n) continue;
156b3a44c85SBarry Smith     aa = a->a + ii[i];
157b3a44c85SBarry Smith     for (j=0; j<n; j++) {
158b3a44c85SBarry Smith       if (aa[j] != 0.0) {
159b3a44c85SBarry Smith         rows[cnt++] = i;
160b3a44c85SBarry Smith         break;
161b3a44c85SBarry Smith       }
162b3a44c85SBarry Smith     }
163b3a44c85SBarry Smith   }
164b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
165b3a44c85SBarry Smith   PetscFunctionReturn(0);
166b3a44c85SBarry Smith }
167b3a44c85SBarry Smith 
1687087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
16979299369SBarry Smith {
17079299369SBarry Smith   PetscErrorCode    ierr;
17179299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17299e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17399e65526SBarry Smith   const PetscInt    *diag;
17454f21887SBarry Smith   MatScalar         *aa = aij->a;
17599e65526SBarry Smith   const PetscScalar *v;
176ace3abfcSBarry Smith   PetscBool         missing;
17779299369SBarry Smith 
17879299369SBarry Smith   PetscFunctionBegin;
17909f38230SBarry Smith   if (Y->assembled) {
1800298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
18109f38230SBarry Smith     if (!missing) {
18279299369SBarry Smith       diag = aij->diag;
18399e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
18479299369SBarry Smith       if (is == INSERT_VALUES) {
18579299369SBarry Smith         for (i=0; i<m; i++) {
18679299369SBarry Smith           aa[diag[i]] = v[i];
18779299369SBarry Smith         }
18879299369SBarry Smith       } else {
18979299369SBarry Smith         for (i=0; i<m; i++) {
19079299369SBarry Smith           aa[diag[i]] += v[i];
19179299369SBarry Smith         }
19279299369SBarry Smith       }
19399e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
19479299369SBarry Smith       PetscFunctionReturn(0);
19579299369SBarry Smith     }
196acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
19709f38230SBarry Smith   }
19809f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
19909f38230SBarry Smith   PetscFunctionReturn(0);
20009f38230SBarry Smith }
20179299369SBarry Smith 
2021a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
20317ab2063SBarry Smith {
204416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
205dfbe8321SBarry Smith   PetscErrorCode ierr;
20697f1f81fSBarry Smith   PetscInt       i,ishift;
20717ab2063SBarry Smith 
2083a40ed3dSBarry Smith   PetscFunctionBegin;
209d0f46423SBarry Smith   *m = A->rmap->n;
2103a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
211bfeeae90SHong Zhang   ishift = 0;
21253e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2132462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
214bfeeae90SHong Zhang   } else if (oshift == 1) {
2151a83f524SJed Brown     PetscInt *tia;
216d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2173b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
218854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2191a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2201a83f524SJed Brown     *ia = tia;
221ecc77c7aSBarry Smith     if (ja) {
2221a83f524SJed Brown       PetscInt *tja;
223854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2241a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2251a83f524SJed Brown       *ja = tja;
226ecc77c7aSBarry Smith     }
2276945ee14SBarry Smith   } else {
228ecc77c7aSBarry Smith     *ia = a->i;
229ecc77c7aSBarry Smith     if (ja) *ja = a->j;
230a2ce50c7SBarry Smith   }
2313a40ed3dSBarry Smith   PetscFunctionReturn(0);
232a2744918SBarry Smith }
233a2744918SBarry Smith 
2341a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2356945ee14SBarry Smith {
236dfbe8321SBarry Smith   PetscErrorCode ierr;
2376945ee14SBarry Smith 
2383a40ed3dSBarry Smith   PetscFunctionBegin;
2393a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
240bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
241606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
242ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
243bcd2baecSBarry Smith   }
2443a40ed3dSBarry Smith   PetscFunctionReturn(0);
24517ab2063SBarry Smith }
24617ab2063SBarry Smith 
2471a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2483b2fbd54SBarry Smith {
2493b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
250dfbe8321SBarry Smith   PetscErrorCode ierr;
251d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
25297f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2533b2fbd54SBarry Smith 
2543a40ed3dSBarry Smith   PetscFunctionBegin;
255899cda47SBarry Smith   *nn = n;
2563a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2573b2fbd54SBarry Smith   if (symmetric) {
2582462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2593b2fbd54SBarry Smith   } else {
260b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
261854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
262b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2633b2fbd54SBarry Smith     jj   = a->j;
2643b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
265bfeeae90SHong Zhang       collengths[jj[i]]++;
2663b2fbd54SBarry Smith     }
2673b2fbd54SBarry Smith     cia[0] = oshift;
2683b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2693b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2703b2fbd54SBarry Smith     }
271580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2723b2fbd54SBarry Smith     jj   = a->j;
273a93ec695SBarry Smith     for (row=0; row<m; row++) {
274a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
275a93ec695SBarry Smith       for (i=0; i<mr; i++) {
276bfeeae90SHong Zhang         col = *jj++;
2772205254eSKarl Rupp 
2783b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2793b2fbd54SBarry Smith       }
2803b2fbd54SBarry Smith     }
281606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2823b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2833b2fbd54SBarry Smith   }
2843a40ed3dSBarry Smith   PetscFunctionReturn(0);
2853b2fbd54SBarry Smith }
2863b2fbd54SBarry Smith 
2871a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2883b2fbd54SBarry Smith {
289dfbe8321SBarry Smith   PetscErrorCode ierr;
290606d414cSSatish Balay 
2913a40ed3dSBarry Smith   PetscFunctionBegin;
2923a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2933b2fbd54SBarry Smith 
294606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
295606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
2963a40ed3dSBarry Smith   PetscFunctionReturn(0);
2973b2fbd54SBarry Smith }
2983b2fbd54SBarry Smith 
2997cee066cSHong Zhang /*
3007cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3017cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
302040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3037cee066cSHong Zhang */
3047cee066cSHong 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)
3057cee066cSHong Zhang {
3067cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3077cee066cSHong Zhang   PetscErrorCode ierr;
3087cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
309071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3107cee066cSHong Zhang   PetscInt       *cspidx;
311071fcb05SBarry Smith   const PetscInt *jj;
3127cee066cSHong Zhang 
3137cee066cSHong Zhang   PetscFunctionBegin;
3147cee066cSHong Zhang   *nn = n;
3157cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
316625f6d37SHong Zhang 
317b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
318854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
319b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
320b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3217cee066cSHong Zhang   jj   = a->j;
3227cee066cSHong Zhang   for (i=0; i<nz; i++) {
3237cee066cSHong Zhang     collengths[jj[i]]++;
3247cee066cSHong Zhang   }
3257cee066cSHong Zhang   cia[0] = oshift;
3267cee066cSHong Zhang   for (i=0; i<n; i++) {
3277cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3287cee066cSHong Zhang   }
329580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3307cee066cSHong Zhang   jj   = a->j;
3317cee066cSHong Zhang   for (row=0; row<m; row++) {
3327cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3337cee066cSHong Zhang     for (i=0; i<mr; i++) {
3347cee066cSHong Zhang       col         = *jj++;
335071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
336071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
337071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3387cee066cSHong Zhang     }
3397cee066cSHong Zhang   }
3407cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
341071fcb05SBarry Smith   *ia    = cia;
342071fcb05SBarry Smith   *ja    = cja;
3437cee066cSHong Zhang   *spidx = cspidx;
3447cee066cSHong Zhang   PetscFunctionReturn(0);
3457cee066cSHong Zhang }
3467cee066cSHong Zhang 
3477cee066cSHong 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)
3487cee066cSHong Zhang {
3497cee066cSHong Zhang   PetscErrorCode ierr;
3507cee066cSHong Zhang 
3517cee066cSHong Zhang   PetscFunctionBegin;
3525243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3537cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3547cee066cSHong Zhang   PetscFunctionReturn(0);
3557cee066cSHong Zhang }
3567cee066cSHong Zhang 
35787d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
35887d4246cSBarry Smith {
35987d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
36087d4246cSBarry Smith   PetscInt       *ai = a->i;
36187d4246cSBarry Smith   PetscErrorCode ierr;
36287d4246cSBarry Smith 
36387d4246cSBarry Smith   PetscFunctionBegin;
364580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
365e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
366c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
367e2cf4d64SStefano Zampini #endif
36887d4246cSBarry Smith   PetscFunctionReturn(0);
36987d4246cSBarry Smith }
37087d4246cSBarry Smith 
371bd04181cSBarry Smith /*
372bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
373bd04181cSBarry Smith 
374bd04181cSBarry Smith       -   a single row of values is set with each call
375bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
376bd04181cSBarry Smith       -   the values are always added to the matrix, not set
377bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
378bd04181cSBarry Smith 
3791f763a69SBarry Smith      This does NOT assume the global column indices are sorted
380bd04181cSBarry Smith 
3811f763a69SBarry Smith */
382bd04181cSBarry Smith 
383af0996ceSBarry Smith #include <petsc/private/isimpl.h>
384189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
385189e4007SBarry Smith {
386189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3871f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
3881f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
3891f763a69SBarry Smith   PetscInt       lastcol = -1;
390189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
391189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
392189e4007SBarry Smith 
393f38dd0b8SBarry Smith   row  = ridx[im[0]];
3941f763a69SBarry Smith   rp   = aj + ai[row];
3951f763a69SBarry Smith   ap   = aa + ai[row];
3961f763a69SBarry Smith   nrow = ailen[row];
397189e4007SBarry Smith   low  = 0;
398189e4007SBarry Smith   high = nrow;
399189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
400189e4007SBarry Smith     col = cidx[in[l]];
401f38dd0b8SBarry Smith     value = v[l];
402189e4007SBarry Smith 
403189e4007SBarry Smith     if (col <= lastcol) low = 0;
404189e4007SBarry Smith     else high = nrow;
405189e4007SBarry Smith     lastcol = col;
406189e4007SBarry Smith     while (high-low > 5) {
407189e4007SBarry Smith       t = (low+high)/2;
408189e4007SBarry Smith       if (rp[t] > col) high = t;
409189e4007SBarry Smith       else low = t;
410189e4007SBarry Smith     }
411189e4007SBarry Smith     for (i=low; i<high; i++) {
412189e4007SBarry Smith       if (rp[i] == col) {
4131f763a69SBarry Smith         ap[i] += value;
414189e4007SBarry Smith         low = i + 1;
4151f763a69SBarry Smith         break;
416189e4007SBarry Smith       }
417189e4007SBarry Smith     }
418189e4007SBarry Smith   }
419e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
420c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
421e2cf4d64SStefano Zampini #endif
422f38dd0b8SBarry Smith   return 0;
423189e4007SBarry Smith }
424189e4007SBarry Smith 
42597f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
42617ab2063SBarry Smith {
427416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
428e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
42997f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4306849ba73SBarry Smith   PetscErrorCode ierr;
431e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
432d8cdefa3SHong Zhang   MatScalar      *ap=NULL,value=0.0,*aa = a->a;
433ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
434ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
435e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
436e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
437e2cf4d64SStefano Zampini #endif
43817ab2063SBarry Smith 
4393a40ed3dSBarry Smith   PetscFunctionBegin;
44017ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
441416022c9SBarry Smith     row = im[k];
4425ef9f2a5SBarry Smith     if (row < 0) continue;
4432515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
444e32f2f54SBarry 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);
4453b2fbd54SBarry Smith #endif
446720833daSHong Zhang     rp   = aj + ai[row];
447876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
44817ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
449416022c9SBarry Smith     low  = 0;
450c71e6ed7SBarry Smith     high = nrow;
45117ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4525ef9f2a5SBarry Smith       if (in[l] < 0) continue;
4532515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
454e32f2f54SBarry 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);
4553b2fbd54SBarry Smith #endif
456bfeeae90SHong Zhang       col = in[l];
457071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
458071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
45936db0b34SBarry Smith 
4602205254eSKarl Rupp       if (col <= lastcol) low = 0;
4612205254eSKarl Rupp       else high = nrow;
462e2ee6c50SBarry Smith       lastcol = col;
463416022c9SBarry Smith       while (high-low > 5) {
464416022c9SBarry Smith         t = (low+high)/2;
465416022c9SBarry Smith         if (rp[t] > col) high = t;
466416022c9SBarry Smith         else low = t;
46717ab2063SBarry Smith       }
468416022c9SBarry Smith       for (i=low; i<high; i++) {
46917ab2063SBarry Smith         if (rp[i] > col) break;
47017ab2063SBarry Smith         if (rp[i] == col) {
471876c6284SHong Zhang           if (!A->structure_only) {
4720c0d7e18SFande Kong             if (is == ADD_VALUES) {
4730c0d7e18SFande Kong               ap[i] += value;
4740c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4750c0d7e18SFande Kong             }
47617ab2063SBarry Smith             else ap[i] = value;
477e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
478e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
479e2cf4d64SStefano Zampini #endif
480720833daSHong Zhang           }
481e44c0bd4SBarry Smith           low = i + 1;
48217ab2063SBarry Smith           goto noinsert;
48317ab2063SBarry Smith         }
48417ab2063SBarry Smith       }
485dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
486c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
487e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
488720833daSHong Zhang       if (A->structure_only) {
489876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
490720833daSHong Zhang       } else {
491fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
492720833daSHong Zhang       }
493c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
494416022c9SBarry Smith       /* shift up all the later entries in this row */
495580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
49617ab2063SBarry Smith       rp[i] = col;
497580bdb30SBarry Smith       if (!A->structure_only){
498580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
499580bdb30SBarry Smith         ap[i] = value;
500580bdb30SBarry Smith       }
501416022c9SBarry Smith       low = i + 1;
502e56f5c9eSBarry Smith       A->nonzerostate++;
503e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
504e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
505e2cf4d64SStefano Zampini #endif
506e44c0bd4SBarry Smith noinsert:;
50717ab2063SBarry Smith     }
50817ab2063SBarry Smith     ailen[row] = nrow;
50917ab2063SBarry Smith   }
510e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
511c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
512e2cf4d64SStefano Zampini #endif
5133a40ed3dSBarry Smith   PetscFunctionReturn(0);
51417ab2063SBarry Smith }
51517ab2063SBarry Smith 
516071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
517071fcb05SBarry Smith {
518071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
519071fcb05SBarry Smith   PetscInt       *rp,k,row;
520071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
521071fcb05SBarry Smith   PetscErrorCode ierr;
522071fcb05SBarry Smith   PetscInt       *aj = a->j;
523071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
524071fcb05SBarry Smith 
525071fcb05SBarry Smith   PetscFunctionBegin;
526071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
527071fcb05SBarry Smith     row  = im[k];
528071fcb05SBarry Smith     rp   = aj + ai[row];
529071fcb05SBarry Smith     ap   = aa + ai[row];
530071fcb05SBarry Smith     if (!A->was_assembled) {
531071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
532071fcb05SBarry Smith     }
533071fcb05SBarry Smith     if (!A->structure_only) {
534071fcb05SBarry Smith       if (v) {
535071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
536071fcb05SBarry Smith         v   += n;
537071fcb05SBarry Smith       } else {
538071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
539071fcb05SBarry Smith       }
540071fcb05SBarry Smith     }
541071fcb05SBarry Smith     ailen[row] = n;
542071fcb05SBarry Smith     a->nz      += n;
543071fcb05SBarry Smith   }
544e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
545c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
546e2cf4d64SStefano Zampini #endif
547071fcb05SBarry Smith   PetscFunctionReturn(0);
548071fcb05SBarry Smith }
549071fcb05SBarry Smith 
55081824310SBarry Smith 
551a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
5527eb43aa7SLois Curfman McInnes {
5537eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
55497f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
55597f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
55654f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
5577eb43aa7SLois Curfman McInnes 
5583a40ed3dSBarry Smith   PetscFunctionBegin;
5597eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
5607eb43aa7SLois Curfman McInnes     row = im[k];
561e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
562e32f2f54SBarry 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);
563bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
5647eb43aa7SLois Curfman McInnes     nrow = ailen[row];
5657eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
566e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
567e32f2f54SBarry 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);
568bfeeae90SHong Zhang       col  = in[l];
5697eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
5707eb43aa7SLois Curfman McInnes       while (high-low > 5) {
5717eb43aa7SLois Curfman McInnes         t = (low+high)/2;
5727eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
5737eb43aa7SLois Curfman McInnes         else low = t;
5747eb43aa7SLois Curfman McInnes       }
5757eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
5767eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
5777eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
578b49de8d1SLois Curfman McInnes           *v++ = ap[i];
5797eb43aa7SLois Curfman McInnes           goto finished;
5807eb43aa7SLois Curfman McInnes         }
5817eb43aa7SLois Curfman McInnes       }
58297e567efSBarry Smith       *v++ = 0.0;
5837eb43aa7SLois Curfman McInnes finished:;
5847eb43aa7SLois Curfman McInnes     }
5857eb43aa7SLois Curfman McInnes   }
5863a40ed3dSBarry Smith   PetscFunctionReturn(0);
5877eb43aa7SLois Curfman McInnes }
5887eb43aa7SLois Curfman McInnes 
58917ab2063SBarry Smith 
590dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Binary(Mat A,PetscViewer viewer)
59117ab2063SBarry Smith {
592416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
5936849ba73SBarry Smith   PetscErrorCode ierr;
5946f69ff64SBarry Smith   PetscInt       i,*col_lens;
5956f69ff64SBarry Smith   int            fd;
596b37d52dbSMark F. Adams   FILE           *file;
59717ab2063SBarry Smith 
5983a40ed3dSBarry Smith   PetscFunctionBegin;
599b0a32e0cSBarry Smith   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
600854ce69bSBarry Smith   ierr = PetscMalloc1(4+A->rmap->n,&col_lens);CHKERRQ(ierr);
6012205254eSKarl Rupp 
6020700a824SBarry Smith   col_lens[0] = MAT_FILE_CLASSID;
603d0f46423SBarry Smith   col_lens[1] = A->rmap->n;
604d0f46423SBarry Smith   col_lens[2] = A->cmap->n;
605416022c9SBarry Smith   col_lens[3] = a->nz;
606416022c9SBarry Smith 
607416022c9SBarry Smith   /* store lengths of each row and write (including header) to file */
608d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
609416022c9SBarry Smith     col_lens[4+i] = a->i[i+1] - a->i[i];
61017ab2063SBarry Smith   }
611d0f46423SBarry Smith   ierr = PetscBinaryWrite(fd,col_lens,4+A->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
612606d414cSSatish Balay   ierr = PetscFree(col_lens);CHKERRQ(ierr);
613416022c9SBarry Smith 
614416022c9SBarry Smith   /* store column indices (zero start index) */
6156f69ff64SBarry Smith   ierr = PetscBinaryWrite(fd,a->j,a->nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
616416022c9SBarry Smith 
617416022c9SBarry Smith   /* store nonzero values */
6186f69ff64SBarry Smith   ierr = PetscBinaryWrite(fd,a->a,a->nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
619b37d52dbSMark F. Adams 
620b37d52dbSMark F. Adams   ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr);
621b37d52dbSMark F. Adams   if (file) {
62233d57670SJed Brown     fprintf(file,"-matload_block_size %d\n",(int)PetscAbs(A->rmap->bs));
623b37d52dbSMark F. Adams   }
6243a40ed3dSBarry Smith   PetscFunctionReturn(0);
62517ab2063SBarry Smith }
626416022c9SBarry Smith 
6277dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
6287dc0baabSHong Zhang {
6297dc0baabSHong Zhang   PetscErrorCode ierr;
6307dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
6317dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
6327dc0baabSHong Zhang 
6337dc0baabSHong Zhang   PetscFunctionBegin;
6347dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
6357dc0baabSHong Zhang   for (i=0; i<m; i++) {
6367dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
6377dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
6387dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
6397dc0baabSHong Zhang     }
6407dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
6417dc0baabSHong Zhang   }
6427dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
6437dc0baabSHong Zhang   PetscFunctionReturn(0);
6447dc0baabSHong Zhang }
6457dc0baabSHong Zhang 
64609573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
647cd155464SBarry Smith 
648dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
649416022c9SBarry Smith {
650416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
651dfbe8321SBarry Smith   PetscErrorCode    ierr;
65260e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
653e060cb09SBarry Smith   const char        *name;
654f3ef73ceSBarry Smith   PetscViewerFormat format;
65517ab2063SBarry Smith 
6563a40ed3dSBarry Smith   PetscFunctionBegin;
6577dc0baabSHong Zhang   if (A->structure_only) {
6587dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
6597dc0baabSHong Zhang     PetscFunctionReturn(0);
6607dc0baabSHong Zhang   }
66143e49210SHong Zhang 
662b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
66371c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
66497f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
66560e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
666c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
667d00d2cf4SBarry Smith       nofinalvalue = 1;
668d00d2cf4SBarry Smith     }
669d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
670d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
67177431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
672fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
673fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
674fbfe6fa7SJed Brown #else
67577431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
676fbfe6fa7SJed Brown #endif
677b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
67817ab2063SBarry Smith 
67917ab2063SBarry Smith     for (i=0; i<m; i++) {
68060e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
681aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
682a9bf72d8SJed 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);
68317ab2063SBarry Smith #else
68460e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
68517ab2063SBarry Smith #endif
68617ab2063SBarry Smith       }
68717ab2063SBarry Smith     }
688d00d2cf4SBarry Smith     if (nofinalvalue) {
689c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
690c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
691c337ccceSJed Brown #else
692d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
693c337ccceSJed Brown #endif
694d00d2cf4SBarry Smith     }
695317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
696fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
697d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
6982950ac48SStefano Zampini   } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
699cd155464SBarry Smith     PetscFunctionReturn(0);
700fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
701d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
70244cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
70377431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
70460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
705aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
70636db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
70760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
70836db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
70960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
71036db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
71160e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
7126831982aSBarry Smith         }
71344cd7ae7SLois Curfman McInnes #else
71460e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
71544cd7ae7SLois Curfman McInnes #endif
71644cd7ae7SLois Curfman McInnes       }
717b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
71844cd7ae7SLois Curfman McInnes     }
719d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
720fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
72197f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
722d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
723854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
724496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
725496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
72660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
727496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
728aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
72936db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
730496be53dSLois Curfman McInnes #else
731496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
732496be53dSLois Curfman McInnes #endif
733496be53dSLois Curfman McInnes         }
734496be53dSLois Curfman McInnes       }
735496be53dSLois Curfman McInnes     }
7362e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
73777431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
7382e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
7392205254eSKarl Rupp       if (i+4<m) {
7402205254eSKarl 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);
7412205254eSKarl Rupp       } else if (i+3<m) {
7422205254eSKarl 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);
7432205254eSKarl Rupp       } else if (i+2<m) {
7442205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
7452205254eSKarl Rupp       } else if (i+1<m) {
7462205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
7472205254eSKarl Rupp       } else if (i<m) {
7482205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
7492205254eSKarl Rupp       } else {
7502205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
7512205254eSKarl Rupp       }
752496be53dSLois Curfman McInnes     }
753b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
754606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
755496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
75660e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
75777431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
758496be53dSLois Curfman McInnes       }
759b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
760496be53dSLois Curfman McInnes     }
761b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
762496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
76360e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
764496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
765aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
76636db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
76760e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
7686831982aSBarry Smith           }
769496be53dSLois Curfman McInnes #else
77060e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
771496be53dSLois Curfman McInnes #endif
772496be53dSLois Curfman McInnes         }
773496be53dSLois Curfman McInnes       }
774b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
775496be53dSLois Curfman McInnes     }
776d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
777fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
77897f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
77987828ca2SBarry Smith     PetscScalar value;
78068f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
78168f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
78268f1ed48SBarry Smith 
78368f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
78468f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
78568f1ed48SBarry Smith         realonly = PETSC_FALSE;
78668f1ed48SBarry Smith         break;
78768f1ed48SBarry Smith       }
78868f1ed48SBarry Smith     }
78968f1ed48SBarry Smith #endif
79002594712SBarry Smith 
791d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
79202594712SBarry Smith     for (i=0; i<m; i++) {
79302594712SBarry Smith       jcnt = 0;
794d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
795e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
79602594712SBarry Smith           value = a->a[cnt++];
797e24b481bSBarry Smith           jcnt++;
79802594712SBarry Smith         } else {
79902594712SBarry Smith           value = 0.0;
80002594712SBarry Smith         }
801aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
80268f1ed48SBarry Smith         if (realonly) {
80360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
80468f1ed48SBarry Smith         } else {
80560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
80668f1ed48SBarry Smith         }
80702594712SBarry Smith #else
80860e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
80902594712SBarry Smith #endif
81002594712SBarry Smith       }
811b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
81202594712SBarry Smith     }
813d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
8143c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
815150b93efSMatthew G. Knepley     PetscInt fshift=1;
816d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
8173c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
81819303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
8193c215bfdSMatthew Knepley #else
82019303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
8213c215bfdSMatthew Knepley #endif
822d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
8233c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
82460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
8253c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
826a9a0e077SKarl 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);
8273c215bfdSMatthew Knepley #else
828150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
8293c215bfdSMatthew Knepley #endif
8303c215bfdSMatthew Knepley       }
8313c215bfdSMatthew Knepley     }
832d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
8333a40ed3dSBarry Smith   } else {
834d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
835d5f3da31SBarry Smith     if (A->factortype) {
83616cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
83716cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
83816cd7e1dSShri Abhyankar         /* L part */
83960e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
84016cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
84116cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
84260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
84316cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8446712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
84516cd7e1dSShri Abhyankar           } else {
84660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
84716cd7e1dSShri Abhyankar           }
84816cd7e1dSShri Abhyankar #else
84960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
85016cd7e1dSShri Abhyankar #endif
85116cd7e1dSShri Abhyankar         }
85216cd7e1dSShri Abhyankar         /* diagonal */
85316cd7e1dSShri Abhyankar         j = a->diag[i];
85416cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
85516cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
85660e0710aSBarry 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);
85716cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
8586712e2f1SBarry 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);
85916cd7e1dSShri Abhyankar         } else {
86060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
86116cd7e1dSShri Abhyankar         }
86216cd7e1dSShri Abhyankar #else
86360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
86416cd7e1dSShri Abhyankar #endif
86516cd7e1dSShri Abhyankar 
86616cd7e1dSShri Abhyankar         /* U part */
86760e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
86816cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
86916cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
87060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
87116cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
87222ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
87316cd7e1dSShri Abhyankar           } else {
87460e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
87516cd7e1dSShri Abhyankar           }
87616cd7e1dSShri Abhyankar #else
87760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
87816cd7e1dSShri Abhyankar #endif
87916cd7e1dSShri Abhyankar         }
88016cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
88116cd7e1dSShri Abhyankar       }
88216cd7e1dSShri Abhyankar     } else {
88317ab2063SBarry Smith       for (i=0; i<m; i++) {
88477431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
88560e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
886aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
88736db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
88860e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
88936db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
89060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8913a40ed3dSBarry Smith           } else {
89260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
89317ab2063SBarry Smith           }
89417ab2063SBarry Smith #else
89560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
89617ab2063SBarry Smith #endif
89717ab2063SBarry Smith         }
898b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
89917ab2063SBarry Smith       }
90016cd7e1dSShri Abhyankar     }
901d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
90217ab2063SBarry Smith   }
903b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
9043a40ed3dSBarry Smith   PetscFunctionReturn(0);
905416022c9SBarry Smith }
906416022c9SBarry Smith 
9079804daf3SBarry Smith #include <petscdraw.h>
908dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
909416022c9SBarry Smith {
910480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
911416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
912dfbe8321SBarry Smith   PetscErrorCode    ierr;
913383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
914383922c3SLisandro Dalcin   int               color;
915b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
916b0a32e0cSBarry Smith   PetscViewer       viewer;
917f3ef73ceSBarry Smith   PetscViewerFormat format;
918cddf8d76SBarry Smith 
9193a40ed3dSBarry Smith   PetscFunctionBegin;
920480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
921b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
922b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
923383922c3SLisandro Dalcin 
924416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
9250513a670SBarry Smith 
926fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
927383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
9280513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
929b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
930416022c9SBarry Smith     for (i=0; i<m; i++) {
931cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
932bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
933bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
93436db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
935b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
936cddf8d76SBarry Smith       }
937cddf8d76SBarry Smith     }
938b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
939cddf8d76SBarry Smith     for (i=0; i<m; i++) {
940cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
941bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
942bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
943cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
944b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
945cddf8d76SBarry Smith       }
946cddf8d76SBarry Smith     }
947b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
948cddf8d76SBarry Smith     for (i=0; i<m; i++) {
949cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
950bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
951bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
95236db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
953b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
954416022c9SBarry Smith       }
955416022c9SBarry Smith     }
956383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
9570513a670SBarry Smith   } else {
9580513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
9590513a670SBarry Smith     /* first determine max of all nonzero values */
960b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
961383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
962b0a32e0cSBarry Smith     PetscDraw popup;
9630513a670SBarry Smith 
9640513a670SBarry Smith     for (i=0; i<nz; i++) {
9650513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
9660513a670SBarry Smith     }
967383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
968b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
96945f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
970383922c3SLisandro Dalcin 
971383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
9720513a670SBarry Smith     for (i=0; i<m; i++) {
973383922c3SLisandro Dalcin       y_l = m - i - 1.0;
974383922c3SLisandro Dalcin       y_r = y_l + 1.0;
975bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
976383922c3SLisandro Dalcin         x_l = a->j[j];
977383922c3SLisandro Dalcin         x_r = x_l + 1.0;
978b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
979b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
9800513a670SBarry Smith         count++;
9810513a670SBarry Smith       }
9820513a670SBarry Smith     }
983383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
9840513a670SBarry Smith   }
985480ef9eaSBarry Smith   PetscFunctionReturn(0);
986480ef9eaSBarry Smith }
987cddf8d76SBarry Smith 
9889804daf3SBarry Smith #include <petscdraw.h>
989dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
990480ef9eaSBarry Smith {
991dfbe8321SBarry Smith   PetscErrorCode ierr;
992b0a32e0cSBarry Smith   PetscDraw      draw;
99336db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
994ace3abfcSBarry Smith   PetscBool      isnull;
995480ef9eaSBarry Smith 
996480ef9eaSBarry Smith   PetscFunctionBegin;
997b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
998b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
999480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1000480ef9eaSBarry Smith 
1001d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1002480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1003b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1004832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1005b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
10060298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1007832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
10083a40ed3dSBarry Smith   PetscFunctionReturn(0);
1009416022c9SBarry Smith }
1010416022c9SBarry Smith 
1011dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1012416022c9SBarry Smith {
1013dfbe8321SBarry Smith   PetscErrorCode ierr;
1014ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1015416022c9SBarry Smith 
10163a40ed3dSBarry Smith   PetscFunctionBegin;
1017251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1018251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1019251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1020c45a1595SBarry Smith   if (iascii) {
10213a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
10220f5bd95cSBarry Smith   } else if (isbinary) {
10233a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
10240f5bd95cSBarry Smith   } else if (isdraw) {
10253a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
102611aeaf0aSBarry Smith   }
10274108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
10283a40ed3dSBarry Smith   PetscFunctionReturn(0);
102917ab2063SBarry Smith }
103019bcc07fSBarry Smith 
1031dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
103217ab2063SBarry Smith {
1033416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
10346849ba73SBarry Smith   PetscErrorCode ierr;
1035580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1036d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
103754f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
10383447b6efSHong Zhang   PetscReal      ratio  = 0.6;
103917ab2063SBarry Smith 
10403a40ed3dSBarry Smith   PetscFunctionBegin;
10413a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1042071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1043071fcb05SBarry Smith   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) PetscFunctionReturn(0);
104417ab2063SBarry Smith 
104543ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
104617ab2063SBarry Smith   for (i=1; i<m; i++) {
1047416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
104817ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
104994a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
105017ab2063SBarry Smith     if (fshift) {
1051bfeeae90SHong Zhang       ip = aj + ai[i];
1052bfeeae90SHong Zhang       ap = aa + ai[i];
105317ab2063SBarry Smith       N  = ailen[i];
1054580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1055580bdb30SBarry Smith       if (!A->structure_only) {
1056580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
105717ab2063SBarry Smith       }
105817ab2063SBarry Smith     }
105917ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
106017ab2063SBarry Smith   }
106117ab2063SBarry Smith   if (m) {
106217ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
106317ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
106417ab2063SBarry Smith   }
10657b083b7cSBarry Smith 
106617ab2063SBarry Smith   /* reset ilen and imax for each row */
10677b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1068396832f4SHong Zhang   if (A->structure_only) {
1069071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1070071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1071396832f4SHong Zhang   } else { /* !A->structure_only */
107217ab2063SBarry Smith     for (i=0; i<m; i++) {
107317ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
10747b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
107517ab2063SBarry Smith     }
1076396832f4SHong Zhang   }
1077bfeeae90SHong Zhang   a->nz = ai[m];
107865e19b50SBarry 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);
107917ab2063SBarry Smith 
108009f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1081d0f46423SBarry 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);
1082ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1083ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
10842205254eSKarl Rupp 
10858e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1086dd5f02e7SSatish Balay   a->reallocs         = 0;
10876712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
108836db0b34SBarry Smith   a->rmax             = rmax;
10894e220ebcSLois Curfman McInnes 
1090396832f4SHong Zhang   if (!A->structure_only) {
109111e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1092396832f4SHong Zhang   }
10934108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
10943a40ed3dSBarry Smith   PetscFunctionReturn(0);
109517ab2063SBarry Smith }
109617ab2063SBarry Smith 
109799cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
109899cafbc1SBarry Smith {
109999cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
110099cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
110154f21887SBarry Smith   MatScalar      *aa = a->a;
1102acf2f550SJed Brown   PetscErrorCode ierr;
110399cafbc1SBarry Smith 
110499cafbc1SBarry Smith   PetscFunctionBegin;
110599cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1106acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1107e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1108c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1109e2cf4d64SStefano Zampini #endif
111099cafbc1SBarry Smith   PetscFunctionReturn(0);
111199cafbc1SBarry Smith }
111299cafbc1SBarry Smith 
111399cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
111499cafbc1SBarry Smith {
111599cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
111699cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
111754f21887SBarry Smith   MatScalar      *aa = a->a;
1118acf2f550SJed Brown   PetscErrorCode ierr;
111999cafbc1SBarry Smith 
112099cafbc1SBarry Smith   PetscFunctionBegin;
112199cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1122acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1123e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1124c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1125e2cf4d64SStefano Zampini #endif
112699cafbc1SBarry Smith   PetscFunctionReturn(0);
112799cafbc1SBarry Smith }
112899cafbc1SBarry Smith 
1129dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
113017ab2063SBarry Smith {
1131416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1132dfbe8321SBarry Smith   PetscErrorCode ierr;
11333a40ed3dSBarry Smith 
11343a40ed3dSBarry Smith   PetscFunctionBegin;
1135580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1136acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1137e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1138c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1139e2cf4d64SStefano Zampini #endif
11403a40ed3dSBarry Smith   PetscFunctionReturn(0);
114117ab2063SBarry Smith }
1142416022c9SBarry Smith 
1143dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
114417ab2063SBarry Smith {
1145416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1146dfbe8321SBarry Smith   PetscErrorCode ierr;
1147d5d45c9bSBarry Smith 
11483a40ed3dSBarry Smith   PetscFunctionBegin;
1149aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1150d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
115117ab2063SBarry Smith #endif
1152e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
11536bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
11546bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
115505b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1156d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1157071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1158071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1159846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
116071f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
116105b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
11626bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
116305b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
11646bf464f9SBarry Smith   ierr = ISColoringDestroy(&a->coloring);CHKERRQ(ierr);
1165cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
11660b7e3e3dSHong Zhang   ierr = PetscFree(a->matmult_abdense);CHKERRQ(ierr);
1167a30b2313SHong Zhang 
11684108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1169bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1170901853e0SKris Buschelman 
1171dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
1172bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1173bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1174bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1175bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1176bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1177bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
1178af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1179af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1180af8000cdSHong Zhang #endif
118163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
118263c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
11833dad0653Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatMatMatMult_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
118463c07aadSStefano Zampini #endif
1185b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1186c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1187c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1188bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1189bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1190846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1191bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1192bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
119375d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatPtAP_is_seqaij_C",NULL);CHKERRQ(ierr);
11943a40ed3dSBarry Smith   PetscFunctionReturn(0);
119517ab2063SBarry Smith }
119617ab2063SBarry Smith 
1197ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
119817ab2063SBarry Smith {
1199416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
12004846f1f5SKris Buschelman   PetscErrorCode ierr;
12013a40ed3dSBarry Smith 
12023a40ed3dSBarry Smith   PetscFunctionBegin;
1203a65d3064SKris Buschelman   switch (op) {
1204a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
12054e0d8c25SBarry Smith     a->roworiented = flg;
1206a65d3064SKris Buschelman     break;
1207a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1208a9817697SBarry Smith     a->keepnonzeropattern = flg;
1209a65d3064SKris Buschelman     break;
1210512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1211512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1212a65d3064SKris Buschelman     break;
1213a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
12144e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1215a65d3064SKris Buschelman     break;
1216a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
12174e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1218a65d3064SKris Buschelman     break;
121928b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
122028b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
122128b2fa4aSMatthew Knepley     break;
1222a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
12234e0d8c25SBarry Smith     a->ignorezeroentries = flg;
12240df259c2SBarry Smith     break;
12253d472b54SHong Zhang   case MAT_SPD:
1226b1646e73SJed Brown   case MAT_SYMMETRIC:
1227b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1228b1646e73SJed Brown   case MAT_HERMITIAN:
1229b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1230957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
12315021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
12325021d80fSJed Brown     break;
12334e0d8c25SBarry Smith   case MAT_NEW_DIAGONALS:
1234a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1235a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1236290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1237a65d3064SKris Buschelman     break;
1238b87ac2d8SJed Brown   case MAT_USE_INODES:
1239b87ac2d8SJed Brown     /* Not an error because MatSetOption_SeqAIJ_Inode handles this one */
1240b87ac2d8SJed Brown     break;
1241c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1242c10200c1SHong Zhang     A->submat_singleis = flg;
1243c10200c1SHong Zhang     break;
1244071fcb05SBarry Smith   case MAT_SORTED_FULL:
1245071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1246071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1247071fcb05SBarry Smith     break;
1248a65d3064SKris Buschelman   default:
1249e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1250a65d3064SKris Buschelman   }
12514108e4d5SBarry Smith   ierr = MatSetOption_SeqAIJ_Inode(A,op,flg);CHKERRQ(ierr);
12523a40ed3dSBarry Smith   PetscFunctionReturn(0);
125317ab2063SBarry Smith }
125417ab2063SBarry Smith 
1255dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
125617ab2063SBarry Smith {
1257416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
12586849ba73SBarry Smith   PetscErrorCode ierr;
1259fdc842d1SBarry Smith   PetscInt       i,j,n,*ai=a->i,*aj=a->j;
1260fdc842d1SBarry Smith   PetscScalar    *aa=a->a,*x;
126117ab2063SBarry Smith 
12623a40ed3dSBarry Smith   PetscFunctionBegin;
1263d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1264e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
126535e7444dSHong Zhang 
1266d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1267d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1268fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
12692c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1270fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
127135e7444dSHong Zhang     PetscFunctionReturn(0);
127235e7444dSHong Zhang   }
127335e7444dSHong Zhang 
1274fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
127535e7444dSHong Zhang   for (i=0; i<n; i++) {
1276fdc842d1SBarry Smith     x[i] = 0.0;
127735e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
127835e7444dSHong Zhang       if (aj[j] == i) {
127935e7444dSHong Zhang         x[i] = aa[j];
128017ab2063SBarry Smith         break;
128117ab2063SBarry Smith       }
128217ab2063SBarry Smith     }
128317ab2063SBarry Smith   }
1284fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
12853a40ed3dSBarry Smith   PetscFunctionReturn(0);
128617ab2063SBarry Smith }
128717ab2063SBarry Smith 
1288c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1289dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
129017ab2063SBarry Smith {
1291416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1292d9ca1df4SBarry Smith   PetscScalar       *y;
1293d9ca1df4SBarry Smith   const PetscScalar *x;
1294dfbe8321SBarry Smith   PetscErrorCode    ierr;
1295d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
12965c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1297d9ca1df4SBarry Smith   const MatScalar   *v;
1298a77337e4SBarry Smith   PetscScalar       alpha;
1299d9ca1df4SBarry Smith   PetscInt          n,i,j;
1300d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
13013447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1302ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
13035c897100SBarry Smith #endif
130417ab2063SBarry Smith 
13053a40ed3dSBarry Smith   PetscFunctionBegin;
13062e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1307d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
13081ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
13095c897100SBarry Smith 
13105c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1311bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
13125c897100SBarry Smith #else
13133447b6efSHong Zhang   if (usecprow) {
13143447b6efSHong Zhang     m    = cprow.nrows;
13153447b6efSHong Zhang     ii   = cprow.i;
13167b2bb3b9SHong Zhang     ridx = cprow.rindex;
13173447b6efSHong Zhang   } else {
13183447b6efSHong Zhang     ii = a->i;
13193447b6efSHong Zhang   }
132017ab2063SBarry Smith   for (i=0; i<m; i++) {
13213447b6efSHong Zhang     idx = a->j + ii[i];
13223447b6efSHong Zhang     v   = a->a + ii[i];
13233447b6efSHong Zhang     n   = ii[i+1] - ii[i];
13243447b6efSHong Zhang     if (usecprow) {
13257b2bb3b9SHong Zhang       alpha = x[ridx[i]];
13263447b6efSHong Zhang     } else {
132717ab2063SBarry Smith       alpha = x[i];
13283447b6efSHong Zhang     }
132904fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
133017ab2063SBarry Smith   }
13315c897100SBarry Smith #endif
1332dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1333d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
13341ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
13353a40ed3dSBarry Smith   PetscFunctionReturn(0);
133617ab2063SBarry Smith }
133717ab2063SBarry Smith 
1338dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
13395c897100SBarry Smith {
1340dfbe8321SBarry Smith   PetscErrorCode ierr;
13415c897100SBarry Smith 
13425c897100SBarry Smith   PetscFunctionBegin;
1343170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
13445c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
13455c897100SBarry Smith   PetscFunctionReturn(0);
13465c897100SBarry Smith }
13475c897100SBarry Smith 
1348c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
134978b84d54SShri Abhyankar 
1350dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
135117ab2063SBarry Smith {
1352416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1353d9fead3dSBarry Smith   PetscScalar       *y;
135454f21887SBarry Smith   const PetscScalar *x;
135554f21887SBarry Smith   const MatScalar   *aa;
1356dfbe8321SBarry Smith   PetscErrorCode    ierr;
1357003131ecSBarry Smith   PetscInt          m=A->rmap->n;
13580298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
13597b083b7cSBarry Smith   PetscInt          n,i;
1360362ced78SSatish Balay   PetscScalar       sum;
1361ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
136217ab2063SBarry Smith 
1363b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
136497952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1365fee21e36SBarry Smith #endif
1366fee21e36SBarry Smith 
13673a40ed3dSBarry Smith   PetscFunctionBegin;
13683649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
13691ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1370416022c9SBarry Smith   ii   = a->i;
13714eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1372580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
137397952fefSHong Zhang     m    = a->compressedrow.nrows;
137497952fefSHong Zhang     ii   = a->compressedrow.i;
137597952fefSHong Zhang     ridx = a->compressedrow.rindex;
137697952fefSHong Zhang     for (i=0; i<m; i++) {
137797952fefSHong Zhang       n           = ii[i+1] - ii[i];
137897952fefSHong Zhang       aj          = a->j + ii[i];
137997952fefSHong Zhang       aa          = a->a + ii[i];
138097952fefSHong Zhang       sum         = 0.0;
1381003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1382003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
138397952fefSHong Zhang       y[*ridx++] = sum;
138497952fefSHong Zhang     }
138597952fefSHong Zhang   } else { /* do not use compressed row format */
1386b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
13873d3eaba7SBarry Smith     aj   = a->j;
13883d3eaba7SBarry Smith     aa   = a->a;
1389b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1390b05257ddSBarry Smith #else
139117ab2063SBarry Smith     for (i=0; i<m; i++) {
1392003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1393003131ecSBarry Smith       aj          = a->j + ii[i];
1394003131ecSBarry Smith       aa          = a->a + ii[i];
139517ab2063SBarry Smith       sum         = 0.0;
1396003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
139717ab2063SBarry Smith       y[i] = sum;
139817ab2063SBarry Smith     }
13998d195f9aSBarry Smith #endif
1400b05257ddSBarry Smith   }
14017b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
14023649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14031ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14043a40ed3dSBarry Smith   PetscFunctionReturn(0);
140517ab2063SBarry Smith }
140617ab2063SBarry Smith 
1407b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1408b434eb95SMatthew G. Knepley {
1409b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1410b434eb95SMatthew G. Knepley   PetscScalar       *y;
1411b434eb95SMatthew G. Knepley   const PetscScalar *x;
1412b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1413b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1414b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1415b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1416b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1417b434eb95SMatthew G. Knepley   PetscScalar       sum;
1418b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1419b434eb95SMatthew G. Knepley 
1420b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1421b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1422b434eb95SMatthew G. Knepley #endif
1423b434eb95SMatthew G. Knepley 
1424b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1425b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1426b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1427b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1428b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1429b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1430b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1431b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1432b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1433b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1434b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1435b434eb95SMatthew G. Knepley       sum         = 0.0;
1436b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1437b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1438b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1439b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1440b434eb95SMatthew G. Knepley     }
1441b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
14423d3eaba7SBarry Smith     ii = a->i;
1443b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1444b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1445b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1446b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1447b434eb95SMatthew G. Knepley       sum         = 0.0;
1448b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1449b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1450b434eb95SMatthew G. Knepley       y[i] = sum;
1451b434eb95SMatthew G. Knepley     }
1452b434eb95SMatthew G. Knepley   }
1453b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1454b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1455b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1456b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1457b434eb95SMatthew G. Knepley }
1458b434eb95SMatthew G. Knepley 
1459b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1460b434eb95SMatthew G. Knepley {
1461b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1462b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1463b434eb95SMatthew G. Knepley   const PetscScalar *x;
1464b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1465b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1466b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1467b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1468b434eb95SMatthew G. Knepley   PetscScalar       sum;
1469b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1470b434eb95SMatthew G. Knepley 
1471b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1472b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1473d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1474b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1475b434eb95SMatthew G. Knepley     if (zz != yy) {
1476580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1477b434eb95SMatthew G. Knepley     }
1478b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1479b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1480b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1481b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1482b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1483b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1484b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1485b434eb95SMatthew G. Knepley       sum = y[*ridx];
1486b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1487b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1488b434eb95SMatthew G. Knepley     }
1489b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
14903d3eaba7SBarry Smith     ii = a->i;
1491b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1492b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1493b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1494b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1495b434eb95SMatthew G. Knepley       sum = y[i];
1496b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1497b434eb95SMatthew G. Knepley       z[i] = sum;
1498b434eb95SMatthew G. Knepley     }
1499b434eb95SMatthew G. Knepley   }
1500b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1501b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1502d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1503b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1504b434eb95SMatthew G. Knepley }
1505b434eb95SMatthew G. Knepley 
1506c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1507dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
150817ab2063SBarry Smith {
1509416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1510f15663dcSBarry Smith   PetscScalar       *y,*z;
1511f15663dcSBarry Smith   const PetscScalar *x;
151254f21887SBarry Smith   const MatScalar   *aa;
1513dfbe8321SBarry Smith   PetscErrorCode    ierr;
1514d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1515d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1516362ced78SSatish Balay   PetscScalar       sum;
1517ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
15189ea0dfa2SSatish Balay 
15193a40ed3dSBarry Smith   PetscFunctionBegin;
1520f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1521d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
15224eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
15234eb6d288SHong Zhang     if (zz != yy) {
1524580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
15254eb6d288SHong Zhang     }
152697952fefSHong Zhang     m    = a->compressedrow.nrows;
152797952fefSHong Zhang     ii   = a->compressedrow.i;
152897952fefSHong Zhang     ridx = a->compressedrow.rindex;
152997952fefSHong Zhang     for (i=0; i<m; i++) {
153097952fefSHong Zhang       n   = ii[i+1] - ii[i];
153197952fefSHong Zhang       aj  = a->j + ii[i];
153297952fefSHong Zhang       aa  = a->a + ii[i];
153397952fefSHong Zhang       sum = y[*ridx];
1534f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
153597952fefSHong Zhang       z[*ridx++] = sum;
153697952fefSHong Zhang     }
153797952fefSHong Zhang   } else { /* do not use compressed row format */
15383d3eaba7SBarry Smith     ii = a->i;
1539f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
15403d3eaba7SBarry Smith     aj = a->j;
15413d3eaba7SBarry Smith     aa = a->a;
1542f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1543f15663dcSBarry Smith #else
154417ab2063SBarry Smith     for (i=0; i<m; i++) {
1545f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1546f15663dcSBarry Smith       aj  = a->j + ii[i];
1547f15663dcSBarry Smith       aa  = a->a + ii[i];
154817ab2063SBarry Smith       sum = y[i];
1549f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
155017ab2063SBarry Smith       z[i] = sum;
155117ab2063SBarry Smith     }
155202ab625aSSatish Balay #endif
1553f15663dcSBarry Smith   }
1554dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1555f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1556d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
15573a40ed3dSBarry Smith   PetscFunctionReturn(0);
155817ab2063SBarry Smith }
155917ab2063SBarry Smith 
156017ab2063SBarry Smith /*
156117ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
156217ab2063SBarry Smith */
1563dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
156417ab2063SBarry Smith {
1565416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
15666849ba73SBarry Smith   PetscErrorCode ierr;
1567d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
156817ab2063SBarry Smith 
15693a40ed3dSBarry Smith   PetscFunctionBegin;
157009f38230SBarry Smith   if (!a->diag) {
1571785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
15723bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
157309f38230SBarry Smith   }
1574d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
157509f38230SBarry Smith     a->diag[i] = a->i[i+1];
1576bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1577bfeeae90SHong Zhang       if (a->j[j] == i) {
157809f38230SBarry Smith         a->diag[i] = j;
157917ab2063SBarry Smith         break;
158017ab2063SBarry Smith       }
158117ab2063SBarry Smith     }
158217ab2063SBarry Smith   }
15833a40ed3dSBarry Smith   PetscFunctionReturn(0);
158417ab2063SBarry Smith }
158517ab2063SBarry Smith 
158661ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
158761ecd0c6SBarry Smith {
158861ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
158961ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
159061ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
159161ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
159261ecd0c6SBarry Smith   PetscErrorCode    ierr;
159361ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
159461ecd0c6SBarry Smith 
159561ecd0c6SBarry Smith   PetscFunctionBegin;
159661ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
159761ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
159861ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
159961ecd0c6SBarry Smith     PetscFunctionReturn(0);
160061ecd0c6SBarry Smith   }
160161ecd0c6SBarry Smith 
160261ecd0c6SBarry Smith   if (a->diagonaldense) {
160361ecd0c6SBarry Smith     cnt = 0;
160461ecd0c6SBarry Smith   } else {
160561ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
160661ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
160761ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
160861ecd0c6SBarry Smith         cnt++;
160961ecd0c6SBarry Smith         mdiag[i] = 1;
161061ecd0c6SBarry Smith       }
161161ecd0c6SBarry Smith     }
161261ecd0c6SBarry Smith   }
161361ecd0c6SBarry Smith   if (!cnt) {
161461ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
161561ecd0c6SBarry Smith   } else {
1616b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1617b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
161861ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
161961ecd0c6SBarry Smith 
162061ecd0c6SBarry Smith     a->a = NULL;
162161ecd0c6SBarry Smith     a->j = NULL;
162261ecd0c6SBarry Smith     a->i = NULL;
162361ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
162461ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
162561ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1626447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
162761ecd0c6SBarry Smith     }
162861ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
162961ecd0c6SBarry Smith 
163061ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
163161ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
163261ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1633447d62f5SStefano Zampini       if (i < A->cmap->n) {
163461ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
163561ecd0c6SBarry Smith       }
1636447d62f5SStefano Zampini     }
163761ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
163861ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
163961ecd0c6SBarry Smith     if (singlemalloc) {
164061ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
164161ecd0c6SBarry Smith     } else {
164261ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
164361ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
164461ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
164561ecd0c6SBarry Smith     }
164661ecd0c6SBarry Smith   }
164761ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
164861ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
164961ecd0c6SBarry Smith   PetscFunctionReturn(0);
165061ecd0c6SBarry Smith }
165161ecd0c6SBarry Smith 
1652be5855fcSBarry Smith /*
1653be5855fcSBarry Smith      Checks for missing diagonals
1654be5855fcSBarry Smith */
1655ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1656be5855fcSBarry Smith {
1657be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
16587734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1659994fe344SLisandro Dalcin   PetscErrorCode ierr;
1660be5855fcSBarry Smith 
1661be5855fcSBarry Smith   PetscFunctionBegin;
166209f38230SBarry Smith   *missing = PETSC_FALSE;
16637734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
166409f38230SBarry Smith     *missing = PETSC_TRUE;
166509f38230SBarry Smith     if (d) *d = 0;
1666994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
166709f38230SBarry Smith   } else {
166801445905SHong Zhang     PetscInt n;
166901445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1670f1e2ffcdSBarry Smith     diag = a->diag;
167101445905SHong Zhang     for (i=0; i<n; i++) {
16727734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
167309f38230SBarry Smith         *missing = PETSC_TRUE;
167409f38230SBarry Smith         if (d) *d = i;
1675994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1676358d2f5dSShri Abhyankar         break;
167709f38230SBarry Smith       }
1678be5855fcSBarry Smith     }
1679be5855fcSBarry Smith   }
1680be5855fcSBarry Smith   PetscFunctionReturn(0);
1681be5855fcSBarry Smith }
1682be5855fcSBarry Smith 
16830da83c2eSBarry Smith #include <petscblaslapack.h>
16840da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
16850da83c2eSBarry Smith 
16860da83c2eSBarry Smith /*
16870da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
16880da83c2eSBarry Smith */
16890da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
16900da83c2eSBarry Smith {
16910da83c2eSBarry Smith   PetscErrorCode  ierr;
16920da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
16930da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
16940da83c2eSBarry Smith   const PetscReal shift = 0.0;
16950da83c2eSBarry Smith   PetscInt        ipvt[5];
16960da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
16970da83c2eSBarry Smith 
16980da83c2eSBarry Smith   PetscFunctionBegin;
16990da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
17000da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
17010da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
17020da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
17030da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
17040da83c2eSBarry Smith   }
17050da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
17060da83c2eSBarry Smith   if (bsizemax > 7) {
17070da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
17080da83c2eSBarry Smith   }
17090da83c2eSBarry Smith   ncnt = 0;
17100da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
17110da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
17120da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
17130da83c2eSBarry Smith     switch (bsizes[i]) {
17140da83c2eSBarry Smith     case 1:
17150da83c2eSBarry Smith       *diag = 1.0/(*diag);
17160da83c2eSBarry Smith       break;
17170da83c2eSBarry Smith     case 2:
17180da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17190da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17200da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
17210da83c2eSBarry Smith       break;
17220da83c2eSBarry Smith     case 3:
17230da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17240da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17250da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
17260da83c2eSBarry Smith       break;
17270da83c2eSBarry Smith     case 4:
17280da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17290da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17300da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
17310da83c2eSBarry Smith       break;
17320da83c2eSBarry Smith     case 5:
17330da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17340da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17350da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
17360da83c2eSBarry Smith       break;
17370da83c2eSBarry Smith     case 6:
17380da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17390da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17400da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
17410da83c2eSBarry Smith       break;
17420da83c2eSBarry Smith     case 7:
17430da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17440da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17450da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
17460da83c2eSBarry Smith       break;
17470da83c2eSBarry Smith     default:
17480da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
17490da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17500da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
17510da83c2eSBarry Smith     }
17520da83c2eSBarry Smith     ncnt   += bsizes[i];
17530da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
17540da83c2eSBarry Smith   }
17550da83c2eSBarry Smith   if (bsizemax > 7) {
17560da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
17570da83c2eSBarry Smith   }
17580da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
17590da83c2eSBarry Smith   PetscFunctionReturn(0);
17600da83c2eSBarry Smith }
17610da83c2eSBarry Smith 
1762422a814eSBarry Smith /*
1763422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1764422a814eSBarry Smith */
17657087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
176671f1c65dSBarry Smith {
176771f1c65dSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*) A->data;
176871f1c65dSBarry Smith   PetscErrorCode ierr;
1769d0f46423SBarry Smith   PetscInt       i,*diag,m = A->rmap->n;
177054f21887SBarry Smith   MatScalar      *v = a->a;
177154f21887SBarry Smith   PetscScalar    *idiag,*mdiag;
177271f1c65dSBarry Smith 
177371f1c65dSBarry Smith   PetscFunctionBegin;
177471f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
177571f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
177671f1c65dSBarry Smith   diag = a->diag;
177771f1c65dSBarry Smith   if (!a->idiag) {
1778dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
17793bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, 3*m*sizeof(PetscScalar));CHKERRQ(ierr);
178071f1c65dSBarry Smith     v    = a->a;
178171f1c65dSBarry Smith   }
178271f1c65dSBarry Smith   mdiag = a->mdiag;
178371f1c65dSBarry Smith   idiag = a->idiag;
178471f1c65dSBarry Smith 
1785422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
178671f1c65dSBarry Smith     for (i=0; i<m; i++) {
178771f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1788899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1789899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1790899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
17917b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
17927b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
17937b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1794a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1795899639b0SHong Zhang       }
179671f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
179771f1c65dSBarry Smith     }
179871f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
179971f1c65dSBarry Smith   } else {
180071f1c65dSBarry Smith     for (i=0; i<m; i++) {
180171f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
180271f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
180371f1c65dSBarry Smith     }
1804dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
180571f1c65dSBarry Smith   }
180671f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
180771f1c65dSBarry Smith   PetscFunctionReturn(0);
180871f1c65dSBarry Smith }
180971f1c65dSBarry Smith 
1810c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
181141f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
181217ab2063SBarry Smith {
1813416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1814e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
18153d3eaba7SBarry Smith   const MatScalar   *v,*idiag=0,*mdiag;
181654f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1817dfbe8321SBarry Smith   PetscErrorCode    ierr;
18183d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
181997f1f81fSBarry Smith   const PetscInt    *idx,*diag;
182017ab2063SBarry Smith 
18213a40ed3dSBarry Smith   PetscFunctionBegin;
1822b965ef7fSBarry Smith   its = its*lits;
182391723122SBarry Smith 
182471f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
182571f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
182671f1c65dSBarry Smith   a->fshift = fshift;
182771f1c65dSBarry Smith   a->omega  = omega;
1828ed480e8bSBarry Smith 
182971f1c65dSBarry Smith   diag  = a->diag;
183071f1c65dSBarry Smith   t     = a->ssor_work;
1831ed480e8bSBarry Smith   idiag = a->idiag;
183271f1c65dSBarry Smith   mdiag = a->mdiag;
1833ed480e8bSBarry Smith 
18341ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
18353649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1836ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
183717ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
183817ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1839ed480e8bSBarry Smith     bs = b;
184017ab2063SBarry Smith     for (i=0; i<m; i++) {
184171f1c65dSBarry Smith       d   = fshift + mdiag[i];
1842416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1843ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1844ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
184517ab2063SBarry Smith       sum = b[i]*d/omega;
1846003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
184717ab2063SBarry Smith       x[i] = sum;
184817ab2063SBarry Smith     }
18491ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
18503649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1851efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
18523a40ed3dSBarry Smith     PetscFunctionReturn(0);
185317ab2063SBarry Smith   }
1854c783ea89SBarry Smith 
18552205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
18562205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
18574c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1858887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
185917ab2063SBarry Smith 
186017ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
186117ab2063SBarry Smith 
1862887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
186317ab2063SBarry Smith     */
186417ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
186517ab2063SBarry Smith 
186617ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
186717ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
1868416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1869ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
1870ed480e8bSBarry Smith       v   = a->a + diag[i] + 1;
187117ab2063SBarry Smith       sum = b[i];
1872e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1873ed480e8bSBarry Smith       x[i] = sum*idiag[i];
187417ab2063SBarry Smith     }
187517ab2063SBarry Smith 
187617ab2063SBarry Smith     /*  t = b - (2*E - D)x */
1877416022c9SBarry Smith     v = a->a;
18782205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
187917ab2063SBarry Smith 
188017ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
1881ed480e8bSBarry Smith     ts   = t;
1882416022c9SBarry Smith     diag = a->diag;
188317ab2063SBarry Smith     for (i=0; i<m; i++) {
1884416022c9SBarry Smith       n   = diag[i] - a->i[i];
1885ed480e8bSBarry Smith       idx = a->j + a->i[i];
1886ed480e8bSBarry Smith       v   = a->a + a->i[i];
188717ab2063SBarry Smith       sum = t[i];
1888003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
1889ed480e8bSBarry Smith       t[i] = sum*idiag[i];
1890733d66baSBarry Smith       /*  x = x + t */
1891733d66baSBarry Smith       x[i] += t[i];
189217ab2063SBarry Smith     }
189317ab2063SBarry Smith 
1894dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
18951ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
18963649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
18973a40ed3dSBarry Smith     PetscFunctionReturn(0);
189817ab2063SBarry Smith   }
189917ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
190017ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
190117ab2063SBarry Smith       for (i=0; i<m; i++) {
1902416022c9SBarry Smith         n   = diag[i] - a->i[i];
1903ed480e8bSBarry Smith         idx = a->j + a->i[i];
1904ed480e8bSBarry Smith         v   = a->a + a->i[i];
190517ab2063SBarry Smith         sum = b[i];
1906e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
19075c99c7daSBarry Smith         t[i] = sum;
1908ed480e8bSBarry Smith         x[i] = sum*idiag[i];
190917ab2063SBarry Smith       }
19105c99c7daSBarry Smith       xb   = t;
1911efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
19123a40ed3dSBarry Smith     } else xb = b;
191317ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
191417ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
1915416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
1916ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
1917ed480e8bSBarry Smith         v   = a->a + diag[i] + 1;
191817ab2063SBarry Smith         sum = xb[i];
1919e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
19205c99c7daSBarry Smith         if (xb == b) {
1921ed480e8bSBarry Smith           x[i] = sum*idiag[i];
19225c99c7daSBarry Smith         } else {
1923b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
192417ab2063SBarry Smith         }
19255c99c7daSBarry Smith       }
1926b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
192717ab2063SBarry Smith     }
192817ab2063SBarry Smith     its--;
192917ab2063SBarry Smith   }
193017ab2063SBarry Smith   while (its--) {
193117ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
193217ab2063SBarry Smith       for (i=0; i<m; i++) {
1933b19a5dc2SMark Adams         /* lower */
1934b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
1935ed480e8bSBarry Smith         idx = a->j + a->i[i];
1936ed480e8bSBarry Smith         v   = a->a + a->i[i];
193717ab2063SBarry Smith         sum = b[i];
1938e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1939b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
1940b19a5dc2SMark Adams         /* upper */
1941b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
1942b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
1943b19a5dc2SMark Adams         v   = a->a + diag[i] + 1;
1944b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
1945b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
194617ab2063SBarry Smith       }
1947b19a5dc2SMark Adams       xb   = t;
19489f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1949b19a5dc2SMark Adams     } else xb = b;
195017ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
195117ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
1952b19a5dc2SMark Adams         sum = xb[i];
1953b19a5dc2SMark Adams         if (xb == b) {
1954b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
1955416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
1956ed480e8bSBarry Smith           idx = a->j + a->i[i];
1957ed480e8bSBarry Smith           v   = a->a + a->i[i];
1958e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
1959ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
1960b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
1961b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
1962b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
1963b19a5dc2SMark Adams           v   = a->a + diag[i] + 1;
1964b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
1965b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
196617ab2063SBarry Smith         }
1967b19a5dc2SMark Adams       }
1968b19a5dc2SMark Adams       if (xb == b) {
19699f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1970b19a5dc2SMark Adams       } else {
1971b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
1972b19a5dc2SMark Adams       }
197317ab2063SBarry Smith     }
197417ab2063SBarry Smith   }
19751ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
19763649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1977365a8a9eSBarry Smith   PetscFunctionReturn(0);
197817ab2063SBarry Smith }
197917ab2063SBarry Smith 
19802af78befSBarry Smith 
1981dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
198217ab2063SBarry Smith {
1983416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
19844e220ebcSLois Curfman McInnes 
19853a40ed3dSBarry Smith   PetscFunctionBegin;
19864e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
19873966268fSBarry Smith   info->nz_allocated = a->maxnz;
19883966268fSBarry Smith   info->nz_used      = a->nz;
19893966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
19903966268fSBarry Smith   info->assemblies   = A->num_ass;
19913966268fSBarry Smith   info->mallocs      = A->info.mallocs;
19927adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
1993d5f3da31SBarry Smith   if (A->factortype) {
19944e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
19954e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
19964e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
19974e220ebcSLois Curfman McInnes   } else {
19984e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
19994e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
20004e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
20014e220ebcSLois Curfman McInnes   }
20023a40ed3dSBarry Smith   PetscFunctionReturn(0);
200317ab2063SBarry Smith }
200417ab2063SBarry Smith 
20052b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
200617ab2063SBarry Smith {
2007416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2008c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
20096849ba73SBarry Smith   PetscErrorCode    ierr;
201097b48c8fSBarry Smith   const PetscScalar *xx;
201197b48c8fSBarry Smith   PetscScalar       *bb;
2012c7da8527SEric Chamberland   PetscInt          d = 0;
201317ab2063SBarry Smith 
20143a40ed3dSBarry Smith   PetscFunctionBegin;
201597b48c8fSBarry Smith   if (x && b) {
201697b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
201797b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
201897b48c8fSBarry Smith     for (i=0; i<N; i++) {
201997b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2020447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
202197b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
202297b48c8fSBarry Smith     }
202397b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
202497b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
202597b48c8fSBarry Smith   }
202697b48c8fSBarry Smith 
2027a9817697SBarry Smith   if (a->keepnonzeropattern) {
2028f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2029e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2030580bdb30SBarry Smith       ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2031f1e2ffcdSBarry Smith     }
2032f4df32b1SMatthew Knepley     if (diag != 0.0) {
2033c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2034c7da8527SEric Chamberland         d = rows[i];
2035447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2036c7da8527SEric 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);
2037c7da8527SEric Chamberland       }
2038f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2039447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2040f4df32b1SMatthew Knepley         a->a[a->diag[rows[i]]] = diag;
2041f1e2ffcdSBarry Smith       }
2042f1e2ffcdSBarry Smith     }
2043f1e2ffcdSBarry Smith   } else {
2044f4df32b1SMatthew Knepley     if (diag != 0.0) {
204517ab2063SBarry Smith       for (i=0; i<N; i++) {
2046e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
20477ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2048447d62f5SStefano Zampini 	  if (rows[i] >= A->cmap->n) {
2049447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2050447d62f5SStefano Zampini           } else {
2051416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
2052f4df32b1SMatthew Knepley             a->a[a->i[rows[i]]] = diag;
2053bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2054447d62f5SStefano Zampini           }
2055447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2056f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
205717ab2063SBarry Smith         }
205817ab2063SBarry Smith       }
20593a40ed3dSBarry Smith     } else {
206017ab2063SBarry Smith       for (i=0; i<N; i++) {
2061e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2062416022c9SBarry Smith         a->ilen[rows[i]] = 0;
206317ab2063SBarry Smith       }
206417ab2063SBarry Smith     }
2065e56f5c9eSBarry Smith     A->nonzerostate++;
2066f1e2ffcdSBarry Smith   }
2067e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2068c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2069e2cf4d64SStefano Zampini #endif
20704099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
20713a40ed3dSBarry Smith   PetscFunctionReturn(0);
207217ab2063SBarry Smith }
207317ab2063SBarry Smith 
20746e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
20756e169961SBarry Smith {
20766e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
20776e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
20786e169961SBarry Smith   PetscErrorCode    ierr;
20792b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
20806e169961SBarry Smith   const PetscScalar *xx;
20816e169961SBarry Smith   PetscScalar       *bb;
20826e169961SBarry Smith 
20836e169961SBarry Smith   PetscFunctionBegin;
20846e169961SBarry Smith   if (x && b) {
20856e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
20866e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
20872b40b63fSBarry Smith     vecs = PETSC_TRUE;
20886e169961SBarry Smith   }
20891795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
20906e169961SBarry Smith   for (i=0; i<N; i++) {
20916e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2092580bdb30SBarry Smith     ierr = PetscArrayzero(&a->a[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
20932205254eSKarl Rupp 
20946e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
20956e169961SBarry Smith   }
20966e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
20976e169961SBarry Smith     if (!zeroed[i]) {
20986e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
20994cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
21002b40b63fSBarry Smith           if (vecs) bb[i] -= a->a[j]*xx[a->j[j]];
21016e169961SBarry Smith           a->a[j] = 0.0;
21026e169961SBarry Smith         }
21036e169961SBarry Smith       }
21044cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
21056e169961SBarry Smith   }
21066e169961SBarry Smith   if (x && b) {
21076e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
21086e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
21096e169961SBarry Smith   }
21106e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
21116e169961SBarry Smith   if (diag != 0.0) {
21126e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
21131d5a398dSstefano_zampini     if (missing) {
21141d5a398dSstefano_zampini       for (i=0; i<N; i++) {
21154cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
21164cf107fdSStefano 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]);
21171d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
21181d5a398dSstefano_zampini       }
21191d5a398dSstefano_zampini     } else {
21206e169961SBarry Smith       for (i=0; i<N; i++) {
21216e169961SBarry Smith         a->a[a->diag[rows[i]]] = diag;
21226e169961SBarry Smith       }
21236e169961SBarry Smith     }
21241d5a398dSstefano_zampini   }
2125e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2126c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2127e2cf4d64SStefano Zampini #endif
21284099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
21296e169961SBarry Smith   PetscFunctionReturn(0);
21306e169961SBarry Smith }
21316e169961SBarry Smith 
2132a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
213317ab2063SBarry Smith {
2134416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
213597f1f81fSBarry Smith   PetscInt   *itmp;
213617ab2063SBarry Smith 
21373a40ed3dSBarry Smith   PetscFunctionBegin;
2138e32f2f54SBarry Smith   if (row < 0 || row >= A->rmap->n) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range",row);
213917ab2063SBarry Smith 
2140416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
2141bfeeae90SHong Zhang   if (v) *v = a->a + a->i[row];
214217ab2063SBarry Smith   if (idx) {
2143bfeeae90SHong Zhang     itmp = a->j + a->i[row];
214426fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
214517ab2063SBarry Smith     else *idx = 0;
214617ab2063SBarry Smith   }
21473a40ed3dSBarry Smith   PetscFunctionReturn(0);
214817ab2063SBarry Smith }
214917ab2063SBarry Smith 
2150bfeeae90SHong Zhang /* remove this function? */
2151a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
215217ab2063SBarry Smith {
21533a40ed3dSBarry Smith   PetscFunctionBegin;
21543a40ed3dSBarry Smith   PetscFunctionReturn(0);
215517ab2063SBarry Smith }
215617ab2063SBarry Smith 
2157dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
215817ab2063SBarry Smith {
2159416022c9SBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
216054f21887SBarry Smith   MatScalar      *v  = a->a;
216136db0b34SBarry Smith   PetscReal      sum = 0.0;
21626849ba73SBarry Smith   PetscErrorCode ierr;
216397f1f81fSBarry Smith   PetscInt       i,j;
216417ab2063SBarry Smith 
21653a40ed3dSBarry Smith   PetscFunctionBegin;
216617ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2167570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2168570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
2169570b7f6dSBarry Smith     *nrm = BLASnrm2_(&nz,v,&one);
2170570b7f6dSBarry Smith #else
2171416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
217236db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
217317ab2063SBarry Smith     }
21748f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2175570b7f6dSBarry Smith #endif
217651f70360SJed Brown     ierr = PetscLogFlops(2*a->nz);CHKERRQ(ierr);
21773a40ed3dSBarry Smith   } else if (type == NORM_1) {
217836db0b34SBarry Smith     PetscReal *tmp;
217997f1f81fSBarry Smith     PetscInt  *jj = a->j;
21801795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2181064f8208SBarry Smith     *nrm = 0.0;
2182416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2183bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
218417ab2063SBarry Smith     }
2185d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2186064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
218717ab2063SBarry Smith     }
2188606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
218951f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
21903a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2191064f8208SBarry Smith     *nrm = 0.0;
2192d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
2193bfeeae90SHong Zhang       v   = a->a + a->i[j];
219417ab2063SBarry Smith       sum = 0.0;
2195416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
2196cddf8d76SBarry Smith         sum += PetscAbsScalar(*v); v++;
219717ab2063SBarry Smith       }
2198064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
219917ab2063SBarry Smith     }
220051f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2201f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
22023a40ed3dSBarry Smith   PetscFunctionReturn(0);
220317ab2063SBarry Smith }
220417ab2063SBarry Smith 
22054e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
22064e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
22074e938277SHong Zhang {
22084e938277SHong Zhang   PetscErrorCode ierr;
22094e938277SHong Zhang   PetscInt       i,j,anzj;
22104e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
22114e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
22124e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
22134e938277SHong Zhang 
22144e938277SHong Zhang   PetscFunctionBegin;
22154e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2216854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2217785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2218785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
22194e938277SHong Zhang 
22204e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
22214e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
222226fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
22234e938277SHong Zhang   /* Form ati for csr format of A^T. */
222426fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
22254e938277SHong Zhang 
22264e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2227580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
22284e938277SHong Zhang 
22294e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
22304e938277SHong Zhang   for (i=0;i<am;i++) {
22314e938277SHong Zhang     anzj = ai[i+1] - ai[i];
22324e938277SHong Zhang     for (j=0;j<anzj;j++) {
22334e938277SHong Zhang       atj[atfill[*aj]] = i;
22344e938277SHong Zhang       atfill[*aj++]   += 1;
22354e938277SHong Zhang     }
22364e938277SHong Zhang   }
22374e938277SHong Zhang 
22384e938277SHong Zhang   /* Clean up temporary space and complete requests. */
22394e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2240ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
224133d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2242b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2243a2f3521dSMark F. Adams 
22444e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
22454e938277SHong Zhang   b->free_a  = PETSC_FALSE;
22464e938277SHong Zhang   b->free_ij = PETSC_TRUE;
22474e938277SHong Zhang   b->nonew   = 0;
22484e938277SHong Zhang   PetscFunctionReturn(0);
22494e938277SHong Zhang }
22504e938277SHong Zhang 
22517087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2252cd0d46ebSvictorle {
22533d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
225454f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
225554f21887SBarry Smith   MatScalar      *va,*vb;
22566849ba73SBarry Smith   PetscErrorCode ierr;
225797f1f81fSBarry Smith   PetscInt       ma,na,mb,nb, i;
2258cd0d46ebSvictorle 
2259cd0d46ebSvictorle   PetscFunctionBegin;
2260cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2261cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
22625485867bSBarry Smith   if (ma!=nb || na!=mb) {
22635485867bSBarry Smith     *f = PETSC_FALSE;
22645485867bSBarry Smith     PetscFunctionReturn(0);
22655485867bSBarry Smith   }
2266cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2267cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2268cd0d46ebSvictorle   va   = aij->a; vb = bij->a;
2269785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2270785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2271cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2272cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2273cd0d46ebSvictorle 
2274cd0d46ebSvictorle   *f = PETSC_TRUE;
2275cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2276cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
227797f1f81fSBarry Smith       PetscInt    idc,idr;
22785485867bSBarry Smith       PetscScalar vc,vr;
2279cd0d46ebSvictorle       /* column/row index/value */
22805485867bSBarry Smith       idc = adx[aptr[i]];
22815485867bSBarry Smith       idr = bdx[bptr[idc]];
22825485867bSBarry Smith       vc  = va[aptr[i]];
22835485867bSBarry Smith       vr  = vb[bptr[idc]];
22845485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
22855485867bSBarry Smith         *f = PETSC_FALSE;
22865485867bSBarry Smith         goto done;
2287cd0d46ebSvictorle       } else {
22885485867bSBarry Smith         aptr[i]++;
22895485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2290cd0d46ebSvictorle       }
2291cd0d46ebSvictorle     }
2292cd0d46ebSvictorle   }
2293cd0d46ebSvictorle done:
2294cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
22953aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
2296cd0d46ebSvictorle   PetscFunctionReturn(0);
2297cd0d46ebSvictorle }
2298cd0d46ebSvictorle 
22997087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
23001cbb95d3SBarry Smith {
23013d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
230254f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
230354f21887SBarry Smith   MatScalar      *va,*vb;
23041cbb95d3SBarry Smith   PetscErrorCode ierr;
23051cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
23061cbb95d3SBarry Smith 
23071cbb95d3SBarry Smith   PetscFunctionBegin;
23081cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
23091cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
23101cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
23111cbb95d3SBarry Smith     *f = PETSC_FALSE;
23121cbb95d3SBarry Smith     PetscFunctionReturn(0);
23131cbb95d3SBarry Smith   }
23141cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
23151cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
23161cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2317785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2318785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
23191cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
23201cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
23211cbb95d3SBarry Smith 
23221cbb95d3SBarry Smith   *f = PETSC_TRUE;
23231cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
23241cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
23251cbb95d3SBarry Smith       PetscInt    idc,idr;
23261cbb95d3SBarry Smith       PetscScalar vc,vr;
23271cbb95d3SBarry Smith       /* column/row index/value */
23281cbb95d3SBarry Smith       idc = adx[aptr[i]];
23291cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
23301cbb95d3SBarry Smith       vc  = va[aptr[i]];
23311cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
23321cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
23331cbb95d3SBarry Smith         *f = PETSC_FALSE;
23341cbb95d3SBarry Smith         goto done;
23351cbb95d3SBarry Smith       } else {
23361cbb95d3SBarry Smith         aptr[i]++;
23371cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
23381cbb95d3SBarry Smith       }
23391cbb95d3SBarry Smith     }
23401cbb95d3SBarry Smith   }
23411cbb95d3SBarry Smith done:
23421cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
23431cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
23441cbb95d3SBarry Smith   PetscFunctionReturn(0);
23451cbb95d3SBarry Smith }
23461cbb95d3SBarry Smith 
2347ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
23489e29f15eSvictorle {
2349dfbe8321SBarry Smith   PetscErrorCode ierr;
23506e111a19SKarl Rupp 
23519e29f15eSvictorle   PetscFunctionBegin;
23525485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
23539e29f15eSvictorle   PetscFunctionReturn(0);
23549e29f15eSvictorle }
23559e29f15eSvictorle 
2356ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
23571cbb95d3SBarry Smith {
23581cbb95d3SBarry Smith   PetscErrorCode ierr;
23596e111a19SKarl Rupp 
23601cbb95d3SBarry Smith   PetscFunctionBegin;
23611cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
23621cbb95d3SBarry Smith   PetscFunctionReturn(0);
23631cbb95d3SBarry Smith }
23641cbb95d3SBarry Smith 
2365dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
236617ab2063SBarry Smith {
2367416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2368fff8e43fSBarry Smith   const PetscScalar *l,*r;
2369fff8e43fSBarry Smith   PetscScalar       x;
237054f21887SBarry Smith   MatScalar         *v;
2371dfbe8321SBarry Smith   PetscErrorCode    ierr;
2372fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2373fff8e43fSBarry Smith   const PetscInt    *jj;
237417ab2063SBarry Smith 
23753a40ed3dSBarry Smith   PetscFunctionBegin;
237617ab2063SBarry Smith   if (ll) {
23773ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
23783ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2379e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2380e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2381fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
2382416022c9SBarry Smith     v    = a->a;
238317ab2063SBarry Smith     for (i=0; i<m; i++) {
238417ab2063SBarry Smith       x = l[i];
2385416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
23862205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
238717ab2063SBarry Smith     }
2388fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2389efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
239017ab2063SBarry Smith   }
239117ab2063SBarry Smith   if (rr) {
2392e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2393e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2394fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
2395416022c9SBarry Smith     v    = a->a; jj = a->j;
23962205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
2397fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2398efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
239917ab2063SBarry Smith   }
2400acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
2401e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2402c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2403e2cf4d64SStefano Zampini #endif
24043a40ed3dSBarry Smith   PetscFunctionReturn(0);
240517ab2063SBarry Smith }
240617ab2063SBarry Smith 
24077dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
240817ab2063SBarry Smith {
2409db02288aSLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*c;
24106849ba73SBarry Smith   PetscErrorCode ierr;
2411d0f46423SBarry Smith   PetscInt       *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
241297f1f81fSBarry Smith   PetscInt       row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
24135d0c19d7SBarry Smith   const PetscInt *irow,*icol;
24145d0c19d7SBarry Smith   PetscInt       nrows,ncols;
241597f1f81fSBarry Smith   PetscInt       *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
241654f21887SBarry Smith   MatScalar      *a_new,*mat_a;
2417416022c9SBarry Smith   Mat            C;
2418cdc6f3adSToby Isaac   PetscBool      stride;
241917ab2063SBarry Smith 
24203a40ed3dSBarry Smith   PetscFunctionBegin;
242199141d43SSatish Balay 
242217ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2423b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2424b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
242517ab2063SBarry Smith 
2426251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2427ff718158SBarry Smith   if (stride) {
2428ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2429ff718158SBarry Smith   } else {
2430ff718158SBarry Smith     first = 0;
2431ff718158SBarry Smith     step  = 0;
2432ff718158SBarry Smith   }
2433fee21e36SBarry Smith   if (stride && step == 1) {
243402834360SBarry Smith     /* special case of contiguous rows */
2435dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
243602834360SBarry Smith     /* loop over new rows determining lens and starting points */
243702834360SBarry Smith     for (i=0; i<nrows; i++) {
2438bfeeae90SHong Zhang       kstart = ai[irow[i]];
2439a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2440a91a9bebSLisandro Dalcin       starts[i] = kstart;
244102834360SBarry Smith       for (k=kstart; k<kend; k++) {
2442bfeeae90SHong Zhang         if (aj[k] >= first) {
244302834360SBarry Smith           starts[i] = k;
244402834360SBarry Smith           break;
244502834360SBarry Smith         }
244602834360SBarry Smith       }
2447a2744918SBarry Smith       sum = 0;
244802834360SBarry Smith       while (k < kend) {
2449bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2450a2744918SBarry Smith         sum++;
245102834360SBarry Smith       }
2452a2744918SBarry Smith       lens[i] = sum;
245302834360SBarry Smith     }
245402834360SBarry Smith     /* create submatrix */
2455cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
245697f1f81fSBarry Smith       PetscInt n_cols,n_rows;
245708480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2458e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2459d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
246008480c60SBarry Smith       C    = *B;
24613a40ed3dSBarry Smith     } else {
24623bef6203SJed Brown       PetscInt rbs,cbs;
2463ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2464f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
24653bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
24663bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
24673bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
24687adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2469ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
247008480c60SBarry Smith     }
2471db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2472db02288aSLois Curfman McInnes 
247302834360SBarry Smith     /* loop over rows inserting into submatrix */
2474db02288aSLois Curfman McInnes     a_new = c->a;
2475db02288aSLois Curfman McInnes     j_new = c->j;
2476db02288aSLois Curfman McInnes     i_new = c->i;
2477bfeeae90SHong Zhang 
247802834360SBarry Smith     for (i=0; i<nrows; i++) {
2479a2744918SBarry Smith       ii    = starts[i];
2480a2744918SBarry Smith       lensi = lens[i];
2481a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2482a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
248302834360SBarry Smith       }
2484580bdb30SBarry Smith       ierr       = PetscArraycpy(a_new,a->a + starts[i],lensi);CHKERRQ(ierr);
2485a2744918SBarry Smith       a_new     += lensi;
2486a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2487a2744918SBarry Smith       c->ilen[i] = lensi;
248802834360SBarry Smith     }
24890e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
24903a40ed3dSBarry Smith   } else {
249102834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
24921795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2493854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
24944dcab191SBarry Smith     for (i=0; i<ncols; i++) {
24954dcab191SBarry Smith #if defined(PETSC_USE_DEBUG)
24964dcab191SBarry Smith       if (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);
24974dcab191SBarry Smith #endif
24984dcab191SBarry Smith       smap[icol[i]] = i+1;
24994dcab191SBarry Smith     }
25004dcab191SBarry Smith 
250102834360SBarry Smith     /* determine lens of each row */
250202834360SBarry Smith     for (i=0; i<nrows; i++) {
2503bfeeae90SHong Zhang       kstart  = ai[irow[i]];
250402834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
250502834360SBarry Smith       lens[i] = 0;
250602834360SBarry Smith       for (k=kstart; k<kend; k++) {
2507bfeeae90SHong Zhang         if (smap[aj[k]]) {
250802834360SBarry Smith           lens[i]++;
250902834360SBarry Smith         }
251002834360SBarry Smith       }
251102834360SBarry Smith     }
251217ab2063SBarry Smith     /* Create and fill new matrix */
2513a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2514ace3abfcSBarry Smith       PetscBool equal;
25150f5bd95cSBarry Smith 
251699141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2517e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2518580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2519f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2520580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
252108480c60SBarry Smith       C    = *B;
25223a40ed3dSBarry Smith     } else {
25233bef6203SJed Brown       PetscInt rbs,cbs;
2524ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2525f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
25263bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
25273bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
25283bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
25297adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2530ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
253108480c60SBarry Smith     }
253299141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
253317ab2063SBarry Smith     for (i=0; i<nrows; i++) {
253499141d43SSatish Balay       row      = irow[i];
2535bfeeae90SHong Zhang       kstart   = ai[row];
253699141d43SSatish Balay       kend     = kstart + a->ilen[row];
2537bfeeae90SHong Zhang       mat_i    = c->i[i];
253899141d43SSatish Balay       mat_j    = c->j + mat_i;
253999141d43SSatish Balay       mat_a    = c->a + mat_i;
254099141d43SSatish Balay       mat_ilen = c->ilen + i;
254117ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2542bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2543ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
254499141d43SSatish Balay           *mat_a++ = a->a[k];
254599141d43SSatish Balay           (*mat_ilen)++;
254699141d43SSatish Balay 
254717ab2063SBarry Smith         }
254817ab2063SBarry Smith       }
254917ab2063SBarry Smith     }
255002834360SBarry Smith     /* Free work space */
255102834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2552606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2553606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2554cdc6f3adSToby Isaac     /* sort */
2555cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2556cdc6f3adSToby Isaac       PetscInt ilen;
2557cdc6f3adSToby Isaac 
2558cdc6f3adSToby Isaac       mat_i = c->i[i];
2559cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2560cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2561cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2562390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2563cdc6f3adSToby Isaac     }
256402834360SBarry Smith   }
2565305c6ccfSStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2566305c6ccfSStefano Zampini   ierr = MatPinToCPU(C,A->pinnedtocpu);CHKERRQ(ierr);
2567305c6ccfSStefano Zampini #endif
25686d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
25696d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
257017ab2063SBarry Smith 
257117ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2572416022c9SBarry Smith   *B   = C;
25733a40ed3dSBarry Smith   PetscFunctionReturn(0);
257417ab2063SBarry Smith }
257517ab2063SBarry Smith 
2576fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
257782d44351SHong Zhang {
257882d44351SHong Zhang   PetscErrorCode ierr;
257982d44351SHong Zhang   Mat            B;
258082d44351SHong Zhang 
258182d44351SHong Zhang   PetscFunctionBegin;
2582c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
258382d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
258482d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
258533d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
258682d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
258782d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
258882d44351SHong Zhang     *subMat = B;
2589c2d650bdSHong Zhang   } else {
2590c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2591c2d650bdSHong Zhang   }
259282d44351SHong Zhang   PetscFunctionReturn(0);
259382d44351SHong Zhang }
259482d44351SHong Zhang 
25959a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2596a871dcd8SBarry Smith {
259763b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2598dfbe8321SBarry Smith   PetscErrorCode ierr;
259963b91edcSBarry Smith   Mat            outA;
2600ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
260163b91edcSBarry Smith 
26023a40ed3dSBarry Smith   PetscFunctionBegin;
2603e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
26041df811f5SHong Zhang 
2605b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2606b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2607a871dcd8SBarry Smith 
260863b91edcSBarry Smith   outA             = inA;
2609d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2610f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2611f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
26122205254eSKarl Rupp 
2613c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
26146bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
26152205254eSKarl Rupp 
2616c3122656SLisandro Dalcin   a->row = row;
26172205254eSKarl Rupp 
2618c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
26196bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
26202205254eSKarl Rupp 
2621c3122656SLisandro Dalcin   a->col = col;
262263b91edcSBarry Smith 
262336db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
26246bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
26254c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
26263bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2627f0ec6fceSSatish Balay 
262894a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2629854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
26303bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
263194a9d846SBarry Smith   }
263263b91edcSBarry Smith 
2633f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2634137fb511SHong Zhang   if (row_identity && col_identity) {
2635ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2636137fb511SHong Zhang   } else {
2637719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2638137fb511SHong Zhang   }
26393a40ed3dSBarry Smith   PetscFunctionReturn(0);
2640a871dcd8SBarry Smith }
2641a871dcd8SBarry Smith 
2642f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2643f0b747eeSBarry Smith {
2644f0b747eeSBarry Smith   Mat_SeqAIJ     *a     = (Mat_SeqAIJ*)inA->data;
2645f4df32b1SMatthew Knepley   PetscScalar    oalpha = alpha;
2646efee365bSSatish Balay   PetscErrorCode ierr;
2647c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
26483a40ed3dSBarry Smith 
26493a40ed3dSBarry Smith   PetscFunctionBegin;
2650c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
26518b83055fSJed Brown   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&oalpha,a->a,&one));
2652efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2653acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
2654e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2655c70f7ee4SJunchao Zhang   if (inA->offloadmask != PETSC_OFFLOAD_UNALLOCATED) inA->offloadmask = PETSC_OFFLOAD_CPU;
2656e2cf4d64SStefano Zampini #endif
26573a40ed3dSBarry Smith   PetscFunctionReturn(0);
2658f0b747eeSBarry Smith }
2659f0b747eeSBarry Smith 
2660f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
266116b64355SHong Zhang {
266216b64355SHong Zhang   PetscErrorCode ierr;
266316b64355SHong Zhang   PetscInt       i;
266416b64355SHong Zhang 
266516b64355SHong Zhang   PetscFunctionBegin;
266616b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
266716b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
266816b64355SHong Zhang 
266916b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
267016b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
267116b64355SHong Zhang     }
267216b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
267316b64355SHong Zhang 
267416b64355SHong Zhang     if (submatj->rbuf1) {
267516b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
267616b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
267716b64355SHong Zhang     }
267816b64355SHong Zhang 
267916b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
268016b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
268116b64355SHong Zhang     }
268216b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
268316b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
268416b64355SHong Zhang   }
268516b64355SHong Zhang 
268616b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
268716b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
268816b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
268916b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
269016b64355SHong Zhang #else
269116b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
269216b64355SHong Zhang #endif
269316b64355SHong Zhang 
269416b64355SHong Zhang   if (!submatj->allcolumns) {
269516b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
269616b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
269716b64355SHong Zhang #else
269816b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
269916b64355SHong Zhang #endif
270016b64355SHong Zhang   }
270116b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
270216b64355SHong Zhang 
270316b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
270416b64355SHong Zhang   PetscFunctionReturn(0);
270516b64355SHong Zhang }
270616b64355SHong Zhang 
27070fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
270816b64355SHong Zhang {
270916b64355SHong Zhang   PetscErrorCode ierr;
271016b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
27115c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
271216b64355SHong Zhang 
271316b64355SHong Zhang   PetscFunctionBegin;
271434136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2715f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
271616b64355SHong Zhang   PetscFunctionReturn(0);
271716b64355SHong Zhang }
271816b64355SHong Zhang 
27192d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
27202d033e1fSHong Zhang {
27212d033e1fSHong Zhang   PetscErrorCode ierr;
27222d033e1fSHong Zhang   PetscInt       i;
27230fb991dcSHong Zhang   Mat            C;
27240fb991dcSHong Zhang   Mat_SeqAIJ     *c;
27250fb991dcSHong Zhang   Mat_SubSppt    *submatj;
27262d033e1fSHong Zhang 
27272d033e1fSHong Zhang   PetscFunctionBegin;
27282d033e1fSHong Zhang   for (i=0; i<n; i++) {
27290fb991dcSHong Zhang     C       = (*mat)[i];
27300fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
27310fb991dcSHong Zhang     submatj = c->submatis1;
27322d033e1fSHong Zhang     if (submatj) {
2733682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
273434136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2735f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
273634136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
27372d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
27382d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
27392d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2740682e4c99SStefano Zampini       }
27412d033e1fSHong Zhang     } else {
27422d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
27432d033e1fSHong Zhang     }
27442d033e1fSHong Zhang   }
274586e85357SHong Zhang 
274663a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
274763a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
274863a75b2aSHong Zhang 
27492d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
27502d033e1fSHong Zhang   PetscFunctionReturn(0);
27512d033e1fSHong Zhang }
27522d033e1fSHong Zhang 
27537dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2754cddf8d76SBarry Smith {
2755dfbe8321SBarry Smith   PetscErrorCode ierr;
275697f1f81fSBarry Smith   PetscInt       i;
2757cddf8d76SBarry Smith 
27583a40ed3dSBarry Smith   PetscFunctionBegin;
2759cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2760df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2761cddf8d76SBarry Smith   }
2762cddf8d76SBarry Smith 
2763cddf8d76SBarry Smith   for (i=0; i<n; i++) {
27647dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2765cddf8d76SBarry Smith   }
27663a40ed3dSBarry Smith   PetscFunctionReturn(0);
2767cddf8d76SBarry Smith }
2768cddf8d76SBarry Smith 
276997f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
27704dcbc457SBarry Smith {
2771e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
27726849ba73SBarry Smith   PetscErrorCode ierr;
27735d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
27745d0c19d7SBarry Smith   const PetscInt *idx;
277597f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2776f1af5d2fSBarry Smith   PetscBT        table;
2777bbd702dbSSatish Balay 
27783a40ed3dSBarry Smith   PetscFunctionBegin;
2779d0f46423SBarry Smith   m  = A->rmap->n;
2780e4d965acSSatish Balay   ai = a->i;
2781bfeeae90SHong Zhang   aj = a->j;
27828a047759SSatish Balay 
2783e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
278406763907SSatish Balay 
2785854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
278653b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
278706763907SSatish Balay 
2788e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2789b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2790e4d965acSSatish Balay     isz  = 0;
27916831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2792e4d965acSSatish Balay 
2793e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
27944dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2795b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2796e4d965acSSatish Balay 
2797dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2798e4d965acSSatish Balay     for (j=0; j<n; ++j) {
27992205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
28004dcbc457SBarry Smith     }
280106763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
28026bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2803e4d965acSSatish Balay 
280404a348a9SBarry Smith     k = 0;
280504a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
280604a348a9SBarry Smith       n = isz;
280706763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2808e4d965acSSatish Balay         row   = nidx[k];
2809e4d965acSSatish Balay         start = ai[row];
2810e4d965acSSatish Balay         end   = ai[row+1];
281104a348a9SBarry Smith         for (l = start; l<end; l++) {
2812efb16452SHong Zhang           val = aj[l];
28132205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2814e4d965acSSatish Balay         }
2815e4d965acSSatish Balay       }
2816e4d965acSSatish Balay     }
281770b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2818e4d965acSSatish Balay   }
281994bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2820606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
28213a40ed3dSBarry Smith   PetscFunctionReturn(0);
28224dcbc457SBarry Smith }
282317ab2063SBarry Smith 
28240513a670SBarry Smith /* -------------------------------------------------------------- */
2825dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
28260513a670SBarry Smith {
28270513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
28286849ba73SBarry Smith   PetscErrorCode ierr;
28293b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
28305d0c19d7SBarry Smith   const PetscInt *row,*col;
28315d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
283256cd22aeSBarry Smith   IS             icolp,irowp;
28330298fd71SBarry Smith   PetscInt       *cwork = NULL;
28340298fd71SBarry Smith   PetscScalar    *vwork = NULL;
28350513a670SBarry Smith 
28363a40ed3dSBarry Smith   PetscFunctionBegin;
28374c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
283856cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
28394c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
284056cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
28410513a670SBarry Smith 
28420513a670SBarry Smith   /* determine lengths of permuted rows */
2843854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
28442205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
2845ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
2846f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
284733d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
28487adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2849ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
2850606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
28510513a670SBarry Smith 
2852785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
28530513a670SBarry Smith   for (i=0; i<m; i++) {
285432ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
28552205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
2856cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
285732ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
28580513a670SBarry Smith   }
2859606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
28602205254eSKarl Rupp 
28613c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
28622205254eSKarl Rupp 
28639fe5e383SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
28649fe5e383SStefano Zampini   ierr = MatPinToCPU(*B,A->pinnedtocpu);CHKERRQ(ierr);
28659fe5e383SStefano Zampini #endif
28660513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
28670513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
286856cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
286956cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
28706bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
28716bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
2872*6768869dSprj-   if (rowp == colp) {
2873*6768869dSprj-     if (A->symmetric) {
2874*6768869dSprj-       ierr = MatSetOption(*B,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
2875*6768869dSprj-     }
2876*6768869dSprj-     if (A->hermitian) {
2877*6768869dSprj-       ierr = MatSetOption(*B,MAT_HERMITIAN,PETSC_TRUE);CHKERRQ(ierr);
2878*6768869dSprj-     }
2879*6768869dSprj-   }
28803a40ed3dSBarry Smith   PetscFunctionReturn(0);
28810513a670SBarry Smith }
28820513a670SBarry Smith 
2883dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2884cb5b572fSBarry Smith {
2885dfbe8321SBarry Smith   PetscErrorCode ierr;
2886cb5b572fSBarry Smith 
2887cb5b572fSBarry Smith   PetscFunctionBegin;
288833f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
288933f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2890be6bf707SBarry Smith     Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
2891be6bf707SBarry Smith     Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data;
2892be6bf707SBarry Smith 
2893700c5bfcSBarry Smith     if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different");
2894580bdb30SBarry Smith     ierr = PetscArraycpy(b->a,a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
2895cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
2896cb5b572fSBarry Smith   } else {
2897cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2898cb5b572fSBarry Smith   }
2899cb5b572fSBarry Smith   PetscFunctionReturn(0);
2900cb5b572fSBarry Smith }
2901cb5b572fSBarry Smith 
29024994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
2903273d9f13SBarry Smith {
2904dfbe8321SBarry Smith   PetscErrorCode ierr;
2905273d9f13SBarry Smith 
2906273d9f13SBarry Smith   PetscFunctionBegin;
2907ab93d7beSBarry Smith   ierr =  MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,0);CHKERRQ(ierr);
2908273d9f13SBarry Smith   PetscFunctionReturn(0);
2909273d9f13SBarry Smith }
2910273d9f13SBarry Smith 
2911f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
29126c0721eeSBarry Smith {
29136c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
29146e111a19SKarl Rupp 
29156c0721eeSBarry Smith   PetscFunctionBegin;
29166c0721eeSBarry Smith   *array = a->a;
29176c0721eeSBarry Smith   PetscFunctionReturn(0);
29186c0721eeSBarry Smith }
29196c0721eeSBarry Smith 
2920f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
29216c0721eeSBarry Smith {
29226c0721eeSBarry Smith   PetscFunctionBegin;
2923f38c1e66SStefano Zampini   *array = NULL;
29246c0721eeSBarry Smith   PetscFunctionReturn(0);
29256c0721eeSBarry Smith }
2926273d9f13SBarry Smith 
29278229c054SShri Abhyankar /*
29288229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
29298229c054SShri Abhyankar    have different nonzero structure.
29308229c054SShri Abhyankar */
2931b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
2932ec7775f6SShri Abhyankar {
2933b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
2934ec7775f6SShri Abhyankar 
2935ec7775f6SShri Abhyankar   PetscFunctionBegin;
2936ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
2937ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
2938b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
2939b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
2940b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
29418af7cee1SJed Brown     nnz[i] = 0;
29428af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
2943b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
2944b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
29458af7cee1SJed Brown       nnz[i]++;
29468af7cee1SJed Brown     }
29478af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
2948ec7775f6SShri Abhyankar   }
2949ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
2950ec7775f6SShri Abhyankar }
2951ec7775f6SShri Abhyankar 
2952b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
2953b264fe52SHong Zhang {
2954b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
2955b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
2956b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
2957b264fe52SHong Zhang   PetscErrorCode ierr;
2958b264fe52SHong Zhang 
2959b264fe52SHong Zhang   PetscFunctionBegin;
2960b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
2961b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
2962b264fe52SHong Zhang   PetscFunctionReturn(0);
2963b264fe52SHong Zhang }
2964b264fe52SHong Zhang 
2965f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
2966ac90fabeSBarry Smith {
2967dfbe8321SBarry Smith   PetscErrorCode ierr;
2968ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
2969c5df96a5SBarry Smith   PetscBLASInt   one=1,bnz;
2970ac90fabeSBarry Smith 
2971ac90fabeSBarry Smith   PetscFunctionBegin;
2972c5df96a5SBarry Smith   ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
2973ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
2974f4df32b1SMatthew Knepley     PetscScalar alpha = a;
29758b83055fSJed Brown     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one));
2976acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
2977a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
2978e2cf4d64SStefano Zampini     /* the MatAXPY_Basic* subroutines calls MatAssembly, so the matrix on the GPU
2979e2cf4d64SStefano Zampini        will be updated */
2980e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2981c70f7ee4SJunchao Zhang     if (Y->offloadmask != PETSC_OFFLOAD_UNALLOCATED) {
2982c70f7ee4SJunchao Zhang       Y->offloadmask = PETSC_OFFLOAD_CPU;
2983e2cf4d64SStefano Zampini     }
2984e2cf4d64SStefano Zampini #endif
2985ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
2986ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
2987ac90fabeSBarry Smith   } else {
29888229c054SShri Abhyankar     Mat      B;
29898229c054SShri Abhyankar     PetscInt *nnz;
2990785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
2991ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
2992bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
29934aa94f47SShri Abhyankar     ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr);
299433d57670SJed Brown     ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr);
2995176df525SBarry Smith     ierr = MatSetType(B,(MatType) ((PetscObject)Y)->type_name);CHKERRQ(ierr);
29968229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
2997ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
2998ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
299928be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
30008229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3001ac90fabeSBarry Smith   }
3002ac90fabeSBarry Smith   PetscFunctionReturn(0);
3003ac90fabeSBarry Smith }
3004ac90fabeSBarry Smith 
30057087cfbeSBarry Smith PetscErrorCode  MatConjugate_SeqAIJ(Mat mat)
3006354c94deSBarry Smith {
3007354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3008354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3009354c94deSBarry Smith   PetscInt    i,nz;
3010354c94deSBarry Smith   PetscScalar *a;
3011354c94deSBarry Smith 
3012354c94deSBarry Smith   PetscFunctionBegin;
3013354c94deSBarry Smith   nz = aij->nz;
3014354c94deSBarry Smith   a  = aij->a;
30152205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3016e2cf4d64SStefano Zampini #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
3017c70f7ee4SJunchao Zhang   if (mat->offloadmask != PETSC_OFFLOAD_UNALLOCATED) mat->offloadmask = PETSC_OFFLOAD_CPU;
3018e2cf4d64SStefano Zampini #endif
3019354c94deSBarry Smith #else
3020354c94deSBarry Smith   PetscFunctionBegin;
3021354c94deSBarry Smith #endif
3022354c94deSBarry Smith   PetscFunctionReturn(0);
3023354c94deSBarry Smith }
3024354c94deSBarry Smith 
3025985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3026e34fafa9SBarry Smith {
3027e34fafa9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3028e34fafa9SBarry Smith   PetscErrorCode ierr;
3029d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3030e34fafa9SBarry Smith   PetscReal      atmp;
3031985db425SBarry Smith   PetscScalar    *x;
3032e34fafa9SBarry Smith   MatScalar      *aa;
3033e34fafa9SBarry Smith 
3034e34fafa9SBarry Smith   PetscFunctionBegin;
3035e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3036e34fafa9SBarry Smith   aa = a->a;
3037e34fafa9SBarry Smith   ai = a->i;
3038e34fafa9SBarry Smith   aj = a->j;
3039e34fafa9SBarry Smith 
3040985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3041e34fafa9SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3042e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3043e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3044e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3045e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
30469189402eSHong Zhang     x[i]  = 0.0;
3047e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3048985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3049985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3050985db425SBarry Smith       aa++; aj++;
3051985db425SBarry Smith     }
3052985db425SBarry Smith   }
3053985db425SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3054985db425SBarry Smith   PetscFunctionReturn(0);
3055985db425SBarry Smith }
3056985db425SBarry Smith 
3057985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3058985db425SBarry Smith {
3059985db425SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3060985db425SBarry Smith   PetscErrorCode ierr;
3061d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3062985db425SBarry Smith   PetscScalar    *x;
3063985db425SBarry Smith   MatScalar      *aa;
3064985db425SBarry Smith 
3065985db425SBarry Smith   PetscFunctionBegin;
3066e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3067985db425SBarry Smith   aa = a->a;
3068985db425SBarry Smith   ai = a->i;
3069985db425SBarry Smith   aj = a->j;
3070985db425SBarry Smith 
3071985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3072985db425SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3073985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3074e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3075985db425SBarry Smith   for (i=0; i<m; i++) {
3076985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3077d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3078985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3079985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3080985db425SBarry Smith       x[i] = 0.0;
3081985db425SBarry Smith       if (idx) {
3082985db425SBarry Smith         idx[i] = 0; /* in case ncols is zero */
3083985db425SBarry Smith         for (j=0;j<ncols;j++) { /* find first implicit 0.0 in the row */
3084985db425SBarry Smith           if (aj[j] > j) {
3085985db425SBarry Smith             idx[i] = j;
3086985db425SBarry Smith             break;
3087985db425SBarry Smith           }
3088985db425SBarry Smith         }
3089985db425SBarry Smith       }
3090985db425SBarry Smith     }
3091985db425SBarry Smith     for (j=0; j<ncols; j++) {
3092985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3093985db425SBarry Smith       aa++; aj++;
3094985db425SBarry Smith     }
3095985db425SBarry Smith   }
3096985db425SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3097985db425SBarry Smith   PetscFunctionReturn(0);
3098985db425SBarry Smith }
3099985db425SBarry Smith 
3100c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3101c87e5d42SMatthew Knepley {
3102c87e5d42SMatthew Knepley   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3103c87e5d42SMatthew Knepley   PetscErrorCode ierr;
3104c87e5d42SMatthew Knepley   PetscInt       i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3105c87e5d42SMatthew Knepley   PetscReal      atmp;
3106c87e5d42SMatthew Knepley   PetscScalar    *x;
3107c87e5d42SMatthew Knepley   MatScalar      *aa;
3108c87e5d42SMatthew Knepley 
3109c87e5d42SMatthew Knepley   PetscFunctionBegin;
3110e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3111c87e5d42SMatthew Knepley   aa = a->a;
3112c87e5d42SMatthew Knepley   ai = a->i;
3113c87e5d42SMatthew Knepley   aj = a->j;
3114c87e5d42SMatthew Knepley 
3115c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3116c87e5d42SMatthew Knepley   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3117c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
311860e0710aSBarry Smith   if (n != A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", A->rmap->n, n);
3119c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3120c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3121289a08f5SMatthew Knepley     if (ncols) {
3122289a08f5SMatthew Knepley       /* Get first nonzero */
3123289a08f5SMatthew Knepley       for (j = 0; j < ncols; j++) {
3124289a08f5SMatthew Knepley         atmp = PetscAbsScalar(aa[j]);
31252205254eSKarl Rupp         if (atmp > 1.0e-12) {
31262205254eSKarl Rupp           x[i] = atmp;
31272205254eSKarl Rupp           if (idx) idx[i] = aj[j];
31282205254eSKarl Rupp           break;
31292205254eSKarl Rupp         }
3130289a08f5SMatthew Knepley       }
313112431cb0SMatthew G Knepley       if (j == ncols) {x[i] = PetscAbsScalar(*aa); if (idx) idx[i] = *aj;}
3132289a08f5SMatthew Knepley     } else {
3133289a08f5SMatthew Knepley       x[i] = 0.0; if (idx) idx[i] = 0;
3134289a08f5SMatthew Knepley     }
3135c87e5d42SMatthew Knepley     for (j = 0; j < ncols; j++) {
3136c87e5d42SMatthew Knepley       atmp = PetscAbsScalar(*aa);
3137289a08f5SMatthew Knepley       if (atmp > 1.0e-12 && PetscAbsScalar(x[i]) > atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3138c87e5d42SMatthew Knepley       aa++; aj++;
3139c87e5d42SMatthew Knepley     }
3140c87e5d42SMatthew Knepley   }
3141c87e5d42SMatthew Knepley   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3142c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3143c87e5d42SMatthew Knepley }
3144c87e5d42SMatthew Knepley 
3145985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3146985db425SBarry Smith {
3147985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3148985db425SBarry Smith   PetscErrorCode  ierr;
3149d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3150d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3151985db425SBarry Smith   PetscScalar     *x;
3152d9ca1df4SBarry Smith   const MatScalar *aa;
3153985db425SBarry Smith 
3154985db425SBarry Smith   PetscFunctionBegin;
3155e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3156985db425SBarry Smith   aa = a->a;
3157985db425SBarry Smith   ai = a->i;
3158985db425SBarry Smith   aj = a->j;
3159985db425SBarry Smith 
3160985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3161985db425SBarry Smith   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
3162985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3163e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3164985db425SBarry Smith   for (i=0; i<m; i++) {
3165985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3166d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3167985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3168985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3169985db425SBarry Smith       x[i] = 0.0;
3170985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3171985db425SBarry Smith         idx[i] = 0; /* in case ncols is zero */
3172985db425SBarry Smith         for (j=0; j<ncols; j++) {
3173985db425SBarry Smith           if (aj[j] > j) {
3174985db425SBarry Smith             idx[i] = j;
3175985db425SBarry Smith             break;
3176985db425SBarry Smith           }
3177985db425SBarry Smith         }
3178985db425SBarry Smith       }
3179985db425SBarry Smith     }
3180985db425SBarry Smith     for (j=0; j<ncols; j++) {
3181985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3182985db425SBarry Smith       aa++; aj++;
3183e34fafa9SBarry Smith     }
3184e34fafa9SBarry Smith   }
3185e34fafa9SBarry Smith   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
3186e34fafa9SBarry Smith   PetscFunctionReturn(0);
3187e34fafa9SBarry Smith }
3188bbead8a2SBarry Smith 
3189713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3190bbead8a2SBarry Smith {
3191bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3192bbead8a2SBarry Smith   PetscErrorCode  ierr;
319333d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3194bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
31950da83c2eSBarry Smith   const PetscReal shift = 0.0;
31961a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3197bbead8a2SBarry Smith 
3198bbead8a2SBarry Smith   PetscFunctionBegin;
3199a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
32004a0d0026SBarry Smith   if (a->ibdiagvalid) {
32014a0d0026SBarry Smith     if (values) *values = a->ibdiag;
32024a0d0026SBarry Smith     PetscFunctionReturn(0);
32034a0d0026SBarry Smith   }
3204bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3205bbead8a2SBarry Smith   if (!a->ibdiag) {
3206785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
32073bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3208bbead8a2SBarry Smith   }
3209bbead8a2SBarry Smith   diag = a->ibdiag;
3210bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3211bbead8a2SBarry Smith   /* factor and invert each block */
3212bbead8a2SBarry Smith   switch (bs) {
3213bbead8a2SBarry Smith   case 1:
3214bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3215bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3216ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3217ec1892c8SHong Zhang         if (allowzeropivot) {
32187b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
32197b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
32207b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
32217b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
32227b6c816cSBarry 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);
3223ec1892c8SHong Zhang       }
3224bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3225bbead8a2SBarry Smith     }
3226bbead8a2SBarry Smith     break;
3227bbead8a2SBarry Smith   case 2:
3228bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3229bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3230bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3231a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32327b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
323396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3234bbead8a2SBarry Smith       diag += 4;
3235bbead8a2SBarry Smith     }
3236bbead8a2SBarry Smith     break;
3237bbead8a2SBarry Smith   case 3:
3238bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3239bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3240bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3241a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32427b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
324396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3244bbead8a2SBarry Smith       diag += 9;
3245bbead8a2SBarry Smith     }
3246bbead8a2SBarry Smith     break;
3247bbead8a2SBarry Smith   case 4:
3248bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3249bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3250bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3251a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32527b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
325396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3254bbead8a2SBarry Smith       diag += 16;
3255bbead8a2SBarry Smith     }
3256bbead8a2SBarry Smith     break;
3257bbead8a2SBarry Smith   case 5:
3258bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3259bbead8a2SBarry 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;
3260bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3261a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32627b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
326396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3264bbead8a2SBarry Smith       diag += 25;
3265bbead8a2SBarry Smith     }
3266bbead8a2SBarry Smith     break;
3267bbead8a2SBarry Smith   case 6:
3268bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3269bbead8a2SBarry 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;
3270bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3271a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32727b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
327396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3274bbead8a2SBarry Smith       diag += 36;
3275bbead8a2SBarry Smith     }
3276bbead8a2SBarry Smith     break;
3277bbead8a2SBarry Smith   case 7:
3278bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3279bbead8a2SBarry 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;
3280bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3281a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32827b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
328396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3284bbead8a2SBarry Smith       diag += 49;
3285bbead8a2SBarry Smith     }
3286bbead8a2SBarry Smith     break;
3287bbead8a2SBarry Smith   default:
3288dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3289bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3290bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3291bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3292bbead8a2SBarry Smith       }
3293bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
32945f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
32957b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
329696b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3297bbead8a2SBarry Smith       diag += bs2;
3298bbead8a2SBarry Smith     }
3299bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3300bbead8a2SBarry Smith   }
3301bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3302bbead8a2SBarry Smith   PetscFunctionReturn(0);
3303bbead8a2SBarry Smith }
3304bbead8a2SBarry Smith 
330573a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
330673a71a0fSBarry Smith {
330773a71a0fSBarry Smith   PetscErrorCode ierr;
330873a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
330973a71a0fSBarry Smith   PetscScalar    a;
331073a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
331173a71a0fSBarry Smith 
331273a71a0fSBarry Smith   PetscFunctionBegin;
331373a71a0fSBarry Smith   if (!x->assembled) {
331473a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
331573a71a0fSBarry Smith     for (i=0; i<m; i++) {
331673a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
331773a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
331873a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
331973a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
332073a71a0fSBarry Smith       }
332173a71a0fSBarry Smith     }
3322e2ce353bSJunchao Zhang   } else {
3323e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3324e2ce353bSJunchao Zhang   }
332573a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
332673a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
332773a71a0fSBarry Smith   PetscFunctionReturn(0);
332873a71a0fSBarry Smith }
332973a71a0fSBarry Smith 
3330679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3331679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3332679944adSJunchao Zhang {
3333679944adSJunchao Zhang   PetscErrorCode ierr;
3334679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3335679944adSJunchao Zhang   PetscScalar    a;
3336679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3337679944adSJunchao Zhang 
3338679944adSJunchao Zhang   PetscFunctionBegin;
3339679944adSJunchao Zhang   nskip = high - low;
3340679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3341679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3342679944adSJunchao Zhang   for (i=0; i<m; i++) {
3343679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3344679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3345679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3346679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3347679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3348679944adSJunchao Zhang     }
3349e2ce353bSJunchao Zhang   }
3350679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3351679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3352679944adSJunchao Zhang   PetscFunctionReturn(0);
3353679944adSJunchao Zhang }
3354679944adSJunchao Zhang 
3355679944adSJunchao Zhang 
3356682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
33570a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3358cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3359cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3360cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
336197304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
33627c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
33637c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3364db4efbfdSBarry Smith                                         0,
3365db4efbfdSBarry Smith                                         0,
3366db4efbfdSBarry Smith                                         0,
3367db4efbfdSBarry Smith                                 /* 10*/ 0,
3368cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3369cb5b572fSBarry Smith                                         0,
337041f059aeSBarry Smith                                         MatSOR_SeqAIJ,
337191e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
337297304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3373cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3374cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3375cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3376cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
337797304618SKris Buschelman                                 /* 20*/ 0,
3378cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3379cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3380cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3381d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3382db4efbfdSBarry Smith                                         0,
3383db4efbfdSBarry Smith                                         0,
3384db4efbfdSBarry Smith                                         0,
3385db4efbfdSBarry Smith                                         0,
33864994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3387db4efbfdSBarry Smith                                         0,
3388db4efbfdSBarry Smith                                         0,
33898c778c55SBarry Smith                                         0,
33908c778c55SBarry Smith                                         0,
3391d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3392cb5b572fSBarry Smith                                         0,
3393cb5b572fSBarry Smith                                         0,
3394cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3395cb5b572fSBarry Smith                                         0,
3396d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
33977dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3398cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3399cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3400cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3401d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3402cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
34037d68702bSBarry Smith                                         MatShift_SeqAIJ,
340479299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
34056e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
340673a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
34073b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
34083b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
34093b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3410a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
341193dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3412b9617806SBarry Smith                                         0,
34130513a670SBarry Smith                                         0,
3414cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3415cda55fadSBarry Smith                                         0,
3416d519adbfSMatthew Knepley                                 /* 59*/ 0,
3417b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3418b9b97703SBarry Smith                                         MatView_SeqAIJ,
3419357abbc8SBarry Smith                                         0,
3420321b30b9SSatish Balay                                         MatMatMatMult_SeqAIJ_SeqAIJ_SeqAIJ,
3421321b30b9SSatish Balay                                 /* 64*/ MatMatMatMultSymbolic_SeqAIJ_SeqAIJ_SeqAIJ,
3422321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3423ee4f033dSBarry Smith                                         0,
3424ee4f033dSBarry Smith                                         0,
3425ee4f033dSBarry Smith                                         0,
3426d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3427c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3428ee4f033dSBarry Smith                                         0,
3429dcf5cc72SBarry Smith                                         0,
34302c93a97aSBarry Smith                                         0,
34312c93a97aSBarry Smith                                 /* 74*/ 0,
34323acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
343397304618SKris Buschelman                                         0,
343497304618SKris Buschelman                                         0,
343597304618SKris Buschelman                                         0,
34366ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
343797304618SKris Buschelman                                         0,
343897304618SKris Buschelman                                         0,
343997304618SKris Buschelman                                         0,
3440bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3441d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
34421cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
34436284ec50SHong Zhang                                         0,
34446284ec50SHong Zhang                                         0,
3445bc011b1eSHong Zhang                                         0,
3446d519adbfSMatthew Knepley                                 /* 89*/ MatMatMult_SeqAIJ_SeqAIJ,
344726be0446SHong Zhang                                         MatMatMultSymbolic_SeqAIJ_SeqAIJ,
344826be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
344965e8a0caSHong Zhang                                         MatPtAP_SeqAIJ_SeqAIJ,
34508fa4b5a6SHong Zhang                                         MatPtAPSymbolic_SeqAIJ_SeqAIJ_SparseAxpy,
34518fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
34526fc122caSHong Zhang                                         MatMatTransposeMult_SeqAIJ_SeqAIJ,
34536fc122caSHong Zhang                                         MatMatTransposeMultSymbolic_SeqAIJ_SeqAIJ,
34546fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
34552121bac1SHong Zhang                                         0,
34562121bac1SHong Zhang                                 /* 99*/ 0,
3457609c6c4dSKris Buschelman                                         0,
3458609c6c4dSKris Buschelman                                         0,
345987d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
346087d4246cSBarry Smith                                         0,
3461d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
346299cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3463f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3464f5edf698SHong Zhang                                         0,
34652bebee5dSHong Zhang                                         0,
3466cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3467985db425SBarry Smith                                         0,
34682af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
34692af78befSBarry Smith                                         0,
3470599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3471d519adbfSMatthew Knepley                                 /*114*/ 0,
3472599ef60dSHong Zhang                                         0,
34733c2a7987SHong Zhang                                         0,
3474fe97e370SBarry Smith                                         0,
3475fbdbba38SShri Abhyankar                                         0,
3476fbdbba38SShri Abhyankar                                 /*119*/ 0,
3477fbdbba38SShri Abhyankar                                         0,
3478fbdbba38SShri Abhyankar                                         0,
347982d44351SHong Zhang                                         0,
3480b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
34810716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3482bbead8a2SBarry Smith                                         MatGetColumnNorms_SeqAIJ,
348337868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
34840da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
348537868618SMatthew G Knepley                                         0,
34865df89d91SHong Zhang                                 /*129*/ 0,
348775648e8dSHong Zhang                                         MatTransposeMatMult_SeqAIJ_SeqAIJ,
348875648e8dSHong Zhang                                         MatTransposeMatMultSymbolic_SeqAIJ_SeqAIJ,
348975648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3490b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3491b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
34922b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
34932b8ad9a3SHong Zhang                                         MatRARt_SeqAIJ_SeqAIJ,
34942b8ad9a3SHong Zhang                                         MatRARtSymbolic_SeqAIJ_SeqAIJ,
34953964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
34963964eb88SJed Brown                                  /*139*/0,
3497f9426fe0SMark Adams                                         0,
34981919a2e2SJed Brown                                         0,
34993a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
35009c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
35012d033e1fSHong Zhang                                  /*144*/MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
35022d033e1fSHong Zhang                                         MatDestroySubMatrices_SeqAIJ
35039e29f15eSvictorle };
350417ab2063SBarry Smith 
35057087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3506bef8e0ddSBarry Smith {
3507bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
350897f1f81fSBarry Smith   PetscInt   i,nz,n;
3509bef8e0ddSBarry Smith 
3510bef8e0ddSBarry Smith   PetscFunctionBegin;
3511bef8e0ddSBarry Smith   nz = aij->maxnz;
3512d0f46423SBarry Smith   n  = mat->rmap->n;
3513bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3514bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3515bef8e0ddSBarry Smith   }
3516bef8e0ddSBarry Smith   aij->nz = nz;
3517bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3518bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3519bef8e0ddSBarry Smith   }
3520bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3521bef8e0ddSBarry Smith }
3522bef8e0ddSBarry Smith 
3523a3bb6f32SFande Kong /*
3524e8b528d9SFande Kong  * When a sparse matrix has many zero columns, we should compact them out to save the space
3525a3bb6f32SFande Kong  * This happens in MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3526a3bb6f32SFande Kong  * */
3527a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3528a3bb6f32SFande Kong {
3529a3bb6f32SFande Kong   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
3530a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3531a3bb6f32SFande Kong   PetscTablePosition tpos;
3532a3bb6f32SFande Kong   PetscInt           gid,lid,i,j,ncols,ec;
3533a3bb6f32SFande Kong   PetscInt           *garray;
3534a3bb6f32SFande Kong   PetscErrorCode  ierr;
3535a3bb6f32SFande Kong 
3536a3bb6f32SFande Kong   PetscFunctionBegin;
3537a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3538a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3539a3bb6f32SFande Kong   /* use a table */
3540a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3541a3bb6f32SFande Kong   ec = 0;
3542a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3543a3bb6f32SFande Kong     ncols = aij->i[i+1] - aij->i[i];
3544a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3545a3bb6f32SFande Kong       PetscInt data,gid1 = aij->j[aij->i[i] + j] + 1;
3546a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3547a3bb6f32SFande Kong       if (!data) {
3548a3bb6f32SFande Kong         /* one based table */
3549a3bb6f32SFande Kong         ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3550a3bb6f32SFande Kong       }
3551a3bb6f32SFande Kong     }
3552a3bb6f32SFande Kong   }
3553a3bb6f32SFande Kong   /* form array of columns we need */
3554a3bb6f32SFande Kong   ierr = PetscMalloc1(ec+1,&garray);CHKERRQ(ierr);
3555a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3556a3bb6f32SFande Kong   while (tpos) {
3557a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3558a3bb6f32SFande Kong     gid--;
3559a3bb6f32SFande Kong     lid--;
3560a3bb6f32SFande Kong     garray[lid] = gid;
3561a3bb6f32SFande Kong   }
3562a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3563a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3564a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3565a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3566a3bb6f32SFande Kong   }
3567a3bb6f32SFande Kong   /* compact out the extra columns in B */
3568a3bb6f32SFande Kong   for (i=0; i<mat->rmap->n; i++) {
3569a3bb6f32SFande Kong 	ncols = aij->i[i+1] - aij->i[i];
3570a3bb6f32SFande Kong     for (j=0; j<ncols; j++) {
3571a3bb6f32SFande Kong       PetscInt gid1 = aij->j[aij->i[i] + j] + 1;
3572a3bb6f32SFande Kong       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3573a3bb6f32SFande Kong       lid--;
3574a3bb6f32SFande Kong       aij->j[aij->i[i] + j] = lid;
3575a3bb6f32SFande Kong     }
3576a3bb6f32SFande Kong   }
3577ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3578ca5434daSLawrence Mitchell   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3579a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
3580a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3581a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3582a3bb6f32SFande Kong   PetscFunctionReturn(0);
3583a3bb6f32SFande Kong }
3584a3bb6f32SFande Kong 
3585bef8e0ddSBarry Smith /*@
3586bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3587bef8e0ddSBarry Smith        in the matrix.
3588bef8e0ddSBarry Smith 
3589bef8e0ddSBarry Smith   Input Parameters:
3590bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3591bef8e0ddSBarry Smith -  indices - the column indices
3592bef8e0ddSBarry Smith 
359315091d37SBarry Smith   Level: advanced
359415091d37SBarry Smith 
3595bef8e0ddSBarry Smith   Notes:
3596bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3597bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3598bef8e0ddSBarry Smith   of the MatSetValues() operation.
3599bef8e0ddSBarry Smith 
3600bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3601d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3602bef8e0ddSBarry Smith 
3603bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3604bef8e0ddSBarry Smith 
3605b9617806SBarry Smith     The indices should start with zero, not one.
3606b9617806SBarry Smith 
3607bef8e0ddSBarry Smith @*/
36087087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3609bef8e0ddSBarry Smith {
36104ac538c5SBarry Smith   PetscErrorCode ierr;
3611bef8e0ddSBarry Smith 
3612bef8e0ddSBarry Smith   PetscFunctionBegin;
36130700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
36144482741eSBarry Smith   PetscValidPointer(indices,2);
36154ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3616bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3617bef8e0ddSBarry Smith }
3618bef8e0ddSBarry Smith 
3619be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3620be6bf707SBarry Smith 
36217087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3622be6bf707SBarry Smith {
3623be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
36246849ba73SBarry Smith   PetscErrorCode ierr;
3625d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3626be6bf707SBarry Smith 
3627be6bf707SBarry Smith   PetscFunctionBegin;
3628169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3629be6bf707SBarry Smith 
3630be6bf707SBarry Smith   /* allocate space for values if not already there */
3631be6bf707SBarry Smith   if (!aij->saved_values) {
3632854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
36333bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3634be6bf707SBarry Smith   }
3635be6bf707SBarry Smith 
3636be6bf707SBarry Smith   /* copy values over */
3637580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3638be6bf707SBarry Smith   PetscFunctionReturn(0);
3639be6bf707SBarry Smith }
3640be6bf707SBarry Smith 
3641be6bf707SBarry Smith /*@
3642be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3643be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3644be6bf707SBarry Smith        nonlinear portion.
3645be6bf707SBarry Smith 
3646be6bf707SBarry Smith    Collect on Mat
3647be6bf707SBarry Smith 
3648be6bf707SBarry Smith   Input Parameters:
36490e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3650be6bf707SBarry Smith 
365115091d37SBarry Smith   Level: advanced
365215091d37SBarry Smith 
3653be6bf707SBarry Smith   Common Usage, with SNESSolve():
3654be6bf707SBarry Smith $    Create Jacobian matrix
3655be6bf707SBarry Smith $    Set linear terms into matrix
3656be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3657be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3658be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3659512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3660be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3661be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3662be6bf707SBarry Smith $    In your Jacobian routine
3663be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3664be6bf707SBarry Smith $      Set nonlinear terms in matrix
3665be6bf707SBarry Smith 
3666be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3667be6bf707SBarry Smith $    // build linear portion of Jacobian
3668512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3669be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3670be6bf707SBarry Smith $    loop over nonlinear iterations
3671be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3672be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3673be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3674be6bf707SBarry Smith $       Solve linear system with Jacobian
3675be6bf707SBarry Smith $    endloop
3676be6bf707SBarry Smith 
3677be6bf707SBarry Smith   Notes:
3678be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3679512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3680be6bf707SBarry Smith     calling this routine.
3681be6bf707SBarry Smith 
36820c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
36830c468ba9SBarry Smith     and does not allocated additional space.
36840c468ba9SBarry Smith 
3685be6bf707SBarry Smith .seealso: MatRetrieveValues()
3686be6bf707SBarry Smith 
3687be6bf707SBarry Smith @*/
36887087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3689be6bf707SBarry Smith {
36904ac538c5SBarry Smith   PetscErrorCode ierr;
3691be6bf707SBarry Smith 
3692be6bf707SBarry Smith   PetscFunctionBegin;
36930700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3694e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3695e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
36964ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3697be6bf707SBarry Smith   PetscFunctionReturn(0);
3698be6bf707SBarry Smith }
3699be6bf707SBarry Smith 
37007087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3701be6bf707SBarry Smith {
3702be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
37036849ba73SBarry Smith   PetscErrorCode ierr;
3704d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3705be6bf707SBarry Smith 
3706be6bf707SBarry Smith   PetscFunctionBegin;
3707169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3708f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3709be6bf707SBarry Smith   /* copy values over */
3710580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3711be6bf707SBarry Smith   PetscFunctionReturn(0);
3712be6bf707SBarry Smith }
3713be6bf707SBarry Smith 
3714be6bf707SBarry Smith /*@
3715be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3716be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3717be6bf707SBarry Smith        nonlinear portion.
3718be6bf707SBarry Smith 
3719be6bf707SBarry Smith    Collect on Mat
3720be6bf707SBarry Smith 
3721be6bf707SBarry Smith   Input Parameters:
3722386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3723be6bf707SBarry Smith 
372415091d37SBarry Smith   Level: advanced
372515091d37SBarry Smith 
3726be6bf707SBarry Smith .seealso: MatStoreValues()
3727be6bf707SBarry Smith 
3728be6bf707SBarry Smith @*/
37297087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3730be6bf707SBarry Smith {
37314ac538c5SBarry Smith   PetscErrorCode ierr;
3732be6bf707SBarry Smith 
3733be6bf707SBarry Smith   PetscFunctionBegin;
37340700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3735e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3736e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
37374ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3738be6bf707SBarry Smith   PetscFunctionReturn(0);
3739be6bf707SBarry Smith }
3740be6bf707SBarry Smith 
3741f83d6046SBarry Smith 
3742be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
374317ab2063SBarry Smith /*@C
3744682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
37450d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
37466e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
374751c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
37482bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
374917ab2063SBarry Smith 
3750d083f849SBarry Smith    Collective
3751db81eaa0SLois Curfman McInnes 
375217ab2063SBarry Smith    Input Parameters:
3753db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
375417ab2063SBarry Smith .  m - number of rows
375517ab2063SBarry Smith .  n - number of columns
375617ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
375751c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
37580298fd71SBarry Smith          (possibly different for each row) or NULL
375917ab2063SBarry Smith 
376017ab2063SBarry Smith    Output Parameter:
3761416022c9SBarry Smith .  A - the matrix
376217ab2063SBarry Smith 
3763175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3764f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3765175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3766175b88e8SBarry Smith 
3767b259b22eSLois Curfman McInnes    Notes:
376849a6f317SBarry Smith    If nnz is given then nz is ignored
376949a6f317SBarry Smith 
377017ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
377117ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
37720002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
377344cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
377417ab2063SBarry Smith 
377517ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
37760298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
37773d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
37786da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
377917ab2063SBarry Smith 
3780682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
37814fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3782682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
37836c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
37846c7ebb05SLois Curfman McInnes 
37856c7ebb05SLois Curfman McInnes    Options Database Keys:
3786698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
37879db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
378817ab2063SBarry Smith 
3789027ccd11SLois Curfman McInnes    Level: intermediate
3790027ccd11SLois Curfman McInnes 
379169b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
379236db0b34SBarry Smith 
379317ab2063SBarry Smith @*/
37947087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
379517ab2063SBarry Smith {
3796dfbe8321SBarry Smith   PetscErrorCode ierr;
37976945ee14SBarry Smith 
37983a40ed3dSBarry Smith   PetscFunctionBegin;
3799f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3800117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3801c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3802d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3803273d9f13SBarry Smith   PetscFunctionReturn(0);
3804273d9f13SBarry Smith }
3805273d9f13SBarry Smith 
3806273d9f13SBarry Smith /*@C
3807273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3808273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3809273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3810273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3811273d9f13SBarry Smith 
3812d083f849SBarry Smith    Collective
3813273d9f13SBarry Smith 
3814273d9f13SBarry Smith    Input Parameters:
38151c4f3114SJed Brown +  B - The matrix
3816273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3817273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
38180298fd71SBarry Smith          (possibly different for each row) or NULL
3819273d9f13SBarry Smith 
3820273d9f13SBarry Smith    Notes:
382149a6f317SBarry Smith      If nnz is given then nz is ignored
382249a6f317SBarry Smith 
3823273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3824273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3825273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3826273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3827273d9f13SBarry Smith 
3828273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
38290298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3830273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3831273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3832273d9f13SBarry Smith 
3833aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3834aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3835aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3836aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3837aa95bbe8SBarry Smith 
3838a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3839a96a251dSBarry Smith    entries or columns indices
3840a96a251dSBarry Smith 
3841273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3842273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3843273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3844273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3845273d9f13SBarry Smith 
3846273d9f13SBarry Smith    Options Database Keys:
3847698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
384847b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3849273d9f13SBarry Smith 
3850273d9f13SBarry Smith    Level: intermediate
3851273d9f13SBarry Smith 
385269b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo()
3853273d9f13SBarry Smith 
3854273d9f13SBarry Smith @*/
38557087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3856273d9f13SBarry Smith {
38574ac538c5SBarry Smith   PetscErrorCode ierr;
3858a23d5eceSKris Buschelman 
3859a23d5eceSKris Buschelman   PetscFunctionBegin;
38606ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
38616ba663aaSJed Brown   PetscValidType(B,1);
38624ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
3863a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3864a23d5eceSKris Buschelman }
3865a23d5eceSKris Buschelman 
38667087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3867a23d5eceSKris Buschelman {
3868273d9f13SBarry Smith   Mat_SeqAIJ     *b;
38692576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
38706849ba73SBarry Smith   PetscErrorCode ierr;
387197f1f81fSBarry Smith   PetscInt       i;
3872273d9f13SBarry Smith 
3873273d9f13SBarry Smith   PetscFunctionBegin;
38742576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3875a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
3876c461c341SBarry Smith     skipallocation = PETSC_TRUE;
3877c461c341SBarry Smith     nz             = 0;
3878c461c341SBarry Smith   }
387926283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
388026283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3881899cda47SBarry Smith 
3882435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
388360e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
3884071fcb05SBarry Smith #if defined(PETSC_USE_DEBUG)
3885b73539f3SBarry Smith   if (nnz) {
3886d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
388760e0710aSBarry 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]);
388860e0710aSBarry 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);
3889b73539f3SBarry Smith     }
3890b73539f3SBarry Smith   }
3891071fcb05SBarry Smith #endif
3892b73539f3SBarry Smith 
3893273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
38942205254eSKarl Rupp 
3895273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
3896273d9f13SBarry Smith 
3897ab93d7beSBarry Smith   if (!skipallocation) {
38982ee49352SLisandro Dalcin     if (!b->imax) {
3899071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
3900071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3901071fcb05SBarry Smith     }
3902071fcb05SBarry Smith     if (!b->ilen) {
3903071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
3904071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
3905071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3906071fcb05SBarry Smith     } else {
3907071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
39082ee49352SLisandro Dalcin     }
3909846b4da1SFande Kong     if (!b->ipre) {
3910846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
3911846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
3912846b4da1SFande Kong     }
3913273d9f13SBarry Smith     if (!nnz) {
3914435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
3915c62bd62aSJed Brown       else if (nz < 0) nz = 1;
39165d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
3917d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
3918d0f46423SBarry Smith       nz = nz*B->rmap->n;
3919273d9f13SBarry Smith     } else {
3920c73702f5SBarry Smith       PetscInt64 nz64 = 0;
3921c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
3922c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
3923273d9f13SBarry Smith     }
3924ab93d7beSBarry Smith 
3925273d9f13SBarry Smith     /* allocate the matrix space */
392653dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
39272ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
3928396832f4SHong Zhang     if (B->structure_only) {
39295848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
39305848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
3931396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
3932396832f4SHong Zhang     } else {
3933dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
39343bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
3935396832f4SHong Zhang     }
3936bfeeae90SHong Zhang     b->i[0] = 0;
3937d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
39385da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
39395da197adSKris Buschelman     }
3940396832f4SHong Zhang     if (B->structure_only) {
3941396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
3942396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
3943396832f4SHong Zhang     } else {
3944273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
3945e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
3946396832f4SHong Zhang     }
3947e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
3948c461c341SBarry Smith   } else {
3949e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
3950e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
3951c461c341SBarry Smith   }
3952273d9f13SBarry Smith 
3953846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
3954846b4da1SFande Kong     /* reserve user-requested sparsity */
3955580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
3956846b4da1SFande Kong   }
3957846b4da1SFande Kong 
3958846b4da1SFande Kong 
3959273d9f13SBarry Smith   b->nz               = 0;
3960273d9f13SBarry Smith   b->maxnz            = nz;
3961273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
39622205254eSKarl Rupp   if (realalloc) {
39632205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
39642205254eSKarl Rupp   }
3965cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
3966cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
3967273d9f13SBarry Smith   PetscFunctionReturn(0);
3968273d9f13SBarry Smith }
3969273d9f13SBarry Smith 
3970846b4da1SFande Kong 
3971846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
3972846b4da1SFande Kong {
3973846b4da1SFande Kong   Mat_SeqAIJ     *a;
3974a5bbaf83SFande Kong   PetscInt       i;
3975846b4da1SFande Kong   PetscErrorCode ierr;
3976846b4da1SFande Kong 
3977846b4da1SFande Kong   PetscFunctionBegin;
3978846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
397914d0e64fSAlex Lindsay 
398014d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
398114d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
398214d0e64fSAlex Lindsay 
3983846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
39842c814fdeSFande Kong   /* if no saved info, we error out */
3985fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
39862c814fdeSFande Kong 
3987fb4dc15dSAlex 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");
39882c814fdeSFande Kong 
3989580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
3990580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
3991846b4da1SFande Kong   a->i[0] = 0;
3992846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
3993846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
3994846b4da1SFande Kong   }
3995846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
3996846b4da1SFande Kong   a->nz               = 0;
3997846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
3998846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
3999846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4000846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4001846b4da1SFande Kong   PetscFunctionReturn(0);
4002846b4da1SFande Kong }
4003846b4da1SFande Kong 
400458d36128SBarry Smith /*@
4005a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4006a1661176SMatthew Knepley 
4007a1661176SMatthew Knepley    Input Parameters:
4008a1661176SMatthew Knepley +  B - the matrix
4009a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4010a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4011a1661176SMatthew Knepley -  v - optional values in the matrix
4012a1661176SMatthew Knepley 
4013a1661176SMatthew Knepley    Level: developer
4014a1661176SMatthew Knepley 
401558d36128SBarry Smith    The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
401658d36128SBarry Smith 
4017c1c1d628SHong Zhang .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ
4018a1661176SMatthew Knepley @*/
4019a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4020a1661176SMatthew Knepley {
4021a1661176SMatthew Knepley   PetscErrorCode ierr;
4022a1661176SMatthew Knepley 
4023a1661176SMatthew Knepley   PetscFunctionBegin;
40240700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40256ba663aaSJed Brown   PetscValidType(B,1);
40264ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4027a1661176SMatthew Knepley   PetscFunctionReturn(0);
4028a1661176SMatthew Knepley }
4029a1661176SMatthew Knepley 
40307087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4031a1661176SMatthew Knepley {
4032a1661176SMatthew Knepley   PetscInt       i;
4033a1661176SMatthew Knepley   PetscInt       m,n;
4034a1661176SMatthew Knepley   PetscInt       nz;
4035a1661176SMatthew Knepley   PetscInt       *nnz, nz_max = 0;
4036a1661176SMatthew Knepley   PetscErrorCode ierr;
4037a1661176SMatthew Knepley 
4038a1661176SMatthew Knepley   PetscFunctionBegin;
403965e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4040779a8d59SSatish Balay 
4041779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4042779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4043779a8d59SSatish Balay 
4044779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4045854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4046a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4047b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
4048a1661176SMatthew Knepley     nz_max = PetscMax(nz_max, nz);
404965e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4050a1661176SMatthew Knepley     nnz[i] = nz;
4051a1661176SMatthew Knepley   }
4052a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4053a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4054a1661176SMatthew Knepley 
4055a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4056071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4057a1661176SMatthew Knepley   }
4058a1661176SMatthew Knepley 
4059a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4060a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4061a1661176SMatthew Knepley 
40627827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4063a1661176SMatthew Knepley   PetscFunctionReturn(0);
4064a1661176SMatthew Knepley }
4065a1661176SMatthew Knepley 
4066c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4067af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4068170fe5c8SBarry Smith 
4069170fe5c8SBarry Smith /*
4070170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4071170fe5c8SBarry Smith 
4072170fe5c8SBarry Smith                n                       p                          p
4073170fe5c8SBarry Smith         (              )       (              )         (                  )
4074170fe5c8SBarry Smith       m (      A       )  *  n (       B      )   =   m (         C        )
4075170fe5c8SBarry Smith         (              )       (              )         (                  )
4076170fe5c8SBarry Smith 
4077170fe5c8SBarry Smith */
4078170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4079170fe5c8SBarry Smith {
4080170fe5c8SBarry Smith   PetscErrorCode    ierr;
4081170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4082170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4083170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
40841de00fd4SBarry Smith   PetscInt          i,n,m,q,p;
4085170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4086170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4087170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
4088170fe5c8SBarry Smith 
4089170fe5c8SBarry Smith   PetscFunctionBegin;
4090d0f46423SBarry Smith   m    = A->rmap->n;
4091d0f46423SBarry Smith   n    = A->cmap->n;
4092d0f46423SBarry Smith   p    = B->cmap->n;
4093170fe5c8SBarry Smith   a    = sub_a->v;
4094170fe5c8SBarry Smith   b    = sub_b->a;
4095170fe5c8SBarry Smith   c    = sub_c->v;
4096580bdb30SBarry Smith   ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
4097170fe5c8SBarry Smith 
4098170fe5c8SBarry Smith   ii  = sub_b->i;
4099170fe5c8SBarry Smith   idx = sub_b->j;
4100170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4101170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4102170fe5c8SBarry Smith     while (q-->0) {
4103170fe5c8SBarry Smith       c_q = c + m*(*idx);
4104170fe5c8SBarry Smith       a_q = a + m*i;
4105854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4106170fe5c8SBarry Smith       idx++;
4107170fe5c8SBarry Smith       b++;
4108170fe5c8SBarry Smith     }
4109170fe5c8SBarry Smith   }
4110170fe5c8SBarry Smith   PetscFunctionReturn(0);
4111170fe5c8SBarry Smith }
4112170fe5c8SBarry Smith 
4113170fe5c8SBarry Smith PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat *C)
4114170fe5c8SBarry Smith {
4115170fe5c8SBarry Smith   PetscErrorCode ierr;
4116d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
4117170fe5c8SBarry Smith   Mat            Cmat;
4118170fe5c8SBarry Smith 
4119170fe5c8SBarry Smith   PetscFunctionBegin;
412060e0710aSBarry 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);
4121ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr);
4122170fe5c8SBarry Smith   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
412333d57670SJed Brown   ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr);
4124170fe5c8SBarry Smith   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
41250298fd71SBarry Smith   ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr);
4126d73949e8SHong Zhang 
4127d73949e8SHong Zhang   Cmat->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
41282205254eSKarl Rupp 
4129170fe5c8SBarry Smith   *C = Cmat;
4130170fe5c8SBarry Smith   PetscFunctionReturn(0);
4131170fe5c8SBarry Smith }
4132170fe5c8SBarry Smith 
4133170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
4134150d2497SBarry Smith PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
4135170fe5c8SBarry Smith {
4136170fe5c8SBarry Smith   PetscErrorCode ierr;
4137170fe5c8SBarry Smith 
4138170fe5c8SBarry Smith   PetscFunctionBegin;
4139170fe5c8SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
41403ff4c91cSHong Zhang     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
4141170fe5c8SBarry Smith     ierr = MatMatMultSymbolic_SeqDense_SeqAIJ(A,B,fill,C);CHKERRQ(ierr);
41423ff4c91cSHong Zhang     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
4143170fe5c8SBarry Smith   }
41443ff4c91cSHong Zhang   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
4145170fe5c8SBarry Smith   ierr = MatMatMultNumeric_SeqDense_SeqAIJ(A,B,*C);CHKERRQ(ierr);
41463ff4c91cSHong Zhang   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
4147170fe5c8SBarry Smith   PetscFunctionReturn(0);
4148170fe5c8SBarry Smith }
4149170fe5c8SBarry Smith 
4150170fe5c8SBarry Smith 
41510bad9183SKris Buschelman /*MC
4152fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
41530bad9183SKris Buschelman    based on compressed sparse row format.
41540bad9183SKris Buschelman 
41550bad9183SKris Buschelman    Options Database Keys:
41560bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
41570bad9183SKris Buschelman 
41580bad9183SKris Buschelman    Level: beginner
41590bad9183SKris Buschelman 
41600cd7f59aSBarry Smith    Notes:
41610cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
41620cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
41630cd7f59aSBarry Smith     in the matrix
41640cd7f59aSBarry Smith 
41650cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
41660cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
41670cd7f59aSBarry Smith 
41680cd7f59aSBarry Smith   Developer Notes:
41690cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
41700cd7f59aSBarry Smith 
4171f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
41720bad9183SKris Buschelman M*/
41730bad9183SKris Buschelman 
4174ccd284c7SBarry Smith /*MC
4175ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4176ccd284c7SBarry Smith 
4177ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4178ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
41790cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4180ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4181ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4182ccd284c7SBarry Smith 
4183ccd284c7SBarry Smith    Options Database Keys:
4184ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4185ccd284c7SBarry Smith 
418695452b02SPatrick Sanan   Developer Notes:
4187ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4188ccd284c7SBarry Smith    enough exist.
4189ccd284c7SBarry Smith 
4190ccd284c7SBarry Smith   Level: beginner
4191ccd284c7SBarry Smith 
4192ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4193ccd284c7SBarry Smith M*/
4194ccd284c7SBarry Smith 
4195ccd284c7SBarry Smith /*MC
4196ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4197ccd284c7SBarry Smith 
4198ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4199ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4200ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4201ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4202ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4203ccd284c7SBarry Smith 
4204ccd284c7SBarry Smith    Options Database Keys:
4205ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4206ccd284c7SBarry Smith 
4207ccd284c7SBarry Smith   Level: beginner
4208ccd284c7SBarry Smith 
4209ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4210ccd284c7SBarry Smith M*/
4211ccd284c7SBarry Smith 
42127906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
42137906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
42147906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
42157906f579SHong Zhang #endif
42167906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
42177906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
42187906f579SHong Zhang PETSC_INTERN PetscErrorCode MatMatMatMult_Transpose_AIJ_AIJ(Mat,Mat,Mat,MatReuse,PetscReal,Mat*);
42197906f579SHong Zhang #endif
42207906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat,MatType,MatReuse,Mat*);
42217906f579SHong Zhang 
4222d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4223c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
422475d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat,Mat,MatReuse,PetscReal,Mat*);
42257906f579SHong Zhang 
42268c778c55SBarry Smith /*@C
42278f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
42288c778c55SBarry Smith 
42298c778c55SBarry Smith    Not Collective
42308c778c55SBarry Smith 
42318c778c55SBarry Smith    Input Parameter:
4232579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
42338c778c55SBarry Smith 
42348c778c55SBarry Smith    Output Parameter:
42358c778c55SBarry Smith .   array - pointer to the data
42368c778c55SBarry Smith 
42378c778c55SBarry Smith    Level: intermediate
42388c778c55SBarry Smith 
4239774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
42408c778c55SBarry Smith @*/
42418c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
42428c778c55SBarry Smith {
42438c778c55SBarry Smith   PetscErrorCode ierr;
42448c778c55SBarry Smith 
42458c778c55SBarry Smith   PetscFunctionBegin;
42468c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
42478c778c55SBarry Smith   PetscFunctionReturn(0);
42488c778c55SBarry Smith }
42498c778c55SBarry Smith 
425021e72a00SBarry Smith /*@C
42518f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
42528f1ea47aSStefano Zampini 
42538f1ea47aSStefano Zampini    Not Collective
42548f1ea47aSStefano Zampini 
42558f1ea47aSStefano Zampini    Input Parameter:
42568f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
42578f1ea47aSStefano Zampini 
42588f1ea47aSStefano Zampini    Output Parameter:
42598f1ea47aSStefano Zampini .   array - pointer to the data
42608f1ea47aSStefano Zampini 
42618f1ea47aSStefano Zampini    Level: intermediate
42628f1ea47aSStefano Zampini 
42638f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
42648f1ea47aSStefano Zampini @*/
42658f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
42668f1ea47aSStefano Zampini {
42678f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4268c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
42698f1ea47aSStefano Zampini #endif
42708f1ea47aSStefano Zampini   PetscErrorCode ierr;
42718f1ea47aSStefano Zampini 
42728f1ea47aSStefano Zampini   PetscFunctionBegin;
42738f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4274c70f7ee4SJunchao Zhang   oval = A->offloadmask;
42758f1ea47aSStefano Zampini #endif
42768f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
42778f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4278c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
42798f1ea47aSStefano Zampini #endif
42808f1ea47aSStefano Zampini   PetscFunctionReturn(0);
42818f1ea47aSStefano Zampini }
42828f1ea47aSStefano Zampini 
42838f1ea47aSStefano Zampini /*@C
42848f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
42858f1ea47aSStefano Zampini 
42868f1ea47aSStefano Zampini    Not Collective
42878f1ea47aSStefano Zampini 
42888f1ea47aSStefano Zampini    Input Parameter:
42898f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
42908f1ea47aSStefano Zampini 
42918f1ea47aSStefano Zampini    Output Parameter:
42928f1ea47aSStefano Zampini .   array - pointer to the data
42938f1ea47aSStefano Zampini 
42948f1ea47aSStefano Zampini    Level: intermediate
42958f1ea47aSStefano Zampini 
42968f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
42978f1ea47aSStefano Zampini @*/
42988f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
42998f1ea47aSStefano Zampini {
43008f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4301c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
43028f1ea47aSStefano Zampini #endif
43038f1ea47aSStefano Zampini   PetscErrorCode ierr;
43048f1ea47aSStefano Zampini 
43058f1ea47aSStefano Zampini   PetscFunctionBegin;
43068f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4307c70f7ee4SJunchao Zhang   oval = A->offloadmask;
43088f1ea47aSStefano Zampini #endif
43098f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
43108f1ea47aSStefano Zampini #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
4311c70f7ee4SJunchao Zhang   A->offloadmask = oval;
43128f1ea47aSStefano Zampini #endif
43138f1ea47aSStefano Zampini   PetscFunctionReturn(0);
43148f1ea47aSStefano Zampini }
43158f1ea47aSStefano Zampini 
43168f1ea47aSStefano Zampini /*@C
431721e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
431821e72a00SBarry Smith 
431921e72a00SBarry Smith    Not Collective
432021e72a00SBarry Smith 
432121e72a00SBarry Smith    Input Parameter:
4322579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
432321e72a00SBarry Smith 
432421e72a00SBarry Smith    Output Parameter:
432521e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
432621e72a00SBarry Smith 
432721e72a00SBarry Smith    Level: intermediate
432821e72a00SBarry Smith 
432921e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
433021e72a00SBarry Smith @*/
433121e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
433221e72a00SBarry Smith {
433321e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
433421e72a00SBarry Smith 
433521e72a00SBarry Smith   PetscFunctionBegin;
433621e72a00SBarry Smith   *nz = aij->rmax;
433721e72a00SBarry Smith   PetscFunctionReturn(0);
433821e72a00SBarry Smith }
433921e72a00SBarry Smith 
43408c778c55SBarry Smith /*@C
4341579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
43428c778c55SBarry Smith 
43438c778c55SBarry Smith    Not Collective
43448c778c55SBarry Smith 
43458c778c55SBarry Smith    Input Parameters:
4346a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4347a2b725a8SWilliam Gropp -  array - pointer to the data
43488c778c55SBarry Smith 
43498c778c55SBarry Smith    Level: intermediate
43508c778c55SBarry Smith 
4351774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
43528c778c55SBarry Smith @*/
43538c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
43548c778c55SBarry Smith {
43558c778c55SBarry Smith   PetscErrorCode ierr;
43568c778c55SBarry Smith 
43578c778c55SBarry Smith   PetscFunctionBegin;
43588c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
43598c778c55SBarry Smith   PetscFunctionReturn(0);
43608c778c55SBarry Smith }
43618c778c55SBarry Smith 
436234b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
436302fe1965SBarry Smith PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
436402fe1965SBarry Smith #endif
436502fe1965SBarry Smith 
43668cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4367273d9f13SBarry Smith {
4368273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4369dfbe8321SBarry Smith   PetscErrorCode ierr;
437038baddfdSBarry Smith   PetscMPIInt    size;
4371273d9f13SBarry Smith 
4372273d9f13SBarry Smith   PetscFunctionBegin;
4373ce94432eSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
4374e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4375273d9f13SBarry Smith 
4376b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
43772205254eSKarl Rupp 
4378b0a32e0cSBarry Smith   B->data = (void*)b;
43792205254eSKarl Rupp 
4380549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4381071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
43822205254eSKarl Rupp 
4383416022c9SBarry Smith   b->row                = 0;
4384416022c9SBarry Smith   b->col                = 0;
438582bf6240SBarry Smith   b->icol               = 0;
4386b810aeb4SBarry Smith   b->reallocs           = 0;
438736db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4388f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4389416022c9SBarry Smith   b->nonew              = 0;
4390416022c9SBarry Smith   b->diag               = 0;
4391416022c9SBarry Smith   b->solve_work         = 0;
43922a1b7f2aSHong Zhang   B->spptr              = 0;
4393be6bf707SBarry Smith   b->saved_values       = 0;
4394d7f994e1SBarry Smith   b->idiag              = 0;
439571f1c65dSBarry Smith   b->mdiag              = 0;
439671f1c65dSBarry Smith   b->ssor_work          = 0;
439771f1c65dSBarry Smith   b->omega              = 1.0;
439871f1c65dSBarry Smith   b->fshift             = 0.0;
439971f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4400bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4401a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
440217ab2063SBarry Smith 
440335d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4404bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4405bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
44068c778c55SBarry Smith 
4407b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4408bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4409bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4410b3866ffcSBarry Smith #endif
441117f1a0eaSHong Zhang 
4412bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4413bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4414bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4415bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4416bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4417bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
44184dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
44199779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
44204a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4421191b95cbSRichard Tran Mills #endif
442234b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
442302fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
442402fe1965SBarry Smith #endif
4425bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4426af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4427af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4428af8000cdSHong Zhang #endif
442963c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
443063c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
44313dad0653Sstefano_zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMatMult_transpose_seqaij_seqaij_C",MatMatMatMult_Transpose_AIJ_AIJ);CHKERRQ(ierr);
443263c07aadSStefano Zampini #endif
4433b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4434d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4435c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4436bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4437bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4438bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4439846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4440bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4441bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
4442bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqdense_seqaij_C",MatMatMult_SeqDense_SeqAIJ);CHKERRQ(ierr);
4443bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqdense_seqaij_C",MatMatMultSymbolic_SeqDense_SeqAIJ);CHKERRQ(ierr);
4444bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqdense_seqaij_C",MatMatMultNumeric_SeqDense_SeqAIJ);CHKERRQ(ierr);
444575d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_is_seqaij_C",MatPtAP_IS_XAIJ);CHKERRQ(ierr);
44464108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
444717667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
44484099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
44493a40ed3dSBarry Smith   PetscFunctionReturn(0);
445017ab2063SBarry Smith }
445117ab2063SBarry Smith 
4452b24902e0SBarry Smith /*
4453b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4454b24902e0SBarry Smith */
4455ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
445617ab2063SBarry Smith {
4457416022c9SBarry Smith   Mat_SeqAIJ     *c,*a = (Mat_SeqAIJ*)A->data;
44586849ba73SBarry Smith   PetscErrorCode ierr;
4459071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
446017ab2063SBarry Smith 
44613a40ed3dSBarry Smith   PetscFunctionBegin;
4462273d9f13SBarry Smith   c = (Mat_SeqAIJ*)C->data;
4463273d9f13SBarry Smith 
4464d5f3da31SBarry Smith   C->factortype = A->factortype;
4465416022c9SBarry Smith   c->row        = 0;
4466416022c9SBarry Smith   c->col        = 0;
446782bf6240SBarry Smith   c->icol       = 0;
44686ad4291fSHong Zhang   c->reallocs   = 0;
446917ab2063SBarry Smith 
44706ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
447117ab2063SBarry Smith 
4472aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4473aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4474eec197d1SBarry Smith 
4475071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4476071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4477071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4478071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
44793bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
448017ab2063SBarry Smith 
448117ab2063SBarry Smith   /* allocate the matrix space */
4482f77e22a1SHong Zhang   if (mallocmatspace) {
4483dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
44843bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
44852205254eSKarl Rupp 
4486f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
44872205254eSKarl Rupp 
4488580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
448917ab2063SBarry Smith     if (m > 0) {
4490580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4491be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
4492580bdb30SBarry Smith         ierr = PetscArraycpy(c->a,a->a,a->i[m]);CHKERRQ(ierr);
4493be6bf707SBarry Smith       } else {
4494580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
449517ab2063SBarry Smith       }
449608480c60SBarry Smith     }
4497f77e22a1SHong Zhang   }
449817ab2063SBarry Smith 
44996ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4500416022c9SBarry Smith   c->roworiented       = a->roworiented;
4501416022c9SBarry Smith   c->nonew             = a->nonew;
4502416022c9SBarry Smith   if (a->diag) {
4503854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4504071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
45053bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4506071fcb05SBarry Smith   } else c->diag = NULL;
45072205254eSKarl Rupp 
45086ad4291fSHong Zhang   c->solve_work         = 0;
45096ad4291fSHong Zhang   c->saved_values       = 0;
45106ad4291fSHong Zhang   c->idiag              = 0;
451171f1c65dSBarry Smith   c->ssor_work          = 0;
4512a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4513e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4514e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
45156ad4291fSHong Zhang 
4516893ad86cSHong Zhang   c->rmax         = a->rmax;
4517416022c9SBarry Smith   c->nz           = a->nz;
45188ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4519273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4520754ec7b1SSatish Balay 
45216ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
45226ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4523cd6b891eSBarry Smith   if (a->compressedrow.use) {
45246ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4525dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4526580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4527580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
452827ea64f8SHong Zhang   } else {
452927ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
45300298fd71SBarry Smith     c->compressedrow.i      = NULL;
45310298fd71SBarry Smith     c->compressedrow.rindex = NULL;
45326ad4291fSHong Zhang   }
4533ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4534e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
45354846f1f5SKris Buschelman 
45362205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4537140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
45383a40ed3dSBarry Smith   PetscFunctionReturn(0);
453917ab2063SBarry Smith }
454017ab2063SBarry Smith 
4541b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4542b24902e0SBarry Smith {
4543b24902e0SBarry Smith   PetscErrorCode ierr;
4544b24902e0SBarry Smith 
4545b24902e0SBarry Smith   PetscFunctionBegin;
4546ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
45474b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4548cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
454933d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4550cfd3f464SBarry Smith   }
4551a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4552f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4553b24902e0SBarry Smith   PetscFunctionReturn(0);
4554b24902e0SBarry Smith }
4555b24902e0SBarry Smith 
4556112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4557fbdbba38SShri Abhyankar {
455852f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
455952f91c60SVaclav Hapla   PetscErrorCode ierr;
456052f91c60SVaclav Hapla 
456152f91c60SVaclav Hapla   PetscFunctionBegin;
456252f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
456352f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4564c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4565c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
456652f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
456752f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
456852f91c60SVaclav Hapla   if (isbinary) {
456952f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
457052f91c60SVaclav Hapla   } else if (ishdf5) {
457152f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
457252f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
457352f91c60SVaclav Hapla #else
457452f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
457552f91c60SVaclav Hapla #endif
457652f91c60SVaclav Hapla   } else {
457752f91c60SVaclav 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);
457852f91c60SVaclav Hapla   }
457952f91c60SVaclav Hapla   PetscFunctionReturn(0);
458052f91c60SVaclav Hapla }
458152f91c60SVaclav Hapla 
458252f91c60SVaclav Hapla PetscErrorCode MatLoad_SeqAIJ_Binary(Mat newMat, PetscViewer viewer)
458352f91c60SVaclav Hapla {
4584fbdbba38SShri Abhyankar   Mat_SeqAIJ     *a;
4585fbdbba38SShri Abhyankar   PetscErrorCode ierr;
4586fbdbba38SShri Abhyankar   PetscInt       i,sum,nz,header[4],*rowlengths = 0,M,N,rows,cols;
4587fbdbba38SShri Abhyankar   int            fd;
4588fbdbba38SShri Abhyankar   PetscMPIInt    size;
4589fbdbba38SShri Abhyankar   MPI_Comm       comm;
45903059b6faSBarry Smith   PetscInt       bs = newMat->rmap->bs;
4591fbdbba38SShri Abhyankar 
4592fbdbba38SShri Abhyankar   PetscFunctionBegin;
4593fbdbba38SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
4594fbdbba38SShri Abhyankar   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
4595fbdbba38SShri Abhyankar   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"view must have one processor");
4596bbead8a2SBarry Smith 
45970298fd71SBarry Smith   ierr = PetscOptionsBegin(comm,NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr);
45980298fd71SBarry Smith   ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL);CHKERRQ(ierr);
4599bbead8a2SBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
46003059b6faSBarry Smith   if (bs < 0) bs = 1;
46013059b6faSBarry Smith   ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);
4602bbead8a2SBarry Smith 
4603fbdbba38SShri Abhyankar   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
46049860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
4605fbdbba38SShri Abhyankar   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object in file");
4606fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
4607fbdbba38SShri Abhyankar 
4608bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as SeqAIJ");
4609fbdbba38SShri Abhyankar 
4610fbdbba38SShri Abhyankar   /* read in row lengths */
4611785e854fSJed Brown   ierr = PetscMalloc1(M,&rowlengths);CHKERRQ(ierr);
46129860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,rowlengths,M,NULL,PETSC_INT);CHKERRQ(ierr);
4613fbdbba38SShri Abhyankar 
4614fbdbba38SShri Abhyankar   /* check if sum of rowlengths is same as nz */
4615fbdbba38SShri Abhyankar   for (i=0,sum=0; i< M; i++) sum +=rowlengths[i];
461660e0710aSBarry Smith   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_READ,"Inconsistant matrix data in file. no-nonzeros = %dD, sum-row-lengths = %D\n",nz,sum);
4617fbdbba38SShri Abhyankar 
4618fbdbba38SShri Abhyankar   /* set global size if not set already*/
4619f501eaabSShri Abhyankar   if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) {
4620fbdbba38SShri Abhyankar     ierr = MatSetSizes(newMat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
4621aabbc4fbSShri Abhyankar   } else {
46229d36ed5fSBarry Smith     /* if sizes and type are already set, check if the matrix  global sizes are correct */
4623fbdbba38SShri Abhyankar     ierr = MatGetSize(newMat,&rows,&cols);CHKERRQ(ierr);
46244c5b953cSHong Zhang     if (rows < 0 && cols < 0) { /* user might provide local size instead of global size */
46254c5b953cSHong Zhang       ierr = MatGetLocalSize(newMat,&rows,&cols);CHKERRQ(ierr);
46264c5b953cSHong Zhang     }
462760e0710aSBarry 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);
4628aabbc4fbSShri Abhyankar   }
4629fbdbba38SShri Abhyankar   ierr = MatSeqAIJSetPreallocation_SeqAIJ(newMat,0,rowlengths);CHKERRQ(ierr);
4630fbdbba38SShri Abhyankar   a    = (Mat_SeqAIJ*)newMat->data;
4631fbdbba38SShri Abhyankar 
46329860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
4633fbdbba38SShri Abhyankar 
4634fbdbba38SShri Abhyankar   /* read in nonzero values */
46359860990eSLisandro Dalcin   ierr = PetscBinaryRead(fd,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4636fbdbba38SShri Abhyankar 
4637fbdbba38SShri Abhyankar   /* set matrix "i" values */
4638fbdbba38SShri Abhyankar   a->i[0] = 0;
4639fbdbba38SShri Abhyankar   for (i=1; i<= M; i++) {
4640fbdbba38SShri Abhyankar     a->i[i]      = a->i[i-1] + rowlengths[i-1];
4641fbdbba38SShri Abhyankar     a->ilen[i-1] = rowlengths[i-1];
4642fbdbba38SShri Abhyankar   }
4643fbdbba38SShri Abhyankar   ierr = PetscFree(rowlengths);CHKERRQ(ierr);
4644fbdbba38SShri Abhyankar 
4645fbdbba38SShri Abhyankar   ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4646fbdbba38SShri Abhyankar   ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4647fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4648fbdbba38SShri Abhyankar }
4649fbdbba38SShri Abhyankar 
4650ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
46517264ac53SSatish Balay {
46527264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4653dfbe8321SBarry Smith   PetscErrorCode ierr;
4654eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4655eeffb40dSHong Zhang   PetscInt k;
4656eeffb40dSHong Zhang #endif
46577264ac53SSatish Balay 
46583a40ed3dSBarry Smith   PetscFunctionBegin;
4659bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4660d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4661ca44d042SBarry Smith     *flg = PETSC_FALSE;
4662ca44d042SBarry Smith     PetscFunctionReturn(0);
4663bcd2baecSBarry Smith   }
46647264ac53SSatish Balay 
46657264ac53SSatish Balay   /* if the a->i are the same */
4666580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4667abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
46687264ac53SSatish Balay 
46697264ac53SSatish Balay   /* if a->j are the same */
4670580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4671abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4672bcd2baecSBarry Smith 
4673bcd2baecSBarry Smith   /* if a->a are the same */
4674eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4675eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4676eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4677eeffb40dSHong Zhang       *flg = PETSC_FALSE;
46783a40ed3dSBarry Smith       PetscFunctionReturn(0);
4679eeffb40dSHong Zhang     }
4680eeffb40dSHong Zhang   }
4681eeffb40dSHong Zhang #else
4682580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4683eeffb40dSHong Zhang #endif
4684eeffb40dSHong Zhang   PetscFunctionReturn(0);
46857264ac53SSatish Balay }
468636db0b34SBarry Smith 
468705869f15SSatish Balay /*@
468836db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
468936db0b34SBarry Smith               provided by the user.
469036db0b34SBarry Smith 
4691d083f849SBarry Smith       Collective
469236db0b34SBarry Smith 
469336db0b34SBarry Smith    Input Parameters:
469436db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
469536db0b34SBarry Smith .   m - number of rows
469636db0b34SBarry Smith .   n - number of columns
4697483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
469836db0b34SBarry Smith .   j - column indices
469936db0b34SBarry Smith -   a - matrix values
470036db0b34SBarry Smith 
470136db0b34SBarry Smith    Output Parameter:
470236db0b34SBarry Smith .   mat - the matrix
470336db0b34SBarry Smith 
470436db0b34SBarry Smith    Level: intermediate
470536db0b34SBarry Smith 
470636db0b34SBarry Smith    Notes:
47070551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
4708292fb18eSBarry Smith     once the matrix is destroyed and not before
470936db0b34SBarry Smith 
471036db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
471136db0b34SBarry Smith 
4712bfeeae90SHong Zhang        The i and j indices are 0 based
471336db0b34SBarry Smith 
4714a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
4715a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
47168eef79e4SBarry Smith     as shown
4717a4552177SSatish Balay 
47188eef79e4SBarry Smith $        1 0 0
47198eef79e4SBarry Smith $        2 0 3
47208eef79e4SBarry Smith $        4 5 6
47218eef79e4SBarry Smith $
47228eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
47238eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
47248eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
4725a4552177SSatish Balay 
47269985e31cSBarry Smith 
472769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
472836db0b34SBarry Smith 
472936db0b34SBarry Smith @*/
4730c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
473136db0b34SBarry Smith {
4732dfbe8321SBarry Smith   PetscErrorCode ierr;
4733cbcfb4deSHong Zhang   PetscInt       ii;
473436db0b34SBarry Smith   Mat_SeqAIJ     *aij;
4735cbcfb4deSHong Zhang #if defined(PETSC_USE_DEBUG)
4736cbcfb4deSHong Zhang   PetscInt jj;
4737cbcfb4deSHong Zhang #endif
473836db0b34SBarry Smith 
473936db0b34SBarry Smith   PetscFunctionBegin;
474041096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
4741f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
4742f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
4743a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
4744ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
4745ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,0);CHKERRQ(ierr);
4746ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
4747071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
4748071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
4749ab93d7beSBarry Smith 
475036db0b34SBarry Smith   aij->i            = i;
475136db0b34SBarry Smith   aij->j            = j;
475236db0b34SBarry Smith   aij->a            = a;
475336db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
475436db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
4755e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
4756e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
475736db0b34SBarry Smith 
475836db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
475936db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
47602515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
476160e0710aSBarry 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]);
47629985e31cSBarry Smith     for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
4763a061629eSStefano 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);
4764a061629eSStefano 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);
47659985e31cSBarry Smith     }
476636db0b34SBarry Smith #endif
476736db0b34SBarry Smith   }
47682515c552SBarry Smith #if defined(PETSC_USE_DEBUG)
476936db0b34SBarry Smith   for (ii=0; ii<aij->i[m]; ii++) {
477060e0710aSBarry Smith     if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
477160e0710aSBarry 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]);
477236db0b34SBarry Smith   }
477336db0b34SBarry Smith #endif
477436db0b34SBarry Smith 
4775b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4776b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
477736db0b34SBarry Smith   PetscFunctionReturn(0);
477836db0b34SBarry Smith }
477980ef6e79SMatthew G Knepley /*@C
4780d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
47818a0b0e6bSVictor Minden               provided by the user.
47828a0b0e6bSVictor Minden 
4783d083f849SBarry Smith       Collective
47848a0b0e6bSVictor Minden 
47858a0b0e6bSVictor Minden    Input Parameters:
47868a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
47878a0b0e6bSVictor Minden .   m   - number of rows
47888a0b0e6bSVictor Minden .   n   - number of columns
47898a0b0e6bSVictor Minden .   i   - row indices
47908a0b0e6bSVictor Minden .   j   - column indices
47911230e6d1SVictor Minden .   a   - matrix values
47921230e6d1SVictor Minden .   nz  - number of nonzeros
47931230e6d1SVictor Minden -   idx - 0 or 1 based
47948a0b0e6bSVictor Minden 
47958a0b0e6bSVictor Minden    Output Parameter:
47968a0b0e6bSVictor Minden .   mat - the matrix
47978a0b0e6bSVictor Minden 
47988a0b0e6bSVictor Minden    Level: intermediate
47998a0b0e6bSVictor Minden 
48008a0b0e6bSVictor Minden    Notes:
48018a0b0e6bSVictor Minden        The i and j indices are 0 based
48028a0b0e6bSVictor Minden 
48038a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
48048a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
48058a0b0e6bSVictor Minden     as shown:
48068a0b0e6bSVictor Minden 
48078a0b0e6bSVictor Minden         1 0 0
48088a0b0e6bSVictor Minden         2 0 3
48098a0b0e6bSVictor Minden         4 5 6
48108a0b0e6bSVictor Minden 
48118a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
48128a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
48138a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
48148a0b0e6bSVictor Minden 
48158a0b0e6bSVictor Minden 
481669b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
48178a0b0e6bSVictor Minden 
48188a0b0e6bSVictor Minden @*/
4819c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
48208a0b0e6bSVictor Minden {
48218a0b0e6bSVictor Minden   PetscErrorCode ierr;
4822d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
48238a0b0e6bSVictor Minden 
48248a0b0e6bSVictor Minden 
48258a0b0e6bSVictor Minden   PetscFunctionBegin;
48261795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
48271230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
4828c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
48291230e6d1SVictor Minden   }
48308a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
48318a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
48328a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
48331230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
48341230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
48351230e6d1SVictor Minden     if (idx) {
48361230e6d1SVictor Minden       row = i[ii] - 1;
48371230e6d1SVictor Minden       col = j[ii] - 1;
48381230e6d1SVictor Minden     } else {
48391230e6d1SVictor Minden       row = i[ii];
48401230e6d1SVictor Minden       col = j[ii];
48418a0b0e6bSVictor Minden     }
48421230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
48438a0b0e6bSVictor Minden   }
48448a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
48458a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4846d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
48478a0b0e6bSVictor Minden   PetscFunctionReturn(0);
48488a0b0e6bSVictor Minden }
484936db0b34SBarry Smith 
4850acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
4851acf2f550SJed Brown {
4852acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
4853acf2f550SJed Brown   PetscErrorCode ierr;
4854acf2f550SJed Brown 
4855acf2f550SJed Brown   PetscFunctionBegin;
4856acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
4857acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
48582205254eSKarl Rupp 
4859acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
4860acf2f550SJed Brown   PetscFunctionReturn(0);
4861acf2f550SJed Brown }
4862acf2f550SJed Brown 
48639c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
48649c8f2541SHong Zhang {
48659c8f2541SHong Zhang   PetscErrorCode ierr;
48668761c3d6SHong Zhang   PetscMPIInt    size;
48679c8f2541SHong Zhang 
48689c8f2541SHong Zhang   PetscFunctionBegin;
48698761c3d6SHong Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
48707bbdc51dSHong Zhang   if (size == 1) {
48717bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
48727bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
48737bbdc51dSHong Zhang     } else {
48748761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
48757bbdc51dSHong Zhang     }
48768761c3d6SHong Zhang   } else {
48779c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
48788761c3d6SHong Zhang   }
48799c8f2541SHong Zhang   PetscFunctionReturn(0);
48809c8f2541SHong Zhang }
48819c8f2541SHong Zhang 
488281824310SBarry Smith /*
488353dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
488453dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
488553dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
488653dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
488753dd7562SDmitry Karpeev  */
488853dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
488953dd7562SDmitry Karpeev {
489053dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
489153dd7562SDmitry Karpeev   PetscErrorCode ierr;
489253dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
489353dd7562SDmitry Karpeev   PetscBool      seqaij;
489453dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
489553dd7562SDmitry Karpeev   PetscScalar    v;
489653dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
489753dd7562SDmitry Karpeev 
489853dd7562SDmitry Karpeev   PetscFunctionBegin;
489953dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
490053dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
49014099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
490253dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
490353dd7562SDmitry Karpeev   if (rowemb) {
490453dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
490553dd7562SDmitry 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);
490653dd7562SDmitry Karpeev   } else {
49076c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
490853dd7562SDmitry Karpeev   }
490953dd7562SDmitry Karpeev   if (colemb) {
491053dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
491153dd7562SDmitry 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);
491253dd7562SDmitry Karpeev   } else {
491353dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
491453dd7562SDmitry Karpeev   }
491553dd7562SDmitry Karpeev 
491653dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
491753dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
491853dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
491953dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
492053dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
492153dd7562SDmitry Karpeev     }
492253dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
492353dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
492453dd7562SDmitry Karpeev   }
492553dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
492653dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
492753dd7562SDmitry Karpeev   }
492853dd7562SDmitry Karpeev   count = 0;
492953dd7562SDmitry Karpeev   rowindices = NULL;
493053dd7562SDmitry Karpeev   colindices = NULL;
493153dd7562SDmitry Karpeev   if (rowemb) {
493253dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
493353dd7562SDmitry Karpeev   }
493453dd7562SDmitry Karpeev   if (colemb) {
493553dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
493653dd7562SDmitry Karpeev   }
493753dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
493853dd7562SDmitry Karpeev     PetscInt row;
493953dd7562SDmitry Karpeev     row = i;
494053dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
494153dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
494253dd7562SDmitry Karpeev       PetscInt col;
494353dd7562SDmitry Karpeev       col  = Baij->j[count];
494453dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
494553dd7562SDmitry Karpeev       v    = Baij->a[count];
494653dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
494753dd7562SDmitry Karpeev       ++count;
494853dd7562SDmitry Karpeev     }
494953dd7562SDmitry Karpeev   }
495053dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
495153dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
495253dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
495353dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
495453dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
495553dd7562SDmitry Karpeev   PetscFunctionReturn(0);
495653dd7562SDmitry Karpeev }
495753dd7562SDmitry Karpeev 
49584099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
49594099cc6bSBarry Smith 
49604099cc6bSBarry Smith /*@C
49614099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
49624099cc6bSBarry Smith 
49634099cc6bSBarry Smith    Collective on Mat
49644099cc6bSBarry Smith 
49654099cc6bSBarry Smith    Input Parameters:
49664099cc6bSBarry Smith +  mat      - the matrix object
49674099cc6bSBarry Smith -  matype   - matrix type
49684099cc6bSBarry Smith 
49694099cc6bSBarry Smith    Options Database Key:
49704099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
49714099cc6bSBarry Smith 
49724099cc6bSBarry Smith 
49734099cc6bSBarry Smith   Level: intermediate
49744099cc6bSBarry Smith 
49754099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
49764099cc6bSBarry Smith @*/
49774099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
49784099cc6bSBarry Smith {
4979fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
49804099cc6bSBarry Smith   PetscBool      sametype;
49814099cc6bSBarry Smith 
49824099cc6bSBarry Smith   PetscFunctionBegin;
49834099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
49844099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
49854099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
49864099cc6bSBarry Smith 
49874099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
49884099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
49894099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
49904099cc6bSBarry Smith   PetscFunctionReturn(0);
49914099cc6bSBarry Smith }
49924099cc6bSBarry Smith 
49934099cc6bSBarry Smith 
49944099cc6bSBarry Smith /*@C
49954099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
49964099cc6bSBarry Smith 
49974099cc6bSBarry Smith    Not Collective
49984099cc6bSBarry Smith 
49994099cc6bSBarry Smith    Input Parameters:
50004099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
50014099cc6bSBarry Smith -  function - routine to convert to subtype
50024099cc6bSBarry Smith 
50034099cc6bSBarry Smith    Notes:
50044099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
50054099cc6bSBarry Smith 
50064099cc6bSBarry Smith 
50074099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
50084099cc6bSBarry Smith $     -mat_seqaij_type my_mat
50094099cc6bSBarry Smith 
50104099cc6bSBarry Smith    Level: advanced
50114099cc6bSBarry Smith 
50124099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
50134099cc6bSBarry Smith 
50144099cc6bSBarry Smith 
50154099cc6bSBarry Smith   Level: advanced
50164099cc6bSBarry Smith @*/
5017388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
50184099cc6bSBarry Smith {
50194099cc6bSBarry Smith   PetscErrorCode ierr;
50204099cc6bSBarry Smith 
50214099cc6bSBarry Smith   PetscFunctionBegin;
50229cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
50234099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
50244099cc6bSBarry Smith   PetscFunctionReturn(0);
50254099cc6bSBarry Smith }
50264099cc6bSBarry Smith 
50274099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
50284099cc6bSBarry Smith 
50294099cc6bSBarry Smith /*@C
50304099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
50314099cc6bSBarry Smith 
50324099cc6bSBarry Smith   Not Collective
50334099cc6bSBarry Smith 
50344099cc6bSBarry Smith   Level: advanced
50354099cc6bSBarry Smith 
50364099cc6bSBarry Smith   Developers Note: CUSP and CUSPARSE do not yet support the  MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
50374099cc6bSBarry Smith 
50384099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
50394099cc6bSBarry Smith @*/
50404099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
50414099cc6bSBarry Smith {
50424099cc6bSBarry Smith   PetscErrorCode ierr;
50434099cc6bSBarry Smith 
50444099cc6bSBarry Smith   PetscFunctionBegin;
50454099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
50464099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
50474099cc6bSBarry Smith 
50484099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
50494099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
50504dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
50519779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
50526b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5053485f9817SRichard Tran Mills #endif
50544099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
50554099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
50564099cc6bSBarry Smith #endif
50574099cc6bSBarry Smith   PetscFunctionReturn(0);
50584099cc6bSBarry Smith }
505953dd7562SDmitry Karpeev 
506053dd7562SDmitry Karpeev /*
506181824310SBarry Smith     Special version for direct calls from Fortran
506281824310SBarry Smith */
5063af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
506481824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
506581824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
506681824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
506781824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
506881824310SBarry Smith #endif
506981824310SBarry Smith 
507081824310SBarry Smith /* Change these macros so can be used in void function */
507181824310SBarry Smith #undef CHKERRQ
5072ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
507381824310SBarry Smith #undef SETERRQ2
5074e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
50754994cf47SJed Brown #undef SETERRQ3
50764994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
507781824310SBarry Smith 
50788cc058d9SJed Brown PETSC_EXTERN void PETSC_STDCALL matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
507981824310SBarry Smith {
508081824310SBarry Smith   Mat            A  = *AA;
508181824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
508281824310SBarry Smith   InsertMode     is = *isis;
508381824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
508481824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
508581824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
508681824310SBarry Smith   PetscErrorCode ierr;
508781824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
508854f21887SBarry Smith   MatScalar      *ap,value,*aa;
5089ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5090ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
509181824310SBarry Smith 
509281824310SBarry Smith   PetscFunctionBegin;
50934994cf47SJed Brown   MatCheckPreallocated(A,1);
509481824310SBarry Smith   imax  = a->imax;
509581824310SBarry Smith   ai    = a->i;
509681824310SBarry Smith   ailen = a->ilen;
509781824310SBarry Smith   aj    = a->j;
509881824310SBarry Smith   aa    = a->a;
509981824310SBarry Smith 
510081824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
510181824310SBarry Smith     row = im[k];
510281824310SBarry Smith     if (row < 0) continue;
510381824310SBarry Smith #if defined(PETSC_USE_DEBUG)
5104ce94432eSBarry Smith     if (row >= A->rmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
510581824310SBarry Smith #endif
510681824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
510781824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
510881824310SBarry Smith     low  = 0;
510981824310SBarry Smith     high = nrow;
511081824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
511181824310SBarry Smith       if (in[l] < 0) continue;
511281824310SBarry Smith #if defined(PETSC_USE_DEBUG)
5113ce94432eSBarry Smith       if (in[l] >= A->cmap->n) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
511481824310SBarry Smith #endif
511581824310SBarry Smith       col = in[l];
51162205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
51172205254eSKarl Rupp       else value = v[k + l*m];
51182205254eSKarl Rupp 
511981824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
512081824310SBarry Smith 
51212205254eSKarl Rupp       if (col <= lastcol) low = 0;
51222205254eSKarl Rupp       else high = nrow;
512381824310SBarry Smith       lastcol = col;
512481824310SBarry Smith       while (high-low > 5) {
512581824310SBarry Smith         t = (low+high)/2;
512681824310SBarry Smith         if (rp[t] > col) high = t;
512781824310SBarry Smith         else             low  = t;
512881824310SBarry Smith       }
512981824310SBarry Smith       for (i=low; i<high; i++) {
513081824310SBarry Smith         if (rp[i] > col) break;
513181824310SBarry Smith         if (rp[i] == col) {
513281824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
513381824310SBarry Smith           else                  ap[i] = value;
513481824310SBarry Smith           goto noinsert;
513581824310SBarry Smith         }
513681824310SBarry Smith       }
513781824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
513881824310SBarry Smith       if (nonew == 1) goto noinsert;
5139ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5140fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
514181824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
514281824310SBarry Smith       /* shift up all the later entries in this row */
514381824310SBarry Smith       for (ii=N; ii>=i; ii--) {
514481824310SBarry Smith         rp[ii+1] = rp[ii];
514581824310SBarry Smith         ap[ii+1] = ap[ii];
514681824310SBarry Smith       }
514781824310SBarry Smith       rp[i] = col;
514881824310SBarry Smith       ap[i] = value;
5149e56f5c9eSBarry Smith       A->nonzerostate++;
515081824310SBarry Smith noinsert:;
515181824310SBarry Smith       low = i + 1;
515281824310SBarry Smith     }
515381824310SBarry Smith     ailen[row] = nrow;
515481824310SBarry Smith   }
515581824310SBarry Smith   PetscFunctionReturnVoid();
515681824310SBarry Smith }
5157