xref: /petsc/src/mat/impls/aij/seq/aij.c (revision cbc6b2250e380677eada4bbc58a36dc55ca92067)
1d5d45c9bSBarry Smith /*
23369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
3d5d45c9bSBarry Smith   matrix storage format.
4d5d45c9bSBarry Smith */
53369ce9aSBarry Smith 
6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
7c6db04a5SJed Brown #include <petscblaslapack.h>
8c6db04a5SJed Brown #include <petscbt.h>
9af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
100716a85fSBarry Smith 
114099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
124099cc6bSBarry Smith {
134099cc6bSBarry Smith   PetscErrorCode       ierr;
144099cc6bSBarry Smith   PetscBool            flg;
154099cc6bSBarry Smith   char                 type[256];
164099cc6bSBarry Smith 
174099cc6bSBarry Smith   PetscFunctionBegin;
181e1ea65dSPierre Jolivet   ierr = PetscObjectOptionsBegin((PetscObject)A);CHKERRQ(ierr);
194099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
204099cc6bSBarry Smith   if (flg) {
214099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
224099cc6bSBarry Smith   }
234099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
244099cc6bSBarry Smith   PetscFunctionReturn(0);
254099cc6bSBarry Smith }
264099cc6bSBarry Smith 
27857cbf51SRichard Tran Mills PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A,PetscInt type,PetscReal *reductions)
280716a85fSBarry Smith {
290716a85fSBarry Smith   PetscErrorCode ierr;
300716a85fSBarry Smith   PetscInt       i,m,n;
310716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
320716a85fSBarry Smith 
330716a85fSBarry Smith   PetscFunctionBegin;
340716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
35a873a8cdSSam Reynolds   ierr = PetscArrayzero(reductions,n);CHKERRQ(ierr);
360716a85fSBarry Smith   if (type == NORM_2) {
370716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
38a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
390716a85fSBarry Smith     }
400716a85fSBarry Smith   } else if (type == NORM_1) {
410716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
42a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]);
430716a85fSBarry Smith     }
440716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
450716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
46a873a8cdSSam Reynolds       reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),reductions[aij->j[i]]);
470716a85fSBarry Smith     }
48857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
49a873a8cdSSam Reynolds     for (i=0; i<aij->i[m]; i++) {
50857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscRealPart(aij->a[i]);
51a873a8cdSSam Reynolds     }
52857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
53857cbf51SRichard Tran Mills     for (i=0; i<aij->i[m]; i++) {
54857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]);
55857cbf51SRichard Tran Mills     }
56857cbf51SRichard Tran Mills   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown reduction type");
570716a85fSBarry Smith 
580716a85fSBarry Smith   if (type == NORM_2) {
59a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
60857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
61a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] /= m;
620716a85fSBarry Smith   }
630716a85fSBarry Smith   PetscFunctionReturn(0);
640716a85fSBarry Smith }
650716a85fSBarry Smith 
663a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
673a062f41SBarry Smith {
683a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
693a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
703a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
713a062f41SBarry Smith   PetscInt        *rows;
723a062f41SBarry Smith   PetscErrorCode  ierr;
733a062f41SBarry Smith 
743a062f41SBarry Smith   PetscFunctionBegin;
753a062f41SBarry Smith   for (i=0; i<m; i++) {
763a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
773a062f41SBarry Smith       cnt++;
783a062f41SBarry Smith     }
793a062f41SBarry Smith   }
803a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
813a062f41SBarry Smith   cnt  = 0;
823a062f41SBarry Smith   for (i=0; i<m; i++) {
833a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
843a062f41SBarry Smith       rows[cnt] = i;
853a062f41SBarry Smith       cnt++;
863a062f41SBarry Smith     }
873a062f41SBarry Smith   }
883a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
893a062f41SBarry Smith   PetscFunctionReturn(0);
903a062f41SBarry Smith }
913a062f41SBarry Smith 
92f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
936ce1633cSBarry Smith {
946ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
95fff043a9SJunchao Zhang   const MatScalar *aa;
966ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
97b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
986ce1633cSBarry Smith   PetscInt        *rows;
996ce1633cSBarry Smith   PetscErrorCode  ierr;
1006ce1633cSBarry Smith 
1016ce1633cSBarry Smith   PetscFunctionBegin;
102fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1036ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1046ce1633cSBarry Smith   diag = a->diag;
1056ce1633cSBarry Smith   for (i=0; i<m; i++) {
106b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1076ce1633cSBarry Smith       cnt++;
1086ce1633cSBarry Smith     }
1096ce1633cSBarry Smith   }
110785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
1116ce1633cSBarry Smith   cnt  = 0;
1126ce1633cSBarry Smith   for (i=0; i<m; i++) {
113b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1146ce1633cSBarry Smith       rows[cnt++] = i;
1156ce1633cSBarry Smith     }
1166ce1633cSBarry Smith   }
117f1f41ecbSJed Brown   *nrows = cnt;
118f1f41ecbSJed Brown   *zrows = rows;
119fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
120f1f41ecbSJed Brown   PetscFunctionReturn(0);
121f1f41ecbSJed Brown }
122f1f41ecbSJed Brown 
123f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
124f1f41ecbSJed Brown {
125f1f41ecbSJed Brown   PetscInt       nrows,*rows;
126f1f41ecbSJed Brown   PetscErrorCode ierr;
127f1f41ecbSJed Brown 
128f1f41ecbSJed Brown   PetscFunctionBegin;
1290298fd71SBarry Smith   *zrows = NULL;
130f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
131ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
1326ce1633cSBarry Smith   PetscFunctionReturn(0);
1336ce1633cSBarry Smith }
1346ce1633cSBarry Smith 
135b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
136b3a44c85SBarry Smith {
137b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
138b3a44c85SBarry Smith   const MatScalar *aa;
139b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
140b3a44c85SBarry Smith   const PetscInt  *ii;
141b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
142b3a44c85SBarry Smith   PetscErrorCode  ierr;
143b3a44c85SBarry Smith 
144b3a44c85SBarry Smith   PetscFunctionBegin;
1452e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
146f4259b30SLisandro Dalcin   *keptrows = NULL;
147b3a44c85SBarry Smith   ii        = a->i;
148b3a44c85SBarry Smith   for (i=0; i<m; i++) {
149b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
150b3a44c85SBarry Smith     if (!n) {
151b3a44c85SBarry Smith       cnt++;
152b3a44c85SBarry Smith       goto ok1;
153b3a44c85SBarry Smith     }
1542e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
155b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
156b3a44c85SBarry Smith     }
157b3a44c85SBarry Smith     cnt++;
158b3a44c85SBarry Smith ok1:;
159b3a44c85SBarry Smith   }
1602e5835c6SStefano Zampini   if (!cnt) {
1612e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1622e5835c6SStefano Zampini     PetscFunctionReturn(0);
1632e5835c6SStefano Zampini   }
164854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
165b3a44c85SBarry Smith   cnt  = 0;
166b3a44c85SBarry Smith   for (i=0; i<m; i++) {
167b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
168b3a44c85SBarry Smith     if (!n) continue;
1692e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
170b3a44c85SBarry Smith       if (aa[j] != 0.0) {
171b3a44c85SBarry Smith         rows[cnt++] = i;
172b3a44c85SBarry Smith         break;
173b3a44c85SBarry Smith       }
174b3a44c85SBarry Smith     }
175b3a44c85SBarry Smith   }
1762e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
177b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
178b3a44c85SBarry Smith   PetscFunctionReturn(0);
179b3a44c85SBarry Smith }
180b3a44c85SBarry Smith 
1817087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
18279299369SBarry Smith {
18379299369SBarry Smith   PetscErrorCode    ierr;
18479299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
18599e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
18699e65526SBarry Smith   const PetscInt    *diag;
1872e5835c6SStefano Zampini   MatScalar         *aa;
18899e65526SBarry Smith   const PetscScalar *v;
189ace3abfcSBarry Smith   PetscBool         missing;
19079299369SBarry Smith 
19179299369SBarry Smith   PetscFunctionBegin;
19209f38230SBarry Smith   if (Y->assembled) {
1930298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
19409f38230SBarry Smith     if (!missing) {
19579299369SBarry Smith       diag = aij->diag;
19699e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
1972e5835c6SStefano Zampini       ierr = MatSeqAIJGetArray(Y,&aa);CHKERRQ(ierr);
19879299369SBarry Smith       if (is == INSERT_VALUES) {
19979299369SBarry Smith         for (i=0; i<m; i++) {
20079299369SBarry Smith           aa[diag[i]] = v[i];
20179299369SBarry Smith         }
20279299369SBarry Smith       } else {
20379299369SBarry Smith         for (i=0; i<m; i++) {
20479299369SBarry Smith           aa[diag[i]] += v[i];
20579299369SBarry Smith         }
20679299369SBarry Smith       }
2072e5835c6SStefano Zampini       ierr = MatSeqAIJRestoreArray(Y,&aa);CHKERRQ(ierr);
20899e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
20979299369SBarry Smith       PetscFunctionReturn(0);
21079299369SBarry Smith     }
211acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
21209f38230SBarry Smith   }
21309f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
21409f38230SBarry Smith   PetscFunctionReturn(0);
21509f38230SBarry Smith }
21679299369SBarry Smith 
2171a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21817ab2063SBarry Smith {
219416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
220dfbe8321SBarry Smith   PetscErrorCode ierr;
22197f1f81fSBarry Smith   PetscInt       i,ishift;
22217ab2063SBarry Smith 
2233a40ed3dSBarry Smith   PetscFunctionBegin;
224d0f46423SBarry Smith   *m = A->rmap->n;
2253a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
226bfeeae90SHong Zhang   ishift = 0;
22753e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2282462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
229bfeeae90SHong Zhang   } else if (oshift == 1) {
2301a83f524SJed Brown     PetscInt *tia;
231d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2323b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
233854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2341a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2351a83f524SJed Brown     *ia = tia;
236ecc77c7aSBarry Smith     if (ja) {
2371a83f524SJed Brown       PetscInt *tja;
238854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2391a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2401a83f524SJed Brown       *ja = tja;
241ecc77c7aSBarry Smith     }
2426945ee14SBarry Smith   } else {
243ecc77c7aSBarry Smith     *ia = a->i;
244ecc77c7aSBarry Smith     if (ja) *ja = a->j;
245a2ce50c7SBarry Smith   }
2463a40ed3dSBarry Smith   PetscFunctionReturn(0);
247a2744918SBarry Smith }
248a2744918SBarry Smith 
2491a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2506945ee14SBarry Smith {
251dfbe8321SBarry Smith   PetscErrorCode ierr;
2526945ee14SBarry Smith 
2533a40ed3dSBarry Smith   PetscFunctionBegin;
2543a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
255bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
256606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
257ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
258bcd2baecSBarry Smith   }
2593a40ed3dSBarry Smith   PetscFunctionReturn(0);
26017ab2063SBarry Smith }
26117ab2063SBarry Smith 
2621a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2633b2fbd54SBarry Smith {
2643b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
265dfbe8321SBarry Smith   PetscErrorCode ierr;
266d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
26797f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2683b2fbd54SBarry Smith 
2693a40ed3dSBarry Smith   PetscFunctionBegin;
270899cda47SBarry Smith   *nn = n;
2713a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2723b2fbd54SBarry Smith   if (symmetric) {
2732462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2743b2fbd54SBarry Smith   } else {
275b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
276854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
277b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2783b2fbd54SBarry Smith     jj   = a->j;
2793b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
280bfeeae90SHong Zhang       collengths[jj[i]]++;
2813b2fbd54SBarry Smith     }
2823b2fbd54SBarry Smith     cia[0] = oshift;
2833b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2843b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2853b2fbd54SBarry Smith     }
286580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2873b2fbd54SBarry Smith     jj   = a->j;
288a93ec695SBarry Smith     for (row=0; row<m; row++) {
289a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
290a93ec695SBarry Smith       for (i=0; i<mr; i++) {
291bfeeae90SHong Zhang         col = *jj++;
2922205254eSKarl Rupp 
2933b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2943b2fbd54SBarry Smith       }
2953b2fbd54SBarry Smith     }
296606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
2973b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2983b2fbd54SBarry Smith   }
2993a40ed3dSBarry Smith   PetscFunctionReturn(0);
3003b2fbd54SBarry Smith }
3013b2fbd54SBarry Smith 
3021a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
3033b2fbd54SBarry Smith {
304dfbe8321SBarry Smith   PetscErrorCode ierr;
305606d414cSSatish Balay 
3063a40ed3dSBarry Smith   PetscFunctionBegin;
3073a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3083b2fbd54SBarry Smith 
309606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
310606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3113a40ed3dSBarry Smith   PetscFunctionReturn(0);
3123b2fbd54SBarry Smith }
3133b2fbd54SBarry Smith 
3147cee066cSHong Zhang /*
3157cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3167cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
317040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3187cee066cSHong Zhang */
3197cee066cSHong Zhang PetscErrorCode MatGetColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3207cee066cSHong Zhang {
3217cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3227cee066cSHong Zhang   PetscErrorCode ierr;
3237cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
324071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3257cee066cSHong Zhang   PetscInt       *cspidx;
326071fcb05SBarry Smith   const PetscInt *jj;
3277cee066cSHong Zhang 
3287cee066cSHong Zhang   PetscFunctionBegin;
3297cee066cSHong Zhang   *nn = n;
3307cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
331625f6d37SHong Zhang 
332b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
333854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
334b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
335b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3367cee066cSHong Zhang   jj   = a->j;
3377cee066cSHong Zhang   for (i=0; i<nz; i++) {
3387cee066cSHong Zhang     collengths[jj[i]]++;
3397cee066cSHong Zhang   }
3407cee066cSHong Zhang   cia[0] = oshift;
3417cee066cSHong Zhang   for (i=0; i<n; i++) {
3427cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3437cee066cSHong Zhang   }
344580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3457cee066cSHong Zhang   jj   = a->j;
3467cee066cSHong Zhang   for (row=0; row<m; row++) {
3477cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3487cee066cSHong Zhang     for (i=0; i<mr; i++) {
3497cee066cSHong Zhang       col         = *jj++;
350071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
351071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
352071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3537cee066cSHong Zhang     }
3547cee066cSHong Zhang   }
3557cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
356071fcb05SBarry Smith   *ia    = cia;
357071fcb05SBarry Smith   *ja    = cja;
3587cee066cSHong Zhang   *spidx = cspidx;
3597cee066cSHong Zhang   PetscFunctionReturn(0);
3607cee066cSHong Zhang }
3617cee066cSHong Zhang 
3627cee066cSHong Zhang PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3637cee066cSHong Zhang {
3647cee066cSHong Zhang   PetscErrorCode ierr;
3657cee066cSHong Zhang 
3667cee066cSHong Zhang   PetscFunctionBegin;
3675243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3687cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3697cee066cSHong Zhang   PetscFunctionReturn(0);
3707cee066cSHong Zhang }
3717cee066cSHong Zhang 
37287d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
37387d4246cSBarry Smith {
37487d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
37587d4246cSBarry Smith   PetscInt       *ai = a->i;
376fff043a9SJunchao Zhang   PetscScalar    *aa;
37787d4246cSBarry Smith   PetscErrorCode ierr;
37887d4246cSBarry Smith 
37987d4246cSBarry Smith   PetscFunctionBegin;
380fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
381fff043a9SJunchao Zhang   ierr = PetscArraycpy(aa+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
382fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
38387d4246cSBarry Smith   PetscFunctionReturn(0);
38487d4246cSBarry Smith }
38587d4246cSBarry Smith 
386bd04181cSBarry Smith /*
387bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
388bd04181cSBarry Smith 
389bd04181cSBarry Smith       -   a single row of values is set with each call
390bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
391bd04181cSBarry Smith       -   the values are always added to the matrix, not set
392bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
393bd04181cSBarry Smith 
3941f763a69SBarry Smith      This does NOT assume the global column indices are sorted
395bd04181cSBarry Smith 
3961f763a69SBarry Smith */
397bd04181cSBarry Smith 
398af0996ceSBarry Smith #include <petsc/private/isimpl.h>
399189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
400189e4007SBarry Smith {
401fff043a9SJunchao Zhang   PetscErrorCode ierr;
402189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4031f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
4041f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4051f763a69SBarry Smith   PetscInt       lastcol = -1;
406fff043a9SJunchao Zhang   MatScalar      *ap,value,*aa;
407189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
408189e4007SBarry Smith 
409fff043a9SJunchao Zhang   PetscFunctionBegin;
410fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
411f38dd0b8SBarry Smith   row  = ridx[im[0]];
4121f763a69SBarry Smith   rp   = aj + ai[row];
4131f763a69SBarry Smith   ap   = aa + ai[row];
4141f763a69SBarry Smith   nrow = ailen[row];
415189e4007SBarry Smith   low  = 0;
416189e4007SBarry Smith   high = nrow;
417189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
418189e4007SBarry Smith     col = cidx[in[l]];
419f38dd0b8SBarry Smith     value = v[l];
420189e4007SBarry Smith 
421189e4007SBarry Smith     if (col <= lastcol) low = 0;
422189e4007SBarry Smith     else high = nrow;
423189e4007SBarry Smith     lastcol = col;
424189e4007SBarry Smith     while (high-low > 5) {
425189e4007SBarry Smith       t = (low+high)/2;
426189e4007SBarry Smith       if (rp[t] > col) high = t;
427189e4007SBarry Smith       else low = t;
428189e4007SBarry Smith     }
429189e4007SBarry Smith     for (i=low; i<high; i++) {
430189e4007SBarry Smith       if (rp[i] == col) {
4311f763a69SBarry Smith         ap[i] += value;
432189e4007SBarry Smith         low = i + 1;
4331f763a69SBarry Smith         break;
434189e4007SBarry Smith       }
435189e4007SBarry Smith     }
436189e4007SBarry Smith   }
437fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
438f38dd0b8SBarry Smith   return 0;
439189e4007SBarry Smith }
440189e4007SBarry Smith 
44197f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
44217ab2063SBarry Smith {
443fff043a9SJunchao Zhang   PetscErrorCode ierr;
444416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
445e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
44697f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
447e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
448ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
449ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
450ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
45117ab2063SBarry Smith 
4523a40ed3dSBarry Smith   PetscFunctionBegin;
453fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
45417ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
455416022c9SBarry Smith     row = im[k];
4565ef9f2a5SBarry Smith     if (row < 0) continue;
4576bdcaf15SBarry Smith     PetscCheck(row < A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,row,A->rmap->n-1);
458720833daSHong Zhang     rp   = aj + ai[row];
459876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
46017ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
461416022c9SBarry Smith     low  = 0;
462c71e6ed7SBarry Smith     high = nrow;
46317ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4645ef9f2a5SBarry Smith       if (in[l] < 0) continue;
4656bdcaf15SBarry Smith       PetscCheck(in[l] < A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[l],A->cmap->n-1);
466bfeeae90SHong Zhang       col = in[l];
467071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
468071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
46936db0b34SBarry Smith 
4702205254eSKarl Rupp       if (col <= lastcol) low = 0;
4712205254eSKarl Rupp       else high = nrow;
472e2ee6c50SBarry Smith       lastcol = col;
473416022c9SBarry Smith       while (high-low > 5) {
474416022c9SBarry Smith         t = (low+high)/2;
475416022c9SBarry Smith         if (rp[t] > col) high = t;
476416022c9SBarry Smith         else low = t;
47717ab2063SBarry Smith       }
478416022c9SBarry Smith       for (i=low; i<high; i++) {
47917ab2063SBarry Smith         if (rp[i] > col) break;
48017ab2063SBarry Smith         if (rp[i] == col) {
481876c6284SHong Zhang           if (!A->structure_only) {
4820c0d7e18SFande Kong             if (is == ADD_VALUES) {
4830c0d7e18SFande Kong               ap[i] += value;
4840c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4850c0d7e18SFande Kong             }
48617ab2063SBarry Smith             else ap[i] = value;
487720833daSHong Zhang           }
488e44c0bd4SBarry Smith           low = i + 1;
48917ab2063SBarry Smith           goto noinsert;
49017ab2063SBarry Smith         }
49117ab2063SBarry Smith       }
492dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
493c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
4942c71b3e2SJacob Faibussowitsch       PetscCheckFalse(nonew == -1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%" PetscInt_FMT ",%" PetscInt_FMT ") in the matrix",row,col);
495720833daSHong Zhang       if (A->structure_only) {
496876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
497720833daSHong Zhang       } else {
498fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
499720833daSHong Zhang       }
500c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
501416022c9SBarry Smith       /* shift up all the later entries in this row */
502580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
50317ab2063SBarry Smith       rp[i] = col;
504580bdb30SBarry Smith       if (!A->structure_only) {
505580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
506580bdb30SBarry Smith         ap[i] = value;
507580bdb30SBarry Smith       }
508416022c9SBarry Smith       low = i + 1;
509e56f5c9eSBarry Smith       A->nonzerostate++;
510e44c0bd4SBarry Smith noinsert:;
51117ab2063SBarry Smith     }
51217ab2063SBarry Smith     ailen[row] = nrow;
51317ab2063SBarry Smith   }
514fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
5153a40ed3dSBarry Smith   PetscFunctionReturn(0);
51617ab2063SBarry Smith }
51717ab2063SBarry Smith 
51819b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
51919b08ed1SBarry Smith {
52019b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
52119b08ed1SBarry Smith   PetscInt       *rp,k,row;
52219b08ed1SBarry Smith   PetscInt       *ai = a->i;
52319b08ed1SBarry Smith   PetscErrorCode ierr;
52419b08ed1SBarry Smith   PetscInt       *aj = a->j;
525fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
52619b08ed1SBarry Smith 
52719b08ed1SBarry Smith   PetscFunctionBegin;
5282c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->was_assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
5292c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m*n+a->nz > a->maxnz,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of entries in matrix will be larger than maximum nonzeros allocated for %" PetscInt_FMT " in MatSeqAIJSetTotalPreallocation()",a->maxnz);
530fff043a9SJunchao Zhang 
531fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
53219b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
53319b08ed1SBarry Smith     row  = im[k];
53419b08ed1SBarry Smith     rp   = aj + ai[row];
53519b08ed1SBarry Smith     ap   = aa + ai[row];
53619b08ed1SBarry Smith 
53719b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
53819b08ed1SBarry Smith     if (!A->structure_only) {
53919b08ed1SBarry Smith       if (v) {
54019b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
54119b08ed1SBarry Smith         v   += n;
54219b08ed1SBarry Smith       } else {
54319b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
54419b08ed1SBarry Smith       }
54519b08ed1SBarry Smith     }
54619b08ed1SBarry Smith     a->ilen[row] = n;
54719b08ed1SBarry Smith     a->imax[row] = n;
54819b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
54919b08ed1SBarry Smith     a->nz       += n;
55019b08ed1SBarry Smith   }
551fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
55219b08ed1SBarry Smith   PetscFunctionReturn(0);
55319b08ed1SBarry Smith }
55419b08ed1SBarry Smith 
55519b08ed1SBarry Smith /*@
55619b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
55719b08ed1SBarry Smith 
55819b08ed1SBarry Smith   Input Parameters:
55919b08ed1SBarry Smith +  A - the SeqAIJ matrix
56019b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
56119b08ed1SBarry Smith 
56219b08ed1SBarry Smith   Level: advanced
56319b08ed1SBarry Smith 
56419b08ed1SBarry Smith   Notes:
56519b08ed1SBarry Smith     This can be called if you will be provided the matrix row by row (from row zero) with sorted column indices for each row.
56619b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
56719b08ed1SBarry Smith     as always with multiple matrix assemblies.
56819b08ed1SBarry Smith 
56919b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
57019b08ed1SBarry Smith @*/
57119b08ed1SBarry Smith 
57219b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
57319b08ed1SBarry Smith {
57419b08ed1SBarry Smith   PetscErrorCode ierr;
57519b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
57619b08ed1SBarry Smith 
57719b08ed1SBarry Smith   PetscFunctionBegin;
57819b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
57919b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
58019b08ed1SBarry Smith   a->maxnz  = nztotal;
58119b08ed1SBarry Smith   if (!a->imax) {
58219b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
58319b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
58419b08ed1SBarry Smith   }
58519b08ed1SBarry Smith   if (!a->ilen) {
58619b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
58719b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
58819b08ed1SBarry Smith   } else {
58919b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
59019b08ed1SBarry Smith   }
59119b08ed1SBarry Smith 
59219b08ed1SBarry Smith   /* allocate the matrix space */
59319b08ed1SBarry Smith   if (A->structure_only) {
59419b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
59519b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
59619b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
59719b08ed1SBarry Smith   } else {
59819b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
59919b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
60019b08ed1SBarry Smith   }
60119b08ed1SBarry Smith   a->i[0] = 0;
60219b08ed1SBarry Smith   if (A->structure_only) {
60319b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
60419b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
60519b08ed1SBarry Smith   } else {
60619b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
60719b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
60819b08ed1SBarry Smith   }
60919b08ed1SBarry Smith   a->free_ij        = PETSC_TRUE;
61019b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
61119b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
61219b08ed1SBarry Smith   PetscFunctionReturn(0);
61319b08ed1SBarry Smith }
61419b08ed1SBarry Smith 
615071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
616071fcb05SBarry Smith {
617071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
618071fcb05SBarry Smith   PetscInt       *rp,k,row;
619071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
620071fcb05SBarry Smith   PetscErrorCode ierr;
621071fcb05SBarry Smith   PetscInt       *aj = a->j;
622fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
623071fcb05SBarry Smith 
624071fcb05SBarry Smith   PetscFunctionBegin;
625fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
626071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
627071fcb05SBarry Smith     row  = im[k];
6286bdcaf15SBarry Smith     PetscCheck(n <= a->imax[row],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Preallocation for row %" PetscInt_FMT " does not match number of columns provided",n);
629071fcb05SBarry Smith     rp   = aj + ai[row];
630071fcb05SBarry Smith     ap   = aa + ai[row];
631071fcb05SBarry Smith     if (!A->was_assembled) {
632071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
633071fcb05SBarry Smith     }
634071fcb05SBarry Smith     if (!A->structure_only) {
635071fcb05SBarry Smith       if (v) {
636071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
637071fcb05SBarry Smith         v   += n;
638071fcb05SBarry Smith       } else {
639071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
640071fcb05SBarry Smith       }
641071fcb05SBarry Smith     }
642071fcb05SBarry Smith     ailen[row] = n;
643071fcb05SBarry Smith     a->nz      += n;
644071fcb05SBarry Smith   }
645fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
646071fcb05SBarry Smith   PetscFunctionReturn(0);
647071fcb05SBarry Smith }
648071fcb05SBarry Smith 
649a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6507eb43aa7SLois Curfman McInnes {
651fff043a9SJunchao Zhang   PetscErrorCode ierr;
6527eb43aa7SLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
65397f1f81fSBarry Smith   PetscInt       *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
65497f1f81fSBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
655fff043a9SJunchao Zhang   MatScalar      *ap,*aa;
6567eb43aa7SLois Curfman McInnes 
6573a40ed3dSBarry Smith   PetscFunctionBegin;
658fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
6597eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6607eb43aa7SLois Curfman McInnes     row = im[k];
66154c59aa7SJacob Faibussowitsch     if (row < 0) {v += n; continue;} /* negative row */
66254c59aa7SJacob Faibussowitsch     PetscCheck(row < A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,row,A->rmap->n-1);
663bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6647eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6657eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
66654c59aa7SJacob Faibussowitsch       if (in[l] < 0) {v++; continue;} /* negative column */
66754c59aa7SJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[l],A->cmap->n-1);
668bfeeae90SHong Zhang       col  = in[l];
6697eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6707eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6717eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6727eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6737eb43aa7SLois Curfman McInnes         else low = t;
6747eb43aa7SLois Curfman McInnes       }
6757eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6767eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6777eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
678b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6797eb43aa7SLois Curfman McInnes           goto finished;
6807eb43aa7SLois Curfman McInnes         }
6817eb43aa7SLois Curfman McInnes       }
68297e567efSBarry Smith       *v++ = 0.0;
6837eb43aa7SLois Curfman McInnes finished:;
6847eb43aa7SLois Curfman McInnes     }
6857eb43aa7SLois Curfman McInnes   }
686fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
6873a40ed3dSBarry Smith   PetscFunctionReturn(0);
6887eb43aa7SLois Curfman McInnes }
6897eb43aa7SLois Curfman McInnes 
6903ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
69117ab2063SBarry Smith {
6923ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
693c898d852SStefano Zampini   const PetscScalar *av;
6943ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
6953ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
6966849ba73SBarry Smith   PetscErrorCode    ierr;
69717ab2063SBarry Smith 
6983a40ed3dSBarry Smith   PetscFunctionBegin;
6993ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7002205254eSKarl Rupp 
7013ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7023ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7033ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7043ea6fe3dSLisandro Dalcin   nz = A->nz;
705416022c9SBarry Smith 
7063ea6fe3dSLisandro Dalcin   /* write matrix header */
7073ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7083ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7093ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
710416022c9SBarry Smith 
7113ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7123ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7133ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7143ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7153ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7163ea6fe3dSLisandro Dalcin   /* store column indices */
7173ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
718416022c9SBarry Smith   /* store nonzero values */
719c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
720c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
721c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
722b37d52dbSMark F. Adams 
7233ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7243ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7253a40ed3dSBarry Smith   PetscFunctionReturn(0);
72617ab2063SBarry Smith }
727416022c9SBarry Smith 
7287dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7297dc0baabSHong Zhang {
7307dc0baabSHong Zhang   PetscErrorCode ierr;
7317dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7327dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7337dc0baabSHong Zhang 
7347dc0baabSHong Zhang   PetscFunctionBegin;
7357dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7367dc0baabSHong Zhang   for (i=0; i<m; i++) {
737c0aa6a63SJacob Faibussowitsch     ierr = PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i);CHKERRQ(ierr);
7387dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
739c0aa6a63SJacob Faibussowitsch       ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ") ",a->j[k]);CHKERRQ(ierr);
7407dc0baabSHong Zhang     }
7417dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7427dc0baabSHong Zhang   }
7437dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7447dc0baabSHong Zhang   PetscFunctionReturn(0);
7457dc0baabSHong Zhang }
7467dc0baabSHong Zhang 
74709573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
748cd155464SBarry Smith 
749dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
750416022c9SBarry Smith {
751416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
752c898d852SStefano Zampini   const PetscScalar *av;
753dfbe8321SBarry Smith   PetscErrorCode    ierr;
75460e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
755e060cb09SBarry Smith   const char        *name;
756f3ef73ceSBarry Smith   PetscViewerFormat format;
75717ab2063SBarry Smith 
7583a40ed3dSBarry Smith   PetscFunctionBegin;
7597dc0baabSHong Zhang   if (A->structure_only) {
7607dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7617dc0baabSHong Zhang     PetscFunctionReturn(0);
7627dc0baabSHong Zhang   }
76343e49210SHong Zhang 
764b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
7652e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7662e5835c6SStefano Zampini 
767c898d852SStefano Zampini   /* trigger copy to CPU if needed */
768c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
769c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
77071c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
77197f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
77260e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
773c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
774d00d2cf4SBarry Smith       nofinalvalue = 1;
775d00d2cf4SBarry Smith     }
776d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
777c0aa6a63SJacob Faibussowitsch     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n",m,A->cmap->n);CHKERRQ(ierr);
778c0aa6a63SJacob Faibussowitsch     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %" PetscInt_FMT " \n",a->nz);CHKERRQ(ierr);
779fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
780c0aa6a63SJacob Faibussowitsch     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
781fbfe6fa7SJed Brown #else
782c0aa6a63SJacob Faibussowitsch     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
783fbfe6fa7SJed Brown #endif
784b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
78517ab2063SBarry Smith 
78617ab2063SBarry Smith     for (i=0; i<m; i++) {
78760e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
788aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
789c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e %18.16e\n",i+1,a->j[j]+1,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
79017ab2063SBarry Smith #else
791c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
79217ab2063SBarry Smith #endif
79317ab2063SBarry Smith       }
79417ab2063SBarry Smith     }
795d00d2cf4SBarry Smith     if (nofinalvalue) {
796c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
797c0aa6a63SJacob Faibussowitsch       ierr = PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
798c337ccceSJed Brown #else
799c0aa6a63SJacob Faibussowitsch       ierr = PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
800c337ccceSJed Brown #endif
801d00d2cf4SBarry Smith     }
802317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
803fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
804d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
805fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
806d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
80744cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
808c0aa6a63SJacob Faibussowitsch       ierr = PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i);CHKERRQ(ierr);
80960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
810aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
81136db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
812c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81336db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
814c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81536db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
816c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8176831982aSBarry Smith         }
81844cd7ae7SLois Curfman McInnes #else
819c0aa6a63SJacob Faibussowitsch         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
82044cd7ae7SLois Curfman McInnes #endif
82144cd7ae7SLois Curfman McInnes       }
822b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
82344cd7ae7SLois Curfman McInnes     }
824d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
825fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
82697f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
827d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
828854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
829496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
830496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
83160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
832496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
833aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
83436db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
835496be53dSLois Curfman McInnes #else
836496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
837496be53dSLois Curfman McInnes #endif
838496be53dSLois Curfman McInnes         }
839496be53dSLois Curfman McInnes       }
840496be53dSLois Curfman McInnes     }
8412e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
842c0aa6a63SJacob Faibussowitsch     ierr    = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n\n",m,nzd);CHKERRQ(ierr);
8432e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8442205254eSKarl Rupp       if (i+4<m) {
845c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);CHKERRQ(ierr);
8462205254eSKarl Rupp       } else if (i+3<m) {
847c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);CHKERRQ(ierr);
8482205254eSKarl Rupp       } else if (i+2<m) {
849c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8502205254eSKarl Rupp       } else if (i+1<m) {
851c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8522205254eSKarl Rupp       } else if (i<m) {
853c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8542205254eSKarl Rupp       } else {
855c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT "\n",sptr[i]);CHKERRQ(ierr);
8562205254eSKarl Rupp       }
857496be53dSLois Curfman McInnes     }
858b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
859606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
860496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
86160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
862c0aa6a63SJacob Faibussowitsch         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " ",a->j[j]+fshift);CHKERRQ(ierr);}
863496be53dSLois Curfman McInnes       }
864b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
865496be53dSLois Curfman McInnes     }
866b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
867496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
86860e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
869496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
870aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
87136db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
87260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8736831982aSBarry Smith           }
874496be53dSLois Curfman McInnes #else
87560e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
876496be53dSLois Curfman McInnes #endif
877496be53dSLois Curfman McInnes         }
878496be53dSLois Curfman McInnes       }
879b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
880496be53dSLois Curfman McInnes     }
881d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
882fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
88397f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
88487828ca2SBarry Smith     PetscScalar value;
88568f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
88668f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
88768f1ed48SBarry Smith 
88868f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
88968f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
89068f1ed48SBarry Smith         realonly = PETSC_FALSE;
89168f1ed48SBarry Smith         break;
89268f1ed48SBarry Smith       }
89368f1ed48SBarry Smith     }
89468f1ed48SBarry Smith #endif
89502594712SBarry Smith 
896d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
89702594712SBarry Smith     for (i=0; i<m; i++) {
89802594712SBarry Smith       jcnt = 0;
899d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
900e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
90102594712SBarry Smith           value = a->a[cnt++];
902e24b481bSBarry Smith           jcnt++;
90302594712SBarry Smith         } else {
90402594712SBarry Smith           value = 0.0;
90502594712SBarry Smith         }
906aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
90768f1ed48SBarry Smith         if (realonly) {
90860e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
90968f1ed48SBarry Smith         } else {
91060e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
91168f1ed48SBarry Smith         }
91202594712SBarry Smith #else
91360e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
91402594712SBarry Smith #endif
91502594712SBarry Smith       }
916b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
91702594712SBarry Smith     }
918d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9193c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
920150b93efSMatthew G. Knepley     PetscInt fshift=1;
921d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9223c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
92319303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9243c215bfdSMatthew Knepley #else
92519303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9263c215bfdSMatthew Knepley #endif
927c0aa6a63SJacob Faibussowitsch     ierr = PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9283c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
92960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9303c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
931c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %g %g\n", i+fshift,a->j[j]+fshift,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9323c215bfdSMatthew Knepley #else
933c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9343c215bfdSMatthew Knepley #endif
9353c215bfdSMatthew Knepley       }
9363c215bfdSMatthew Knepley     }
937d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9383a40ed3dSBarry Smith   } else {
939d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
940d5f3da31SBarry Smith     if (A->factortype) {
94116cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
942c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i);CHKERRQ(ierr);
94316cd7e1dSShri Abhyankar         /* L part */
94460e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
94516cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
94616cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
947c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
94816cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
949c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
95016cd7e1dSShri Abhyankar           } else {
951c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
95216cd7e1dSShri Abhyankar           }
95316cd7e1dSShri Abhyankar #else
954c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
95516cd7e1dSShri Abhyankar #endif
95616cd7e1dSShri Abhyankar         }
95716cd7e1dSShri Abhyankar         /* diagonal */
95816cd7e1dSShri Abhyankar         j = a->diag[i];
95916cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
96016cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
961c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j]));CHKERRQ(ierr);
96216cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
963c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j])));CHKERRQ(ierr);
96416cd7e1dSShri Abhyankar         } else {
965c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
96616cd7e1dSShri Abhyankar         }
96716cd7e1dSShri Abhyankar #else
968c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
96916cd7e1dSShri Abhyankar #endif
97016cd7e1dSShri Abhyankar 
97116cd7e1dSShri Abhyankar         /* U part */
97260e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
97316cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
97416cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
975c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
97616cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
977c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
97816cd7e1dSShri Abhyankar           } else {
979c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
98016cd7e1dSShri Abhyankar           }
98116cd7e1dSShri Abhyankar #else
982c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
98316cd7e1dSShri Abhyankar #endif
98416cd7e1dSShri Abhyankar         }
98516cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
98616cd7e1dSShri Abhyankar       }
98716cd7e1dSShri Abhyankar     } else {
98817ab2063SBarry Smith       for (i=0; i<m; i++) {
989c0aa6a63SJacob Faibussowitsch         ierr = PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i);CHKERRQ(ierr);
99060e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
991aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
99236db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
993c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
99436db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
995c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9963a40ed3dSBarry Smith           } else {
997c0aa6a63SJacob Faibussowitsch             ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
99817ab2063SBarry Smith           }
99917ab2063SBarry Smith #else
1000c0aa6a63SJacob Faibussowitsch           ierr = PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
100117ab2063SBarry Smith #endif
100217ab2063SBarry Smith         }
1003b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
100417ab2063SBarry Smith       }
100516cd7e1dSShri Abhyankar     }
1006d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
100717ab2063SBarry Smith   }
1008b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10093a40ed3dSBarry Smith   PetscFunctionReturn(0);
1010416022c9SBarry Smith }
1011416022c9SBarry Smith 
10129804daf3SBarry Smith #include <petscdraw.h>
1013dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1014416022c9SBarry Smith {
1015480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1016416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1017dfbe8321SBarry Smith   PetscErrorCode    ierr;
1018383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1019383922c3SLisandro Dalcin   int               color;
1020b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1021b0a32e0cSBarry Smith   PetscViewer       viewer;
1022f3ef73ceSBarry Smith   PetscViewerFormat format;
1023fff043a9SJunchao Zhang   const PetscScalar *aa;
1024cddf8d76SBarry Smith 
10253a40ed3dSBarry Smith   PetscFunctionBegin;
1026480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1027b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1028b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1029383922c3SLisandro Dalcin 
1030416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
1031fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1032fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1033383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10340513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1035b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1036416022c9SBarry Smith     for (i=0; i<m; i++) {
1037cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1038bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1039bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1040fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) >=  0.) continue;
1041b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1042cddf8d76SBarry Smith       }
1043cddf8d76SBarry Smith     }
1044b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1045cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1046cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1047bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1048bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1049fff043a9SJunchao Zhang         if (aa[j] !=  0.) continue;
1050b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1051cddf8d76SBarry Smith       }
1052cddf8d76SBarry Smith     }
1053b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1054cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1055cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1056bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1057bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1058fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) <=  0.) continue;
1059b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1060416022c9SBarry Smith       }
1061416022c9SBarry Smith     }
1062383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10630513a670SBarry Smith   } else {
10640513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10650513a670SBarry Smith     /* first determine max of all nonzero values */
1066b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1067383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1068b0a32e0cSBarry Smith     PetscDraw popup;
10690513a670SBarry Smith 
10700513a670SBarry Smith     for (i=0; i<nz; i++) {
1071fff043a9SJunchao Zhang       if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]);
10720513a670SBarry Smith     }
1073383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1074b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
107545f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1076383922c3SLisandro Dalcin 
1077383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10780513a670SBarry Smith     for (i=0; i<m; i++) {
1079383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1080383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1081bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1082383922c3SLisandro Dalcin         x_l = a->j[j];
1083383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1084fff043a9SJunchao Zhang         color = PetscDrawRealToColor(PetscAbsScalar(aa[count]),minv,maxv);
1085b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
10860513a670SBarry Smith         count++;
10870513a670SBarry Smith       }
10880513a670SBarry Smith     }
1089383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10900513a670SBarry Smith   }
1091fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1092480ef9eaSBarry Smith   PetscFunctionReturn(0);
1093480ef9eaSBarry Smith }
1094cddf8d76SBarry Smith 
10959804daf3SBarry Smith #include <petscdraw.h>
1096dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1097480ef9eaSBarry Smith {
1098dfbe8321SBarry Smith   PetscErrorCode ierr;
1099b0a32e0cSBarry Smith   PetscDraw      draw;
110036db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1101ace3abfcSBarry Smith   PetscBool      isnull;
1102480ef9eaSBarry Smith 
1103480ef9eaSBarry Smith   PetscFunctionBegin;
1104b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1105b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1106480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1107480ef9eaSBarry Smith 
1108d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1109480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1110b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1111832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1112b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11130298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1114832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11153a40ed3dSBarry Smith   PetscFunctionReturn(0);
1116416022c9SBarry Smith }
1117416022c9SBarry Smith 
1118dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1119416022c9SBarry Smith {
1120dfbe8321SBarry Smith   PetscErrorCode ierr;
1121ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1122416022c9SBarry Smith 
11233a40ed3dSBarry Smith   PetscFunctionBegin;
1124251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1125251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1126251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1127c45a1595SBarry Smith   if (iascii) {
11283a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11290f5bd95cSBarry Smith   } else if (isbinary) {
11303a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11310f5bd95cSBarry Smith   } else if (isdraw) {
11323a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
113311aeaf0aSBarry Smith   }
11344108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11353a40ed3dSBarry Smith   PetscFunctionReturn(0);
113617ab2063SBarry Smith }
113719bcc07fSBarry Smith 
1138dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
113917ab2063SBarry Smith {
1140416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11416849ba73SBarry Smith   PetscErrorCode ierr;
1142580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1143d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
114454f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11453447b6efSHong Zhang   PetscReal      ratio  = 0.6;
114617ab2063SBarry Smith 
11473a40ed3dSBarry Smith   PetscFunctionBegin;
11483a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1149071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1150b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1151b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1152b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1153b215bc84SStefano Zampini     PetscFunctionReturn(0);
1154b215bc84SStefano Zampini   }
115517ab2063SBarry Smith 
115643ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
115717ab2063SBarry Smith   for (i=1; i<m; i++) {
1158416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
115917ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
116094a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
116117ab2063SBarry Smith     if (fshift) {
1162bfeeae90SHong Zhang       ip = aj + ai[i];
1163bfeeae90SHong Zhang       ap = aa + ai[i];
116417ab2063SBarry Smith       N  = ailen[i];
1165580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1166580bdb30SBarry Smith       if (!A->structure_only) {
1167580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
116817ab2063SBarry Smith       }
116917ab2063SBarry Smith     }
117017ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
117117ab2063SBarry Smith   }
117217ab2063SBarry Smith   if (m) {
117317ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
117417ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
117517ab2063SBarry Smith   }
11767b083b7cSBarry Smith 
117717ab2063SBarry Smith   /* reset ilen and imax for each row */
11787b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1179396832f4SHong Zhang   if (A->structure_only) {
1180071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1181071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1182396832f4SHong Zhang   } else { /* !A->structure_only */
118317ab2063SBarry Smith     for (i=0; i<m; i++) {
118417ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11857b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
118617ab2063SBarry Smith     }
1187396832f4SHong Zhang   }
1188bfeeae90SHong Zhang   a->nz = ai[m];
11892c71b3e2SJacob Faibussowitsch   PetscCheckFalse(fshift && a->nounused == -1,PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %" PetscInt_FMT " X %" PetscInt_FMT ", %" PetscInt_FMT " unneeded", m, A->cmap->n, fshift);
119017ab2063SBarry Smith 
119109f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
11927d3de750SJacob Faibussowitsch   ierr = PetscInfo(A,"Matrix size: %" PetscInt_FMT " X %" PetscInt_FMT "; storage space: %" PetscInt_FMT " unneeded,%" PetscInt_FMT " used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr);
11937d3de750SJacob Faibussowitsch   ierr = PetscInfo(A,"Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n",a->reallocs);CHKERRQ(ierr);
11947d3de750SJacob Faibussowitsch   ierr = PetscInfo(A,"Maximum nonzeros in any row is %" PetscInt_FMT "\n",rmax);CHKERRQ(ierr);
11952205254eSKarl Rupp 
11968e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1197dd5f02e7SSatish Balay   a->reallocs         = 0;
11986712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
119936db0b34SBarry Smith   a->rmax             = rmax;
12004e220ebcSLois Curfman McInnes 
1201396832f4SHong Zhang   if (!A->structure_only) {
120211e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1203396832f4SHong Zhang   }
12044108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12053a40ed3dSBarry Smith   PetscFunctionReturn(0);
120617ab2063SBarry Smith }
120717ab2063SBarry Smith 
120899cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
120999cafbc1SBarry Smith {
121099cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
121199cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12122e5835c6SStefano Zampini   MatScalar      *aa;
1213acf2f550SJed Brown   PetscErrorCode ierr;
121499cafbc1SBarry Smith 
121599cafbc1SBarry Smith   PetscFunctionBegin;
12162e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
121799cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
12182e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1219acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
122099cafbc1SBarry Smith   PetscFunctionReturn(0);
122199cafbc1SBarry Smith }
122299cafbc1SBarry Smith 
122399cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
122499cafbc1SBarry Smith {
122599cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
122699cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12272e5835c6SStefano Zampini   MatScalar      *aa;
1228acf2f550SJed Brown   PetscErrorCode ierr;
122999cafbc1SBarry Smith 
123099cafbc1SBarry Smith   PetscFunctionBegin;
12312e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
123299cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12332e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1234acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
123599cafbc1SBarry Smith   PetscFunctionReturn(0);
123699cafbc1SBarry Smith }
123799cafbc1SBarry Smith 
1238dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
123917ab2063SBarry Smith {
1240dfbe8321SBarry Smith   PetscErrorCode ierr;
1241fff043a9SJunchao Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1242fff043a9SJunchao Zhang   MatScalar      *aa;
12433a40ed3dSBarry Smith 
12443a40ed3dSBarry Smith   PetscFunctionBegin;
1245fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayWrite(A,&aa);CHKERRQ(ierr);
1246fff043a9SJunchao Zhang   ierr = PetscArrayzero(aa,a->i[A->rmap->n]);CHKERRQ(ierr);
1247fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayWrite(A,&aa);CHKERRQ(ierr);
1248acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12493a40ed3dSBarry Smith   PetscFunctionReturn(0);
125017ab2063SBarry Smith }
1251416022c9SBarry Smith 
1252*cbc6b225SStefano Zampini PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A)
1253*cbc6b225SStefano Zampini {
1254*cbc6b225SStefano Zampini   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1255*cbc6b225SStefano Zampini   PetscErrorCode ierr;
1256*cbc6b225SStefano Zampini 
1257*cbc6b225SStefano Zampini   PetscFunctionBegin;
1258*cbc6b225SStefano Zampini   ierr = PetscFree(a->perm);CHKERRQ(ierr);
1259*cbc6b225SStefano Zampini   ierr = PetscFree(a->jmap);CHKERRQ(ierr);
1260*cbc6b225SStefano Zampini   PetscFunctionReturn(0);
1261*cbc6b225SStefano Zampini }
1262*cbc6b225SStefano Zampini 
1263dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
126417ab2063SBarry Smith {
1265416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1266dfbe8321SBarry Smith   PetscErrorCode ierr;
1267d5d45c9bSBarry Smith 
12683a40ed3dSBarry Smith   PetscFunctionBegin;
1269aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1270c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)A,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,A->rmap->n,A->cmap->n,a->nz);
127117ab2063SBarry Smith #endif
1272e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
1273*cbc6b225SStefano Zampini   ierr = MatResetPreallocationCOO_SeqAIJ(A);CHKERRQ(ierr);
12746bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12756bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
127605b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1277d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1278071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1279071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1280846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
128171f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
128205b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12836bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
128405b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1285cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
12864108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1287bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1288901853e0SKris Buschelman 
12896718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12906718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12916718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12926718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12936718818eSStefano Zampini      due to different matrix sizes */
12946718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
12956718818eSStefano Zampini 
1296f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1297bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1298bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1299bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1300bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1301bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1302bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
13034222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
13044222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1305e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1306fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
13074222ddf1SHong Zhang #endif
13083d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
13093d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13103d0639e7SStefano Zampini #endif
13114222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1312af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1313af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1314af8000cdSHong Zhang #endif
1315d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1316d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1317d24d4204SJose E. Roman #endif
131863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
131963c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13204222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
132163c07aadSStefano Zampini #endif
1322b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1323c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1324c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1325bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1326bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1327846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1328bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1329bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13304222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13314222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13324222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
1333ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL);CHKERRQ(ierr);
1334394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL);CHKERRQ(ierr);
1335394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL);CHKERRQ(ierr);
13363a40ed3dSBarry Smith   PetscFunctionReturn(0);
133717ab2063SBarry Smith }
133817ab2063SBarry Smith 
1339ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
134017ab2063SBarry Smith {
1341416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13424846f1f5SKris Buschelman   PetscErrorCode ierr;
13433a40ed3dSBarry Smith 
13443a40ed3dSBarry Smith   PetscFunctionBegin;
1345a65d3064SKris Buschelman   switch (op) {
1346a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13474e0d8c25SBarry Smith     a->roworiented = flg;
1348a65d3064SKris Buschelman     break;
1349a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1350a9817697SBarry Smith     a->keepnonzeropattern = flg;
1351a65d3064SKris Buschelman     break;
1352512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1353512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1354a65d3064SKris Buschelman     break;
1355a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13564e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1357a65d3064SKris Buschelman     break;
1358a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13594e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1360a65d3064SKris Buschelman     break;
136128b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
136228b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
136328b2fa4aSMatthew Knepley     break;
1364a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13654e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13660df259c2SBarry Smith     break;
13673d472b54SHong Zhang   case MAT_SPD:
1368b1646e73SJed Brown   case MAT_SYMMETRIC:
1369b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1370b1646e73SJed Brown   case MAT_HERMITIAN:
1371b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1372957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13735021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13745021d80fSJed Brown     break;
13758c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1376a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1377a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
13787d3de750SJacob Faibussowitsch     ierr = PetscInfo(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1379a65d3064SKris Buschelman     break;
1380b87ac2d8SJed Brown   case MAT_USE_INODES:
1381b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1382b87ac2d8SJed Brown     break;
1383c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1384c10200c1SHong Zhang     A->submat_singleis = flg;
1385c10200c1SHong Zhang     break;
1386071fcb05SBarry Smith   case MAT_SORTED_FULL:
1387071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1388071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1389071fcb05SBarry Smith     break;
13901a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
13911a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
13921a2c6b5cSJunchao Zhang     break;
1393a65d3064SKris Buschelman   default:
139498921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1395a65d3064SKris Buschelman   }
13963a40ed3dSBarry Smith   PetscFunctionReturn(0);
139717ab2063SBarry Smith }
139817ab2063SBarry Smith 
1399dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
140017ab2063SBarry Smith {
1401416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14026849ba73SBarry Smith   PetscErrorCode    ierr;
1403fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1404c898d852SStefano Zampini   PetscScalar       *x;
1405c898d852SStefano Zampini   const PetscScalar *aa;
140617ab2063SBarry Smith 
14073a40ed3dSBarry Smith   PetscFunctionBegin;
1408d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
14092c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1410c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1411d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1412d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1413fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14142c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1415fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1416c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
141735e7444dSHong Zhang     PetscFunctionReturn(0);
141835e7444dSHong Zhang   }
141935e7444dSHong Zhang 
1420fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
142135e7444dSHong Zhang   for (i=0; i<n; i++) {
1422fdc842d1SBarry Smith     x[i] = 0.0;
142335e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
142435e7444dSHong Zhang       if (aj[j] == i) {
142535e7444dSHong Zhang         x[i] = aa[j];
142617ab2063SBarry Smith         break;
142717ab2063SBarry Smith       }
142817ab2063SBarry Smith     }
142917ab2063SBarry Smith   }
1430fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1431c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14323a40ed3dSBarry Smith   PetscFunctionReturn(0);
143317ab2063SBarry Smith }
143417ab2063SBarry Smith 
1435c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1436dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
143717ab2063SBarry Smith {
1438416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14395f22a7b3SSebastian Grimberg   const MatScalar   *aa;
1440d9ca1df4SBarry Smith   PetscScalar       *y;
1441d9ca1df4SBarry Smith   const PetscScalar *x;
1442dfbe8321SBarry Smith   PetscErrorCode    ierr;
1443d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14445c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
14455f22a7b3SSebastian Grimberg   const MatScalar   *v;
1446a77337e4SBarry Smith   PetscScalar       alpha;
1447d9ca1df4SBarry Smith   PetscInt          n,i,j;
1448d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14493447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1450ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14515c897100SBarry Smith #endif
145217ab2063SBarry Smith 
14533a40ed3dSBarry Smith   PetscFunctionBegin;
14542e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1455d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14561ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1457fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
14585c897100SBarry Smith 
14595c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1460fff043a9SJunchao Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y);
14615c897100SBarry Smith #else
14623447b6efSHong Zhang   if (usecprow) {
14633447b6efSHong Zhang     m    = cprow.nrows;
14643447b6efSHong Zhang     ii   = cprow.i;
14657b2bb3b9SHong Zhang     ridx = cprow.rindex;
14663447b6efSHong Zhang   } else {
14673447b6efSHong Zhang     ii = a->i;
14683447b6efSHong Zhang   }
146917ab2063SBarry Smith   for (i=0; i<m; i++) {
14703447b6efSHong Zhang     idx = a->j + ii[i];
1471fff043a9SJunchao Zhang     v   = aa + ii[i];
14723447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14733447b6efSHong Zhang     if (usecprow) {
14747b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14753447b6efSHong Zhang     } else {
147617ab2063SBarry Smith       alpha = x[i];
14773447b6efSHong Zhang     }
147804fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
147917ab2063SBarry Smith   }
14805c897100SBarry Smith #endif
1481dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1482d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14831ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1484fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14853a40ed3dSBarry Smith   PetscFunctionReturn(0);
148617ab2063SBarry Smith }
148717ab2063SBarry Smith 
1488dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14895c897100SBarry Smith {
1490dfbe8321SBarry Smith   PetscErrorCode ierr;
14915c897100SBarry Smith 
14925c897100SBarry Smith   PetscFunctionBegin;
1493170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14945c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14955c897100SBarry Smith   PetscFunctionReturn(0);
14965c897100SBarry Smith }
14975c897100SBarry Smith 
1498c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
149978b84d54SShri Abhyankar 
1500dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
150117ab2063SBarry Smith {
1502416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1503d9fead3dSBarry Smith   PetscScalar       *y;
150454f21887SBarry Smith   const PetscScalar *x;
1505fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1506dfbe8321SBarry Smith   PetscErrorCode    ierr;
1507003131ecSBarry Smith   PetscInt          m=A->rmap->n;
15080298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
15097b083b7cSBarry Smith   PetscInt          n,i;
1510362ced78SSatish Balay   PetscScalar       sum;
1511ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
151217ab2063SBarry Smith 
1513b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
151497952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1515fee21e36SBarry Smith #endif
1516fee21e36SBarry Smith 
15173a40ed3dSBarry Smith   PetscFunctionBegin;
1518b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1519b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1520b215bc84SStefano Zampini     PetscFunctionReturn(0);
1521b215bc84SStefano Zampini   }
1522fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
15233649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15241ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1525416022c9SBarry Smith   ii   = a->i;
15264eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1527580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
152897952fefSHong Zhang     m    = a->compressedrow.nrows;
152997952fefSHong Zhang     ii   = a->compressedrow.i;
153097952fefSHong Zhang     ridx = a->compressedrow.rindex;
153197952fefSHong Zhang     for (i=0; i<m; i++) {
153297952fefSHong Zhang       n           = ii[i+1] - ii[i];
153397952fefSHong Zhang       aj          = a->j + ii[i];
1534fff043a9SJunchao Zhang       aa          = a_a + ii[i];
153597952fefSHong Zhang       sum         = 0.0;
1536003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1537003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
153897952fefSHong Zhang       y[*ridx++] = sum;
153997952fefSHong Zhang     }
154097952fefSHong Zhang   } else { /* do not use compressed row format */
1541b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15423d3eaba7SBarry Smith     aj   = a->j;
1543fff043a9SJunchao Zhang     aa   = a_a;
1544b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1545b05257ddSBarry Smith #else
154617ab2063SBarry Smith     for (i=0; i<m; i++) {
1547003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1548003131ecSBarry Smith       aj          = a->j + ii[i];
1549fff043a9SJunchao Zhang       aa          = a_a + ii[i];
155017ab2063SBarry Smith       sum         = 0.0;
1551003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
155217ab2063SBarry Smith       y[i] = sum;
155317ab2063SBarry Smith     }
15548d195f9aSBarry Smith #endif
1555b05257ddSBarry Smith   }
15567b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15573649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15581ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1559fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
15603a40ed3dSBarry Smith   PetscFunctionReturn(0);
156117ab2063SBarry Smith }
156217ab2063SBarry Smith 
1563b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1564b434eb95SMatthew G. Knepley {
1565b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1566b434eb95SMatthew G. Knepley   PetscScalar       *y;
1567b434eb95SMatthew G. Knepley   const PetscScalar *x;
1568fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1569b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1570b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1571b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1572b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1573b434eb95SMatthew G. Knepley   PetscScalar       sum;
1574b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1575b434eb95SMatthew G. Knepley 
1576b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1577b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1578b434eb95SMatthew G. Knepley #endif
1579b434eb95SMatthew G. Knepley 
1580b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1581fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1582b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1583b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1584b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1585b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1586b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1587b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1588b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1589b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1590b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1591fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1592b434eb95SMatthew G. Knepley       sum         = 0.0;
1593b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1594b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1595b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1596b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1597b434eb95SMatthew G. Knepley     }
1598b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15993d3eaba7SBarry Smith     ii = a->i;
1600b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1601b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1602b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1603fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1604b434eb95SMatthew G. Knepley       sum         = 0.0;
1605b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1606b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1607b434eb95SMatthew G. Knepley       y[i] = sum;
1608b434eb95SMatthew G. Knepley     }
1609b434eb95SMatthew G. Knepley   }
1610b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1611b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1612b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1613fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
1614b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1615b434eb95SMatthew G. Knepley }
1616b434eb95SMatthew G. Knepley 
1617b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1618b434eb95SMatthew G. Knepley {
1619b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1620b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1621b434eb95SMatthew G. Knepley   const PetscScalar *x;
1622fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1623b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1624b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1625b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1626b434eb95SMatthew G. Knepley   PetscScalar       sum;
1627b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1628b434eb95SMatthew G. Knepley 
1629b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1630fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1631b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1632d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1633b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1634b434eb95SMatthew G. Knepley     if (zz != yy) {
1635580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1636b434eb95SMatthew G. Knepley     }
1637b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1638b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1639b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1640b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1641b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1642b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1643fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1644b434eb95SMatthew G. Knepley       sum = y[*ridx];
1645b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1646b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1647b434eb95SMatthew G. Knepley     }
1648b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16493d3eaba7SBarry Smith     ii = a->i;
1650b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1651b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1652b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1653fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1654b434eb95SMatthew G. Knepley       sum = y[i];
1655b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1656b434eb95SMatthew G. Knepley       z[i] = sum;
1657b434eb95SMatthew G. Knepley     }
1658b434eb95SMatthew G. Knepley   }
1659b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1660b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1661d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1662fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
1663b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1664b434eb95SMatthew G. Knepley }
1665b434eb95SMatthew G. Knepley 
1666c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1667dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
166817ab2063SBarry Smith {
1669416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1670f15663dcSBarry Smith   PetscScalar       *y,*z;
1671f15663dcSBarry Smith   const PetscScalar *x;
1672fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1673dfbe8321SBarry Smith   PetscErrorCode    ierr;
1674d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1675d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1676362ced78SSatish Balay   PetscScalar       sum;
1677ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16789ea0dfa2SSatish Balay 
16793a40ed3dSBarry Smith   PetscFunctionBegin;
1680b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1681b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1682b215bc84SStefano Zampini     PetscFunctionReturn(0);
1683b215bc84SStefano Zampini   }
1684fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1685f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1686d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16874eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16884eb6d288SHong Zhang     if (zz != yy) {
1689580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16904eb6d288SHong Zhang     }
169197952fefSHong Zhang     m    = a->compressedrow.nrows;
169297952fefSHong Zhang     ii   = a->compressedrow.i;
169397952fefSHong Zhang     ridx = a->compressedrow.rindex;
169497952fefSHong Zhang     for (i=0; i<m; i++) {
169597952fefSHong Zhang       n   = ii[i+1] - ii[i];
169697952fefSHong Zhang       aj  = a->j + ii[i];
1697fff043a9SJunchao Zhang       aa  = a_a + ii[i];
169897952fefSHong Zhang       sum = y[*ridx];
1699f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
170097952fefSHong Zhang       z[*ridx++] = sum;
170197952fefSHong Zhang     }
170297952fefSHong Zhang   } else { /* do not use compressed row format */
17033d3eaba7SBarry Smith     ii = a->i;
1704f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
17053d3eaba7SBarry Smith     aj = a->j;
1706fff043a9SJunchao Zhang     aa = a_a;
1707f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1708f15663dcSBarry Smith #else
170917ab2063SBarry Smith     for (i=0; i<m; i++) {
1710f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1711f15663dcSBarry Smith       aj  = a->j + ii[i];
1712fff043a9SJunchao Zhang       aa  = a_a + ii[i];
171317ab2063SBarry Smith       sum = y[i];
1714f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
171517ab2063SBarry Smith       z[i] = sum;
171617ab2063SBarry Smith     }
171702ab625aSSatish Balay #endif
1718f15663dcSBarry Smith   }
1719dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1720f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1721d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1722fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
17233a40ed3dSBarry Smith   PetscFunctionReturn(0);
172417ab2063SBarry Smith }
172517ab2063SBarry Smith 
172617ab2063SBarry Smith /*
172717ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
172817ab2063SBarry Smith */
1729dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
173017ab2063SBarry Smith {
1731416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17326849ba73SBarry Smith   PetscErrorCode ierr;
1733d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
173417ab2063SBarry Smith 
17353a40ed3dSBarry Smith   PetscFunctionBegin;
173609f38230SBarry Smith   if (!a->diag) {
1737785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17383bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
173909f38230SBarry Smith   }
1740d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
174109f38230SBarry Smith     a->diag[i] = a->i[i+1];
1742bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1743bfeeae90SHong Zhang       if (a->j[j] == i) {
174409f38230SBarry Smith         a->diag[i] = j;
174517ab2063SBarry Smith         break;
174617ab2063SBarry Smith       }
174717ab2063SBarry Smith     }
174817ab2063SBarry Smith   }
17493a40ed3dSBarry Smith   PetscFunctionReturn(0);
175017ab2063SBarry Smith }
175117ab2063SBarry Smith 
175261ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
175361ecd0c6SBarry Smith {
175461ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
175561ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
175661ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
175761ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
175861ecd0c6SBarry Smith   PetscErrorCode    ierr;
175961ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
176061ecd0c6SBarry Smith 
176161ecd0c6SBarry Smith   PetscFunctionBegin;
176261ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
176361ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
176461ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
176561ecd0c6SBarry Smith     PetscFunctionReturn(0);
176661ecd0c6SBarry Smith   }
176761ecd0c6SBarry Smith 
176861ecd0c6SBarry Smith   if (a->diagonaldense) {
176961ecd0c6SBarry Smith     cnt = 0;
177061ecd0c6SBarry Smith   } else {
177161ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
177261ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
177361ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
177461ecd0c6SBarry Smith         cnt++;
177561ecd0c6SBarry Smith         mdiag[i] = 1;
177661ecd0c6SBarry Smith       }
177761ecd0c6SBarry Smith     }
177861ecd0c6SBarry Smith   }
177961ecd0c6SBarry Smith   if (!cnt) {
178061ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
178161ecd0c6SBarry Smith   } else {
1782b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1783b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
178461ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
178561ecd0c6SBarry Smith 
178661ecd0c6SBarry Smith     a->a = NULL;
178761ecd0c6SBarry Smith     a->j = NULL;
178861ecd0c6SBarry Smith     a->i = NULL;
178961ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
179061ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
179161ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1792447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
179361ecd0c6SBarry Smith     }
179461ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
179561ecd0c6SBarry Smith 
179661ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
179761ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
179861ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1799447d62f5SStefano Zampini       if (i < A->cmap->n) {
180061ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
180161ecd0c6SBarry Smith       }
1802447d62f5SStefano Zampini     }
180361ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180461ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180561ecd0c6SBarry Smith     if (singlemalloc) {
180661ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
180761ecd0c6SBarry Smith     } else {
180861ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
180961ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
181061ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
181161ecd0c6SBarry Smith     }
181261ecd0c6SBarry Smith   }
181361ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
181461ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
181561ecd0c6SBarry Smith   PetscFunctionReturn(0);
181661ecd0c6SBarry Smith }
181761ecd0c6SBarry Smith 
1818be5855fcSBarry Smith /*
1819be5855fcSBarry Smith      Checks for missing diagonals
1820be5855fcSBarry Smith */
1821ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1822be5855fcSBarry Smith {
1823be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18247734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1825994fe344SLisandro Dalcin   PetscErrorCode ierr;
1826be5855fcSBarry Smith 
1827be5855fcSBarry Smith   PetscFunctionBegin;
182809f38230SBarry Smith   *missing = PETSC_FALSE;
18297734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
183009f38230SBarry Smith     *missing = PETSC_TRUE;
183109f38230SBarry Smith     if (d) *d = 0;
1832994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
183309f38230SBarry Smith   } else {
183401445905SHong Zhang     PetscInt n;
183501445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1836f1e2ffcdSBarry Smith     diag = a->diag;
183701445905SHong Zhang     for (i=0; i<n; i++) {
18387734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
183909f38230SBarry Smith         *missing = PETSC_TRUE;
184009f38230SBarry Smith         if (d) *d = i;
18417d3de750SJacob Faibussowitsch         ierr = PetscInfo(A,"Matrix is missing diagonal number %" PetscInt_FMT "\n",i);CHKERRQ(ierr);
1842358d2f5dSShri Abhyankar         break;
184309f38230SBarry Smith       }
1844be5855fcSBarry Smith     }
1845be5855fcSBarry Smith   }
1846be5855fcSBarry Smith   PetscFunctionReturn(0);
1847be5855fcSBarry Smith }
1848be5855fcSBarry Smith 
18490da83c2eSBarry Smith #include <petscblaslapack.h>
18500da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18510da83c2eSBarry Smith 
18520da83c2eSBarry Smith /*
18530da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18540da83c2eSBarry Smith */
18550da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18560da83c2eSBarry Smith {
18570da83c2eSBarry Smith   PetscErrorCode  ierr;
18580da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18590da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18600da83c2eSBarry Smith   const PetscReal shift = 0.0;
18610da83c2eSBarry Smith   PetscInt        ipvt[5];
18620da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18630da83c2eSBarry Smith 
18640da83c2eSBarry Smith   PetscFunctionBegin;
18650da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18660da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18672c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ncnt != n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %" PetscInt_FMT " doesn't match number matrix rows %" PetscInt_FMT,ncnt,n);
18680da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18690da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18700da83c2eSBarry Smith   }
18710da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18720da83c2eSBarry Smith   if (bsizemax > 7) {
18730da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18740da83c2eSBarry Smith   }
18750da83c2eSBarry Smith   ncnt = 0;
18760da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18770da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18780da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18790da83c2eSBarry Smith     switch (bsizes[i]) {
18800da83c2eSBarry Smith     case 1:
18810da83c2eSBarry Smith       *diag = 1.0/(*diag);
18820da83c2eSBarry Smith       break;
18830da83c2eSBarry Smith     case 2:
18840da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18850da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18860da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18870da83c2eSBarry Smith       break;
18880da83c2eSBarry Smith     case 3:
18890da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18900da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18910da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18920da83c2eSBarry Smith       break;
18930da83c2eSBarry Smith     case 4:
18940da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18950da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18960da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18970da83c2eSBarry Smith       break;
18980da83c2eSBarry Smith     case 5:
18990da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19000da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19010da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
19020da83c2eSBarry Smith       break;
19030da83c2eSBarry Smith     case 6:
19040da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19050da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19060da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
19070da83c2eSBarry Smith       break;
19080da83c2eSBarry Smith     case 7:
19090da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19100da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19110da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
19120da83c2eSBarry Smith       break;
19130da83c2eSBarry Smith     default:
19140da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19150da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19160da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19170da83c2eSBarry Smith     }
19180da83c2eSBarry Smith     ncnt   += bsizes[i];
19190da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19200da83c2eSBarry Smith   }
19210da83c2eSBarry Smith   if (bsizemax > 7) {
19220da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19230da83c2eSBarry Smith   }
19240da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19250da83c2eSBarry Smith   PetscFunctionReturn(0);
19260da83c2eSBarry Smith }
19270da83c2eSBarry Smith 
1928422a814eSBarry Smith /*
1929422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1930422a814eSBarry Smith */
19317087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
193271f1c65dSBarry Smith {
193371f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
193471f1c65dSBarry Smith   PetscErrorCode  ierr;
1935d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19362e5835c6SStefano Zampini   const MatScalar *v;
193754f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
193871f1c65dSBarry Smith 
193971f1c65dSBarry Smith   PetscFunctionBegin;
194071f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
194171f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
194271f1c65dSBarry Smith   diag = a->diag;
194371f1c65dSBarry Smith   if (!a->idiag) {
1944dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19453bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
194671f1c65dSBarry Smith   }
19472e5835c6SStefano Zampini 
194871f1c65dSBarry Smith   mdiag = a->mdiag;
194971f1c65dSBarry Smith   idiag = a->idiag;
19502e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1951422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
195271f1c65dSBarry Smith     for (i=0; i<m; i++) {
195371f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1954899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1955899639b0SHong Zhang         if (PetscRealPart(fshift)) {
19567d3de750SJacob Faibussowitsch           ierr = PetscInfo(A,"Zero diagonal on row %" PetscInt_FMT "\n",i);CHKERRQ(ierr);
19577b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19587b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19597b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
196098921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %" PetscInt_FMT,i);
1961899639b0SHong Zhang       }
196271f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
196371f1c65dSBarry Smith     }
196471f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
196571f1c65dSBarry Smith   } else {
196671f1c65dSBarry Smith     for (i=0; i<m; i++) {
196771f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
196871f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
196971f1c65dSBarry Smith     }
1970dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
197171f1c65dSBarry Smith   }
197271f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19732e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
197471f1c65dSBarry Smith   PetscFunctionReturn(0);
197571f1c65dSBarry Smith }
197671f1c65dSBarry Smith 
1977c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
197841f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
197917ab2063SBarry Smith {
1980416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1981e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19822e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
198354f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1984dfbe8321SBarry Smith   PetscErrorCode    ierr;
19853d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
198697f1f81fSBarry Smith   const PetscInt    *idx,*diag;
198717ab2063SBarry Smith 
19883a40ed3dSBarry Smith   PetscFunctionBegin;
1989b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1990b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1991b215bc84SStefano Zampini     PetscFunctionReturn(0);
1992b215bc84SStefano Zampini   }
1993b965ef7fSBarry Smith   its = its*lits;
199491723122SBarry Smith 
199571f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
199671f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
199771f1c65dSBarry Smith   a->fshift = fshift;
199871f1c65dSBarry Smith   a->omega  = omega;
1999ed480e8bSBarry Smith 
200071f1c65dSBarry Smith   diag  = a->diag;
200171f1c65dSBarry Smith   t     = a->ssor_work;
2002ed480e8bSBarry Smith   idiag = a->idiag;
200371f1c65dSBarry Smith   mdiag = a->mdiag;
2004ed480e8bSBarry Smith 
20052e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
20061ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
20073649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
2008ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
200917ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
201017ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
2011ed480e8bSBarry Smith     bs = b;
201217ab2063SBarry Smith     for (i=0; i<m; i++) {
201371f1c65dSBarry Smith       d   = fshift + mdiag[i];
2014416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2015ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20162e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
201717ab2063SBarry Smith       sum = b[i]*d/omega;
2018003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
201917ab2063SBarry Smith       x[i] = sum;
202017ab2063SBarry Smith     }
20211ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20223649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20232e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2024efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20253a40ed3dSBarry Smith     PetscFunctionReturn(0);
202617ab2063SBarry Smith   }
2027c783ea89SBarry Smith 
20282c71b3e2SJacob Faibussowitsch   PetscCheckFalse(flag == SOR_APPLY_LOWER,PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20292205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20304c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2031887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
203217ab2063SBarry Smith 
203317ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
203417ab2063SBarry Smith 
2035887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
203617ab2063SBarry Smith     */
203717ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
203817ab2063SBarry Smith 
203917ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
204017ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2041416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2042ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20432e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
204417ab2063SBarry Smith       sum = b[i];
2045e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2046ed480e8bSBarry Smith       x[i] = sum*idiag[i];
204717ab2063SBarry Smith     }
204817ab2063SBarry Smith 
204917ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20502e5835c6SStefano Zampini     v = aa;
20512205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
205217ab2063SBarry Smith 
205317ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2054ed480e8bSBarry Smith     ts   = t;
2055416022c9SBarry Smith     diag = a->diag;
205617ab2063SBarry Smith     for (i=0; i<m; i++) {
2057416022c9SBarry Smith       n   = diag[i] - a->i[i];
2058ed480e8bSBarry Smith       idx = a->j + a->i[i];
20592e5835c6SStefano Zampini       v   = aa + a->i[i];
206017ab2063SBarry Smith       sum = t[i];
2061003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2062ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2063733d66baSBarry Smith       /*  x = x + t */
2064733d66baSBarry Smith       x[i] += t[i];
206517ab2063SBarry Smith     }
206617ab2063SBarry Smith 
2067dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20681ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20693649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20703a40ed3dSBarry Smith     PetscFunctionReturn(0);
207117ab2063SBarry Smith   }
207217ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
207317ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
207417ab2063SBarry Smith       for (i=0; i<m; i++) {
2075416022c9SBarry Smith         n   = diag[i] - a->i[i];
2076ed480e8bSBarry Smith         idx = a->j + a->i[i];
20772e5835c6SStefano Zampini         v   = aa + a->i[i];
207817ab2063SBarry Smith         sum = b[i];
2079e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20805c99c7daSBarry Smith         t[i] = sum;
2081ed480e8bSBarry Smith         x[i] = sum*idiag[i];
208217ab2063SBarry Smith       }
20835c99c7daSBarry Smith       xb   = t;
2084efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20853a40ed3dSBarry Smith     } else xb = b;
208617ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
208717ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2088416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2089ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20902e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
209117ab2063SBarry Smith         sum = xb[i];
2092e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20935c99c7daSBarry Smith         if (xb == b) {
2094ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20955c99c7daSBarry Smith         } else {
2096b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
209717ab2063SBarry Smith         }
20985c99c7daSBarry Smith       }
2099b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
210017ab2063SBarry Smith     }
210117ab2063SBarry Smith     its--;
210217ab2063SBarry Smith   }
210317ab2063SBarry Smith   while (its--) {
210417ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
210517ab2063SBarry Smith       for (i=0; i<m; i++) {
2106b19a5dc2SMark Adams         /* lower */
2107b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2108ed480e8bSBarry Smith         idx = a->j + a->i[i];
21092e5835c6SStefano Zampini         v   = aa + a->i[i];
211017ab2063SBarry Smith         sum = b[i];
2111e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2112b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2113b19a5dc2SMark Adams         /* upper */
2114b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2115b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21162e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2117b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2118b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
211917ab2063SBarry Smith       }
2120b19a5dc2SMark Adams       xb   = t;
21219f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2122b19a5dc2SMark Adams     } else xb = b;
212317ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
212417ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2125b19a5dc2SMark Adams         sum = xb[i];
2126b19a5dc2SMark Adams         if (xb == b) {
2127b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2128416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2129ed480e8bSBarry Smith           idx = a->j + a->i[i];
21302e5835c6SStefano Zampini           v   = aa + a->i[i];
2131e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2132ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2133b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2134b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2135b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21362e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2137b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2138b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
213917ab2063SBarry Smith         }
2140b19a5dc2SMark Adams       }
2141b19a5dc2SMark Adams       if (xb == b) {
21429f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2143b19a5dc2SMark Adams       } else {
2144b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2145b19a5dc2SMark Adams       }
214617ab2063SBarry Smith     }
214717ab2063SBarry Smith   }
21482e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21491ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21503649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2151365a8a9eSBarry Smith   PetscFunctionReturn(0);
215217ab2063SBarry Smith }
215317ab2063SBarry Smith 
2154dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
215517ab2063SBarry Smith {
2156416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21574e220ebcSLois Curfman McInnes 
21583a40ed3dSBarry Smith   PetscFunctionBegin;
21594e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21603966268fSBarry Smith   info->nz_allocated = a->maxnz;
21613966268fSBarry Smith   info->nz_used      = a->nz;
21623966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21633966268fSBarry Smith   info->assemblies   = A->num_ass;
21643966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21657adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2166d5f3da31SBarry Smith   if (A->factortype) {
21674e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21684e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21694e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21704e220ebcSLois Curfman McInnes   } else {
21714e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21724e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21734e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21744e220ebcSLois Curfman McInnes   }
21753a40ed3dSBarry Smith   PetscFunctionReturn(0);
217617ab2063SBarry Smith }
217717ab2063SBarry Smith 
21782b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
217917ab2063SBarry Smith {
2180416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2181c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21826849ba73SBarry Smith   PetscErrorCode    ierr;
218397b48c8fSBarry Smith   const PetscScalar *xx;
21842e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2185c7da8527SEric Chamberland   PetscInt          d = 0;
218617ab2063SBarry Smith 
21873a40ed3dSBarry Smith   PetscFunctionBegin;
218897b48c8fSBarry Smith   if (x && b) {
218997b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
219097b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
219197b48c8fSBarry Smith     for (i=0; i<N; i++) {
21922c71b3e2SJacob Faibussowitsch       PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2193447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
219497b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
219597b48c8fSBarry Smith     }
219697b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
219797b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
219897b48c8fSBarry Smith   }
219997b48c8fSBarry Smith 
22002e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
2201a9817697SBarry Smith   if (a->keepnonzeropattern) {
2202f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
22032c71b3e2SJacob Faibussowitsch       PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
22042e5835c6SStefano Zampini       ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2205f1e2ffcdSBarry Smith     }
2206f4df32b1SMatthew Knepley     if (diag != 0.0) {
2207c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2208c7da8527SEric Chamberland         d = rows[i];
2209447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22102c71b3e2SJacob Faibussowitsch         PetscCheckFalse(a->diag[d] >= a->i[d+1],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in the zeroed row %" PetscInt_FMT,d);
2211c7da8527SEric Chamberland       }
2212f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2213447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22142e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2215f1e2ffcdSBarry Smith       }
2216f1e2ffcdSBarry Smith     }
2217f1e2ffcdSBarry Smith   } else {
2218f4df32b1SMatthew Knepley     if (diag != 0.0) {
221917ab2063SBarry Smith       for (i=0; i<N; i++) {
22202c71b3e2SJacob Faibussowitsch         PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
22217ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2222447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2223447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2224447d62f5SStefano Zampini           } else {
2225416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
22262e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2227bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2228447d62f5SStefano Zampini           }
2229447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2230f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
223117ab2063SBarry Smith         }
223217ab2063SBarry Smith       }
22333a40ed3dSBarry Smith     } else {
223417ab2063SBarry Smith       for (i=0; i<N; i++) {
22352c71b3e2SJacob Faibussowitsch         PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2236416022c9SBarry Smith         a->ilen[rows[i]] = 0;
223717ab2063SBarry Smith       }
223817ab2063SBarry Smith     }
2239e56f5c9eSBarry Smith     A->nonzerostate++;
2240f1e2ffcdSBarry Smith   }
22412e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22424099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22433a40ed3dSBarry Smith   PetscFunctionReturn(0);
224417ab2063SBarry Smith }
224517ab2063SBarry Smith 
22466e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22476e169961SBarry Smith {
22486e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22496e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22506e169961SBarry Smith   PetscErrorCode    ierr;
22512b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22526e169961SBarry Smith   const PetscScalar *xx;
22532e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22546e169961SBarry Smith 
22556e169961SBarry Smith   PetscFunctionBegin;
22562e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22572e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
22586e169961SBarry Smith   if (x && b) {
22596e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22606e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22612b40b63fSBarry Smith     vecs = PETSC_TRUE;
22626e169961SBarry Smith   }
22631795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22646e169961SBarry Smith   for (i=0; i<N; i++) {
22652c71b3e2SJacob Faibussowitsch     PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
22662e5835c6SStefano Zampini     ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22672205254eSKarl Rupp 
22686e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22696e169961SBarry Smith   }
22706e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22716e169961SBarry Smith     if (!zeroed[i]) {
22726e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22734cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22742e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22752e5835c6SStefano Zampini           aa[j] = 0.0;
22766e169961SBarry Smith         }
22776e169961SBarry Smith       }
22784cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22796e169961SBarry Smith   }
22806e169961SBarry Smith   if (x && b) {
22816e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22826e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22836e169961SBarry Smith   }
22846e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22856e169961SBarry Smith   if (diag != 0.0) {
22866e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22871d5a398dSstefano_zampini     if (missing) {
22881d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22894cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22902c71b3e2SJacob Faibussowitsch         PetscCheckFalse(a->nonew && rows[i] >= d,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %" PetscInt_FMT " (%" PetscInt_FMT ")",d,rows[i]);
22911d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22921d5a398dSstefano_zampini       }
22931d5a398dSstefano_zampini     } else {
22946e169961SBarry Smith       for (i=0; i<N; i++) {
22952e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
22966e169961SBarry Smith       }
22976e169961SBarry Smith     }
22981d5a398dSstefano_zampini   }
22992e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
23004099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23016e169961SBarry Smith   PetscFunctionReturn(0);
23026e169961SBarry Smith }
23036e169961SBarry Smith 
2304a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
230517ab2063SBarry Smith {
23062e5835c6SStefano Zampini   PetscErrorCode  ierr;
2307fff043a9SJunchao Zhang   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2308fff043a9SJunchao Zhang   const PetscScalar *aa;
2309fff043a9SJunchao Zhang   PetscInt          *itmp;
231017ab2063SBarry Smith 
23113a40ed3dSBarry Smith   PetscFunctionBegin;
23122e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
2313416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
23142e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
231517ab2063SBarry Smith   if (idx) {
2316bfeeae90SHong Zhang     itmp = a->j + a->i[row];
231726fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2318f4259b30SLisandro Dalcin     else *idx = NULL;
231917ab2063SBarry Smith   }
23202e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
23213a40ed3dSBarry Smith   PetscFunctionReturn(0);
232217ab2063SBarry Smith }
232317ab2063SBarry Smith 
2324a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
232517ab2063SBarry Smith {
23263a40ed3dSBarry Smith   PetscFunctionBegin;
2327cb4a9cd9SHong Zhang   if (nz)  *nz = 0;
23282e5835c6SStefano Zampini   if (idx) *idx = NULL;
23292e5835c6SStefano Zampini   if (v)   *v = NULL;
23303a40ed3dSBarry Smith   PetscFunctionReturn(0);
233117ab2063SBarry Smith }
233217ab2063SBarry Smith 
2333dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
233417ab2063SBarry Smith {
2335416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
23362e5835c6SStefano Zampini   const MatScalar *v;
233736db0b34SBarry Smith   PetscReal       sum = 0.0;
23386849ba73SBarry Smith   PetscErrorCode  ierr;
233997f1f81fSBarry Smith   PetscInt        i,j;
234017ab2063SBarry Smith 
23413a40ed3dSBarry Smith   PetscFunctionBegin;
23422e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
234317ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2344570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2345570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
234673cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2347570b7f6dSBarry Smith #else
2348416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
234936db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
235017ab2063SBarry Smith     }
23518f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2352570b7f6dSBarry Smith #endif
2353ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23543a40ed3dSBarry Smith   } else if (type == NORM_1) {
235536db0b34SBarry Smith     PetscReal *tmp;
235697f1f81fSBarry Smith     PetscInt  *jj = a->j;
23571795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2358064f8208SBarry Smith     *nrm = 0.0;
2359416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2360bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
236117ab2063SBarry Smith     }
2362d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2363064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
236417ab2063SBarry Smith     }
2365606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
236651f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23673a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2368064f8208SBarry Smith     *nrm = 0.0;
2369d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23702e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
237117ab2063SBarry Smith       sum = 0.0;
2372416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23732e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
237417ab2063SBarry Smith       }
2375064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
237617ab2063SBarry Smith     }
237751f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2378f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23792e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
23803a40ed3dSBarry Smith   PetscFunctionReturn(0);
238117ab2063SBarry Smith }
238217ab2063SBarry Smith 
23834e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23844e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23854e938277SHong Zhang {
23864e938277SHong Zhang   PetscErrorCode ierr;
23874e938277SHong Zhang   PetscInt       i,j,anzj;
23884e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23894e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23904e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23914e938277SHong Zhang 
23924e938277SHong Zhang   PetscFunctionBegin;
23934e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2394854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2395785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2396785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
23974e938277SHong Zhang 
23984e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23994e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
240026fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
24014e938277SHong Zhang   /* Form ati for csr format of A^T. */
240226fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
24034e938277SHong Zhang 
24044e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2405580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
24064e938277SHong Zhang 
24074e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
24084e938277SHong Zhang   for (i=0;i<am;i++) {
24094e938277SHong Zhang     anzj = ai[i+1] - ai[i];
24104e938277SHong Zhang     for (j=0;j<anzj;j++) {
24114e938277SHong Zhang       atj[atfill[*aj]] = i;
24124e938277SHong Zhang       atfill[*aj++]   += 1;
24134e938277SHong Zhang     }
24144e938277SHong Zhang   }
24154e938277SHong Zhang 
24164e938277SHong Zhang   /* Clean up temporary space and complete requests. */
24174e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2418ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
241933d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2420b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2421a2f3521dSMark F. Adams 
24224e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
24234e938277SHong Zhang   b->free_a  = PETSC_FALSE;
24244e938277SHong Zhang   b->free_ij = PETSC_TRUE;
24254e938277SHong Zhang   b->nonew   = 0;
24264e938277SHong Zhang   PetscFunctionReturn(0);
24274e938277SHong Zhang }
24284e938277SHong Zhang 
24297087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2430cd0d46ebSvictorle {
24313d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
243254f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
24332e5835c6SStefano Zampini   const MatScalar *va,*vb;
24346849ba73SBarry Smith   PetscErrorCode  ierr;
243597f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2436cd0d46ebSvictorle 
2437cd0d46ebSvictorle   PetscFunctionBegin;
2438cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2439cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24405485867bSBarry Smith   if (ma!=nb || na!=mb) {
24415485867bSBarry Smith     *f = PETSC_FALSE;
24425485867bSBarry Smith     PetscFunctionReturn(0);
24435485867bSBarry Smith   }
24442e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr);
24452e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr);
2446cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2447cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2448785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2449785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2450cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2451cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2452cd0d46ebSvictorle 
2453cd0d46ebSvictorle   *f = PETSC_TRUE;
2454cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2455cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
245697f1f81fSBarry Smith       PetscInt    idc,idr;
24575485867bSBarry Smith       PetscScalar vc,vr;
2458cd0d46ebSvictorle       /* column/row index/value */
24595485867bSBarry Smith       idc = adx[aptr[i]];
24605485867bSBarry Smith       idr = bdx[bptr[idc]];
24615485867bSBarry Smith       vc  = va[aptr[i]];
24625485867bSBarry Smith       vr  = vb[bptr[idc]];
24635485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24645485867bSBarry Smith         *f = PETSC_FALSE;
24655485867bSBarry Smith         goto done;
2466cd0d46ebSvictorle       } else {
24675485867bSBarry Smith         aptr[i]++;
24685485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2469cd0d46ebSvictorle       }
2470cd0d46ebSvictorle     }
2471cd0d46ebSvictorle   }
2472cd0d46ebSvictorle done:
2473cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24743aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
24752e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr);
24762e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr);
2477cd0d46ebSvictorle   PetscFunctionReturn(0);
2478cd0d46ebSvictorle }
2479cd0d46ebSvictorle 
24807087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24811cbb95d3SBarry Smith {
24823d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
248354f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
248454f21887SBarry Smith   MatScalar      *va,*vb;
24851cbb95d3SBarry Smith   PetscErrorCode ierr;
24861cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24871cbb95d3SBarry Smith 
24881cbb95d3SBarry Smith   PetscFunctionBegin;
24891cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
24901cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24911cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24921cbb95d3SBarry Smith     *f = PETSC_FALSE;
24931cbb95d3SBarry Smith     PetscFunctionReturn(0);
24941cbb95d3SBarry Smith   }
24951cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24961cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24971cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2498785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2499785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
25001cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
25011cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
25021cbb95d3SBarry Smith 
25031cbb95d3SBarry Smith   *f = PETSC_TRUE;
25041cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
25051cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
25061cbb95d3SBarry Smith       PetscInt    idc,idr;
25071cbb95d3SBarry Smith       PetscScalar vc,vr;
25081cbb95d3SBarry Smith       /* column/row index/value */
25091cbb95d3SBarry Smith       idc = adx[aptr[i]];
25101cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
25111cbb95d3SBarry Smith       vc  = va[aptr[i]];
25121cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
25131cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
25141cbb95d3SBarry Smith         *f = PETSC_FALSE;
25151cbb95d3SBarry Smith         goto done;
25161cbb95d3SBarry Smith       } else {
25171cbb95d3SBarry Smith         aptr[i]++;
25181cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
25191cbb95d3SBarry Smith       }
25201cbb95d3SBarry Smith     }
25211cbb95d3SBarry Smith   }
25221cbb95d3SBarry Smith done:
25231cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
25241cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
25251cbb95d3SBarry Smith   PetscFunctionReturn(0);
25261cbb95d3SBarry Smith }
25271cbb95d3SBarry Smith 
2528ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25299e29f15eSvictorle {
2530dfbe8321SBarry Smith   PetscErrorCode ierr;
25316e111a19SKarl Rupp 
25329e29f15eSvictorle   PetscFunctionBegin;
25335485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25349e29f15eSvictorle   PetscFunctionReturn(0);
25359e29f15eSvictorle }
25369e29f15eSvictorle 
2537ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25381cbb95d3SBarry Smith {
25391cbb95d3SBarry Smith   PetscErrorCode ierr;
25406e111a19SKarl Rupp 
25411cbb95d3SBarry Smith   PetscFunctionBegin;
25421cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25431cbb95d3SBarry Smith   PetscFunctionReturn(0);
25441cbb95d3SBarry Smith }
25451cbb95d3SBarry Smith 
2546dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
254717ab2063SBarry Smith {
2548416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2549fff8e43fSBarry Smith   const PetscScalar *l,*r;
2550fff8e43fSBarry Smith   PetscScalar       x;
255154f21887SBarry Smith   MatScalar         *v;
2552dfbe8321SBarry Smith   PetscErrorCode    ierr;
2553fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2554fff8e43fSBarry Smith   const PetscInt    *jj;
255517ab2063SBarry Smith 
25563a40ed3dSBarry Smith   PetscFunctionBegin;
255717ab2063SBarry Smith   if (ll) {
25583ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25593ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2560e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
25612c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2562fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
25632e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
256417ab2063SBarry Smith     for (i=0; i<m; i++) {
256517ab2063SBarry Smith       x = l[i];
2566416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25672205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
256817ab2063SBarry Smith     }
2569fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2570efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
25712e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
257217ab2063SBarry Smith   }
257317ab2063SBarry Smith   if (rr) {
2574e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
25752c71b3e2SJacob Faibussowitsch     PetscCheckFalse(n != A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2576fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
25772e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
25782e5835c6SStefano Zampini     jj = a->j;
25792205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
25802e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
2581fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2582efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
258317ab2063SBarry Smith   }
2584acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
25853a40ed3dSBarry Smith   PetscFunctionReturn(0);
258617ab2063SBarry Smith }
258717ab2063SBarry Smith 
25887dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
258917ab2063SBarry Smith {
2590db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
25916849ba73SBarry Smith   PetscErrorCode    ierr;
2592d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
259397f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25945d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
25952e5835c6SStefano Zampini   const PetscScalar *aa;
25965d0c19d7SBarry Smith   PetscInt          nrows,ncols;
259797f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
259854f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2599416022c9SBarry Smith   Mat               C;
2600cdc6f3adSToby Isaac   PetscBool         stride;
260117ab2063SBarry Smith 
26023a40ed3dSBarry Smith   PetscFunctionBegin;
260317ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2604b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2605b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
260617ab2063SBarry Smith 
2607251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2608ff718158SBarry Smith   if (stride) {
2609ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2610ff718158SBarry Smith   } else {
2611ff718158SBarry Smith     first = 0;
2612ff718158SBarry Smith     step  = 0;
2613ff718158SBarry Smith   }
2614fee21e36SBarry Smith   if (stride && step == 1) {
261502834360SBarry Smith     /* special case of contiguous rows */
2616dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
261702834360SBarry Smith     /* loop over new rows determining lens and starting points */
261802834360SBarry Smith     for (i=0; i<nrows; i++) {
2619bfeeae90SHong Zhang       kstart = ai[irow[i]];
2620a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2621a91a9bebSLisandro Dalcin       starts[i] = kstart;
262202834360SBarry Smith       for (k=kstart; k<kend; k++) {
2623bfeeae90SHong Zhang         if (aj[k] >= first) {
262402834360SBarry Smith           starts[i] = k;
262502834360SBarry Smith           break;
262602834360SBarry Smith         }
262702834360SBarry Smith       }
2628a2744918SBarry Smith       sum = 0;
262902834360SBarry Smith       while (k < kend) {
2630bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2631a2744918SBarry Smith         sum++;
263202834360SBarry Smith       }
2633a2744918SBarry Smith       lens[i] = sum;
263402834360SBarry Smith     }
263502834360SBarry Smith     /* create submatrix */
2636cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
263797f1f81fSBarry Smith       PetscInt n_cols,n_rows;
263808480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
26392c71b3e2SJacob Faibussowitsch       PetscCheckFalse(n_rows != nrows || n_cols != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2640d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
264108480c60SBarry Smith       C    = *B;
26423a40ed3dSBarry Smith     } else {
26433bef6203SJed Brown       PetscInt rbs,cbs;
2644ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2645f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26463bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26473bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26483bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26497adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2650ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
265108480c60SBarry Smith     }
2652db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2653db02288aSLois Curfman McInnes 
265402834360SBarry Smith     /* loop over rows inserting into submatrix */
2655db02288aSLois Curfman McInnes     a_new = c->a;
2656db02288aSLois Curfman McInnes     j_new = c->j;
2657db02288aSLois Curfman McInnes     i_new = c->i;
26582e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
265902834360SBarry Smith     for (i=0; i<nrows; i++) {
2660a2744918SBarry Smith       ii    = starts[i];
2661a2744918SBarry Smith       lensi = lens[i];
2662a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2663a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
266402834360SBarry Smith       }
26652e5835c6SStefano Zampini       ierr       = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr);
2666a2744918SBarry Smith       a_new     += lensi;
2667a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2668a2744918SBarry Smith       c->ilen[i] = lensi;
266902834360SBarry Smith     }
26702e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
26710e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26723a40ed3dSBarry Smith   } else {
267302834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26741795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2675854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26764dcab191SBarry Smith     for (i=0; i<ncols; i++) {
26776bdcaf15SBarry Smith       PetscCheck(icol[i] < oldcols,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%" PetscInt_FMT "] %" PetscInt_FMT " >= A->cmap->n %" PetscInt_FMT,i,icol[i],oldcols);
26784dcab191SBarry Smith       smap[icol[i]] = i+1;
26794dcab191SBarry Smith     }
26804dcab191SBarry Smith 
268102834360SBarry Smith     /* determine lens of each row */
268202834360SBarry Smith     for (i=0; i<nrows; i++) {
2683bfeeae90SHong Zhang       kstart  = ai[irow[i]];
268402834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
268502834360SBarry Smith       lens[i] = 0;
268602834360SBarry Smith       for (k=kstart; k<kend; k++) {
2687bfeeae90SHong Zhang         if (smap[aj[k]]) {
268802834360SBarry Smith           lens[i]++;
268902834360SBarry Smith         }
269002834360SBarry Smith       }
269102834360SBarry Smith     }
269217ab2063SBarry Smith     /* Create and fill new matrix */
2693a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2694ace3abfcSBarry Smith       PetscBool equal;
26950f5bd95cSBarry Smith 
269699141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
26972c71b3e2SJacob Faibussowitsch       PetscCheckFalse((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2698580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
26992c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!equal,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2700580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
270108480c60SBarry Smith       C    = *B;
27023a40ed3dSBarry Smith     } else {
27033bef6203SJed Brown       PetscInt rbs,cbs;
2704ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2705f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
27063bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
27073bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
27083bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
27097adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2710ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
271108480c60SBarry Smith     }
27122e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
271399141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
271417ab2063SBarry Smith     for (i=0; i<nrows; i++) {
271599141d43SSatish Balay       row      = irow[i];
2716bfeeae90SHong Zhang       kstart   = ai[row];
271799141d43SSatish Balay       kend     = kstart + a->ilen[row];
2718bfeeae90SHong Zhang       mat_i    = c->i[i];
271999141d43SSatish Balay       mat_j    = c->j + mat_i;
272099141d43SSatish Balay       mat_a    = c->a + mat_i;
272199141d43SSatish Balay       mat_ilen = c->ilen + i;
272217ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2723bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2724ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
27252e5835c6SStefano Zampini           *mat_a++ = aa[k];
272699141d43SSatish Balay           (*mat_ilen)++;
272799141d43SSatish Balay 
272817ab2063SBarry Smith         }
272917ab2063SBarry Smith       }
273017ab2063SBarry Smith     }
27312e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
273202834360SBarry Smith     /* Free work space */
273302834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2734606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2735606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2736cdc6f3adSToby Isaac     /* sort */
2737cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2738cdc6f3adSToby Isaac       PetscInt ilen;
2739cdc6f3adSToby Isaac 
2740cdc6f3adSToby Isaac       mat_i = c->i[i];
2741cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2742cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2743cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2744390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2745cdc6f3adSToby Isaac     }
274602834360SBarry Smith   }
27478c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2748b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2749305c6ccfSStefano Zampini #endif
27506d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27516d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
275217ab2063SBarry Smith 
275317ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2754416022c9SBarry Smith   *B   = C;
27553a40ed3dSBarry Smith   PetscFunctionReturn(0);
275617ab2063SBarry Smith }
275717ab2063SBarry Smith 
2758fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
275982d44351SHong Zhang {
276082d44351SHong Zhang   PetscErrorCode ierr;
276182d44351SHong Zhang   Mat            B;
276282d44351SHong Zhang 
276382d44351SHong Zhang   PetscFunctionBegin;
2764c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
276582d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
276682d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
276733d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
276882d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
276982d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
277082d44351SHong Zhang     *subMat = B;
2771c2d650bdSHong Zhang   } else {
2772c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2773c2d650bdSHong Zhang   }
277482d44351SHong Zhang   PetscFunctionReturn(0);
277582d44351SHong Zhang }
277682d44351SHong Zhang 
27779a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2778a871dcd8SBarry Smith {
277963b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2780dfbe8321SBarry Smith   PetscErrorCode ierr;
278163b91edcSBarry Smith   Mat            outA;
2782ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
278363b91edcSBarry Smith 
27843a40ed3dSBarry Smith   PetscFunctionBegin;
27852c71b3e2SJacob Faibussowitsch   PetscCheckFalse(info->levels != 0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27861df811f5SHong Zhang 
2787b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2788b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2789a871dcd8SBarry Smith 
279063b91edcSBarry Smith   outA             = inA;
2791d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2792f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2793f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
27942205254eSKarl Rupp 
2795c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
27966bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
27972205254eSKarl Rupp 
2798c3122656SLisandro Dalcin   a->row = row;
27992205254eSKarl Rupp 
2800c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
28016bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
28022205254eSKarl Rupp 
2803c3122656SLisandro Dalcin   a->col = col;
280463b91edcSBarry Smith 
280536db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
28066bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
28074c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
28083bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2809f0ec6fceSSatish Balay 
281094a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2811854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
28123bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
281394a9d846SBarry Smith   }
281463b91edcSBarry Smith 
2815f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2816137fb511SHong Zhang   if (row_identity && col_identity) {
2817ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2818137fb511SHong Zhang   } else {
2819719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2820137fb511SHong Zhang   }
28213a40ed3dSBarry Smith   PetscFunctionReturn(0);
2822a871dcd8SBarry Smith }
2823a871dcd8SBarry Smith 
2824f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2825f0b747eeSBarry Smith {
2826f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2827dfa0f9e5SStefano Zampini   PetscScalar    *v;
2828efee365bSSatish Balay   PetscErrorCode ierr;
2829c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
28303a40ed3dSBarry Smith 
28313a40ed3dSBarry Smith   PetscFunctionBegin;
2832dfa0f9e5SStefano Zampini   ierr = MatSeqAIJGetArray(inA,&v);CHKERRQ(ierr);
2833c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
2834dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
2835efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2836dfa0f9e5SStefano Zampini   ierr = MatSeqAIJRestoreArray(inA,&v);CHKERRQ(ierr);
2837acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
28383a40ed3dSBarry Smith   PetscFunctionReturn(0);
2839f0b747eeSBarry Smith }
2840f0b747eeSBarry Smith 
2841f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
284216b64355SHong Zhang {
284316b64355SHong Zhang   PetscErrorCode ierr;
284416b64355SHong Zhang   PetscInt       i;
284516b64355SHong Zhang 
284616b64355SHong Zhang   PetscFunctionBegin;
284716b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
284816b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
284916b64355SHong Zhang 
285016b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
285116b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
285216b64355SHong Zhang     }
285316b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
285416b64355SHong Zhang 
285516b64355SHong Zhang     if (submatj->rbuf1) {
285616b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
285716b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
285816b64355SHong Zhang     }
285916b64355SHong Zhang 
286016b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
286116b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
286216b64355SHong Zhang     }
286316b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
286416b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
286516b64355SHong Zhang   }
286616b64355SHong Zhang 
286716b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
286816b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
286916b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
287016b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
287116b64355SHong Zhang #else
287216b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
287316b64355SHong Zhang #endif
287416b64355SHong Zhang 
287516b64355SHong Zhang   if (!submatj->allcolumns) {
287616b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
287716b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
287816b64355SHong Zhang #else
287916b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
288016b64355SHong Zhang #endif
288116b64355SHong Zhang   }
288216b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
288316b64355SHong Zhang 
288416b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
288516b64355SHong Zhang   PetscFunctionReturn(0);
288616b64355SHong Zhang }
288716b64355SHong Zhang 
28880fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
288916b64355SHong Zhang {
289016b64355SHong Zhang   PetscErrorCode ierr;
289116b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28925c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
289316b64355SHong Zhang 
289416b64355SHong Zhang   PetscFunctionBegin;
289534136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2896f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
289716b64355SHong Zhang   PetscFunctionReturn(0);
289816b64355SHong Zhang }
289916b64355SHong Zhang 
29002d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
29012d033e1fSHong Zhang {
29022d033e1fSHong Zhang   PetscErrorCode ierr;
29032d033e1fSHong Zhang   PetscInt       i;
29040fb991dcSHong Zhang   Mat            C;
29050fb991dcSHong Zhang   Mat_SeqAIJ     *c;
29060fb991dcSHong Zhang   Mat_SubSppt    *submatj;
29072d033e1fSHong Zhang 
29082d033e1fSHong Zhang   PetscFunctionBegin;
29092d033e1fSHong Zhang   for (i=0; i<n; i++) {
29100fb991dcSHong Zhang     C       = (*mat)[i];
29110fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
29120fb991dcSHong Zhang     submatj = c->submatis1;
29132d033e1fSHong Zhang     if (submatj) {
2914682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
291534136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2916f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
291734136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
29182d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
29192d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
29202d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2921682e4c99SStefano Zampini       }
29222d033e1fSHong Zhang     } else {
29232d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
29242d033e1fSHong Zhang     }
29252d033e1fSHong Zhang   }
292686e85357SHong Zhang 
292763a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
292863a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
292963a75b2aSHong Zhang 
29302d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
29312d033e1fSHong Zhang   PetscFunctionReturn(0);
29322d033e1fSHong Zhang }
29332d033e1fSHong Zhang 
29347dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2935cddf8d76SBarry Smith {
2936dfbe8321SBarry Smith   PetscErrorCode ierr;
293797f1f81fSBarry Smith   PetscInt       i;
2938cddf8d76SBarry Smith 
29393a40ed3dSBarry Smith   PetscFunctionBegin;
2940cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2941df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2942cddf8d76SBarry Smith   }
2943cddf8d76SBarry Smith 
2944cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29457dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2946cddf8d76SBarry Smith   }
29473a40ed3dSBarry Smith   PetscFunctionReturn(0);
2948cddf8d76SBarry Smith }
2949cddf8d76SBarry Smith 
295097f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29514dcbc457SBarry Smith {
2952e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29536849ba73SBarry Smith   PetscErrorCode ierr;
29545d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29555d0c19d7SBarry Smith   const PetscInt *idx;
295697f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2957f1af5d2fSBarry Smith   PetscBT        table;
2958bbd702dbSSatish Balay 
29593a40ed3dSBarry Smith   PetscFunctionBegin;
2960d0f46423SBarry Smith   m  = A->rmap->n;
2961e4d965acSSatish Balay   ai = a->i;
2962bfeeae90SHong Zhang   aj = a->j;
29638a047759SSatish Balay 
29642c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ov < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
296506763907SSatish Balay 
2966854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
296753b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
296806763907SSatish Balay 
2969e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2970b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2971e4d965acSSatish Balay     isz  = 0;
29726831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2973e4d965acSSatish Balay 
2974e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29754dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2976b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2977e4d965acSSatish Balay 
2978dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2979e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29802205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29814dcbc457SBarry Smith     }
298206763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
29836bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2984e4d965acSSatish Balay 
298504a348a9SBarry Smith     k = 0;
298604a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
298704a348a9SBarry Smith       n = isz;
298806763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2989e4d965acSSatish Balay         row   = nidx[k];
2990e4d965acSSatish Balay         start = ai[row];
2991e4d965acSSatish Balay         end   = ai[row+1];
299204a348a9SBarry Smith         for (l = start; l<end; l++) {
2993efb16452SHong Zhang           val = aj[l];
29942205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2995e4d965acSSatish Balay         }
2996e4d965acSSatish Balay       }
2997e4d965acSSatish Balay     }
299870b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2999e4d965acSSatish Balay   }
300094bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
3001606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
30023a40ed3dSBarry Smith   PetscFunctionReturn(0);
30034dcbc457SBarry Smith }
300417ab2063SBarry Smith 
30050513a670SBarry Smith /* -------------------------------------------------------------- */
3006dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
30070513a670SBarry Smith {
30080513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
30096849ba73SBarry Smith   PetscErrorCode ierr;
30103b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
30115d0c19d7SBarry Smith   const PetscInt *row,*col;
30125d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
301356cd22aeSBarry Smith   IS             icolp,irowp;
30140298fd71SBarry Smith   PetscInt       *cwork = NULL;
30150298fd71SBarry Smith   PetscScalar    *vwork = NULL;
30160513a670SBarry Smith 
30173a40ed3dSBarry Smith   PetscFunctionBegin;
30184c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
301956cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
30204c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
302156cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
30220513a670SBarry Smith 
30230513a670SBarry Smith   /* determine lengths of permuted rows */
3024854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
30252205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
3026ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
3027f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
302833d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
30297adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
3030ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
3031606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
30320513a670SBarry Smith 
3033785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
30340513a670SBarry Smith   for (i=0; i<m; i++) {
303532ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30362205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3037cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
303832ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30390513a670SBarry Smith   }
3040606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30412205254eSKarl Rupp 
30423c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30432205254eSKarl Rupp 
30448c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3045b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30469fe5e383SStefano Zampini #endif
30470513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30480513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
304956cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
305056cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30516bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30526bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30536768869dSprj-   if (rowp == colp) {
3054dc29a518SPierre Jolivet     ierr = MatPropagateSymmetryOptions(A,*B);CHKERRQ(ierr);
30556768869dSprj-   }
30563a40ed3dSBarry Smith   PetscFunctionReturn(0);
30570513a670SBarry Smith }
30580513a670SBarry Smith 
3059dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3060cb5b572fSBarry Smith {
3061dfbe8321SBarry Smith   PetscErrorCode ierr;
3062cb5b572fSBarry Smith 
3063cb5b572fSBarry Smith   PetscFunctionBegin;
306433f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
306533f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3066be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3067be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30682e5835c6SStefano Zampini     const PetscScalar *aa;
3069be6bf707SBarry Smith 
30702e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30712c71b3e2SJacob Faibussowitsch     PetscCheckFalse(a->i[A->rmap->n] != b->i[B->rmap->n],PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different %" PetscInt_FMT " != %" PetscInt_FMT,a->i[A->rmap->n],b->i[B->rmap->n]);
30722e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3073cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
30742e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3075cb5b572fSBarry Smith   } else {
3076cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3077cb5b572fSBarry Smith   }
3078cb5b572fSBarry Smith   PetscFunctionReturn(0);
3079cb5b572fSBarry Smith }
3080cb5b572fSBarry Smith 
30814994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3082273d9f13SBarry Smith {
3083dfbe8321SBarry Smith   PetscErrorCode ierr;
3084273d9f13SBarry Smith 
3085273d9f13SBarry Smith   PetscFunctionBegin;
3086f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3087273d9f13SBarry Smith   PetscFunctionReturn(0);
3088273d9f13SBarry Smith }
3089273d9f13SBarry Smith 
3090f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30916c0721eeSBarry Smith {
30926c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30936e111a19SKarl Rupp 
30946c0721eeSBarry Smith   PetscFunctionBegin;
30956c0721eeSBarry Smith   *array = a->a;
30966c0721eeSBarry Smith   PetscFunctionReturn(0);
30976c0721eeSBarry Smith }
30986c0721eeSBarry Smith 
3099f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
31006c0721eeSBarry Smith {
31016c0721eeSBarry Smith   PetscFunctionBegin;
3102f38c1e66SStefano Zampini   *array = NULL;
31036c0721eeSBarry Smith   PetscFunctionReturn(0);
31046c0721eeSBarry Smith }
3105273d9f13SBarry Smith 
31068229c054SShri Abhyankar /*
31078229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
31088229c054SShri Abhyankar    have different nonzero structure.
31098229c054SShri Abhyankar */
3110b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3111ec7775f6SShri Abhyankar {
3112b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3113ec7775f6SShri Abhyankar 
3114ec7775f6SShri Abhyankar   PetscFunctionBegin;
3115ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3116ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3117b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3118b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3119b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31208af7cee1SJed Brown     nnz[i] = 0;
31218af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3122b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3123b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31248af7cee1SJed Brown       nnz[i]++;
31258af7cee1SJed Brown     }
31268af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3127ec7775f6SShri Abhyankar   }
3128ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3129ec7775f6SShri Abhyankar }
3130ec7775f6SShri Abhyankar 
3131b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3132b264fe52SHong Zhang {
3133b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3134b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3135b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3136b264fe52SHong Zhang   PetscErrorCode ierr;
3137b264fe52SHong Zhang 
3138b264fe52SHong Zhang   PetscFunctionBegin;
3139b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3140b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3141b264fe52SHong Zhang   PetscFunctionReturn(0);
3142b264fe52SHong Zhang }
3143b264fe52SHong Zhang 
3144f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3145ac90fabeSBarry Smith {
3146dfbe8321SBarry Smith   PetscErrorCode ierr;
3147ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3148ac90fabeSBarry Smith 
3149ac90fabeSBarry Smith   PetscFunctionBegin;
3150134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
3151134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE;
3152134adf20SPierre Jolivet     if (e) {
315381fa06acSBarry Smith       ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
315481fa06acSBarry Smith       if (e) {
315581fa06acSBarry Smith         ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
3156134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
315781fa06acSBarry Smith       }
315881fa06acSBarry Smith     }
315954c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatStructure is not SAME_NONZERO_PATTERN");
316081fa06acSBarry Smith   }
3161ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31622e5835c6SStefano Zampini     const PetscScalar *xa;
31632e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
316481fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
316581fa06acSBarry Smith 
316681fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31672e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31682e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31692e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31702e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31712e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
317241f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3173acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3174a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3175ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3176ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3177ac90fabeSBarry Smith   } else {
31788229c054SShri Abhyankar     Mat      B;
31798229c054SShri Abhyankar     PetscInt *nnz;
3180785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3181ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3182bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
318381fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
31842e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
31858229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3186ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3187ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
318879c2fd05SStefano Zampini     ierr = MatHeaderMerge(Y,&B);CHKERRQ(ierr);
31898229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3190ac90fabeSBarry Smith   }
3191ac90fabeSBarry Smith   PetscFunctionReturn(0);
3192ac90fabeSBarry Smith }
3193ac90fabeSBarry Smith 
31942726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3195354c94deSBarry Smith {
3196354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3197354c94deSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3198354c94deSBarry Smith   PetscInt       i,nz;
3199354c94deSBarry Smith   PetscScalar    *a;
3200ce496241SStefano Zampini   PetscErrorCode ierr;
3201354c94deSBarry Smith 
3202354c94deSBarry Smith   PetscFunctionBegin;
3203354c94deSBarry Smith   nz = aij->nz;
3204ce496241SStefano Zampini   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
32052205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3206ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3207354c94deSBarry Smith #else
3208354c94deSBarry Smith   PetscFunctionBegin;
3209354c94deSBarry Smith #endif
3210354c94deSBarry Smith   PetscFunctionReturn(0);
3211354c94deSBarry Smith }
3212354c94deSBarry Smith 
3213985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3214e34fafa9SBarry Smith {
3215e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3216e34fafa9SBarry Smith   PetscErrorCode  ierr;
3217d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3218e34fafa9SBarry Smith   PetscReal       atmp;
3219985db425SBarry Smith   PetscScalar     *x;
3220ce496241SStefano Zampini   const MatScalar *aa,*av;
3221e34fafa9SBarry Smith 
3222e34fafa9SBarry Smith   PetscFunctionBegin;
32232c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3224ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3225ce496241SStefano Zampini   aa = av;
3226e34fafa9SBarry Smith   ai = a->i;
3227e34fafa9SBarry Smith   aj = a->j;
3228e34fafa9SBarry Smith 
3229985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3230475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3231e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
32322c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3233e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3234e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3235e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3236985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3237985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3238985db425SBarry Smith       aa++; aj++;
3239985db425SBarry Smith     }
3240985db425SBarry Smith   }
3241475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3242ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3243985db425SBarry Smith   PetscFunctionReturn(0);
3244985db425SBarry Smith }
3245985db425SBarry Smith 
3246985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3247985db425SBarry Smith {
3248985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3249985db425SBarry Smith   PetscErrorCode  ierr;
3250d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3251985db425SBarry Smith   PetscScalar     *x;
3252ce496241SStefano Zampini   const MatScalar *aa,*av;
3253985db425SBarry Smith 
3254985db425SBarry Smith   PetscFunctionBegin;
32552c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3256ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3257ce496241SStefano Zampini   aa = av;
3258985db425SBarry Smith   ai = a->i;
3259985db425SBarry Smith   aj = a->j;
3260985db425SBarry Smith 
3261985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3262fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3263985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
32642c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3265985db425SBarry Smith   for (i=0; i<m; i++) {
3266985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3267d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3268985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3269985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3270985db425SBarry Smith       x[i] = 0.0;
3271985db425SBarry Smith       if (idx) {
3272985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3273985db425SBarry Smith           if (aj[j] > j) {
3274985db425SBarry Smith             idx[i] = j;
3275985db425SBarry Smith             break;
3276985db425SBarry Smith           }
3277985db425SBarry Smith         }
32781a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32791a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3280985db425SBarry Smith       }
3281985db425SBarry Smith     }
3282985db425SBarry Smith     for (j=0; j<ncols; j++) {
3283985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3284985db425SBarry Smith       aa++; aj++;
3285985db425SBarry Smith     }
3286985db425SBarry Smith   }
3287fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3288ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3289985db425SBarry Smith   PetscFunctionReturn(0);
3290985db425SBarry Smith }
3291985db425SBarry Smith 
3292c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3293c87e5d42SMatthew Knepley {
3294c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3295c87e5d42SMatthew Knepley   PetscErrorCode  ierr;
3296c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3297ce496241SStefano Zampini   PetscScalar     *x;
3298ce496241SStefano Zampini   const MatScalar *aa,*av;
3299c87e5d42SMatthew Knepley 
3300c87e5d42SMatthew Knepley   PetscFunctionBegin;
3301ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3302ce496241SStefano Zampini   aa = av;
3303c87e5d42SMatthew Knepley   ai = a->i;
3304c87e5d42SMatthew Knepley   aj = a->j;
3305c87e5d42SMatthew Knepley 
3306c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3307f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3308c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
33092c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n);
3310c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3311c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3312f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3313f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3314f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3315f07e67edSHong Zhang       x[i] = 0.0;
3316f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3317289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3318f07e67edSHong Zhang           if (aj[j] > j) {
3319f07e67edSHong Zhang             idx[i] = j;
33202205254eSKarl Rupp             break;
33212205254eSKarl Rupp           }
3322289a08f5SMatthew Knepley         }
3323f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3324f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3325f07e67edSHong Zhang       }
3326289a08f5SMatthew Knepley     }
3327c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3328f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3329c87e5d42SMatthew Knepley       aa++; aj++;
3330c87e5d42SMatthew Knepley     }
3331c87e5d42SMatthew Knepley   }
3332f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3333ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3334c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3335c87e5d42SMatthew Knepley }
3336c87e5d42SMatthew Knepley 
3337985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3338985db425SBarry Smith {
3339985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3340985db425SBarry Smith   PetscErrorCode  ierr;
3341d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3342d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3343985db425SBarry Smith   PetscScalar     *x;
3344ce496241SStefano Zampini   const MatScalar *aa,*av;
3345985db425SBarry Smith 
3346985db425SBarry Smith   PetscFunctionBegin;
33472c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3348ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3349ce496241SStefano Zampini   aa = av;
3350985db425SBarry Smith   ai = a->i;
3351985db425SBarry Smith   aj = a->j;
3352985db425SBarry Smith 
3353985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3354fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3355985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
33562c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3357985db425SBarry Smith   for (i=0; i<m; i++) {
3358985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3359d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3360985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3361985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3362985db425SBarry Smith       x[i] = 0.0;
3363985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3364985db425SBarry Smith         for (j=0; j<ncols; j++) {
3365985db425SBarry Smith           if (aj[j] > j) {
3366985db425SBarry Smith             idx[i] = j;
3367985db425SBarry Smith             break;
3368985db425SBarry Smith           }
3369985db425SBarry Smith         }
3370fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3371fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3372985db425SBarry Smith       }
3373985db425SBarry Smith     }
3374985db425SBarry Smith     for (j=0; j<ncols; j++) {
3375985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3376985db425SBarry Smith       aa++; aj++;
3377e34fafa9SBarry Smith     }
3378e34fafa9SBarry Smith   }
3379fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3380ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3381e34fafa9SBarry Smith   PetscFunctionReturn(0);
3382e34fafa9SBarry Smith }
3383bbead8a2SBarry Smith 
3384713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3385bbead8a2SBarry Smith {
3386bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3387bbead8a2SBarry Smith   PetscErrorCode  ierr;
338833d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3389bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33900da83c2eSBarry Smith   const PetscReal shift = 0.0;
33911a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3392bbead8a2SBarry Smith 
3393bbead8a2SBarry Smith   PetscFunctionBegin;
3394a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33954a0d0026SBarry Smith   if (a->ibdiagvalid) {
33964a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33974a0d0026SBarry Smith     PetscFunctionReturn(0);
33984a0d0026SBarry Smith   }
3399bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3400bbead8a2SBarry Smith   if (!a->ibdiag) {
3401785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
34023bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3403bbead8a2SBarry Smith   }
3404bbead8a2SBarry Smith   diag = a->ibdiag;
3405bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3406bbead8a2SBarry Smith   /* factor and invert each block */
3407bbead8a2SBarry Smith   switch (bs) {
3408bbead8a2SBarry Smith   case 1:
3409bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3410bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3411ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3412ec1892c8SHong Zhang         if (allowzeropivot) {
34137b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34147b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34157b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34167d3de750SJacob Faibussowitsch           ierr = PetscInfo(A,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
341798921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);
3418ec1892c8SHong Zhang       }
3419bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3420bbead8a2SBarry Smith     }
3421bbead8a2SBarry Smith     break;
3422bbead8a2SBarry Smith   case 2:
3423bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3424bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3425bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3426a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34277b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
342896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3429bbead8a2SBarry Smith       diag += 4;
3430bbead8a2SBarry Smith     }
3431bbead8a2SBarry Smith     break;
3432bbead8a2SBarry Smith   case 3:
3433bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3434bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3435bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3436a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34377b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
343896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3439bbead8a2SBarry Smith       diag += 9;
3440bbead8a2SBarry Smith     }
3441bbead8a2SBarry Smith     break;
3442bbead8a2SBarry Smith   case 4:
3443bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3444bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3445bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3446a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34477b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
344896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3449bbead8a2SBarry Smith       diag += 16;
3450bbead8a2SBarry Smith     }
3451bbead8a2SBarry Smith     break;
3452bbead8a2SBarry Smith   case 5:
3453bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3454bbead8a2SBarry 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;
3455bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3456a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34577b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3459bbead8a2SBarry Smith       diag += 25;
3460bbead8a2SBarry Smith     }
3461bbead8a2SBarry Smith     break;
3462bbead8a2SBarry Smith   case 6:
3463bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3464bbead8a2SBarry 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;
3465bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3466a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34677b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3469bbead8a2SBarry Smith       diag += 36;
3470bbead8a2SBarry Smith     }
3471bbead8a2SBarry Smith     break;
3472bbead8a2SBarry Smith   case 7:
3473bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3474bbead8a2SBarry 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;
3475bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3476a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34777b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
347896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3479bbead8a2SBarry Smith       diag += 49;
3480bbead8a2SBarry Smith     }
3481bbead8a2SBarry Smith     break;
3482bbead8a2SBarry Smith   default:
3483dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3484bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3485bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3486bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3487bbead8a2SBarry Smith       }
3488bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
34895f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34907b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
349196b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3492bbead8a2SBarry Smith       diag += bs2;
3493bbead8a2SBarry Smith     }
3494bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3495bbead8a2SBarry Smith   }
3496bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3497bbead8a2SBarry Smith   PetscFunctionReturn(0);
3498bbead8a2SBarry Smith }
3499bbead8a2SBarry Smith 
350073a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
350173a71a0fSBarry Smith {
350273a71a0fSBarry Smith   PetscErrorCode ierr;
350373a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3504fff043a9SJunchao Zhang   PetscScalar    a,*aa;
350573a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
350673a71a0fSBarry Smith 
350773a71a0fSBarry Smith   PetscFunctionBegin;
350873a71a0fSBarry Smith   if (!x->assembled) {
350973a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
351073a71a0fSBarry Smith     for (i=0; i<m; i++) {
351173a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
351273a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
351373a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
351473a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
351573a71a0fSBarry Smith       }
351673a71a0fSBarry Smith     }
3517e2ce353bSJunchao Zhang   } else {
3518fff043a9SJunchao Zhang     ierr = MatSeqAIJGetArrayWrite(x,&aa);CHKERRQ(ierr);
3519fff043a9SJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aa+i);CHKERRQ(ierr);}
3520fff043a9SJunchao Zhang     ierr = MatSeqAIJRestoreArrayWrite(x,&aa);CHKERRQ(ierr);
3521e2ce353bSJunchao Zhang   }
352273a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
352373a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
352473a71a0fSBarry Smith   PetscFunctionReturn(0);
352573a71a0fSBarry Smith }
352673a71a0fSBarry Smith 
3527679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3528679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3529679944adSJunchao Zhang {
3530679944adSJunchao Zhang   PetscErrorCode ierr;
3531679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3532679944adSJunchao Zhang   PetscScalar    a;
3533679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3534679944adSJunchao Zhang 
3535679944adSJunchao Zhang   PetscFunctionBegin;
3536679944adSJunchao Zhang   nskip = high - low;
3537679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3538679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3539679944adSJunchao Zhang   for (i=0; i<m; i++) {
3540679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3541679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3542679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3543679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3544679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3545679944adSJunchao Zhang     }
3546e2ce353bSJunchao Zhang   }
3547679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3548679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3549679944adSJunchao Zhang   PetscFunctionReturn(0);
3550679944adSJunchao Zhang }
3551679944adSJunchao Zhang 
3552682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35530a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3554cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3555cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3556cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
355797304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35587c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35597c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3560f4259b30SLisandro Dalcin                                         NULL,
3561f4259b30SLisandro Dalcin                                         NULL,
3562f4259b30SLisandro Dalcin                                         NULL,
3563f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3564cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3565f4259b30SLisandro Dalcin                                         NULL,
356641f059aeSBarry Smith                                         MatSOR_SeqAIJ,
356791e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
356897304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3569cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3570cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3571cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3572cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3573f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3574cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3575cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3576cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3577d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3578f4259b30SLisandro Dalcin                                         NULL,
3579f4259b30SLisandro Dalcin                                         NULL,
3580f4259b30SLisandro Dalcin                                         NULL,
3581f4259b30SLisandro Dalcin                                         NULL,
35824994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3583f4259b30SLisandro Dalcin                                         NULL,
3584f4259b30SLisandro Dalcin                                         NULL,
3585f4259b30SLisandro Dalcin                                         NULL,
3586f4259b30SLisandro Dalcin                                         NULL,
3587d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3588f4259b30SLisandro Dalcin                                         NULL,
3589f4259b30SLisandro Dalcin                                         NULL,
3590cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3591f4259b30SLisandro Dalcin                                         NULL,
3592d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35937dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3594cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3595cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3596cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3597d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3598cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35997d68702bSBarry Smith                                         MatShift_SeqAIJ,
360079299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
36016e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
360273a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
36033b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
36043b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
36053b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3606a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
360793dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3608f4259b30SLisandro Dalcin                                         NULL,
3609f4259b30SLisandro Dalcin                                         NULL,
3610cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3611f4259b30SLisandro Dalcin                                         NULL,
3612f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3613b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3614b9b97703SBarry Smith                                         MatView_SeqAIJ,
3615f4259b30SLisandro Dalcin                                         NULL,
3616f4259b30SLisandro Dalcin                                         NULL,
3617f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3618321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3619f4259b30SLisandro Dalcin                                         NULL,
3620f4259b30SLisandro Dalcin                                         NULL,
3621f4259b30SLisandro Dalcin                                         NULL,
3622d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3623c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3624f4259b30SLisandro Dalcin                                         NULL,
3625f4259b30SLisandro Dalcin                                         NULL,
3626f4259b30SLisandro Dalcin                                         NULL,
3627f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36283acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3629f4259b30SLisandro Dalcin                                         NULL,
3630f4259b30SLisandro Dalcin                                         NULL,
3631f4259b30SLisandro Dalcin                                         NULL,
36326ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3633f4259b30SLisandro Dalcin                                         NULL,
3634f4259b30SLisandro Dalcin                                         NULL,
3635f4259b30SLisandro Dalcin                                         NULL,
3636bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3637d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36381cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3639f4259b30SLisandro Dalcin                                         NULL,
3640f4259b30SLisandro Dalcin                                         NULL,
3641f4259b30SLisandro Dalcin                                         NULL,
3642f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3643f4259b30SLisandro Dalcin                                         NULL,
364426be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3645f4259b30SLisandro Dalcin                                         NULL,
3646f4259b30SLisandro Dalcin                                         NULL,
36478fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3648f4259b30SLisandro Dalcin                                         NULL,
3649f4259b30SLisandro Dalcin                                         NULL,
36506fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3651f4259b30SLisandro Dalcin                                         NULL,
36524222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3653f4259b30SLisandro Dalcin                                         NULL,
3654f4259b30SLisandro Dalcin                                         NULL,
365587d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3656f4259b30SLisandro Dalcin                                         NULL,
3657d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
365899cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3659f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3660f4259b30SLisandro Dalcin                                         NULL,
3661f4259b30SLisandro Dalcin                                         NULL,
3662cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3663f4259b30SLisandro Dalcin                                         NULL,
36642af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3665f4259b30SLisandro Dalcin                                         NULL,
3666599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3667f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3668f4259b30SLisandro Dalcin                                         NULL,
3669f4259b30SLisandro Dalcin                                         NULL,
3670f4259b30SLisandro Dalcin                                         NULL,
3671f4259b30SLisandro Dalcin                                         NULL,
3672f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3673f4259b30SLisandro Dalcin                                         NULL,
3674f4259b30SLisandro Dalcin                                         NULL,
3675f4259b30SLisandro Dalcin                                         NULL,
3676b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36770716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3678a873a8cdSSam Reynolds                                         MatGetColumnReductions_SeqAIJ,
367937868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36800da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3681f4259b30SLisandro Dalcin                                         NULL,
3682f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3683f4259b30SLisandro Dalcin                                         NULL,
3684f4259b30SLisandro Dalcin                                         NULL,
368575648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3686b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3687b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36882b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3689f4259b30SLisandro Dalcin                                         NULL,
3690f4259b30SLisandro Dalcin                                         NULL,
36913964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3692f4259b30SLisandro Dalcin                                  /*139*/NULL,
3693f4259b30SLisandro Dalcin                                         NULL,
3694f4259b30SLisandro Dalcin                                         NULL,
36953a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36969c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36974222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36984222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3699f4259b30SLisandro Dalcin                                         NULL,
3700f4259b30SLisandro Dalcin                                         NULL
37019e29f15eSvictorle };
370217ab2063SBarry Smith 
37037087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3704bef8e0ddSBarry Smith {
3705bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
370697f1f81fSBarry Smith   PetscInt   i,nz,n;
3707bef8e0ddSBarry Smith 
3708bef8e0ddSBarry Smith   PetscFunctionBegin;
3709bef8e0ddSBarry Smith   nz = aij->maxnz;
3710d0f46423SBarry Smith   n  = mat->rmap->n;
3711bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3712bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3713bef8e0ddSBarry Smith   }
3714bef8e0ddSBarry Smith   aij->nz = nz;
3715bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3716bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3717bef8e0ddSBarry Smith   }
3718bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3719bef8e0ddSBarry Smith }
3720bef8e0ddSBarry Smith 
3721a3bb6f32SFande Kong /*
3722ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3723ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3724ddea5d60SJunchao Zhang  */
3725a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3726a3bb6f32SFande Kong {
3727a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3728a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3729a3bb6f32SFande Kong   PetscTablePosition tpos;
373025b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
373125b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3732a3bb6f32SFande Kong   PetscErrorCode     ierr;
3733a3bb6f32SFande Kong 
3734a3bb6f32SFande Kong   PetscFunctionBegin;
3735a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3736a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3737a3bb6f32SFande Kong   /* use a table */
3738a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3739a3bb6f32SFande Kong   ec = 0;
374025b670f0SStefano Zampini   for (i=0; i<nz; i++) {
374125b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3742a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3743a3bb6f32SFande Kong     if (!data) {
3744a3bb6f32SFande Kong       /* one based table */
3745a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3746a3bb6f32SFande Kong     }
3747a3bb6f32SFande Kong   }
3748a3bb6f32SFande Kong   /* form array of columns we need */
3749b3c64f9dSJunchao Zhang   ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr);
3750a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3751a3bb6f32SFande Kong   while (tpos) {
3752a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3753a3bb6f32SFande Kong     gid--;
3754a3bb6f32SFande Kong     lid--;
3755a3bb6f32SFande Kong     garray[lid] = gid;
3756a3bb6f32SFande Kong   }
3757a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3758a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3759a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3760a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3761a3bb6f32SFande Kong   }
3762a3bb6f32SFande Kong   /* compact out the extra columns in B */
376325b670f0SStefano Zampini   for (i=0; i<nz; i++) {
376425b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3765a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3766a3bb6f32SFande Kong     lid--;
376725b670f0SStefano Zampini     jj[i] = lid;
3768a3bb6f32SFande Kong   }
3769ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3770a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
377125b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3772a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3773a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3774a3bb6f32SFande Kong   PetscFunctionReturn(0);
3775a3bb6f32SFande Kong }
3776a3bb6f32SFande Kong 
3777bef8e0ddSBarry Smith /*@
3778bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3779bef8e0ddSBarry Smith        in the matrix.
3780bef8e0ddSBarry Smith 
3781bef8e0ddSBarry Smith   Input Parameters:
3782bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3783bef8e0ddSBarry Smith -  indices - the column indices
3784bef8e0ddSBarry Smith 
378515091d37SBarry Smith   Level: advanced
378615091d37SBarry Smith 
3787bef8e0ddSBarry Smith   Notes:
3788bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3789bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3790bef8e0ddSBarry Smith   of the MatSetValues() operation.
3791bef8e0ddSBarry Smith 
3792bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3793d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3794bef8e0ddSBarry Smith 
3795bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3796bef8e0ddSBarry Smith 
3797b9617806SBarry Smith     The indices should start with zero, not one.
3798b9617806SBarry Smith 
3799bef8e0ddSBarry Smith @*/
38007087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3801bef8e0ddSBarry Smith {
38024ac538c5SBarry Smith   PetscErrorCode ierr;
3803bef8e0ddSBarry Smith 
3804bef8e0ddSBarry Smith   PetscFunctionBegin;
38050700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38064482741eSBarry Smith   PetscValidPointer(indices,2);
38074ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3808bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3809bef8e0ddSBarry Smith }
3810bef8e0ddSBarry Smith 
3811be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3812be6bf707SBarry Smith 
38137087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3814be6bf707SBarry Smith {
3815be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38166849ba73SBarry Smith   PetscErrorCode ierr;
3817d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3818be6bf707SBarry Smith 
3819be6bf707SBarry Smith   PetscFunctionBegin;
38202c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3821be6bf707SBarry Smith 
3822be6bf707SBarry Smith   /* allocate space for values if not already there */
3823be6bf707SBarry Smith   if (!aij->saved_values) {
3824854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38253bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3826be6bf707SBarry Smith   }
3827be6bf707SBarry Smith 
3828be6bf707SBarry Smith   /* copy values over */
3829580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3830be6bf707SBarry Smith   PetscFunctionReturn(0);
3831be6bf707SBarry Smith }
3832be6bf707SBarry Smith 
3833be6bf707SBarry Smith /*@
3834be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3835be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3836be6bf707SBarry Smith        nonlinear portion.
3837be6bf707SBarry Smith 
3838be6bf707SBarry Smith    Collect on Mat
3839be6bf707SBarry Smith 
3840be6bf707SBarry Smith   Input Parameters:
38410e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3842be6bf707SBarry Smith 
384315091d37SBarry Smith   Level: advanced
384415091d37SBarry Smith 
3845be6bf707SBarry Smith   Common Usage, with SNESSolve():
3846be6bf707SBarry Smith $    Create Jacobian matrix
3847be6bf707SBarry Smith $    Set linear terms into matrix
3848be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3849be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3850be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3851512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3852be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3853be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3854be6bf707SBarry Smith $    In your Jacobian routine
3855be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3856be6bf707SBarry Smith $      Set nonlinear terms in matrix
3857be6bf707SBarry Smith 
3858be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3859be6bf707SBarry Smith $    // build linear portion of Jacobian
3860512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3861be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3862be6bf707SBarry Smith $    loop over nonlinear iterations
3863be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3864be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3865be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3866be6bf707SBarry Smith $       Solve linear system with Jacobian
3867be6bf707SBarry Smith $    endloop
3868be6bf707SBarry Smith 
3869be6bf707SBarry Smith   Notes:
3870be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3871512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3872be6bf707SBarry Smith     calling this routine.
3873be6bf707SBarry Smith 
38740c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38750c468ba9SBarry Smith     and does not allocated additional space.
38760c468ba9SBarry Smith 
3877be6bf707SBarry Smith .seealso: MatRetrieveValues()
3878be6bf707SBarry Smith 
3879be6bf707SBarry Smith @*/
38807087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3881be6bf707SBarry Smith {
38824ac538c5SBarry Smith   PetscErrorCode ierr;
3883be6bf707SBarry Smith 
3884be6bf707SBarry Smith   PetscFunctionBegin;
38850700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38862c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
38872c71b3e2SJacob Faibussowitsch   PetscCheckFalse(mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38884ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3889be6bf707SBarry Smith   PetscFunctionReturn(0);
3890be6bf707SBarry Smith }
3891be6bf707SBarry Smith 
38927087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3893be6bf707SBarry Smith {
3894be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38956849ba73SBarry Smith   PetscErrorCode ierr;
3896d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3897be6bf707SBarry Smith 
3898be6bf707SBarry Smith   PetscFunctionBegin;
38992c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
39002c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!aij->saved_values,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3901be6bf707SBarry Smith   /* copy values over */
3902580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3903be6bf707SBarry Smith   PetscFunctionReturn(0);
3904be6bf707SBarry Smith }
3905be6bf707SBarry Smith 
3906be6bf707SBarry Smith /*@
3907be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3908be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3909be6bf707SBarry Smith        nonlinear portion.
3910be6bf707SBarry Smith 
3911be6bf707SBarry Smith    Collect on Mat
3912be6bf707SBarry Smith 
3913be6bf707SBarry Smith   Input Parameters:
3914386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3915be6bf707SBarry Smith 
391615091d37SBarry Smith   Level: advanced
391715091d37SBarry Smith 
3918be6bf707SBarry Smith .seealso: MatStoreValues()
3919be6bf707SBarry Smith 
3920be6bf707SBarry Smith @*/
39217087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3922be6bf707SBarry Smith {
39234ac538c5SBarry Smith   PetscErrorCode ierr;
3924be6bf707SBarry Smith 
3925be6bf707SBarry Smith   PetscFunctionBegin;
39260700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
39272c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
39282c71b3e2SJacob Faibussowitsch   PetscCheckFalse(mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39294ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3930be6bf707SBarry Smith   PetscFunctionReturn(0);
3931be6bf707SBarry Smith }
3932be6bf707SBarry Smith 
3933be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
393417ab2063SBarry Smith /*@C
3935682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39360d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39376e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
393851c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39392bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
394017ab2063SBarry Smith 
3941d083f849SBarry Smith    Collective
3942db81eaa0SLois Curfman McInnes 
394317ab2063SBarry Smith    Input Parameters:
3944db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
394517ab2063SBarry Smith .  m - number of rows
394617ab2063SBarry Smith .  n - number of columns
394717ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
394851c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39490298fd71SBarry Smith          (possibly different for each row) or NULL
395017ab2063SBarry Smith 
395117ab2063SBarry Smith    Output Parameter:
3952416022c9SBarry Smith .  A - the matrix
395317ab2063SBarry Smith 
3954175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3955f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3956175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3957175b88e8SBarry Smith 
3958b259b22eSLois Curfman McInnes    Notes:
395949a6f317SBarry Smith    If nnz is given then nz is ignored
396049a6f317SBarry Smith 
396117ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
396217ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39630002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
396444cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
396517ab2063SBarry Smith 
396617ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39670298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39683d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39696da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
397017ab2063SBarry Smith 
3971682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39724fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3973682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39746c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39756c7ebb05SLois Curfman McInnes 
39766c7ebb05SLois Curfman McInnes    Options Database Keys:
3977698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39789db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
397917ab2063SBarry Smith 
3980027ccd11SLois Curfman McInnes    Level: intermediate
3981027ccd11SLois Curfman McInnes 
398269b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
398336db0b34SBarry Smith 
398417ab2063SBarry Smith @*/
39857087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
398617ab2063SBarry Smith {
3987dfbe8321SBarry Smith   PetscErrorCode ierr;
39886945ee14SBarry Smith 
39893a40ed3dSBarry Smith   PetscFunctionBegin;
3990f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3991117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3992c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3993d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3994273d9f13SBarry Smith   PetscFunctionReturn(0);
3995273d9f13SBarry Smith }
3996273d9f13SBarry Smith 
3997273d9f13SBarry Smith /*@C
3998273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3999273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
4000273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
4001273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
4002273d9f13SBarry Smith 
4003d083f849SBarry Smith    Collective
4004273d9f13SBarry Smith 
4005273d9f13SBarry Smith    Input Parameters:
40061c4f3114SJed Brown +  B - The matrix
4007273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
4008273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
40090298fd71SBarry Smith          (possibly different for each row) or NULL
4010273d9f13SBarry Smith 
4011273d9f13SBarry Smith    Notes:
401249a6f317SBarry Smith      If nnz is given then nz is ignored
401349a6f317SBarry Smith 
4014273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4015273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4016273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4017273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4018273d9f13SBarry Smith 
4019273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40200298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4021273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4022273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4023273d9f13SBarry Smith 
4024aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4025aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4026aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4027aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4028aa95bbe8SBarry Smith 
4029a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4030a96a251dSBarry Smith    entries or columns indices
4031a96a251dSBarry Smith 
4032273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4033273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4034273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4035273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4036273d9f13SBarry Smith 
4037273d9f13SBarry Smith    Options Database Keys:
4038698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
403947b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4040273d9f13SBarry Smith 
4041273d9f13SBarry Smith    Level: intermediate
4042273d9f13SBarry Smith 
404319b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
404419b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4045273d9f13SBarry Smith 
4046273d9f13SBarry Smith @*/
40477087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4048273d9f13SBarry Smith {
40494ac538c5SBarry Smith   PetscErrorCode ierr;
4050a23d5eceSKris Buschelman 
4051a23d5eceSKris Buschelman   PetscFunctionBegin;
40526ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40536ba663aaSJed Brown   PetscValidType(B,1);
40544ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4055a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4056a23d5eceSKris Buschelman }
4057a23d5eceSKris Buschelman 
40587087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4059a23d5eceSKris Buschelman {
4060273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40612576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40626849ba73SBarry Smith   PetscErrorCode ierr;
406397f1f81fSBarry Smith   PetscInt       i;
4064273d9f13SBarry Smith 
4065273d9f13SBarry Smith   PetscFunctionBegin;
40662576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4067a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4068c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4069c461c341SBarry Smith     nz             = 0;
4070c461c341SBarry Smith   }
407126283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
407226283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4073899cda47SBarry Smith 
4074435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
40752c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz);
4076cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4077d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
40782c71b3e2SJacob Faibussowitsch       PetscCheckFalse(nnz[i] < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %" PetscInt_FMT " value %" PetscInt_FMT,i,nnz[i]);
40792c71b3e2SJacob Faibussowitsch       PetscCheckFalse(nnz[i] > B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %" PetscInt_FMT " value %" PetscInt_FMT " rowlength %" PetscInt_FMT,i,nnz[i],B->cmap->n);
4080b73539f3SBarry Smith     }
4081b73539f3SBarry Smith   }
4082b73539f3SBarry Smith 
4083273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
40842205254eSKarl Rupp 
4085273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4086273d9f13SBarry Smith 
4087ab93d7beSBarry Smith   if (!skipallocation) {
40882ee49352SLisandro Dalcin     if (!b->imax) {
4089071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4090071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4091071fcb05SBarry Smith     }
4092071fcb05SBarry Smith     if (!b->ilen) {
4093071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4094071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4095071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4096071fcb05SBarry Smith     } else {
4097071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
40982ee49352SLisandro Dalcin     }
4099846b4da1SFande Kong     if (!b->ipre) {
4100846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4101846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4102846b4da1SFande Kong     }
4103273d9f13SBarry Smith     if (!nnz) {
4104435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4105c62bd62aSJed Brown       else if (nz < 0) nz = 1;
41065d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4107d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4108d0f46423SBarry Smith       nz = nz*B->rmap->n;
4109273d9f13SBarry Smith     } else {
4110c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4111c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4112c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4113273d9f13SBarry Smith     }
4114ab93d7beSBarry Smith 
4115273d9f13SBarry Smith     /* allocate the matrix space */
411653dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41172ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4118396832f4SHong Zhang     if (B->structure_only) {
41195848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41205848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4121396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4122396832f4SHong Zhang     } else {
4123dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41243bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4125396832f4SHong Zhang     }
4126bfeeae90SHong Zhang     b->i[0] = 0;
4127d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41285da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41295da197adSKris Buschelman     }
4130396832f4SHong Zhang     if (B->structure_only) {
4131396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4132396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4133396832f4SHong Zhang     } else {
4134273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4135e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4136396832f4SHong Zhang     }
4137e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4138c461c341SBarry Smith   } else {
4139e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4140e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4141c461c341SBarry Smith   }
4142273d9f13SBarry Smith 
4143846b4da1SFande Kong   if (b->ipre && nnz != b->ipre && b->imax) {
4144846b4da1SFande Kong     /* reserve user-requested sparsity */
4145580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4146846b4da1SFande Kong   }
4147846b4da1SFande Kong 
4148273d9f13SBarry Smith   b->nz               = 0;
4149273d9f13SBarry Smith   b->maxnz            = nz;
4150273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41512205254eSKarl Rupp   if (realalloc) {
41522205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41532205254eSKarl Rupp   }
4154cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4155cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4156273d9f13SBarry Smith   PetscFunctionReturn(0);
4157273d9f13SBarry Smith }
4158273d9f13SBarry Smith 
4159846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4160846b4da1SFande Kong {
4161846b4da1SFande Kong   Mat_SeqAIJ     *a;
4162a5bbaf83SFande Kong   PetscInt       i;
4163846b4da1SFande Kong   PetscErrorCode ierr;
4164846b4da1SFande Kong 
4165846b4da1SFande Kong   PetscFunctionBegin;
4166846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
416714d0e64fSAlex Lindsay 
416814d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
416914d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
417014d0e64fSAlex Lindsay 
4171846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41722c814fdeSFande Kong   /* if no saved info, we error out */
41732c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!a->ipre,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info ");
41742c814fdeSFande Kong 
41752c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!a->i || !a->j || !a->a || !a->imax || !a->ilen,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation ");
41762c814fdeSFande Kong 
4177580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4178580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4179846b4da1SFande Kong   a->i[0] = 0;
4180846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4181846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4182846b4da1SFande Kong   }
4183846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4184846b4da1SFande Kong   a->nz               = 0;
4185846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4186846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4187846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4188846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4189846b4da1SFande Kong   PetscFunctionReturn(0);
4190846b4da1SFande Kong }
4191846b4da1SFande Kong 
419258d36128SBarry Smith /*@
4193a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4194a1661176SMatthew Knepley 
4195a1661176SMatthew Knepley    Input Parameters:
4196a1661176SMatthew Knepley +  B - the matrix
4197a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4198a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4199a1661176SMatthew Knepley -  v - optional values in the matrix
4200a1661176SMatthew Knepley 
4201a1661176SMatthew Knepley    Level: developer
4202a1661176SMatthew Knepley 
42036a9b8d82SBarry Smith    Notes:
420458d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
420558d36128SBarry Smith 
42066a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
42076a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
42086a9b8d82SBarry Smith 
42096a9b8d82SBarry Smith     Developer Notes:
42106a9b8d82SBarry Smith       An optimization could be added to the implementation where it checks if the i, and j are identical to the current i and j and
42116a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
42126a9b8d82SBarry Smith 
42136a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
42146a9b8d82SBarry Smith 
42156a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4216a1661176SMatthew Knepley @*/
4217a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4218a1661176SMatthew Knepley {
4219a1661176SMatthew Knepley   PetscErrorCode ierr;
4220a1661176SMatthew Knepley 
4221a1661176SMatthew Knepley   PetscFunctionBegin;
42220700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42236ba663aaSJed Brown   PetscValidType(B,1);
42244ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4225a1661176SMatthew Knepley   PetscFunctionReturn(0);
4226a1661176SMatthew Knepley }
4227a1661176SMatthew Knepley 
42287087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4229a1661176SMatthew Knepley {
4230a1661176SMatthew Knepley   PetscInt       i;
4231a1661176SMatthew Knepley   PetscInt       m,n;
4232a1661176SMatthew Knepley   PetscInt       nz;
42336a9b8d82SBarry Smith   PetscInt       *nnz;
4234a1661176SMatthew Knepley   PetscErrorCode ierr;
4235a1661176SMatthew Knepley 
4236a1661176SMatthew Knepley   PetscFunctionBegin;
42372c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Ii[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]);
4238779a8d59SSatish Balay 
4239779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4240779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4241779a8d59SSatish Balay 
4242779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4243854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4244a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4245b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
42462c71b3e2SJacob Faibussowitsch     PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %" PetscInt_FMT " has a negative number of columns %" PetscInt_FMT, i, nz);
4247a1661176SMatthew Knepley     nnz[i] = nz;
4248a1661176SMatthew Knepley   }
4249a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4250a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4251a1661176SMatthew Knepley 
4252a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4253071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4254a1661176SMatthew Knepley   }
4255a1661176SMatthew Knepley 
4256a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4257a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4258a1661176SMatthew Knepley 
42597827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4260a1661176SMatthew Knepley   PetscFunctionReturn(0);
4261a1661176SMatthew Knepley }
4262a1661176SMatthew Knepley 
4263ad7e164aSPierre Jolivet /*@
4264ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4265ad7e164aSPierre Jolivet 
4266ad7e164aSPierre Jolivet    Input Parameters:
4267ad7e164aSPierre Jolivet +  A - left-hand side matrix
4268ad7e164aSPierre Jolivet .  B - right-hand side matrix
4269ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4270ad7e164aSPierre Jolivet 
4271ad7e164aSPierre Jolivet    Output Parameter:
4272ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4273ad7e164aSPierre Jolivet 
4274ad7e164aSPierre Jolivet    Level: intermediate
4275ad7e164aSPierre Jolivet 
4276ad7e164aSPierre Jolivet    Notes:
4277ad7e164aSPierre Jolivet       MAT_REUSE_MATRIX can only be used when the nonzero structure of the product matrix has not changed from that last call to MatSeqAIJKron().
4278ad7e164aSPierre Jolivet 
4279ad7e164aSPierre Jolivet .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4280ad7e164aSPierre Jolivet @*/
4281ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4282ad7e164aSPierre Jolivet {
4283ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4284ad7e164aSPierre Jolivet 
4285ad7e164aSPierre Jolivet   PetscFunctionBegin;
4286ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4287ad7e164aSPierre Jolivet   PetscValidType(A,1);
4288ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4289ad7e164aSPierre Jolivet   PetscValidType(B,2);
4290ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4291ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4292ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4293ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4294ad7e164aSPierre Jolivet   }
4295ad7e164aSPierre Jolivet   ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr);
4296ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4297ad7e164aSPierre Jolivet }
4298ad7e164aSPierre Jolivet 
4299ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4300ad7e164aSPierre Jolivet {
4301fff043a9SJunchao Zhang   PetscErrorCode     ierr;
4302ad7e164aSPierre Jolivet   Mat                newmat;
4303ad7e164aSPierre Jolivet   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
4304ad7e164aSPierre Jolivet   Mat_SeqAIJ         *b = (Mat_SeqAIJ*)B->data;
4305ad7e164aSPierre Jolivet   PetscScalar        *v;
4306fff043a9SJunchao Zhang   const PetscScalar  *aa,*ba;
4307ad7e164aSPierre Jolivet   PetscInt           *i,*j,m,n,p,q,nnz = 0,am = A->rmap->n,bm = B->rmap->n,an = A->cmap->n, bn = B->cmap->n;
4308ad7e164aSPierre Jolivet   PetscBool          flg;
4309ad7e164aSPierre Jolivet 
4310ad7e164aSPierre Jolivet   PetscFunctionBegin;
43112c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
43122c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!A->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
43132c71b3e2SJacob Faibussowitsch   PetscCheckFalse(B->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
43142c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!B->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4315ad7e164aSPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
43162c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
43172c71b3e2SJacob Faibussowitsch   PetscCheckFalse(reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4318ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
4319ad7e164aSPierre Jolivet     ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr);
4320ad7e164aSPierre Jolivet     ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr);
4321ad7e164aSPierre Jolivet     ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr);
4322ad7e164aSPierre Jolivet     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
4323ad7e164aSPierre Jolivet     i[0] = 0;
4324ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4325ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4326ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4327ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4328ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4329ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4330ad7e164aSPierre Jolivet           }
4331ad7e164aSPierre Jolivet         }
4332ad7e164aSPierre Jolivet       }
4333ad7e164aSPierre Jolivet     }
4334ad7e164aSPierre Jolivet     ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr);
4335ad7e164aSPierre Jolivet     *C = newmat;
4336ad7e164aSPierre Jolivet     ierr = PetscFree2(i,j);CHKERRQ(ierr);
4337ad7e164aSPierre Jolivet     nnz = 0;
4338ad7e164aSPierre Jolivet   }
4339ad7e164aSPierre Jolivet   ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr);
4340fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4341fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
4342ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4343ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4344ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4345ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4346fff043a9SJunchao Zhang           v[nnz++] = aa[n] * ba[q];
4347ad7e164aSPierre Jolivet         }
4348ad7e164aSPierre Jolivet       }
4349ad7e164aSPierre Jolivet     }
4350ad7e164aSPierre Jolivet   }
4351ad7e164aSPierre Jolivet   ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr);
4352fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
4353fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
4354ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4355ad7e164aSPierre Jolivet }
4356ad7e164aSPierre Jolivet 
4357c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4358af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4359170fe5c8SBarry Smith 
4360170fe5c8SBarry Smith /*
4361170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4362170fe5c8SBarry Smith 
4363170fe5c8SBarry Smith                n                       p                          p
43642da392ccSBarry Smith         [             ]       [             ]         [                 ]
43652da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
43662da392ccSBarry Smith         [             ]       [             ]         [                 ]
4367170fe5c8SBarry Smith 
4368170fe5c8SBarry Smith */
4369170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4370170fe5c8SBarry Smith {
4371170fe5c8SBarry Smith   PetscErrorCode    ierr;
4372170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4373170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4374170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
437586214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4376170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4377170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4378170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
437986214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
438086214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4381170fe5c8SBarry Smith 
4382170fe5c8SBarry Smith   PetscFunctionBegin;
4383d0f46423SBarry Smith   m    = A->rmap->n;
4384d0f46423SBarry Smith   n    = A->cmap->n;
4385d0f46423SBarry Smith   p    = B->cmap->n;
4386170fe5c8SBarry Smith   a    = sub_a->v;
4387170fe5c8SBarry Smith   b    = sub_b->a;
4388170fe5c8SBarry Smith   c    = sub_c->v;
438986214ceeSStefano Zampini   if (clda == m) {
4390580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
439186214ceeSStefano Zampini   } else {
439286214ceeSStefano Zampini     for (j=0;j<p;j++)
439386214ceeSStefano Zampini       for (i=0;i<m;i++)
439486214ceeSStefano Zampini         c[j*clda + i] = 0.0;
439586214ceeSStefano Zampini   }
4396170fe5c8SBarry Smith   ii  = sub_b->i;
4397170fe5c8SBarry Smith   idx = sub_b->j;
4398170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4399170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4400170fe5c8SBarry Smith     while (q-->0) {
440186214ceeSStefano Zampini       c_q = c + clda*(*idx);
440286214ceeSStefano Zampini       a_q = a + alda*i;
4403854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4404170fe5c8SBarry Smith       idx++;
4405170fe5c8SBarry Smith       b++;
4406170fe5c8SBarry Smith     }
4407170fe5c8SBarry Smith   }
4408170fe5c8SBarry Smith   PetscFunctionReturn(0);
4409170fe5c8SBarry Smith }
4410170fe5c8SBarry Smith 
44114222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4412170fe5c8SBarry Smith {
4413170fe5c8SBarry Smith   PetscErrorCode ierr;
4414d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
441586214ceeSStefano Zampini   PetscBool      cisdense;
4416170fe5c8SBarry Smith 
4417170fe5c8SBarry Smith   PetscFunctionBegin;
44182c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->cmap->n != B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %" PetscInt_FMT " != B->rmap->n %" PetscInt_FMT,A->cmap->n,B->rmap->n);
44194222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
44204222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
442186214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
442286214ceeSStefano Zampini   if (!cisdense) {
442386214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
442486214ceeSStefano Zampini   }
442586214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4426d73949e8SHong Zhang 
44274222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4428170fe5c8SBarry Smith   PetscFunctionReturn(0);
4429170fe5c8SBarry Smith }
4430170fe5c8SBarry Smith 
4431170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
44320bad9183SKris Buschelman /*MC
4433fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
44340bad9183SKris Buschelman    based on compressed sparse row format.
44350bad9183SKris Buschelman 
44360bad9183SKris Buschelman    Options Database Keys:
44370bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
44380bad9183SKris Buschelman 
44390bad9183SKris Buschelman    Level: beginner
44400bad9183SKris Buschelman 
44410cd7f59aSBarry Smith    Notes:
44420cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
44430cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
44440cd7f59aSBarry Smith     in the matrix
44450cd7f59aSBarry Smith 
44460cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
44470cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
44480cd7f59aSBarry Smith 
44490cd7f59aSBarry Smith   Developer Notes:
44500cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
44510cd7f59aSBarry Smith 
4452ed73aabaSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType, MATSELL, MATSEQSELL, MATMPISELL
44530bad9183SKris Buschelman M*/
44540bad9183SKris Buschelman 
4455ccd284c7SBarry Smith /*MC
4456ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4457ccd284c7SBarry Smith 
4458ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4459ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
4460ed73aabaSBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4461ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4462ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4463ccd284c7SBarry Smith 
4464ccd284c7SBarry Smith    Options Database Keys:
4465ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4466ccd284c7SBarry Smith 
446795452b02SPatrick Sanan   Developer Notes:
4468ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4469ccd284c7SBarry Smith    enough exist.
4470ccd284c7SBarry Smith 
4471ccd284c7SBarry Smith   Level: beginner
4472ccd284c7SBarry Smith 
4473ed73aabaSBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ, MATMPIAIJ, MATSELL, MATSEQSELL, MATMPISELL
4474ccd284c7SBarry Smith M*/
4475ccd284c7SBarry Smith 
4476ccd284c7SBarry Smith /*MC
4477ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4478ccd284c7SBarry Smith 
4479ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4480ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4481ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4482ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4483ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4484ccd284c7SBarry Smith 
4485ccd284c7SBarry Smith    Options Database Keys:
4486ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4487ccd284c7SBarry Smith 
4488ccd284c7SBarry Smith   Level: beginner
4489ccd284c7SBarry Smith 
4490ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4491ccd284c7SBarry Smith M*/
4492ccd284c7SBarry Smith 
44937906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
44947906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
44957906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
44967906f579SHong Zhang #endif
4497d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4498d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4499d24d4204SJose E. Roman #endif
45007906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
45017906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
45027906f579SHong Zhang #endif
45037906f579SHong Zhang 
4504d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4505c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
45064222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
45077906f579SHong Zhang 
45088c778c55SBarry Smith /*@C
45098f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
45108c778c55SBarry Smith 
45118c778c55SBarry Smith    Not Collective
45128c778c55SBarry Smith 
45138c778c55SBarry Smith    Input Parameter:
4514579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
45158c778c55SBarry Smith 
45168c778c55SBarry Smith    Output Parameter:
45178c778c55SBarry Smith .   array - pointer to the data
45188c778c55SBarry Smith 
45198c778c55SBarry Smith    Level: intermediate
45208c778c55SBarry Smith 
4521774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
45228c778c55SBarry Smith @*/
45238c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
45248c778c55SBarry Smith {
45258c778c55SBarry Smith   PetscErrorCode ierr;
4526d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45278c778c55SBarry Smith 
45288c778c55SBarry Smith   PetscFunctionBegin;
4529d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
4530d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarray)(A,array);CHKERRQ(ierr);
4531d67d9f35SJunchao Zhang   } else {
4532d67d9f35SJunchao Zhang     *array = aij->a;
4533d67d9f35SJunchao Zhang   }
4534d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4535d67d9f35SJunchao Zhang }
4536d67d9f35SJunchao Zhang 
4537d67d9f35SJunchao Zhang /*@C
4538d67d9f35SJunchao Zhang    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
4539d67d9f35SJunchao Zhang 
4540d67d9f35SJunchao Zhang    Not Collective
4541d67d9f35SJunchao Zhang 
4542d67d9f35SJunchao Zhang    Input Parameters:
4543d67d9f35SJunchao Zhang +  mat - a MATSEQAIJ matrix
4544d67d9f35SJunchao Zhang -  array - pointer to the data
4545d67d9f35SJunchao Zhang 
4546d67d9f35SJunchao Zhang    Level: intermediate
4547d67d9f35SJunchao Zhang 
4548d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
4549d67d9f35SJunchao Zhang @*/
4550d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
4551d67d9f35SJunchao Zhang {
4552d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4553d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4554d67d9f35SJunchao Zhang 
4555d67d9f35SJunchao Zhang   PetscFunctionBegin;
4556d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
4557d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearray)(A,array);CHKERRQ(ierr);
4558d67d9f35SJunchao Zhang   } else {
4559d67d9f35SJunchao Zhang     *array = NULL;
4560d67d9f35SJunchao Zhang   }
4561394ed5ebSJunchao Zhang   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
4562394ed5ebSJunchao Zhang   ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr);
45638c778c55SBarry Smith   PetscFunctionReturn(0);
45648c778c55SBarry Smith }
45658c778c55SBarry Smith 
456621e72a00SBarry Smith /*@C
45678f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
45688f1ea47aSStefano Zampini 
45698f1ea47aSStefano Zampini    Not Collective
45708f1ea47aSStefano Zampini 
45718f1ea47aSStefano Zampini    Input Parameter:
45728f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45738f1ea47aSStefano Zampini 
45748f1ea47aSStefano Zampini    Output Parameter:
45758f1ea47aSStefano Zampini .   array - pointer to the data
45768f1ea47aSStefano Zampini 
45778f1ea47aSStefano Zampini    Level: intermediate
45788f1ea47aSStefano Zampini 
45798f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
45808f1ea47aSStefano Zampini @*/
45818f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
45828f1ea47aSStefano Zampini {
45838f1ea47aSStefano Zampini   PetscErrorCode ierr;
4584d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45858f1ea47aSStefano Zampini 
45868f1ea47aSStefano Zampini   PetscFunctionBegin;
4587d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
4588d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarrayread)(A,array);CHKERRQ(ierr);
4589d67d9f35SJunchao Zhang   } else {
4590d67d9f35SJunchao Zhang     *array = aij->a;
4591d67d9f35SJunchao Zhang   }
45928f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45938f1ea47aSStefano Zampini }
45948f1ea47aSStefano Zampini 
45958f1ea47aSStefano Zampini /*@C
45968f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
45978f1ea47aSStefano Zampini 
45988f1ea47aSStefano Zampini    Not Collective
45998f1ea47aSStefano Zampini 
46008f1ea47aSStefano Zampini    Input Parameter:
46018f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
46028f1ea47aSStefano Zampini 
46038f1ea47aSStefano Zampini    Output Parameter:
46048f1ea47aSStefano Zampini .   array - pointer to the data
46058f1ea47aSStefano Zampini 
46068f1ea47aSStefano Zampini    Level: intermediate
46078f1ea47aSStefano Zampini 
46088f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
46098f1ea47aSStefano Zampini @*/
46108f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
46118f1ea47aSStefano Zampini {
46128f1ea47aSStefano Zampini   PetscErrorCode ierr;
4613d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
46148f1ea47aSStefano Zampini 
46158f1ea47aSStefano Zampini   PetscFunctionBegin;
4616d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
4617d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearrayread)(A,array);CHKERRQ(ierr);
4618d67d9f35SJunchao Zhang   } else {
4619d67d9f35SJunchao Zhang     *array = NULL;
4620d67d9f35SJunchao Zhang   }
4621d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4622d67d9f35SJunchao Zhang }
4623d67d9f35SJunchao Zhang 
4624d67d9f35SJunchao Zhang /*@C
4625d67d9f35SJunchao Zhang    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored
4626d67d9f35SJunchao Zhang 
4627d67d9f35SJunchao Zhang    Not Collective
4628d67d9f35SJunchao Zhang 
4629d67d9f35SJunchao Zhang    Input Parameter:
4630d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4631d67d9f35SJunchao Zhang 
4632d67d9f35SJunchao Zhang    Output Parameter:
4633d67d9f35SJunchao Zhang .   array - pointer to the data
4634d67d9f35SJunchao Zhang 
4635d67d9f35SJunchao Zhang    Level: intermediate
4636d67d9f35SJunchao Zhang 
4637d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
4638d67d9f35SJunchao Zhang @*/
4639d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array)
4640d67d9f35SJunchao Zhang {
4641d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4642d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4643d67d9f35SJunchao Zhang 
4644d67d9f35SJunchao Zhang   PetscFunctionBegin;
4645d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
4646d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarraywrite)(A,array);CHKERRQ(ierr);
4647d67d9f35SJunchao Zhang   } else {
4648d67d9f35SJunchao Zhang     *array = aij->a;
4649d67d9f35SJunchao Zhang   }
4650394ed5ebSJunchao Zhang   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
4651394ed5ebSJunchao Zhang   ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr);
4652d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4653d67d9f35SJunchao Zhang }
4654d67d9f35SJunchao Zhang 
4655d67d9f35SJunchao Zhang /*@C
4656d67d9f35SJunchao Zhang    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4657d67d9f35SJunchao Zhang 
4658d67d9f35SJunchao Zhang    Not Collective
4659d67d9f35SJunchao Zhang 
4660d67d9f35SJunchao Zhang    Input Parameter:
4661d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4662d67d9f35SJunchao Zhang 
4663d67d9f35SJunchao Zhang    Output Parameter:
4664d67d9f35SJunchao Zhang .   array - pointer to the data
4665d67d9f35SJunchao Zhang 
4666d67d9f35SJunchao Zhang    Level: intermediate
4667d67d9f35SJunchao Zhang 
4668d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
4669d67d9f35SJunchao Zhang @*/
4670d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array)
4671d67d9f35SJunchao Zhang {
4672d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4673d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4674d67d9f35SJunchao Zhang 
4675d67d9f35SJunchao Zhang   PetscFunctionBegin;
4676d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
4677d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearraywrite)(A,array);CHKERRQ(ierr);
4678d67d9f35SJunchao Zhang   } else {
4679d67d9f35SJunchao Zhang     *array = NULL;
4680d67d9f35SJunchao Zhang   }
46818f1ea47aSStefano Zampini   PetscFunctionReturn(0);
46828f1ea47aSStefano Zampini }
46838f1ea47aSStefano Zampini 
46848f1ea47aSStefano Zampini /*@C
468521e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
468621e72a00SBarry Smith 
468721e72a00SBarry Smith    Not Collective
468821e72a00SBarry Smith 
468921e72a00SBarry Smith    Input Parameter:
4690579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
469121e72a00SBarry Smith 
469221e72a00SBarry Smith    Output Parameter:
469321e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
469421e72a00SBarry Smith 
469521e72a00SBarry Smith    Level: intermediate
469621e72a00SBarry Smith 
469721e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
469821e72a00SBarry Smith @*/
469921e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
470021e72a00SBarry Smith {
470121e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
470221e72a00SBarry Smith 
470321e72a00SBarry Smith   PetscFunctionBegin;
470421e72a00SBarry Smith   *nz = aij->rmax;
470521e72a00SBarry Smith   PetscFunctionReturn(0);
470621e72a00SBarry Smith }
470721e72a00SBarry Smith 
4708394ed5ebSJunchao Zhang PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, const PetscInt coo_i[], const PetscInt coo_j[])
4709394ed5ebSJunchao Zhang {
4710394ed5ebSJunchao Zhang   PetscErrorCode            ierr;
4711394ed5ebSJunchao Zhang   MPI_Comm                  comm;
4712394ed5ebSJunchao Zhang   PetscInt                  *i,*j;
4713394ed5ebSJunchao Zhang   PetscInt                  M,N,row;
4714394ed5ebSJunchao Zhang   PetscCount                k,p,q,nneg,nnz,start,end; /* Index the coo array, so use PetscCount as their type */
4715394ed5ebSJunchao Zhang   PetscInt                  *Ai; /* Change to PetscCount once we use it for row pointers */
4716394ed5ebSJunchao Zhang   PetscInt                  *Aj;
4717394ed5ebSJunchao Zhang   PetscScalar               *Aa;
4718*cbc6b225SStefano Zampini   Mat_SeqAIJ                *seqaij = (Mat_SeqAIJ*)(mat->data);
4719*cbc6b225SStefano Zampini   MatType                   rtype;
4720394ed5ebSJunchao Zhang   PetscCount                *perm,*jmap;
4721394ed5ebSJunchao Zhang 
4722394ed5ebSJunchao Zhang   PetscFunctionBegin;
4723*cbc6b225SStefano Zampini   ierr = MatResetPreallocationCOO_SeqAIJ(mat);CHKERRQ(ierr);
4724394ed5ebSJunchao Zhang   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4725394ed5ebSJunchao Zhang   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
4726394ed5ebSJunchao Zhang   ierr = PetscMalloc2(coo_n,&i,coo_n,&j);CHKERRQ(ierr);
4727394ed5ebSJunchao Zhang   ierr = PetscArraycpy(i,coo_i,coo_n);CHKERRQ(ierr); /* Make a copy since we'll modify it */
4728394ed5ebSJunchao Zhang   ierr = PetscArraycpy(j,coo_j,coo_n);CHKERRQ(ierr);
4729394ed5ebSJunchao Zhang   ierr = PetscMalloc1(coo_n,&perm);CHKERRQ(ierr);
4730394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) { /* Ignore entries with negative row or col indices */
4731394ed5ebSJunchao Zhang     if (j[k] < 0) i[k] = -1;
4732394ed5ebSJunchao Zhang     perm[k] = k;
4733394ed5ebSJunchao Zhang   }
4734394ed5ebSJunchao Zhang 
4735394ed5ebSJunchao Zhang   /* Sort by row */
4736394ed5ebSJunchao Zhang   ierr = PetscSortIntWithIntCountArrayPair(coo_n,i,j,perm);CHKERRQ(ierr);
4737394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) {if (i[k] >= 0) break;} /* Advance k to the first row with a non-negative index */
4738394ed5ebSJunchao Zhang   nneg = k;
4739394ed5ebSJunchao Zhang   ierr = PetscMalloc1(coo_n-nneg+1,&jmap);CHKERRQ(ierr); /* +1 to make a CSR-like data structure. jmap[i] originally is the number of repeats for i-th nonzero */
4740394ed5ebSJunchao Zhang   nnz  = 0; /* Total number of unique nonzeros to be counted */
4741394ed5ebSJunchao Zhang   jmap++; /* Inc jmap by 1 for convinience */
4742394ed5ebSJunchao Zhang 
4743394ed5ebSJunchao Zhang   ierr = PetscCalloc1(M+1,&Ai);CHKERRQ(ierr); /* CSR of A */
4744394ed5ebSJunchao Zhang   ierr = PetscMalloc1(coo_n-nneg,&Aj);CHKERRQ(ierr); /* We have at most coo_n-nneg unique nonzeros */
4745394ed5ebSJunchao Zhang 
4746394ed5ebSJunchao Zhang   /* In each row, sort by column, then unique column indices to get row length */
4747394ed5ebSJunchao Zhang   Ai++; /* Inc by 1 for convinience */
4748394ed5ebSJunchao Zhang   q = 0; /* q-th unique nonzero, with q starting from 0 */
4749394ed5ebSJunchao Zhang   while (k<coo_n) {
4750394ed5ebSJunchao Zhang     row   = i[k];
4751394ed5ebSJunchao Zhang     start = k; /* [start,end) indices for this row */
4752394ed5ebSJunchao Zhang     while (k<coo_n && i[k] == row) k++;
4753394ed5ebSJunchao Zhang     end   = k;
4754394ed5ebSJunchao Zhang     ierr  = PetscSortIntWithCountArray(end-start,j+start,perm+start);CHKERRQ(ierr);
4755394ed5ebSJunchao Zhang     /* Find number of unique col entries in this row */
4756394ed5ebSJunchao Zhang     Aj[q]   = j[start]; /* Log the first nonzero in this row */
4757394ed5ebSJunchao Zhang     jmap[q] = 1; /* Number of repeats of this nozero entry */
4758394ed5ebSJunchao Zhang     Ai[row] = 1;
4759394ed5ebSJunchao Zhang     nnz++;
4760394ed5ebSJunchao Zhang 
4761394ed5ebSJunchao Zhang     for (p=start+1; p<end; p++) { /* Scan remaining nonzero in this row */
4762394ed5ebSJunchao Zhang       if (j[p] != j[p-1]) { /* Meet a new nonzero */
4763394ed5ebSJunchao Zhang         q++;
4764394ed5ebSJunchao Zhang         jmap[q] = 1;
4765394ed5ebSJunchao Zhang         Aj[q]   = j[p];
4766394ed5ebSJunchao Zhang         Ai[row]++;
4767394ed5ebSJunchao Zhang         nnz++;
4768394ed5ebSJunchao Zhang       } else {
4769394ed5ebSJunchao Zhang         jmap[q]++;
4770394ed5ebSJunchao Zhang       }
4771394ed5ebSJunchao Zhang     }
4772394ed5ebSJunchao Zhang     q++; /* Move to next row and thus next unique nonzero */
4773394ed5ebSJunchao Zhang   }
4774394ed5ebSJunchao Zhang   ierr = PetscFree2(i,j);CHKERRQ(ierr);
4775394ed5ebSJunchao Zhang 
4776394ed5ebSJunchao Zhang   Ai--; /* Back to the beginning of Ai[] */
4777394ed5ebSJunchao Zhang   for (k=0; k<M; k++) Ai[k+1] += Ai[k];
4778394ed5ebSJunchao Zhang   jmap--; /* Back to the beginning of jmap[] */
4779394ed5ebSJunchao Zhang   jmap[0] = 0;
4780394ed5ebSJunchao Zhang   for (k=0; k<nnz; k++) jmap[k+1] += jmap[k];
4781394ed5ebSJunchao Zhang   if (nnz < coo_n-nneg) { /* Realloc with actual number of unique nonzeros */
4782394ed5ebSJunchao Zhang     PetscCount *jmap_new;
4783394ed5ebSJunchao Zhang     PetscInt   *Aj_new;
4784394ed5ebSJunchao Zhang 
4785394ed5ebSJunchao Zhang     ierr = PetscMalloc1(nnz+1,&jmap_new);CHKERRQ(ierr);
4786394ed5ebSJunchao Zhang     ierr = PetscArraycpy(jmap_new,jmap,nnz+1);CHKERRQ(ierr);
4787394ed5ebSJunchao Zhang     ierr = PetscFree(jmap);CHKERRQ(ierr);
4788394ed5ebSJunchao Zhang     jmap = jmap_new;
4789394ed5ebSJunchao Zhang 
4790394ed5ebSJunchao Zhang     ierr = PetscMalloc1(nnz,&Aj_new);CHKERRQ(ierr);
4791394ed5ebSJunchao Zhang     ierr = PetscArraycpy(Aj_new,Aj,nnz);CHKERRQ(ierr);
4792394ed5ebSJunchao Zhang     ierr = PetscFree(Aj);CHKERRQ(ierr);
4793394ed5ebSJunchao Zhang     Aj   = Aj_new;
4794394ed5ebSJunchao Zhang   }
4795394ed5ebSJunchao Zhang 
4796394ed5ebSJunchao Zhang   if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */
4797394ed5ebSJunchao Zhang     PetscCount *perm_new;
4798*cbc6b225SStefano Zampini 
4799394ed5ebSJunchao Zhang     ierr = PetscMalloc1(coo_n-nneg,&perm_new);CHKERRQ(ierr);
4800394ed5ebSJunchao Zhang     ierr = PetscArraycpy(perm_new,perm+nneg,coo_n-nneg);CHKERRQ(ierr);
4801394ed5ebSJunchao Zhang     ierr = PetscFree(perm);CHKERRQ(ierr);
4802394ed5ebSJunchao Zhang     perm = perm_new;
4803394ed5ebSJunchao Zhang   }
4804394ed5ebSJunchao Zhang 
4805*cbc6b225SStefano Zampini   ierr = MatGetRootType_Private(mat,&rtype);CHKERRQ(ierr);
4806394ed5ebSJunchao Zhang   ierr = PetscCalloc1(nnz,&Aa);CHKERRQ(ierr); /* Zero the matrix */
4807*cbc6b225SStefano Zampini   ierr = MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF,M,N,Ai,Aj,Aa,rtype,mat);CHKERRQ(ierr);
4808394ed5ebSJunchao Zhang 
4809394ed5ebSJunchao Zhang   seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */
4810394ed5ebSJunchao Zhang   seqaij->free_a       = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */
4811394ed5ebSJunchao Zhang   /* Record COO fields */
4812394ed5ebSJunchao Zhang   seqaij->coo_n        = coo_n;
4813394ed5ebSJunchao Zhang   seqaij->Atot         = coo_n-nneg; /* Annz is seqaij->nz, so no need to record that again */
4814394ed5ebSJunchao Zhang   seqaij->jmap         = jmap; /* of length nnz+1 */
4815394ed5ebSJunchao Zhang   seqaij->perm         = perm;
4816394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4817394ed5ebSJunchao Zhang }
4818394ed5ebSJunchao Zhang 
4819394ed5ebSJunchao Zhang static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A,const PetscScalar v[],InsertMode imode)
4820394ed5ebSJunchao Zhang {
4821394ed5ebSJunchao Zhang   PetscErrorCode              ierr;
4822394ed5ebSJunchao Zhang   Mat_SeqAIJ                  *aseq = (Mat_SeqAIJ*)A->data;
4823394ed5ebSJunchao Zhang   PetscCount                  i,j,Annz = aseq->nz;
4824394ed5ebSJunchao Zhang   PetscCount                  *perm = aseq->perm,*jmap = aseq->jmap;
4825394ed5ebSJunchao Zhang   PetscScalar                 *Aa;
4826394ed5ebSJunchao Zhang 
4827394ed5ebSJunchao Zhang   PetscFunctionBegin;
4828394ed5ebSJunchao Zhang   ierr = MatSeqAIJGetArray(A,&Aa);CHKERRQ(ierr);
4829394ed5ebSJunchao Zhang   for (i=0; i<Annz; i++) {
4830b6c38306SJunchao Zhang     PetscScalar sum = 0.0;
4831b6c38306SJunchao Zhang     for (j=jmap[i]; j<jmap[i+1]; j++) sum += v[perm[j]];
4832b6c38306SJunchao Zhang     Aa[i] = (imode == INSERT_VALUES? 0.0 : Aa[i]) + sum;
4833394ed5ebSJunchao Zhang   }
4834394ed5ebSJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&Aa);CHKERRQ(ierr);
4835394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4836394ed5ebSJunchao Zhang }
4837394ed5ebSJunchao Zhang 
483834b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
48395063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*);
484002fe1965SBarry Smith #endif
48413d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
48425063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*);
48433d0639e7SStefano Zampini #endif
484402fe1965SBarry Smith 
48458cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4846273d9f13SBarry Smith {
4847273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4848dfbe8321SBarry Smith   PetscErrorCode ierr;
484938baddfdSBarry Smith   PetscMPIInt    size;
4850273d9f13SBarry Smith 
4851273d9f13SBarry Smith   PetscFunctionBegin;
4852ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
48532c71b3e2SJacob Faibussowitsch   PetscCheckFalse(size > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4854273d9f13SBarry Smith 
4855b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
48562205254eSKarl Rupp 
4857b0a32e0cSBarry Smith   B->data = (void*)b;
48582205254eSKarl Rupp 
4859549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4860071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
48612205254eSKarl Rupp 
4862f4259b30SLisandro Dalcin   b->row                = NULL;
4863f4259b30SLisandro Dalcin   b->col                = NULL;
4864f4259b30SLisandro Dalcin   b->icol               = NULL;
4865b810aeb4SBarry Smith   b->reallocs           = 0;
486636db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4867f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4868416022c9SBarry Smith   b->nonew              = 0;
4869f4259b30SLisandro Dalcin   b->diag               = NULL;
4870f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4871f4259b30SLisandro Dalcin   B->spptr              = NULL;
4872f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4873f4259b30SLisandro Dalcin   b->idiag              = NULL;
4874f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4875f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
487671f1c65dSBarry Smith   b->omega              = 1.0;
487771f1c65dSBarry Smith   b->fshift             = 0.0;
487871f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4879bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4880a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
488117ab2063SBarry Smith 
488235d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
48838c778c55SBarry Smith 
4884b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4885bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4886bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4887b3866ffcSBarry Smith #endif
488817f1a0eaSHong Zhang 
4889bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4890bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4891bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4892bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4893bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4894bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
48954dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
48969779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
48974a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4898191b95cbSRichard Tran Mills #endif
489934b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
490002fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
49014222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4902fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
490302fe1965SBarry Smith #endif
49043d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
49053d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
49063d0639e7SStefano Zampini #endif
4907bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4908af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4909af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4910af8000cdSHong Zhang #endif
4911d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4912d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4913d24d4204SJose E. Roman #endif
491463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
491563c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
49164222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
491763c07aadSStefano Zampini #endif
4918b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4919d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4920c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4921bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4922bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4923bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4924846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4925bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4926bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
49274222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
49284222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
49294222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4930ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr);
4931394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_SeqAIJ);CHKERRQ(ierr);
4932394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSetValuesCOO_C",MatSetValuesCOO_SeqAIJ);CHKERRQ(ierr);
49334108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
493417667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
49354099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
49363a40ed3dSBarry Smith   PetscFunctionReturn(0);
493717ab2063SBarry Smith }
493817ab2063SBarry Smith 
4939b24902e0SBarry Smith /*
4940b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4941b24902e0SBarry Smith */
4942ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
494317ab2063SBarry Smith {
49442a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
49456849ba73SBarry Smith   PetscErrorCode ierr;
4946071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
494717ab2063SBarry Smith 
49483a40ed3dSBarry Smith   PetscFunctionBegin;
49492c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4950273d9f13SBarry Smith 
4951d5f3da31SBarry Smith   C->factortype = A->factortype;
4952f4259b30SLisandro Dalcin   c->row        = NULL;
4953f4259b30SLisandro Dalcin   c->col        = NULL;
4954f4259b30SLisandro Dalcin   c->icol       = NULL;
49556ad4291fSHong Zhang   c->reallocs   = 0;
495617ab2063SBarry Smith 
49576ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
495817ab2063SBarry Smith 
4959aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4960aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4961eec197d1SBarry Smith 
4962071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4963071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4964071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4965071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
49663bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
496717ab2063SBarry Smith 
496817ab2063SBarry Smith   /* allocate the matrix space */
4969f77e22a1SHong Zhang   if (mallocmatspace) {
4970dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
49713bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
49722205254eSKarl Rupp 
4973f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
49742205254eSKarl Rupp 
4975580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
497617ab2063SBarry Smith     if (m > 0) {
4977580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4978be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
49792e5835c6SStefano Zampini         const PetscScalar *aa;
49802e5835c6SStefano Zampini 
49812e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
49822e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
49832e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4984be6bf707SBarry Smith       } else {
4985580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
498617ab2063SBarry Smith       }
498708480c60SBarry Smith     }
4988f77e22a1SHong Zhang   }
498917ab2063SBarry Smith 
49906ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4991416022c9SBarry Smith   c->roworiented       = a->roworiented;
4992416022c9SBarry Smith   c->nonew             = a->nonew;
4993416022c9SBarry Smith   if (a->diag) {
4994854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4995071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
49963bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4997071fcb05SBarry Smith   } else c->diag = NULL;
49982205254eSKarl Rupp 
4999f4259b30SLisandro Dalcin   c->solve_work         = NULL;
5000f4259b30SLisandro Dalcin   c->saved_values       = NULL;
5001f4259b30SLisandro Dalcin   c->idiag              = NULL;
5002f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
5003a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
5004e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
5005e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
50066ad4291fSHong Zhang 
5007893ad86cSHong Zhang   c->rmax         = a->rmax;
5008416022c9SBarry Smith   c->nz           = a->nz;
50098ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
5010273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
5011754ec7b1SSatish Balay 
50126ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
50136ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
5014cd6b891eSBarry Smith   if (a->compressedrow.use) {
50156ad4291fSHong Zhang     i    = a->compressedrow.nrows;
5016dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
5017580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
5018580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
501927ea64f8SHong Zhang   } else {
502027ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
50210298fd71SBarry Smith     c->compressedrow.i      = NULL;
50220298fd71SBarry Smith     c->compressedrow.rindex = NULL;
50236ad4291fSHong Zhang   }
5024ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
5025e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
50264846f1f5SKris Buschelman 
50272205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
5028140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
50293a40ed3dSBarry Smith   PetscFunctionReturn(0);
503017ab2063SBarry Smith }
503117ab2063SBarry Smith 
5032b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
5033b24902e0SBarry Smith {
5034b24902e0SBarry Smith   PetscErrorCode ierr;
5035b24902e0SBarry Smith 
5036b24902e0SBarry Smith   PetscFunctionBegin;
5037ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
50384b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
5039cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
504033d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
5041cfd3f464SBarry Smith   }
5042a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
5043f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
5044b24902e0SBarry Smith   PetscFunctionReturn(0);
5045b24902e0SBarry Smith }
5046b24902e0SBarry Smith 
5047112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
5048fbdbba38SShri Abhyankar {
504952f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
505052f91c60SVaclav Hapla   PetscErrorCode ierr;
505152f91c60SVaclav Hapla 
505252f91c60SVaclav Hapla   PetscFunctionBegin;
505352f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
505452f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
5055c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
5056c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
505752f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
505852f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
505952f91c60SVaclav Hapla   if (isbinary) {
506052f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
506152f91c60SVaclav Hapla   } else if (ishdf5) {
506252f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
506352f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
506452f91c60SVaclav Hapla #else
506552f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
506652f91c60SVaclav Hapla #endif
506752f91c60SVaclav Hapla   } else {
506898921bdaSJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name);
506952f91c60SVaclav Hapla   }
507052f91c60SVaclav Hapla   PetscFunctionReturn(0);
507152f91c60SVaclav Hapla }
507252f91c60SVaclav Hapla 
50733ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
507452f91c60SVaclav Hapla {
50753ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
5076fbdbba38SShri Abhyankar   PetscErrorCode ierr;
50773ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
5078fbdbba38SShri Abhyankar 
5079fbdbba38SShri Abhyankar   PetscFunctionBegin;
50803ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
5081bbead8a2SBarry Smith 
50823ea6fe3dSLisandro Dalcin   /* read in matrix header */
50833ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
50842c71b3e2SJacob Faibussowitsch   PetscCheckFalse(header[0] != MAT_FILE_CLASSID,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
5085fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
50862c71b3e2SJacob Faibussowitsch   PetscCheckFalse(M < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M);
50872c71b3e2SJacob Faibussowitsch   PetscCheckFalse(N < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N);
50882c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
5089fbdbba38SShri Abhyankar 
50903ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
50913ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
50923ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
50933ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
50943ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
50953ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
50963ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
50973ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
50983ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
50993ea6fe3dSLisandro Dalcin 
51003ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
51013ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
51022c71b3e2SJacob Faibussowitsch   PetscCheckFalse(M != rows || N != cols,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")",M,N,rows,cols);
51033ea6fe3dSLisandro Dalcin 
5104fbdbba38SShri Abhyankar   /* read in row lengths */
51053ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
51063ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
51073ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
51083ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
51092c71b3e2SJacob Faibussowitsch   PetscCheckFalse(sum != nz,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent matrix data in file: nonzeros = %" PetscInt_FMT ", sum-row-lengths = %" PetscInt_FMT,nz,sum);
51103ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
51113ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
51123ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
51132c71b3e2SJacob Faibussowitsch   PetscCheckFalse(M != rows || N != cols,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%" PetscInt_FMT ", %" PetscInt_FMT ") than the input matrix (%" PetscInt_FMT ", %" PetscInt_FMT ")",M,N,rows,cols);
51143ea6fe3dSLisandro Dalcin   /* store row lengths */
51153ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
51163ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
5117fbdbba38SShri Abhyankar 
51183ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
51193ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
51203ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
51213ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
51223ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
51233ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
5124fbdbba38SShri Abhyankar 
51253ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
51263ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5127fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
5128fbdbba38SShri Abhyankar }
5129fbdbba38SShri Abhyankar 
5130ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
51317264ac53SSatish Balay {
51327264ac53SSatish Balay   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
5133dfbe8321SBarry Smith   PetscErrorCode    ierr;
5134fff043a9SJunchao Zhang   const PetscScalar *aa,*ba;
5135eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5136eeffb40dSHong Zhang   PetscInt k;
5137eeffb40dSHong Zhang #endif
51387264ac53SSatish Balay 
51393a40ed3dSBarry Smith   PetscFunctionBegin;
5140bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
5141d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
5142ca44d042SBarry Smith     *flg = PETSC_FALSE;
5143ca44d042SBarry Smith     PetscFunctionReturn(0);
5144bcd2baecSBarry Smith   }
51457264ac53SSatish Balay 
51467264ac53SSatish Balay   /* if the a->i are the same */
5147580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
5148abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
51497264ac53SSatish Balay 
51507264ac53SSatish Balay   /* if a->j are the same */
5151580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
5152abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
5153bcd2baecSBarry Smith 
5154fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
5155fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
5156bcd2baecSBarry Smith   /* if a->a are the same */
5157eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5158eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
5159fff043a9SJunchao Zhang     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
5160eeffb40dSHong Zhang       *flg = PETSC_FALSE;
51613a40ed3dSBarry Smith       PetscFunctionReturn(0);
5162eeffb40dSHong Zhang     }
5163eeffb40dSHong Zhang   }
5164eeffb40dSHong Zhang #else
5165fff043a9SJunchao Zhang   ierr = PetscArraycmp(aa,ba,a->nz,flg);CHKERRQ(ierr);
5166eeffb40dSHong Zhang #endif
5167fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
5168fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
5169eeffb40dSHong Zhang   PetscFunctionReturn(0);
51707264ac53SSatish Balay }
517136db0b34SBarry Smith 
517205869f15SSatish Balay /*@
517336db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
517436db0b34SBarry Smith               provided by the user.
517536db0b34SBarry Smith 
5176d083f849SBarry Smith       Collective
517736db0b34SBarry Smith 
517836db0b34SBarry Smith    Input Parameters:
517936db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
518036db0b34SBarry Smith .   m - number of rows
518136db0b34SBarry Smith .   n - number of columns
5182483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
518336db0b34SBarry Smith .   j - column indices
518436db0b34SBarry Smith -   a - matrix values
518536db0b34SBarry Smith 
518636db0b34SBarry Smith    Output Parameter:
518736db0b34SBarry Smith .   mat - the matrix
518836db0b34SBarry Smith 
518936db0b34SBarry Smith    Level: intermediate
519036db0b34SBarry Smith 
519136db0b34SBarry Smith    Notes:
51920551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5193292fb18eSBarry Smith     once the matrix is destroyed and not before
519436db0b34SBarry Smith 
519536db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
519636db0b34SBarry Smith 
5197bfeeae90SHong Zhang        The i and j indices are 0 based
519836db0b34SBarry Smith 
5199a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5200a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
52018eef79e4SBarry Smith     as shown
5202a4552177SSatish Balay 
52038eef79e4SBarry Smith $        1 0 0
52048eef79e4SBarry Smith $        2 0 3
52058eef79e4SBarry Smith $        4 5 6
52068eef79e4SBarry Smith $
52078eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
52088eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
52098eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5210a4552177SSatish Balay 
521169b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
521236db0b34SBarry Smith 
521336db0b34SBarry Smith @*/
5214c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
521536db0b34SBarry Smith {
5216dfbe8321SBarry Smith   PetscErrorCode ierr;
5217cbcfb4deSHong Zhang   PetscInt       ii;
521836db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5219cbcfb4deSHong Zhang   PetscInt jj;
522036db0b34SBarry Smith 
522136db0b34SBarry Smith   PetscFunctionBegin;
52222c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m > 0 && i[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5223f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5224f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5225a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
5226ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5227f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
5228ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
5229071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
5230071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
5231ab93d7beSBarry Smith 
523236db0b34SBarry Smith   aij->i            = i;
523336db0b34SBarry Smith   aij->j            = j;
523436db0b34SBarry Smith   aij->a            = a;
523536db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
523636db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5237e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5238e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
523936db0b34SBarry Smith 
5240*cbc6b225SStefano Zampini   for (ii=0,aij->nonzerorowcnt=0,aij->rmax=0; ii<m; ii++) {
524136db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
524276bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
52432c71b3e2SJacob Faibussowitsch       PetscCheckFalse(i[ii+1] - i[ii] < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %" PetscInt_FMT " length = %" PetscInt_FMT,ii,i[ii+1] - i[ii]);
52449985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
52452c71b3e2SJacob Faibussowitsch         PetscCheckFalse(j[jj] < j[jj-1],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is not sorted",jj-i[ii],j[jj],ii);
52462c71b3e2SJacob Faibussowitsch         PetscCheckFalse(j[jj] == j[jj-1],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %" PetscInt_FMT " (actual column %" PetscInt_FMT ") in row %" PetscInt_FMT " is identical to previous entry",jj-i[ii],j[jj],ii);
52479985e31cSBarry Smith       }
524836db0b34SBarry Smith     }
524976bd3646SJed Brown   }
525076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
525136db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
52522c71b3e2SJacob Faibussowitsch       PetscCheckFalse(j[ii] < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]);
52532c71b3e2SJacob Faibussowitsch       PetscCheckFalse(j[ii] > n - 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %" PetscInt_FMT " index = %" PetscInt_FMT,ii,j[ii]);
525436db0b34SBarry Smith     }
525576bd3646SJed Brown   }
525636db0b34SBarry Smith 
5257b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5258b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
525936db0b34SBarry Smith   PetscFunctionReturn(0);
526036db0b34SBarry Smith }
5261*cbc6b225SStefano Zampini 
526280ef6e79SMatthew G Knepley /*@C
5263d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
52648a0b0e6bSVictor Minden               provided by the user.
52658a0b0e6bSVictor Minden 
5266d083f849SBarry Smith       Collective
52678a0b0e6bSVictor Minden 
52688a0b0e6bSVictor Minden    Input Parameters:
52698a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
52708a0b0e6bSVictor Minden .   m   - number of rows
52718a0b0e6bSVictor Minden .   n   - number of columns
52728a0b0e6bSVictor Minden .   i   - row indices
52738a0b0e6bSVictor Minden .   j   - column indices
52741230e6d1SVictor Minden .   a   - matrix values
52751230e6d1SVictor Minden .   nz  - number of nonzeros
52761230e6d1SVictor Minden -   idx - 0 or 1 based
52778a0b0e6bSVictor Minden 
52788a0b0e6bSVictor Minden    Output Parameter:
52798a0b0e6bSVictor Minden .   mat - the matrix
52808a0b0e6bSVictor Minden 
52818a0b0e6bSVictor Minden    Level: intermediate
52828a0b0e6bSVictor Minden 
52838a0b0e6bSVictor Minden    Notes:
52849e99939fSJunchao Zhang        The i and j indices are 0 based. The format which is used for the sparse matrix input, is equivalent to a row-major ordering. i.e for the following matrix,
52859e99939fSJunchao Zhang        the input data expected is as shown
52869e99939fSJunchao Zhang .vb
52878a0b0e6bSVictor Minden         1 0 0
52888a0b0e6bSVictor Minden         2 0 3
52898a0b0e6bSVictor Minden         4 5 6
52908a0b0e6bSVictor Minden 
52918a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
52928a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
52938a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
52949e99939fSJunchao Zhang .ve
52958a0b0e6bSVictor Minden 
529669b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
52978a0b0e6bSVictor Minden 
52988a0b0e6bSVictor Minden @*/
5299c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
53008a0b0e6bSVictor Minden {
53018a0b0e6bSVictor Minden   PetscErrorCode ierr;
5302d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
53038a0b0e6bSVictor Minden 
53048a0b0e6bSVictor Minden   PetscFunctionBegin;
53051795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
53061230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5307c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
53081230e6d1SVictor Minden   }
53098a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
53108a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
53118a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
53121230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
53131230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
53141230e6d1SVictor Minden     if (idx) {
53151230e6d1SVictor Minden       row = i[ii] - 1;
53161230e6d1SVictor Minden       col = j[ii] - 1;
53171230e6d1SVictor Minden     } else {
53181230e6d1SVictor Minden       row = i[ii];
53191230e6d1SVictor Minden       col = j[ii];
53208a0b0e6bSVictor Minden     }
53211230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
53228a0b0e6bSVictor Minden   }
53238a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
53248a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5325d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
53268a0b0e6bSVictor Minden   PetscFunctionReturn(0);
53278a0b0e6bSVictor Minden }
532836db0b34SBarry Smith 
5329acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5330acf2f550SJed Brown {
5331acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5332acf2f550SJed Brown   PetscErrorCode ierr;
5333acf2f550SJed Brown 
5334acf2f550SJed Brown   PetscFunctionBegin;
5335acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5336acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
53372205254eSKarl Rupp 
5338acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5339acf2f550SJed Brown   PetscFunctionReturn(0);
5340acf2f550SJed Brown }
5341acf2f550SJed Brown 
53429c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
53439c8f2541SHong Zhang {
53449c8f2541SHong Zhang   PetscErrorCode ierr;
53458761c3d6SHong Zhang   PetscMPIInt    size;
53469c8f2541SHong Zhang 
53479c8f2541SHong Zhang   PetscFunctionBegin;
5348ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
53497bbdc51dSHong Zhang   if (size == 1) {
53507bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
53517bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
53527bbdc51dSHong Zhang     } else {
53538761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
53547bbdc51dSHong Zhang     }
53558761c3d6SHong Zhang   } else {
53569c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
53578761c3d6SHong Zhang   }
53589c8f2541SHong Zhang   PetscFunctionReturn(0);
53599c8f2541SHong Zhang }
53609c8f2541SHong Zhang 
536181824310SBarry Smith /*
536253dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
536353dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
536453dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
536553dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
536653dd7562SDmitry Karpeev  */
536753dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
536853dd7562SDmitry Karpeev {
536953dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
537053dd7562SDmitry Karpeev   PetscErrorCode ierr;
537153dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
537253dd7562SDmitry Karpeev   PetscBool      seqaij;
537353dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
537453dd7562SDmitry Karpeev   PetscScalar    v;
537553dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
537653dd7562SDmitry Karpeev 
537753dd7562SDmitry Karpeev   PetscFunctionBegin;
537853dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
537953dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
53804099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
53812c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!seqaij,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
538253dd7562SDmitry Karpeev   if (rowemb) {
538353dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
53842c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m != B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row IS of size %" PetscInt_FMT " is incompatible with matrix row size %" PetscInt_FMT,m,B->rmap->n);
538553dd7562SDmitry Karpeev   } else {
53862c71b3e2SJacob Faibussowitsch     PetscCheckFalse(C->rmap->n != B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
538753dd7562SDmitry Karpeev   }
538853dd7562SDmitry Karpeev   if (colemb) {
538953dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
53902c71b3e2SJacob Faibussowitsch     PetscCheckFalse(n != B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Diag col IS of size %" PetscInt_FMT " is incompatible with input matrix col size %" PetscInt_FMT,n,B->cmap->n);
539153dd7562SDmitry Karpeev   } else {
53922c71b3e2SJacob Faibussowitsch     PetscCheckFalse(C->cmap->n != B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
539353dd7562SDmitry Karpeev   }
539453dd7562SDmitry Karpeev 
539553dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
539653dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
539753dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
539853dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
539953dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
540053dd7562SDmitry Karpeev     }
540153dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
540253dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
540353dd7562SDmitry Karpeev   }
540453dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
540553dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
540653dd7562SDmitry Karpeev   }
540753dd7562SDmitry Karpeev   count = 0;
540853dd7562SDmitry Karpeev   rowindices = NULL;
540953dd7562SDmitry Karpeev   colindices = NULL;
541053dd7562SDmitry Karpeev   if (rowemb) {
541153dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
541253dd7562SDmitry Karpeev   }
541353dd7562SDmitry Karpeev   if (colemb) {
541453dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
541553dd7562SDmitry Karpeev   }
541653dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
541753dd7562SDmitry Karpeev     PetscInt row;
541853dd7562SDmitry Karpeev     row = i;
541953dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
542053dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
542153dd7562SDmitry Karpeev       PetscInt col;
542253dd7562SDmitry Karpeev       col  = Baij->j[count];
542353dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
542453dd7562SDmitry Karpeev       v    = Baij->a[count];
542553dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
542653dd7562SDmitry Karpeev       ++count;
542753dd7562SDmitry Karpeev     }
542853dd7562SDmitry Karpeev   }
542953dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
543053dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
543153dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
543253dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
543353dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
543453dd7562SDmitry Karpeev   PetscFunctionReturn(0);
543553dd7562SDmitry Karpeev }
543653dd7562SDmitry Karpeev 
54374099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
54384099cc6bSBarry Smith 
54394099cc6bSBarry Smith /*@C
54404099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
54414099cc6bSBarry Smith 
54424099cc6bSBarry Smith    Collective on Mat
54434099cc6bSBarry Smith 
54444099cc6bSBarry Smith    Input Parameters:
54454099cc6bSBarry Smith +  mat      - the matrix object
54464099cc6bSBarry Smith -  matype   - matrix type
54474099cc6bSBarry Smith 
54484099cc6bSBarry Smith    Options Database Key:
54494099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
54504099cc6bSBarry Smith 
54514099cc6bSBarry Smith   Level: intermediate
54524099cc6bSBarry Smith 
54534099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
54544099cc6bSBarry Smith @*/
54554099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
54564099cc6bSBarry Smith {
5457fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
54584099cc6bSBarry Smith   PetscBool      sametype;
54594099cc6bSBarry Smith 
54604099cc6bSBarry Smith   PetscFunctionBegin;
54614099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
54624099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
54634099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
54644099cc6bSBarry Smith 
54654099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
54662c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
54674099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
54684099cc6bSBarry Smith   PetscFunctionReturn(0);
54694099cc6bSBarry Smith }
54704099cc6bSBarry Smith 
54714099cc6bSBarry Smith /*@C
54724099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
54734099cc6bSBarry Smith 
54744099cc6bSBarry Smith    Not Collective
54754099cc6bSBarry Smith 
54764099cc6bSBarry Smith    Input Parameters:
54774099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
54784099cc6bSBarry Smith -  function - routine to convert to subtype
54794099cc6bSBarry Smith 
54804099cc6bSBarry Smith    Notes:
54814099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
54824099cc6bSBarry Smith 
54834099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
54844099cc6bSBarry Smith $     -mat_seqaij_type my_mat
54854099cc6bSBarry Smith 
54864099cc6bSBarry Smith    Level: advanced
54874099cc6bSBarry Smith 
54884099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
54894099cc6bSBarry Smith 
54904099cc6bSBarry Smith   Level: advanced
54914099cc6bSBarry Smith @*/
5492388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
54934099cc6bSBarry Smith {
54944099cc6bSBarry Smith   PetscErrorCode ierr;
54954099cc6bSBarry Smith 
54964099cc6bSBarry Smith   PetscFunctionBegin;
54979cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
54984099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
54994099cc6bSBarry Smith   PetscFunctionReturn(0);
55004099cc6bSBarry Smith }
55014099cc6bSBarry Smith 
55024099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
55034099cc6bSBarry Smith 
55044099cc6bSBarry Smith /*@C
55054099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
55064099cc6bSBarry Smith 
55074099cc6bSBarry Smith   Not Collective
55084099cc6bSBarry Smith 
55094099cc6bSBarry Smith   Level: advanced
55104099cc6bSBarry Smith 
55114099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
55124099cc6bSBarry Smith @*/
55134099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
55144099cc6bSBarry Smith {
55154099cc6bSBarry Smith   PetscErrorCode ierr;
55164099cc6bSBarry Smith 
55174099cc6bSBarry Smith   PetscFunctionBegin;
55184099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
55194099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
55204099cc6bSBarry Smith 
55214099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
55224099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
55234dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
55249779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
55256b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5526485f9817SRichard Tran Mills #endif
55275063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
55285063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
55295063d097SStefano Zampini #endif
55305063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
55315063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJKOKKOS,   MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
55325063d097SStefano Zampini #endif
55334099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
55344099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
55354099cc6bSBarry Smith #endif
55364099cc6bSBarry Smith   PetscFunctionReturn(0);
55374099cc6bSBarry Smith }
553853dd7562SDmitry Karpeev 
553953dd7562SDmitry Karpeev /*
554081824310SBarry Smith     Special version for direct calls from Fortran
554181824310SBarry Smith */
5542af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
554381824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
554481824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
554581824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
554681824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
554781824310SBarry Smith #endif
554881824310SBarry Smith 
554981824310SBarry Smith /* Change these macros so can be used in void function */
555098921bdaSJacob Faibussowitsch 
555198921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */
555298921bdaSJacob Faibussowitsch /* Identical to CHKERRV, except it assigns to *_ierr */
555381824310SBarry Smith #undef CHKERRQ
555498921bdaSJacob Faibussowitsch #define CHKERRQ(ierr) do {                                                                     \
555598921bdaSJacob Faibussowitsch     PetscErrorCode ierr_msv_mpiaij = (ierr);                                                   \
555698921bdaSJacob Faibussowitsch     if (PetscUnlikely(ierr_msv_mpiaij)) {                                                      \
555798921bdaSJacob Faibussowitsch       *_ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr_msv_mpiaij,PETSC_ERROR_REPEAT," "); \
555898921bdaSJacob Faibussowitsch       return;                                                                                  \
555998921bdaSJacob Faibussowitsch     }                                                                                          \
556098921bdaSJacob Faibussowitsch   } while (0)
556198921bdaSJacob Faibussowitsch 
556298921bdaSJacob Faibussowitsch #undef SETERRQ
556398921bdaSJacob Faibussowitsch #define SETERRQ(comm,ierr,...) do {                                                            \
556498921bdaSJacob Faibussowitsch     *_ierr = PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr,PETSC_ERROR_INITIAL,__VA_ARGS__); \
556598921bdaSJacob Faibussowitsch     return;                                                                                    \
556698921bdaSJacob Faibussowitsch   } while (0)
556781824310SBarry Smith 
556819caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
556981824310SBarry Smith {
557081824310SBarry Smith   Mat            A  = *AA;
557181824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
557281824310SBarry Smith   InsertMode     is = *isis;
557381824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
557481824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
557581824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
557681824310SBarry Smith   PetscErrorCode ierr;
557781824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
557854f21887SBarry Smith   MatScalar      *ap,value,*aa;
5579ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5580ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
558181824310SBarry Smith 
558281824310SBarry Smith   PetscFunctionBegin;
55834994cf47SJed Brown   MatCheckPreallocated(A,1);
558481824310SBarry Smith   imax  = a->imax;
558581824310SBarry Smith   ai    = a->i;
558681824310SBarry Smith   ailen = a->ilen;
558781824310SBarry Smith   aj    = a->j;
558881824310SBarry Smith   aa    = a->a;
558981824310SBarry Smith 
559081824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
559181824310SBarry Smith     row = im[k];
559281824310SBarry Smith     if (row < 0) continue;
5593cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
559481824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
559581824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
559681824310SBarry Smith     low  = 0;
559781824310SBarry Smith     high = nrow;
559881824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
559981824310SBarry Smith       if (in[l] < 0) continue;
5600cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
560181824310SBarry Smith       col = in[l];
56022205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
56032205254eSKarl Rupp       else value = v[k + l*m];
56042205254eSKarl Rupp 
560581824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
560681824310SBarry Smith 
56072205254eSKarl Rupp       if (col <= lastcol) low = 0;
56082205254eSKarl Rupp       else high = nrow;
560981824310SBarry Smith       lastcol = col;
561081824310SBarry Smith       while (high-low > 5) {
561181824310SBarry Smith         t = (low+high)/2;
561281824310SBarry Smith         if (rp[t] > col) high = t;
561381824310SBarry Smith         else             low  = t;
561481824310SBarry Smith       }
561581824310SBarry Smith       for (i=low; i<high; i++) {
561681824310SBarry Smith         if (rp[i] > col) break;
561781824310SBarry Smith         if (rp[i] == col) {
561881824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
561981824310SBarry Smith           else                  ap[i] = value;
562081824310SBarry Smith           goto noinsert;
562181824310SBarry Smith         }
562281824310SBarry Smith       }
562381824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
562481824310SBarry Smith       if (nonew == 1) goto noinsert;
5625ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5626fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
562781824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
562881824310SBarry Smith       /* shift up all the later entries in this row */
562981824310SBarry Smith       for (ii=N; ii>=i; ii--) {
563081824310SBarry Smith         rp[ii+1] = rp[ii];
563181824310SBarry Smith         ap[ii+1] = ap[ii];
563281824310SBarry Smith       }
563381824310SBarry Smith       rp[i] = col;
563481824310SBarry Smith       ap[i] = value;
5635e56f5c9eSBarry Smith       A->nonzerostate++;
563681824310SBarry Smith noinsert:;
563781824310SBarry Smith       low = i + 1;
563881824310SBarry Smith     }
563981824310SBarry Smith     ailen[row] = nrow;
564081824310SBarry Smith   }
564181824310SBarry Smith   PetscFunctionReturnVoid();
564281824310SBarry Smith }
564398921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No
564498921bdaSJacob Faibussowitsch  * other PETSc functions should be defined past this point, as it is impossible to recover the
564598921bdaSJacob Faibussowitsch  * original definitions */
564698921bdaSJacob Faibussowitsch #undef CHKERRQ
564798921bdaSJacob Faibussowitsch #undef SETERRQ
5648