xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 394ed5eb51aeb2fd4d5be41f3bc40ab0c0d7d8f0)
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;
4572c71b3e2SJacob Faibussowitsch     PetscAssertFalse(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;
4652c71b3e2SJacob Faibussowitsch       PetscAssertFalse(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];
6282c71b3e2SJacob Faibussowitsch     PetscAssertFalse(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];
66198921bdaSJacob Faibussowitsch     if (row < 0) {v += n; continue;} /* SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %" PetscInt_FMT,row); */
6622c71b3e2SJacob Faibussowitsch     PetscCheckFalse(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 */
66698921bdaSJacob Faibussowitsch       if (in[l] < 0) {v++; continue;} /* SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %" PetscInt_FMT,in[l]); */
6672c71b3e2SJacob Faibussowitsch       PetscCheckFalse(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 
1252dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
125317ab2063SBarry Smith {
1254416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1255dfbe8321SBarry Smith   PetscErrorCode ierr;
1256d5d45c9bSBarry Smith 
12573a40ed3dSBarry Smith   PetscFunctionBegin;
1258aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1259c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)A,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,A->rmap->n,A->cmap->n,a->nz);
126017ab2063SBarry Smith #endif
1261e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12626bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12636bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
126405b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1265d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1266071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1267071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1268846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
126971f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
127005b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12716bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
127205b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1273cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1274*394ed5ebSJunchao Zhang   ierr = PetscFree(a->perm);CHKERRQ(ierr);
1275*394ed5ebSJunchao Zhang   ierr = PetscFree(a->jmap);CHKERRQ(ierr);
12764108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1277bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1278901853e0SKris Buschelman 
12796718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12806718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12816718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12826718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12836718818eSStefano Zampini      due to different matrix sizes */
12846718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
12856718818eSStefano Zampini 
1286f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1287bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1288bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1289bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1290bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1291bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1292bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
12934222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12944222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1295e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1296fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
12974222ddf1SHong Zhang #endif
12983d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
12993d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13003d0639e7SStefano Zampini #endif
13014222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1302af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1303af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1304af8000cdSHong Zhang #endif
1305d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1306d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1307d24d4204SJose E. Roman #endif
130863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
130963c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13104222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
131163c07aadSStefano Zampini #endif
1312b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1313c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1314c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1315bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1316bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1317846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1318bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1319bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13204222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13214222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13224222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
1323ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL);CHKERRQ(ierr);
1324*394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL);CHKERRQ(ierr);
1325*394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL);CHKERRQ(ierr);
13263a40ed3dSBarry Smith   PetscFunctionReturn(0);
132717ab2063SBarry Smith }
132817ab2063SBarry Smith 
1329ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
133017ab2063SBarry Smith {
1331416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13324846f1f5SKris Buschelman   PetscErrorCode ierr;
13333a40ed3dSBarry Smith 
13343a40ed3dSBarry Smith   PetscFunctionBegin;
1335a65d3064SKris Buschelman   switch (op) {
1336a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13374e0d8c25SBarry Smith     a->roworiented = flg;
1338a65d3064SKris Buschelman     break;
1339a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1340a9817697SBarry Smith     a->keepnonzeropattern = flg;
1341a65d3064SKris Buschelman     break;
1342512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1343512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1344a65d3064SKris Buschelman     break;
1345a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13464e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1347a65d3064SKris Buschelman     break;
1348a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13494e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1350a65d3064SKris Buschelman     break;
135128b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
135228b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
135328b2fa4aSMatthew Knepley     break;
1354a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13554e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13560df259c2SBarry Smith     break;
13573d472b54SHong Zhang   case MAT_SPD:
1358b1646e73SJed Brown   case MAT_SYMMETRIC:
1359b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1360b1646e73SJed Brown   case MAT_HERMITIAN:
1361b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1362957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13635021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13645021d80fSJed Brown     break;
13658c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1366a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1367a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
13687d3de750SJacob Faibussowitsch     ierr = PetscInfo(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1369a65d3064SKris Buschelman     break;
1370b87ac2d8SJed Brown   case MAT_USE_INODES:
1371b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1372b87ac2d8SJed Brown     break;
1373c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1374c10200c1SHong Zhang     A->submat_singleis = flg;
1375c10200c1SHong Zhang     break;
1376071fcb05SBarry Smith   case MAT_SORTED_FULL:
1377071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1378071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1379071fcb05SBarry Smith     break;
13801a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
13811a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
13821a2c6b5cSJunchao Zhang     break;
1383a65d3064SKris Buschelman   default:
138498921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1385a65d3064SKris Buschelman   }
13863a40ed3dSBarry Smith   PetscFunctionReturn(0);
138717ab2063SBarry Smith }
138817ab2063SBarry Smith 
1389dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
139017ab2063SBarry Smith {
1391416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
13926849ba73SBarry Smith   PetscErrorCode    ierr;
1393fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1394c898d852SStefano Zampini   PetscScalar       *x;
1395c898d852SStefano Zampini   const PetscScalar *aa;
139617ab2063SBarry Smith 
13973a40ed3dSBarry Smith   PetscFunctionBegin;
1398d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
13992c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1400c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1401d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1402d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1403fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14042c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1405fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1406c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
140735e7444dSHong Zhang     PetscFunctionReturn(0);
140835e7444dSHong Zhang   }
140935e7444dSHong Zhang 
1410fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
141135e7444dSHong Zhang   for (i=0; i<n; i++) {
1412fdc842d1SBarry Smith     x[i] = 0.0;
141335e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
141435e7444dSHong Zhang       if (aj[j] == i) {
141535e7444dSHong Zhang         x[i] = aa[j];
141617ab2063SBarry Smith         break;
141717ab2063SBarry Smith       }
141817ab2063SBarry Smith     }
141917ab2063SBarry Smith   }
1420fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1421c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14223a40ed3dSBarry Smith   PetscFunctionReturn(0);
142317ab2063SBarry Smith }
142417ab2063SBarry Smith 
1425c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1426dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
142717ab2063SBarry Smith {
1428416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14295f22a7b3SSebastian Grimberg   const MatScalar   *aa;
1430d9ca1df4SBarry Smith   PetscScalar       *y;
1431d9ca1df4SBarry Smith   const PetscScalar *x;
1432dfbe8321SBarry Smith   PetscErrorCode    ierr;
1433d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14345c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
14355f22a7b3SSebastian Grimberg   const MatScalar   *v;
1436a77337e4SBarry Smith   PetscScalar       alpha;
1437d9ca1df4SBarry Smith   PetscInt          n,i,j;
1438d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14393447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1440ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14415c897100SBarry Smith #endif
144217ab2063SBarry Smith 
14433a40ed3dSBarry Smith   PetscFunctionBegin;
14442e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1445d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14461ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1447fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
14485c897100SBarry Smith 
14495c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1450fff043a9SJunchao Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y);
14515c897100SBarry Smith #else
14523447b6efSHong Zhang   if (usecprow) {
14533447b6efSHong Zhang     m    = cprow.nrows;
14543447b6efSHong Zhang     ii   = cprow.i;
14557b2bb3b9SHong Zhang     ridx = cprow.rindex;
14563447b6efSHong Zhang   } else {
14573447b6efSHong Zhang     ii = a->i;
14583447b6efSHong Zhang   }
145917ab2063SBarry Smith   for (i=0; i<m; i++) {
14603447b6efSHong Zhang     idx = a->j + ii[i];
1461fff043a9SJunchao Zhang     v   = aa + ii[i];
14623447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14633447b6efSHong Zhang     if (usecprow) {
14647b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14653447b6efSHong Zhang     } else {
146617ab2063SBarry Smith       alpha = x[i];
14673447b6efSHong Zhang     }
146804fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
146917ab2063SBarry Smith   }
14705c897100SBarry Smith #endif
1471dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1472d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14731ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1474fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14753a40ed3dSBarry Smith   PetscFunctionReturn(0);
147617ab2063SBarry Smith }
147717ab2063SBarry Smith 
1478dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14795c897100SBarry Smith {
1480dfbe8321SBarry Smith   PetscErrorCode ierr;
14815c897100SBarry Smith 
14825c897100SBarry Smith   PetscFunctionBegin;
1483170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
14845c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
14855c897100SBarry Smith   PetscFunctionReturn(0);
14865c897100SBarry Smith }
14875c897100SBarry Smith 
1488c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
148978b84d54SShri Abhyankar 
1490dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
149117ab2063SBarry Smith {
1492416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1493d9fead3dSBarry Smith   PetscScalar       *y;
149454f21887SBarry Smith   const PetscScalar *x;
1495fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1496dfbe8321SBarry Smith   PetscErrorCode    ierr;
1497003131ecSBarry Smith   PetscInt          m=A->rmap->n;
14980298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
14997b083b7cSBarry Smith   PetscInt          n,i;
1500362ced78SSatish Balay   PetscScalar       sum;
1501ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
150217ab2063SBarry Smith 
1503b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
150497952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1505fee21e36SBarry Smith #endif
1506fee21e36SBarry Smith 
15073a40ed3dSBarry Smith   PetscFunctionBegin;
1508b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1509b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1510b215bc84SStefano Zampini     PetscFunctionReturn(0);
1511b215bc84SStefano Zampini   }
1512fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
15133649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15141ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1515416022c9SBarry Smith   ii   = a->i;
15164eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1517580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
151897952fefSHong Zhang     m    = a->compressedrow.nrows;
151997952fefSHong Zhang     ii   = a->compressedrow.i;
152097952fefSHong Zhang     ridx = a->compressedrow.rindex;
152197952fefSHong Zhang     for (i=0; i<m; i++) {
152297952fefSHong Zhang       n           = ii[i+1] - ii[i];
152397952fefSHong Zhang       aj          = a->j + ii[i];
1524fff043a9SJunchao Zhang       aa          = a_a + ii[i];
152597952fefSHong Zhang       sum         = 0.0;
1526003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1527003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
152897952fefSHong Zhang       y[*ridx++] = sum;
152997952fefSHong Zhang     }
153097952fefSHong Zhang   } else { /* do not use compressed row format */
1531b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15323d3eaba7SBarry Smith     aj   = a->j;
1533fff043a9SJunchao Zhang     aa   = a_a;
1534b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1535b05257ddSBarry Smith #else
153617ab2063SBarry Smith     for (i=0; i<m; i++) {
1537003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1538003131ecSBarry Smith       aj          = a->j + ii[i];
1539fff043a9SJunchao Zhang       aa          = a_a + ii[i];
154017ab2063SBarry Smith       sum         = 0.0;
1541003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
154217ab2063SBarry Smith       y[i] = sum;
154317ab2063SBarry Smith     }
15448d195f9aSBarry Smith #endif
1545b05257ddSBarry Smith   }
15467b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15473649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15481ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1549fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
15503a40ed3dSBarry Smith   PetscFunctionReturn(0);
155117ab2063SBarry Smith }
155217ab2063SBarry Smith 
1553b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1554b434eb95SMatthew G. Knepley {
1555b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1556b434eb95SMatthew G. Knepley   PetscScalar       *y;
1557b434eb95SMatthew G. Knepley   const PetscScalar *x;
1558fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1559b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1560b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1561b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1562b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1563b434eb95SMatthew G. Knepley   PetscScalar       sum;
1564b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1565b434eb95SMatthew G. Knepley 
1566b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1567b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1568b434eb95SMatthew G. Knepley #endif
1569b434eb95SMatthew G. Knepley 
1570b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1571fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1572b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1573b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1574b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1575b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1576b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1577b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1578b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1579b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1580b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1581fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1582b434eb95SMatthew G. Knepley       sum         = 0.0;
1583b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1584b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1585b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1586b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1587b434eb95SMatthew G. Knepley     }
1588b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15893d3eaba7SBarry Smith     ii = a->i;
1590b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1591b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1592b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1593fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1594b434eb95SMatthew G. Knepley       sum         = 0.0;
1595b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1596b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1597b434eb95SMatthew G. Knepley       y[i] = sum;
1598b434eb95SMatthew G. Knepley     }
1599b434eb95SMatthew G. Knepley   }
1600b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1601b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1602b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1603fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
1604b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1605b434eb95SMatthew G. Knepley }
1606b434eb95SMatthew G. Knepley 
1607b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1608b434eb95SMatthew G. Knepley {
1609b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1610b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1611b434eb95SMatthew G. Knepley   const PetscScalar *x;
1612fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1613b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1614b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1615b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1616b434eb95SMatthew G. Knepley   PetscScalar       sum;
1617b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1618b434eb95SMatthew G. Knepley 
1619b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1620fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1621b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1622d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1623b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1624b434eb95SMatthew G. Knepley     if (zz != yy) {
1625580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1626b434eb95SMatthew G. Knepley     }
1627b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1628b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1629b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1630b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1631b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1632b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1633fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1634b434eb95SMatthew G. Knepley       sum = y[*ridx];
1635b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1636b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1637b434eb95SMatthew G. Knepley     }
1638b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16393d3eaba7SBarry Smith     ii = a->i;
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[i];
1645b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1646b434eb95SMatthew G. Knepley       z[i] = sum;
1647b434eb95SMatthew G. Knepley     }
1648b434eb95SMatthew G. Knepley   }
1649b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1650b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1651d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1652fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
1653b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1654b434eb95SMatthew G. Knepley }
1655b434eb95SMatthew G. Knepley 
1656c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1657dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
165817ab2063SBarry Smith {
1659416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1660f15663dcSBarry Smith   PetscScalar       *y,*z;
1661f15663dcSBarry Smith   const PetscScalar *x;
1662fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1663dfbe8321SBarry Smith   PetscErrorCode    ierr;
1664d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1665d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1666362ced78SSatish Balay   PetscScalar       sum;
1667ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16689ea0dfa2SSatish Balay 
16693a40ed3dSBarry Smith   PetscFunctionBegin;
1670b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1671b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1672b215bc84SStefano Zampini     PetscFunctionReturn(0);
1673b215bc84SStefano Zampini   }
1674fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&a_a);CHKERRQ(ierr);
1675f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1676d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16774eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16784eb6d288SHong Zhang     if (zz != yy) {
1679580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16804eb6d288SHong Zhang     }
168197952fefSHong Zhang     m    = a->compressedrow.nrows;
168297952fefSHong Zhang     ii   = a->compressedrow.i;
168397952fefSHong Zhang     ridx = a->compressedrow.rindex;
168497952fefSHong Zhang     for (i=0; i<m; i++) {
168597952fefSHong Zhang       n   = ii[i+1] - ii[i];
168697952fefSHong Zhang       aj  = a->j + ii[i];
1687fff043a9SJunchao Zhang       aa  = a_a + ii[i];
168897952fefSHong Zhang       sum = y[*ridx];
1689f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
169097952fefSHong Zhang       z[*ridx++] = sum;
169197952fefSHong Zhang     }
169297952fefSHong Zhang   } else { /* do not use compressed row format */
16933d3eaba7SBarry Smith     ii = a->i;
1694f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16953d3eaba7SBarry Smith     aj = a->j;
1696fff043a9SJunchao Zhang     aa = a_a;
1697f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1698f15663dcSBarry Smith #else
169917ab2063SBarry Smith     for (i=0; i<m; i++) {
1700f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1701f15663dcSBarry Smith       aj  = a->j + ii[i];
1702fff043a9SJunchao Zhang       aa  = a_a + ii[i];
170317ab2063SBarry Smith       sum = y[i];
1704f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
170517ab2063SBarry Smith       z[i] = sum;
170617ab2063SBarry Smith     }
170702ab625aSSatish Balay #endif
1708f15663dcSBarry Smith   }
1709dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1710f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1711d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1712fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&a_a);CHKERRQ(ierr);
17133a40ed3dSBarry Smith   PetscFunctionReturn(0);
171417ab2063SBarry Smith }
171517ab2063SBarry Smith 
171617ab2063SBarry Smith /*
171717ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
171817ab2063SBarry Smith */
1719dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
172017ab2063SBarry Smith {
1721416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17226849ba73SBarry Smith   PetscErrorCode ierr;
1723d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
172417ab2063SBarry Smith 
17253a40ed3dSBarry Smith   PetscFunctionBegin;
172609f38230SBarry Smith   if (!a->diag) {
1727785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17283bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
172909f38230SBarry Smith   }
1730d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
173109f38230SBarry Smith     a->diag[i] = a->i[i+1];
1732bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1733bfeeae90SHong Zhang       if (a->j[j] == i) {
173409f38230SBarry Smith         a->diag[i] = j;
173517ab2063SBarry Smith         break;
173617ab2063SBarry Smith       }
173717ab2063SBarry Smith     }
173817ab2063SBarry Smith   }
17393a40ed3dSBarry Smith   PetscFunctionReturn(0);
174017ab2063SBarry Smith }
174117ab2063SBarry Smith 
174261ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
174361ecd0c6SBarry Smith {
174461ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
174561ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
174661ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
174761ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
174861ecd0c6SBarry Smith   PetscErrorCode    ierr;
174961ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
175061ecd0c6SBarry Smith 
175161ecd0c6SBarry Smith   PetscFunctionBegin;
175261ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
175361ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
175461ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
175561ecd0c6SBarry Smith     PetscFunctionReturn(0);
175661ecd0c6SBarry Smith   }
175761ecd0c6SBarry Smith 
175861ecd0c6SBarry Smith   if (a->diagonaldense) {
175961ecd0c6SBarry Smith     cnt = 0;
176061ecd0c6SBarry Smith   } else {
176161ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
176261ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
176361ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
176461ecd0c6SBarry Smith         cnt++;
176561ecd0c6SBarry Smith         mdiag[i] = 1;
176661ecd0c6SBarry Smith       }
176761ecd0c6SBarry Smith     }
176861ecd0c6SBarry Smith   }
176961ecd0c6SBarry Smith   if (!cnt) {
177061ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
177161ecd0c6SBarry Smith   } else {
1772b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1773b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
177461ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
177561ecd0c6SBarry Smith 
177661ecd0c6SBarry Smith     a->a = NULL;
177761ecd0c6SBarry Smith     a->j = NULL;
177861ecd0c6SBarry Smith     a->i = NULL;
177961ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
178061ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
178161ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1782447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
178361ecd0c6SBarry Smith     }
178461ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
178561ecd0c6SBarry Smith 
178661ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
178761ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
178861ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1789447d62f5SStefano Zampini       if (i < A->cmap->n) {
179061ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
179161ecd0c6SBarry Smith       }
1792447d62f5SStefano Zampini     }
179361ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179461ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
179561ecd0c6SBarry Smith     if (singlemalloc) {
179661ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
179761ecd0c6SBarry Smith     } else {
179861ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
179961ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
180061ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
180161ecd0c6SBarry Smith     }
180261ecd0c6SBarry Smith   }
180361ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
180461ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
180561ecd0c6SBarry Smith   PetscFunctionReturn(0);
180661ecd0c6SBarry Smith }
180761ecd0c6SBarry Smith 
1808be5855fcSBarry Smith /*
1809be5855fcSBarry Smith      Checks for missing diagonals
1810be5855fcSBarry Smith */
1811ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1812be5855fcSBarry Smith {
1813be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18147734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1815994fe344SLisandro Dalcin   PetscErrorCode ierr;
1816be5855fcSBarry Smith 
1817be5855fcSBarry Smith   PetscFunctionBegin;
181809f38230SBarry Smith   *missing = PETSC_FALSE;
18197734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
182009f38230SBarry Smith     *missing = PETSC_TRUE;
182109f38230SBarry Smith     if (d) *d = 0;
1822994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
182309f38230SBarry Smith   } else {
182401445905SHong Zhang     PetscInt n;
182501445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1826f1e2ffcdSBarry Smith     diag = a->diag;
182701445905SHong Zhang     for (i=0; i<n; i++) {
18287734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
182909f38230SBarry Smith         *missing = PETSC_TRUE;
183009f38230SBarry Smith         if (d) *d = i;
18317d3de750SJacob Faibussowitsch         ierr = PetscInfo(A,"Matrix is missing diagonal number %" PetscInt_FMT "\n",i);CHKERRQ(ierr);
1832358d2f5dSShri Abhyankar         break;
183309f38230SBarry Smith       }
1834be5855fcSBarry Smith     }
1835be5855fcSBarry Smith   }
1836be5855fcSBarry Smith   PetscFunctionReturn(0);
1837be5855fcSBarry Smith }
1838be5855fcSBarry Smith 
18390da83c2eSBarry Smith #include <petscblaslapack.h>
18400da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18410da83c2eSBarry Smith 
18420da83c2eSBarry Smith /*
18430da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18440da83c2eSBarry Smith */
18450da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18460da83c2eSBarry Smith {
18470da83c2eSBarry Smith   PetscErrorCode  ierr;
18480da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18490da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18500da83c2eSBarry Smith   const PetscReal shift = 0.0;
18510da83c2eSBarry Smith   PetscInt        ipvt[5];
18520da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18530da83c2eSBarry Smith 
18540da83c2eSBarry Smith   PetscFunctionBegin;
18550da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18560da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18572c71b3e2SJacob 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);
18580da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18590da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18600da83c2eSBarry Smith   }
18610da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18620da83c2eSBarry Smith   if (bsizemax > 7) {
18630da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18640da83c2eSBarry Smith   }
18650da83c2eSBarry Smith   ncnt = 0;
18660da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18670da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18680da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18690da83c2eSBarry Smith     switch (bsizes[i]) {
18700da83c2eSBarry Smith     case 1:
18710da83c2eSBarry Smith       *diag = 1.0/(*diag);
18720da83c2eSBarry Smith       break;
18730da83c2eSBarry Smith     case 2:
18740da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18750da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18760da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18770da83c2eSBarry Smith       break;
18780da83c2eSBarry Smith     case 3:
18790da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18800da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18810da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18820da83c2eSBarry Smith       break;
18830da83c2eSBarry Smith     case 4:
18840da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18850da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18860da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18870da83c2eSBarry Smith       break;
18880da83c2eSBarry Smith     case 5:
18890da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18900da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18910da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
18920da83c2eSBarry Smith       break;
18930da83c2eSBarry Smith     case 6:
18940da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18950da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18960da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
18970da83c2eSBarry Smith       break;
18980da83c2eSBarry Smith     case 7:
18990da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19000da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19010da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
19020da83c2eSBarry Smith       break;
19030da83c2eSBarry Smith     default:
19040da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19050da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19060da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19070da83c2eSBarry Smith     }
19080da83c2eSBarry Smith     ncnt   += bsizes[i];
19090da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19100da83c2eSBarry Smith   }
19110da83c2eSBarry Smith   if (bsizemax > 7) {
19120da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19130da83c2eSBarry Smith   }
19140da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19150da83c2eSBarry Smith   PetscFunctionReturn(0);
19160da83c2eSBarry Smith }
19170da83c2eSBarry Smith 
1918422a814eSBarry Smith /*
1919422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1920422a814eSBarry Smith */
19217087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
192271f1c65dSBarry Smith {
192371f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
192471f1c65dSBarry Smith   PetscErrorCode  ierr;
1925d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19262e5835c6SStefano Zampini   const MatScalar *v;
192754f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
192871f1c65dSBarry Smith 
192971f1c65dSBarry Smith   PetscFunctionBegin;
193071f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
193171f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
193271f1c65dSBarry Smith   diag = a->diag;
193371f1c65dSBarry Smith   if (!a->idiag) {
1934dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19353bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
193671f1c65dSBarry Smith   }
19372e5835c6SStefano Zampini 
193871f1c65dSBarry Smith   mdiag = a->mdiag;
193971f1c65dSBarry Smith   idiag = a->idiag;
19402e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1941422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
194271f1c65dSBarry Smith     for (i=0; i<m; i++) {
194371f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1944899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1945899639b0SHong Zhang         if (PetscRealPart(fshift)) {
19467d3de750SJacob Faibussowitsch           ierr = PetscInfo(A,"Zero diagonal on row %" PetscInt_FMT "\n",i);CHKERRQ(ierr);
19477b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19487b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19497b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
195098921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %" PetscInt_FMT,i);
1951899639b0SHong Zhang       }
195271f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
195371f1c65dSBarry Smith     }
195471f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
195571f1c65dSBarry Smith   } else {
195671f1c65dSBarry Smith     for (i=0; i<m; i++) {
195771f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
195871f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
195971f1c65dSBarry Smith     }
1960dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
196171f1c65dSBarry Smith   }
196271f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19632e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
196471f1c65dSBarry Smith   PetscFunctionReturn(0);
196571f1c65dSBarry Smith }
196671f1c65dSBarry Smith 
1967c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
196841f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
196917ab2063SBarry Smith {
1970416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1971e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19722e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
197354f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1974dfbe8321SBarry Smith   PetscErrorCode    ierr;
19753d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
197697f1f81fSBarry Smith   const PetscInt    *idx,*diag;
197717ab2063SBarry Smith 
19783a40ed3dSBarry Smith   PetscFunctionBegin;
1979b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1980b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1981b215bc84SStefano Zampini     PetscFunctionReturn(0);
1982b215bc84SStefano Zampini   }
1983b965ef7fSBarry Smith   its = its*lits;
198491723122SBarry Smith 
198571f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
198671f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
198771f1c65dSBarry Smith   a->fshift = fshift;
198871f1c65dSBarry Smith   a->omega  = omega;
1989ed480e8bSBarry Smith 
199071f1c65dSBarry Smith   diag  = a->diag;
199171f1c65dSBarry Smith   t     = a->ssor_work;
1992ed480e8bSBarry Smith   idiag = a->idiag;
199371f1c65dSBarry Smith   mdiag = a->mdiag;
1994ed480e8bSBarry Smith 
19952e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
19961ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
19973649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1998ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
199917ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
200017ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
2001ed480e8bSBarry Smith     bs = b;
200217ab2063SBarry Smith     for (i=0; i<m; i++) {
200371f1c65dSBarry Smith       d   = fshift + mdiag[i];
2004416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2005ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20062e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
200717ab2063SBarry Smith       sum = b[i]*d/omega;
2008003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
200917ab2063SBarry Smith       x[i] = sum;
201017ab2063SBarry Smith     }
20111ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20123649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20132e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2014efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20153a40ed3dSBarry Smith     PetscFunctionReturn(0);
201617ab2063SBarry Smith   }
2017c783ea89SBarry Smith 
20182c71b3e2SJacob Faibussowitsch   PetscCheckFalse(flag == SOR_APPLY_LOWER,PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20192205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20204c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2021887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
202217ab2063SBarry Smith 
202317ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
202417ab2063SBarry Smith 
2025887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
202617ab2063SBarry Smith     */
202717ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
202817ab2063SBarry Smith 
202917ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
203017ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2031416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2032ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20332e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
203417ab2063SBarry Smith       sum = b[i];
2035e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2036ed480e8bSBarry Smith       x[i] = sum*idiag[i];
203717ab2063SBarry Smith     }
203817ab2063SBarry Smith 
203917ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20402e5835c6SStefano Zampini     v = aa;
20412205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
204217ab2063SBarry Smith 
204317ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2044ed480e8bSBarry Smith     ts   = t;
2045416022c9SBarry Smith     diag = a->diag;
204617ab2063SBarry Smith     for (i=0; i<m; i++) {
2047416022c9SBarry Smith       n   = diag[i] - a->i[i];
2048ed480e8bSBarry Smith       idx = a->j + a->i[i];
20492e5835c6SStefano Zampini       v   = aa + a->i[i];
205017ab2063SBarry Smith       sum = t[i];
2051003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2052ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2053733d66baSBarry Smith       /*  x = x + t */
2054733d66baSBarry Smith       x[i] += t[i];
205517ab2063SBarry Smith     }
205617ab2063SBarry Smith 
2057dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20581ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20593649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20603a40ed3dSBarry Smith     PetscFunctionReturn(0);
206117ab2063SBarry Smith   }
206217ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
206317ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
206417ab2063SBarry Smith       for (i=0; i<m; i++) {
2065416022c9SBarry Smith         n   = diag[i] - a->i[i];
2066ed480e8bSBarry Smith         idx = a->j + a->i[i];
20672e5835c6SStefano Zampini         v   = aa + a->i[i];
206817ab2063SBarry Smith         sum = b[i];
2069e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20705c99c7daSBarry Smith         t[i] = sum;
2071ed480e8bSBarry Smith         x[i] = sum*idiag[i];
207217ab2063SBarry Smith       }
20735c99c7daSBarry Smith       xb   = t;
2074efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20753a40ed3dSBarry Smith     } else xb = b;
207617ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
207717ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2078416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2079ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20802e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
208117ab2063SBarry Smith         sum = xb[i];
2082e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20835c99c7daSBarry Smith         if (xb == b) {
2084ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20855c99c7daSBarry Smith         } else {
2086b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
208717ab2063SBarry Smith         }
20885c99c7daSBarry Smith       }
2089b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
209017ab2063SBarry Smith     }
209117ab2063SBarry Smith     its--;
209217ab2063SBarry Smith   }
209317ab2063SBarry Smith   while (its--) {
209417ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
209517ab2063SBarry Smith       for (i=0; i<m; i++) {
2096b19a5dc2SMark Adams         /* lower */
2097b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2098ed480e8bSBarry Smith         idx = a->j + a->i[i];
20992e5835c6SStefano Zampini         v   = aa + a->i[i];
210017ab2063SBarry Smith         sum = b[i];
2101e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2102b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2103b19a5dc2SMark Adams         /* upper */
2104b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2105b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21062e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2107b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2108b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
210917ab2063SBarry Smith       }
2110b19a5dc2SMark Adams       xb   = t;
21119f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2112b19a5dc2SMark Adams     } else xb = b;
211317ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
211417ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2115b19a5dc2SMark Adams         sum = xb[i];
2116b19a5dc2SMark Adams         if (xb == b) {
2117b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2118416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2119ed480e8bSBarry Smith           idx = a->j + a->i[i];
21202e5835c6SStefano Zampini           v   = aa + a->i[i];
2121e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2122ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2123b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2124b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2125b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21262e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2127b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2128b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
212917ab2063SBarry Smith         }
2130b19a5dc2SMark Adams       }
2131b19a5dc2SMark Adams       if (xb == b) {
21329f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2133b19a5dc2SMark Adams       } else {
2134b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2135b19a5dc2SMark Adams       }
213617ab2063SBarry Smith     }
213717ab2063SBarry Smith   }
21382e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21391ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21403649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2141365a8a9eSBarry Smith   PetscFunctionReturn(0);
214217ab2063SBarry Smith }
214317ab2063SBarry Smith 
2144dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
214517ab2063SBarry Smith {
2146416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21474e220ebcSLois Curfman McInnes 
21483a40ed3dSBarry Smith   PetscFunctionBegin;
21494e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21503966268fSBarry Smith   info->nz_allocated = a->maxnz;
21513966268fSBarry Smith   info->nz_used      = a->nz;
21523966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21533966268fSBarry Smith   info->assemblies   = A->num_ass;
21543966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21557adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2156d5f3da31SBarry Smith   if (A->factortype) {
21574e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21584e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21594e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21604e220ebcSLois Curfman McInnes   } else {
21614e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21624e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21634e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21644e220ebcSLois Curfman McInnes   }
21653a40ed3dSBarry Smith   PetscFunctionReturn(0);
216617ab2063SBarry Smith }
216717ab2063SBarry Smith 
21682b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
216917ab2063SBarry Smith {
2170416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2171c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21726849ba73SBarry Smith   PetscErrorCode    ierr;
217397b48c8fSBarry Smith   const PetscScalar *xx;
21742e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2175c7da8527SEric Chamberland   PetscInt          d = 0;
217617ab2063SBarry Smith 
21773a40ed3dSBarry Smith   PetscFunctionBegin;
217897b48c8fSBarry Smith   if (x && b) {
217997b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
218097b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
218197b48c8fSBarry Smith     for (i=0; i<N; i++) {
21822c71b3e2SJacob Faibussowitsch       PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2183447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
218497b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
218597b48c8fSBarry Smith     }
218697b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
218797b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
218897b48c8fSBarry Smith   }
218997b48c8fSBarry Smith 
21902e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
2191a9817697SBarry Smith   if (a->keepnonzeropattern) {
2192f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
21932c71b3e2SJacob Faibussowitsch       PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
21942e5835c6SStefano Zampini       ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2195f1e2ffcdSBarry Smith     }
2196f4df32b1SMatthew Knepley     if (diag != 0.0) {
2197c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2198c7da8527SEric Chamberland         d = rows[i];
2199447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22002c71b3e2SJacob 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);
2201c7da8527SEric Chamberland       }
2202f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2203447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22042e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2205f1e2ffcdSBarry Smith       }
2206f1e2ffcdSBarry Smith     }
2207f1e2ffcdSBarry Smith   } else {
2208f4df32b1SMatthew Knepley     if (diag != 0.0) {
220917ab2063SBarry Smith       for (i=0; i<N; i++) {
22102c71b3e2SJacob Faibussowitsch         PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
22117ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2212447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2213447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2214447d62f5SStefano Zampini           } else {
2215416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
22162e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2217bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2218447d62f5SStefano Zampini           }
2219447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2220f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
222117ab2063SBarry Smith         }
222217ab2063SBarry Smith       }
22233a40ed3dSBarry Smith     } else {
222417ab2063SBarry Smith       for (i=0; i<N; i++) {
22252c71b3e2SJacob Faibussowitsch         PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2226416022c9SBarry Smith         a->ilen[rows[i]] = 0;
222717ab2063SBarry Smith       }
222817ab2063SBarry Smith     }
2229e56f5c9eSBarry Smith     A->nonzerostate++;
2230f1e2ffcdSBarry Smith   }
22312e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22324099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22333a40ed3dSBarry Smith   PetscFunctionReturn(0);
223417ab2063SBarry Smith }
223517ab2063SBarry Smith 
22366e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22376e169961SBarry Smith {
22386e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22396e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22406e169961SBarry Smith   PetscErrorCode    ierr;
22412b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22426e169961SBarry Smith   const PetscScalar *xx;
22432e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22446e169961SBarry Smith 
22456e169961SBarry Smith   PetscFunctionBegin;
22462e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22472e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
22486e169961SBarry Smith   if (x && b) {
22496e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22506e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22512b40b63fSBarry Smith     vecs = PETSC_TRUE;
22526e169961SBarry Smith   }
22531795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22546e169961SBarry Smith   for (i=0; i<N; i++) {
22552c71b3e2SJacob Faibussowitsch     PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
22562e5835c6SStefano Zampini     ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22572205254eSKarl Rupp 
22586e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22596e169961SBarry Smith   }
22606e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22616e169961SBarry Smith     if (!zeroed[i]) {
22626e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22634cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22642e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22652e5835c6SStefano Zampini           aa[j] = 0.0;
22666e169961SBarry Smith         }
22676e169961SBarry Smith       }
22684cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22696e169961SBarry Smith   }
22706e169961SBarry Smith   if (x && b) {
22716e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22726e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22736e169961SBarry Smith   }
22746e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22756e169961SBarry Smith   if (diag != 0.0) {
22766e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22771d5a398dSstefano_zampini     if (missing) {
22781d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22794cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22802c71b3e2SJacob 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]);
22811d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22821d5a398dSstefano_zampini       }
22831d5a398dSstefano_zampini     } else {
22846e169961SBarry Smith       for (i=0; i<N; i++) {
22852e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
22866e169961SBarry Smith       }
22876e169961SBarry Smith     }
22881d5a398dSstefano_zampini   }
22892e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22904099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22916e169961SBarry Smith   PetscFunctionReturn(0);
22926e169961SBarry Smith }
22936e169961SBarry Smith 
2294a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
229517ab2063SBarry Smith {
22962e5835c6SStefano Zampini   PetscErrorCode  ierr;
2297fff043a9SJunchao Zhang   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2298fff043a9SJunchao Zhang   const PetscScalar *aa;
2299fff043a9SJunchao Zhang   PetscInt          *itmp;
230017ab2063SBarry Smith 
23013a40ed3dSBarry Smith   PetscFunctionBegin;
23022e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
2303416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
23042e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
230517ab2063SBarry Smith   if (idx) {
2306bfeeae90SHong Zhang     itmp = a->j + a->i[row];
230726fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2308f4259b30SLisandro Dalcin     else *idx = NULL;
230917ab2063SBarry Smith   }
23102e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
23113a40ed3dSBarry Smith   PetscFunctionReturn(0);
231217ab2063SBarry Smith }
231317ab2063SBarry Smith 
2314a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
231517ab2063SBarry Smith {
23163a40ed3dSBarry Smith   PetscFunctionBegin;
2317cb4a9cd9SHong Zhang   if (nz)  *nz = 0;
23182e5835c6SStefano Zampini   if (idx) *idx = NULL;
23192e5835c6SStefano Zampini   if (v)   *v = NULL;
23203a40ed3dSBarry Smith   PetscFunctionReturn(0);
232117ab2063SBarry Smith }
232217ab2063SBarry Smith 
2323dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
232417ab2063SBarry Smith {
2325416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
23262e5835c6SStefano Zampini   const MatScalar *v;
232736db0b34SBarry Smith   PetscReal       sum = 0.0;
23286849ba73SBarry Smith   PetscErrorCode  ierr;
232997f1f81fSBarry Smith   PetscInt        i,j;
233017ab2063SBarry Smith 
23313a40ed3dSBarry Smith   PetscFunctionBegin;
23322e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
233317ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2334570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2335570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
233673cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2337570b7f6dSBarry Smith #else
2338416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
233936db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
234017ab2063SBarry Smith     }
23418f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2342570b7f6dSBarry Smith #endif
2343ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23443a40ed3dSBarry Smith   } else if (type == NORM_1) {
234536db0b34SBarry Smith     PetscReal *tmp;
234697f1f81fSBarry Smith     PetscInt  *jj = a->j;
23471795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2348064f8208SBarry Smith     *nrm = 0.0;
2349416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2350bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
235117ab2063SBarry Smith     }
2352d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2353064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
235417ab2063SBarry Smith     }
2355606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
235651f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23573a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2358064f8208SBarry Smith     *nrm = 0.0;
2359d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23602e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
236117ab2063SBarry Smith       sum = 0.0;
2362416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23632e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
236417ab2063SBarry Smith       }
2365064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
236617ab2063SBarry Smith     }
236751f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2368f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23692e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
23703a40ed3dSBarry Smith   PetscFunctionReturn(0);
237117ab2063SBarry Smith }
237217ab2063SBarry Smith 
23734e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23744e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23754e938277SHong Zhang {
23764e938277SHong Zhang   PetscErrorCode ierr;
23774e938277SHong Zhang   PetscInt       i,j,anzj;
23784e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23794e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23804e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23814e938277SHong Zhang 
23824e938277SHong Zhang   PetscFunctionBegin;
23834e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2384854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2385785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2386785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
23874e938277SHong Zhang 
23884e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23894e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
239026fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
23914e938277SHong Zhang   /* Form ati for csr format of A^T. */
239226fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
23934e938277SHong Zhang 
23944e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2395580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
23964e938277SHong Zhang 
23974e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
23984e938277SHong Zhang   for (i=0;i<am;i++) {
23994e938277SHong Zhang     anzj = ai[i+1] - ai[i];
24004e938277SHong Zhang     for (j=0;j<anzj;j++) {
24014e938277SHong Zhang       atj[atfill[*aj]] = i;
24024e938277SHong Zhang       atfill[*aj++]   += 1;
24034e938277SHong Zhang     }
24044e938277SHong Zhang   }
24054e938277SHong Zhang 
24064e938277SHong Zhang   /* Clean up temporary space and complete requests. */
24074e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2408ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
240933d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2410b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2411a2f3521dSMark F. Adams 
24124e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
24134e938277SHong Zhang   b->free_a  = PETSC_FALSE;
24144e938277SHong Zhang   b->free_ij = PETSC_TRUE;
24154e938277SHong Zhang   b->nonew   = 0;
24164e938277SHong Zhang   PetscFunctionReturn(0);
24174e938277SHong Zhang }
24184e938277SHong Zhang 
24197087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2420cd0d46ebSvictorle {
24213d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
242254f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
24232e5835c6SStefano Zampini   const MatScalar *va,*vb;
24246849ba73SBarry Smith   PetscErrorCode  ierr;
242597f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2426cd0d46ebSvictorle 
2427cd0d46ebSvictorle   PetscFunctionBegin;
2428cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2429cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24305485867bSBarry Smith   if (ma!=nb || na!=mb) {
24315485867bSBarry Smith     *f = PETSC_FALSE;
24325485867bSBarry Smith     PetscFunctionReturn(0);
24335485867bSBarry Smith   }
24342e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr);
24352e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr);
2436cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2437cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2438785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2439785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2440cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2441cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2442cd0d46ebSvictorle 
2443cd0d46ebSvictorle   *f = PETSC_TRUE;
2444cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2445cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
244697f1f81fSBarry Smith       PetscInt    idc,idr;
24475485867bSBarry Smith       PetscScalar vc,vr;
2448cd0d46ebSvictorle       /* column/row index/value */
24495485867bSBarry Smith       idc = adx[aptr[i]];
24505485867bSBarry Smith       idr = bdx[bptr[idc]];
24515485867bSBarry Smith       vc  = va[aptr[i]];
24525485867bSBarry Smith       vr  = vb[bptr[idc]];
24535485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24545485867bSBarry Smith         *f = PETSC_FALSE;
24555485867bSBarry Smith         goto done;
2456cd0d46ebSvictorle       } else {
24575485867bSBarry Smith         aptr[i]++;
24585485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2459cd0d46ebSvictorle       }
2460cd0d46ebSvictorle     }
2461cd0d46ebSvictorle   }
2462cd0d46ebSvictorle done:
2463cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24643aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
24652e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr);
24662e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr);
2467cd0d46ebSvictorle   PetscFunctionReturn(0);
2468cd0d46ebSvictorle }
2469cd0d46ebSvictorle 
24707087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24711cbb95d3SBarry Smith {
24723d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
247354f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
247454f21887SBarry Smith   MatScalar      *va,*vb;
24751cbb95d3SBarry Smith   PetscErrorCode ierr;
24761cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24771cbb95d3SBarry Smith 
24781cbb95d3SBarry Smith   PetscFunctionBegin;
24791cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
24801cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24811cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24821cbb95d3SBarry Smith     *f = PETSC_FALSE;
24831cbb95d3SBarry Smith     PetscFunctionReturn(0);
24841cbb95d3SBarry Smith   }
24851cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24861cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24871cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2488785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2489785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
24901cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
24911cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
24921cbb95d3SBarry Smith 
24931cbb95d3SBarry Smith   *f = PETSC_TRUE;
24941cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
24951cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
24961cbb95d3SBarry Smith       PetscInt    idc,idr;
24971cbb95d3SBarry Smith       PetscScalar vc,vr;
24981cbb95d3SBarry Smith       /* column/row index/value */
24991cbb95d3SBarry Smith       idc = adx[aptr[i]];
25001cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
25011cbb95d3SBarry Smith       vc  = va[aptr[i]];
25021cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
25031cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
25041cbb95d3SBarry Smith         *f = PETSC_FALSE;
25051cbb95d3SBarry Smith         goto done;
25061cbb95d3SBarry Smith       } else {
25071cbb95d3SBarry Smith         aptr[i]++;
25081cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
25091cbb95d3SBarry Smith       }
25101cbb95d3SBarry Smith     }
25111cbb95d3SBarry Smith   }
25121cbb95d3SBarry Smith done:
25131cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
25141cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
25151cbb95d3SBarry Smith   PetscFunctionReturn(0);
25161cbb95d3SBarry Smith }
25171cbb95d3SBarry Smith 
2518ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25199e29f15eSvictorle {
2520dfbe8321SBarry Smith   PetscErrorCode ierr;
25216e111a19SKarl Rupp 
25229e29f15eSvictorle   PetscFunctionBegin;
25235485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25249e29f15eSvictorle   PetscFunctionReturn(0);
25259e29f15eSvictorle }
25269e29f15eSvictorle 
2527ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25281cbb95d3SBarry Smith {
25291cbb95d3SBarry Smith   PetscErrorCode ierr;
25306e111a19SKarl Rupp 
25311cbb95d3SBarry Smith   PetscFunctionBegin;
25321cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25331cbb95d3SBarry Smith   PetscFunctionReturn(0);
25341cbb95d3SBarry Smith }
25351cbb95d3SBarry Smith 
2536dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
253717ab2063SBarry Smith {
2538416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2539fff8e43fSBarry Smith   const PetscScalar *l,*r;
2540fff8e43fSBarry Smith   PetscScalar       x;
254154f21887SBarry Smith   MatScalar         *v;
2542dfbe8321SBarry Smith   PetscErrorCode    ierr;
2543fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2544fff8e43fSBarry Smith   const PetscInt    *jj;
254517ab2063SBarry Smith 
25463a40ed3dSBarry Smith   PetscFunctionBegin;
254717ab2063SBarry Smith   if (ll) {
25483ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25493ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2550e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
25512c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2552fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
25532e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
255417ab2063SBarry Smith     for (i=0; i<m; i++) {
255517ab2063SBarry Smith       x = l[i];
2556416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25572205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
255817ab2063SBarry Smith     }
2559fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2560efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
25612e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
256217ab2063SBarry Smith   }
256317ab2063SBarry Smith   if (rr) {
2564e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
25652c71b3e2SJacob Faibussowitsch     PetscCheckFalse(n != A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2566fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
25672e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
25682e5835c6SStefano Zampini     jj = a->j;
25692205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
25702e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
2571fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2572efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
257317ab2063SBarry Smith   }
2574acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
25753a40ed3dSBarry Smith   PetscFunctionReturn(0);
257617ab2063SBarry Smith }
257717ab2063SBarry Smith 
25787dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
257917ab2063SBarry Smith {
2580db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
25816849ba73SBarry Smith   PetscErrorCode    ierr;
2582d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
258397f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25845d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
25852e5835c6SStefano Zampini   const PetscScalar *aa;
25865d0c19d7SBarry Smith   PetscInt          nrows,ncols;
258797f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
258854f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2589416022c9SBarry Smith   Mat               C;
2590cdc6f3adSToby Isaac   PetscBool         stride;
259117ab2063SBarry Smith 
25923a40ed3dSBarry Smith   PetscFunctionBegin;
259317ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2594b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2595b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
259617ab2063SBarry Smith 
2597251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2598ff718158SBarry Smith   if (stride) {
2599ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2600ff718158SBarry Smith   } else {
2601ff718158SBarry Smith     first = 0;
2602ff718158SBarry Smith     step  = 0;
2603ff718158SBarry Smith   }
2604fee21e36SBarry Smith   if (stride && step == 1) {
260502834360SBarry Smith     /* special case of contiguous rows */
2606dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
260702834360SBarry Smith     /* loop over new rows determining lens and starting points */
260802834360SBarry Smith     for (i=0; i<nrows; i++) {
2609bfeeae90SHong Zhang       kstart = ai[irow[i]];
2610a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2611a91a9bebSLisandro Dalcin       starts[i] = kstart;
261202834360SBarry Smith       for (k=kstart; k<kend; k++) {
2613bfeeae90SHong Zhang         if (aj[k] >= first) {
261402834360SBarry Smith           starts[i] = k;
261502834360SBarry Smith           break;
261602834360SBarry Smith         }
261702834360SBarry Smith       }
2618a2744918SBarry Smith       sum = 0;
261902834360SBarry Smith       while (k < kend) {
2620bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2621a2744918SBarry Smith         sum++;
262202834360SBarry Smith       }
2623a2744918SBarry Smith       lens[i] = sum;
262402834360SBarry Smith     }
262502834360SBarry Smith     /* create submatrix */
2626cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
262797f1f81fSBarry Smith       PetscInt n_cols,n_rows;
262808480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
26292c71b3e2SJacob Faibussowitsch       PetscCheckFalse(n_rows != nrows || n_cols != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2630d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
263108480c60SBarry Smith       C    = *B;
26323a40ed3dSBarry Smith     } else {
26333bef6203SJed Brown       PetscInt rbs,cbs;
2634ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2635f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26363bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26373bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26383bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26397adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2640ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
264108480c60SBarry Smith     }
2642db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2643db02288aSLois Curfman McInnes 
264402834360SBarry Smith     /* loop over rows inserting into submatrix */
2645db02288aSLois Curfman McInnes     a_new = c->a;
2646db02288aSLois Curfman McInnes     j_new = c->j;
2647db02288aSLois Curfman McInnes     i_new = c->i;
26482e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
264902834360SBarry Smith     for (i=0; i<nrows; i++) {
2650a2744918SBarry Smith       ii    = starts[i];
2651a2744918SBarry Smith       lensi = lens[i];
2652a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2653a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
265402834360SBarry Smith       }
26552e5835c6SStefano Zampini       ierr       = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr);
2656a2744918SBarry Smith       a_new     += lensi;
2657a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2658a2744918SBarry Smith       c->ilen[i] = lensi;
265902834360SBarry Smith     }
26602e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
26610e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26623a40ed3dSBarry Smith   } else {
266302834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26641795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2665854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26664dcab191SBarry Smith     for (i=0; i<ncols; i++) {
26672c71b3e2SJacob Faibussowitsch       PetscAssertFalse(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);
26684dcab191SBarry Smith       smap[icol[i]] = i+1;
26694dcab191SBarry Smith     }
26704dcab191SBarry Smith 
267102834360SBarry Smith     /* determine lens of each row */
267202834360SBarry Smith     for (i=0; i<nrows; i++) {
2673bfeeae90SHong Zhang       kstart  = ai[irow[i]];
267402834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
267502834360SBarry Smith       lens[i] = 0;
267602834360SBarry Smith       for (k=kstart; k<kend; k++) {
2677bfeeae90SHong Zhang         if (smap[aj[k]]) {
267802834360SBarry Smith           lens[i]++;
267902834360SBarry Smith         }
268002834360SBarry Smith       }
268102834360SBarry Smith     }
268217ab2063SBarry Smith     /* Create and fill new matrix */
2683a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2684ace3abfcSBarry Smith       PetscBool equal;
26850f5bd95cSBarry Smith 
268699141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
26872c71b3e2SJacob Faibussowitsch       PetscCheckFalse((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2688580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
26892c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!equal,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2690580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
269108480c60SBarry Smith       C    = *B;
26923a40ed3dSBarry Smith     } else {
26933bef6203SJed Brown       PetscInt rbs,cbs;
2694ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2695f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26963bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26973bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26983bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26997adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2700ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
270108480c60SBarry Smith     }
27022e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
270399141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
270417ab2063SBarry Smith     for (i=0; i<nrows; i++) {
270599141d43SSatish Balay       row      = irow[i];
2706bfeeae90SHong Zhang       kstart   = ai[row];
270799141d43SSatish Balay       kend     = kstart + a->ilen[row];
2708bfeeae90SHong Zhang       mat_i    = c->i[i];
270999141d43SSatish Balay       mat_j    = c->j + mat_i;
271099141d43SSatish Balay       mat_a    = c->a + mat_i;
271199141d43SSatish Balay       mat_ilen = c->ilen + i;
271217ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2713bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2714ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
27152e5835c6SStefano Zampini           *mat_a++ = aa[k];
271699141d43SSatish Balay           (*mat_ilen)++;
271799141d43SSatish Balay 
271817ab2063SBarry Smith         }
271917ab2063SBarry Smith       }
272017ab2063SBarry Smith     }
27212e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
272202834360SBarry Smith     /* Free work space */
272302834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2724606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2725606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2726cdc6f3adSToby Isaac     /* sort */
2727cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2728cdc6f3adSToby Isaac       PetscInt ilen;
2729cdc6f3adSToby Isaac 
2730cdc6f3adSToby Isaac       mat_i = c->i[i];
2731cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2732cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2733cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2734390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2735cdc6f3adSToby Isaac     }
273602834360SBarry Smith   }
27378c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2738b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2739305c6ccfSStefano Zampini #endif
27406d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27416d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
274217ab2063SBarry Smith 
274317ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2744416022c9SBarry Smith   *B   = C;
27453a40ed3dSBarry Smith   PetscFunctionReturn(0);
274617ab2063SBarry Smith }
274717ab2063SBarry Smith 
2748fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
274982d44351SHong Zhang {
275082d44351SHong Zhang   PetscErrorCode ierr;
275182d44351SHong Zhang   Mat            B;
275282d44351SHong Zhang 
275382d44351SHong Zhang   PetscFunctionBegin;
2754c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
275582d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
275682d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
275733d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
275882d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
275982d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
276082d44351SHong Zhang     *subMat = B;
2761c2d650bdSHong Zhang   } else {
2762c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2763c2d650bdSHong Zhang   }
276482d44351SHong Zhang   PetscFunctionReturn(0);
276582d44351SHong Zhang }
276682d44351SHong Zhang 
27679a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2768a871dcd8SBarry Smith {
276963b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2770dfbe8321SBarry Smith   PetscErrorCode ierr;
277163b91edcSBarry Smith   Mat            outA;
2772ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
277363b91edcSBarry Smith 
27743a40ed3dSBarry Smith   PetscFunctionBegin;
27752c71b3e2SJacob Faibussowitsch   PetscCheckFalse(info->levels != 0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27761df811f5SHong Zhang 
2777b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2778b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2779a871dcd8SBarry Smith 
278063b91edcSBarry Smith   outA             = inA;
2781d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2782f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2783f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
27842205254eSKarl Rupp 
2785c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
27866bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
27872205254eSKarl Rupp 
2788c3122656SLisandro Dalcin   a->row = row;
27892205254eSKarl Rupp 
2790c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
27916bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
27922205254eSKarl Rupp 
2793c3122656SLisandro Dalcin   a->col = col;
279463b91edcSBarry Smith 
279536db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
27966bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
27974c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
27983bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2799f0ec6fceSSatish Balay 
280094a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2801854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
28023bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
280394a9d846SBarry Smith   }
280463b91edcSBarry Smith 
2805f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2806137fb511SHong Zhang   if (row_identity && col_identity) {
2807ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2808137fb511SHong Zhang   } else {
2809719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2810137fb511SHong Zhang   }
28113a40ed3dSBarry Smith   PetscFunctionReturn(0);
2812a871dcd8SBarry Smith }
2813a871dcd8SBarry Smith 
2814f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2815f0b747eeSBarry Smith {
2816f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2817dfa0f9e5SStefano Zampini   PetscScalar    *v;
2818efee365bSSatish Balay   PetscErrorCode ierr;
2819c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
28203a40ed3dSBarry Smith 
28213a40ed3dSBarry Smith   PetscFunctionBegin;
2822dfa0f9e5SStefano Zampini   ierr = MatSeqAIJGetArray(inA,&v);CHKERRQ(ierr);
2823c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
2824dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
2825efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2826dfa0f9e5SStefano Zampini   ierr = MatSeqAIJRestoreArray(inA,&v);CHKERRQ(ierr);
2827acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
28283a40ed3dSBarry Smith   PetscFunctionReturn(0);
2829f0b747eeSBarry Smith }
2830f0b747eeSBarry Smith 
2831f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
283216b64355SHong Zhang {
283316b64355SHong Zhang   PetscErrorCode ierr;
283416b64355SHong Zhang   PetscInt       i;
283516b64355SHong Zhang 
283616b64355SHong Zhang   PetscFunctionBegin;
283716b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
283816b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
283916b64355SHong Zhang 
284016b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
284116b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
284216b64355SHong Zhang     }
284316b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
284416b64355SHong Zhang 
284516b64355SHong Zhang     if (submatj->rbuf1) {
284616b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
284716b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
284816b64355SHong Zhang     }
284916b64355SHong Zhang 
285016b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
285116b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
285216b64355SHong Zhang     }
285316b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
285416b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
285516b64355SHong Zhang   }
285616b64355SHong Zhang 
285716b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
285816b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
285916b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
286016b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
286116b64355SHong Zhang #else
286216b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
286316b64355SHong Zhang #endif
286416b64355SHong Zhang 
286516b64355SHong Zhang   if (!submatj->allcolumns) {
286616b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
286716b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
286816b64355SHong Zhang #else
286916b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
287016b64355SHong Zhang #endif
287116b64355SHong Zhang   }
287216b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
287316b64355SHong Zhang 
287416b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
287516b64355SHong Zhang   PetscFunctionReturn(0);
287616b64355SHong Zhang }
287716b64355SHong Zhang 
28780fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
287916b64355SHong Zhang {
288016b64355SHong Zhang   PetscErrorCode ierr;
288116b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28825c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
288316b64355SHong Zhang 
288416b64355SHong Zhang   PetscFunctionBegin;
288534136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2886f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
288716b64355SHong Zhang   PetscFunctionReturn(0);
288816b64355SHong Zhang }
288916b64355SHong Zhang 
28902d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
28912d033e1fSHong Zhang {
28922d033e1fSHong Zhang   PetscErrorCode ierr;
28932d033e1fSHong Zhang   PetscInt       i;
28940fb991dcSHong Zhang   Mat            C;
28950fb991dcSHong Zhang   Mat_SeqAIJ     *c;
28960fb991dcSHong Zhang   Mat_SubSppt    *submatj;
28972d033e1fSHong Zhang 
28982d033e1fSHong Zhang   PetscFunctionBegin;
28992d033e1fSHong Zhang   for (i=0; i<n; i++) {
29000fb991dcSHong Zhang     C       = (*mat)[i];
29010fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
29020fb991dcSHong Zhang     submatj = c->submatis1;
29032d033e1fSHong Zhang     if (submatj) {
2904682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
290534136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2906f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
290734136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
29082d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
29092d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
29102d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2911682e4c99SStefano Zampini       }
29122d033e1fSHong Zhang     } else {
29132d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
29142d033e1fSHong Zhang     }
29152d033e1fSHong Zhang   }
291686e85357SHong Zhang 
291763a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
291863a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
291963a75b2aSHong Zhang 
29202d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
29212d033e1fSHong Zhang   PetscFunctionReturn(0);
29222d033e1fSHong Zhang }
29232d033e1fSHong Zhang 
29247dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2925cddf8d76SBarry Smith {
2926dfbe8321SBarry Smith   PetscErrorCode ierr;
292797f1f81fSBarry Smith   PetscInt       i;
2928cddf8d76SBarry Smith 
29293a40ed3dSBarry Smith   PetscFunctionBegin;
2930cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2931df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2932cddf8d76SBarry Smith   }
2933cddf8d76SBarry Smith 
2934cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29357dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2936cddf8d76SBarry Smith   }
29373a40ed3dSBarry Smith   PetscFunctionReturn(0);
2938cddf8d76SBarry Smith }
2939cddf8d76SBarry Smith 
294097f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29414dcbc457SBarry Smith {
2942e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29436849ba73SBarry Smith   PetscErrorCode ierr;
29445d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29455d0c19d7SBarry Smith   const PetscInt *idx;
294697f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2947f1af5d2fSBarry Smith   PetscBT        table;
2948bbd702dbSSatish Balay 
29493a40ed3dSBarry Smith   PetscFunctionBegin;
2950d0f46423SBarry Smith   m  = A->rmap->n;
2951e4d965acSSatish Balay   ai = a->i;
2952bfeeae90SHong Zhang   aj = a->j;
29538a047759SSatish Balay 
29542c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ov < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
295506763907SSatish Balay 
2956854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
295753b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
295806763907SSatish Balay 
2959e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2960b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2961e4d965acSSatish Balay     isz  = 0;
29626831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2963e4d965acSSatish Balay 
2964e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29654dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2966b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
2967e4d965acSSatish Balay 
2968dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2969e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29702205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29714dcbc457SBarry Smith     }
297206763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
29736bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
2974e4d965acSSatish Balay 
297504a348a9SBarry Smith     k = 0;
297604a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
297704a348a9SBarry Smith       n = isz;
297806763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2979e4d965acSSatish Balay         row   = nidx[k];
2980e4d965acSSatish Balay         start = ai[row];
2981e4d965acSSatish Balay         end   = ai[row+1];
298204a348a9SBarry Smith         for (l = start; l<end; l++) {
2983efb16452SHong Zhang           val = aj[l];
29842205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2985e4d965acSSatish Balay         }
2986e4d965acSSatish Balay       }
2987e4d965acSSatish Balay     }
298870b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
2989e4d965acSSatish Balay   }
299094bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
2991606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
29923a40ed3dSBarry Smith   PetscFunctionReturn(0);
29934dcbc457SBarry Smith }
299417ab2063SBarry Smith 
29950513a670SBarry Smith /* -------------------------------------------------------------- */
2996dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
29970513a670SBarry Smith {
29980513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29996849ba73SBarry Smith   PetscErrorCode ierr;
30003b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
30015d0c19d7SBarry Smith   const PetscInt *row,*col;
30025d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
300356cd22aeSBarry Smith   IS             icolp,irowp;
30040298fd71SBarry Smith   PetscInt       *cwork = NULL;
30050298fd71SBarry Smith   PetscScalar    *vwork = NULL;
30060513a670SBarry Smith 
30073a40ed3dSBarry Smith   PetscFunctionBegin;
30084c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
300956cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
30104c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
301156cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
30120513a670SBarry Smith 
30130513a670SBarry Smith   /* determine lengths of permuted rows */
3014854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
30152205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
3016ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
3017f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
301833d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
30197adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
3020ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
3021606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
30220513a670SBarry Smith 
3023785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
30240513a670SBarry Smith   for (i=0; i<m; i++) {
302532ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30262205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3027cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
302832ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30290513a670SBarry Smith   }
3030606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30312205254eSKarl Rupp 
30323c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30332205254eSKarl Rupp 
30348c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3035b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30369fe5e383SStefano Zampini #endif
30370513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30380513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
303956cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
304056cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30416bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30426bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30436768869dSprj-   if (rowp == colp) {
3044dc29a518SPierre Jolivet     ierr = MatPropagateSymmetryOptions(A,*B);CHKERRQ(ierr);
30456768869dSprj-   }
30463a40ed3dSBarry Smith   PetscFunctionReturn(0);
30470513a670SBarry Smith }
30480513a670SBarry Smith 
3049dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3050cb5b572fSBarry Smith {
3051dfbe8321SBarry Smith   PetscErrorCode ierr;
3052cb5b572fSBarry Smith 
3053cb5b572fSBarry Smith   PetscFunctionBegin;
305433f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
305533f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3056be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3057be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30582e5835c6SStefano Zampini     const PetscScalar *aa;
3059be6bf707SBarry Smith 
30602e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30612c71b3e2SJacob 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]);
30622e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3063cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
30642e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3065cb5b572fSBarry Smith   } else {
3066cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3067cb5b572fSBarry Smith   }
3068cb5b572fSBarry Smith   PetscFunctionReturn(0);
3069cb5b572fSBarry Smith }
3070cb5b572fSBarry Smith 
30714994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3072273d9f13SBarry Smith {
3073dfbe8321SBarry Smith   PetscErrorCode ierr;
3074273d9f13SBarry Smith 
3075273d9f13SBarry Smith   PetscFunctionBegin;
3076f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3077273d9f13SBarry Smith   PetscFunctionReturn(0);
3078273d9f13SBarry Smith }
3079273d9f13SBarry Smith 
3080f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30816c0721eeSBarry Smith {
30826c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30836e111a19SKarl Rupp 
30846c0721eeSBarry Smith   PetscFunctionBegin;
30856c0721eeSBarry Smith   *array = a->a;
30866c0721eeSBarry Smith   PetscFunctionReturn(0);
30876c0721eeSBarry Smith }
30886c0721eeSBarry Smith 
3089f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
30906c0721eeSBarry Smith {
30916c0721eeSBarry Smith   PetscFunctionBegin;
3092f38c1e66SStefano Zampini   *array = NULL;
30936c0721eeSBarry Smith   PetscFunctionReturn(0);
30946c0721eeSBarry Smith }
3095273d9f13SBarry Smith 
30968229c054SShri Abhyankar /*
30978229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
30988229c054SShri Abhyankar    have different nonzero structure.
30998229c054SShri Abhyankar */
3100b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3101ec7775f6SShri Abhyankar {
3102b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3103ec7775f6SShri Abhyankar 
3104ec7775f6SShri Abhyankar   PetscFunctionBegin;
3105ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3106ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3107b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3108b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3109b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31108af7cee1SJed Brown     nnz[i] = 0;
31118af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3112b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3113b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31148af7cee1SJed Brown       nnz[i]++;
31158af7cee1SJed Brown     }
31168af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3117ec7775f6SShri Abhyankar   }
3118ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3119ec7775f6SShri Abhyankar }
3120ec7775f6SShri Abhyankar 
3121b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3122b264fe52SHong Zhang {
3123b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3124b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3125b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3126b264fe52SHong Zhang   PetscErrorCode ierr;
3127b264fe52SHong Zhang 
3128b264fe52SHong Zhang   PetscFunctionBegin;
3129b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3130b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3131b264fe52SHong Zhang   PetscFunctionReturn(0);
3132b264fe52SHong Zhang }
3133b264fe52SHong Zhang 
3134f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3135ac90fabeSBarry Smith {
3136dfbe8321SBarry Smith   PetscErrorCode ierr;
3137ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3138ac90fabeSBarry Smith 
3139ac90fabeSBarry Smith   PetscFunctionBegin;
3140134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
3141134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE;
3142134adf20SPierre Jolivet     if (e) {
314381fa06acSBarry Smith       ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
314481fa06acSBarry Smith       if (e) {
314581fa06acSBarry Smith         ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
3146134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
314781fa06acSBarry Smith       }
314881fa06acSBarry Smith     }
3149134adf20SPierre Jolivet     if (!e && str == SAME_NONZERO_PATTERN) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatStructure is not SAME_NONZERO_PATTERN");
315081fa06acSBarry Smith   }
3151ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31522e5835c6SStefano Zampini     const PetscScalar *xa;
31532e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
315481fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
315581fa06acSBarry Smith 
315681fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31572e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31582e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31592e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31602e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31612e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
316241f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3163acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3164a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3165ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3166ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3167ac90fabeSBarry Smith   } else {
31688229c054SShri Abhyankar     Mat      B;
31698229c054SShri Abhyankar     PetscInt *nnz;
3170785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3171ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3172bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
317381fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
31742e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
31758229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3176ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3177ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
317879c2fd05SStefano Zampini     ierr = MatHeaderMerge(Y,&B);CHKERRQ(ierr);
31798229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3180ac90fabeSBarry Smith   }
3181ac90fabeSBarry Smith   PetscFunctionReturn(0);
3182ac90fabeSBarry Smith }
3183ac90fabeSBarry Smith 
31842726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3185354c94deSBarry Smith {
3186354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3187354c94deSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3188354c94deSBarry Smith   PetscInt       i,nz;
3189354c94deSBarry Smith   PetscScalar    *a;
3190ce496241SStefano Zampini   PetscErrorCode ierr;
3191354c94deSBarry Smith 
3192354c94deSBarry Smith   PetscFunctionBegin;
3193354c94deSBarry Smith   nz = aij->nz;
3194ce496241SStefano Zampini   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
31952205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3196ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3197354c94deSBarry Smith #else
3198354c94deSBarry Smith   PetscFunctionBegin;
3199354c94deSBarry Smith #endif
3200354c94deSBarry Smith   PetscFunctionReturn(0);
3201354c94deSBarry Smith }
3202354c94deSBarry Smith 
3203985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3204e34fafa9SBarry Smith {
3205e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3206e34fafa9SBarry Smith   PetscErrorCode  ierr;
3207d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3208e34fafa9SBarry Smith   PetscReal       atmp;
3209985db425SBarry Smith   PetscScalar     *x;
3210ce496241SStefano Zampini   const MatScalar *aa,*av;
3211e34fafa9SBarry Smith 
3212e34fafa9SBarry Smith   PetscFunctionBegin;
32132c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3214ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3215ce496241SStefano Zampini   aa = av;
3216e34fafa9SBarry Smith   ai = a->i;
3217e34fafa9SBarry Smith   aj = a->j;
3218e34fafa9SBarry Smith 
3219985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3220475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3221e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
32222c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3223e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3224e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3225e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3226985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3227985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3228985db425SBarry Smith       aa++; aj++;
3229985db425SBarry Smith     }
3230985db425SBarry Smith   }
3231475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3232ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3233985db425SBarry Smith   PetscFunctionReturn(0);
3234985db425SBarry Smith }
3235985db425SBarry Smith 
3236985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3237985db425SBarry Smith {
3238985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3239985db425SBarry Smith   PetscErrorCode  ierr;
3240d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3241985db425SBarry Smith   PetscScalar     *x;
3242ce496241SStefano Zampini   const MatScalar *aa,*av;
3243985db425SBarry Smith 
3244985db425SBarry Smith   PetscFunctionBegin;
32452c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3246ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3247ce496241SStefano Zampini   aa = av;
3248985db425SBarry Smith   ai = a->i;
3249985db425SBarry Smith   aj = a->j;
3250985db425SBarry Smith 
3251985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3252fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3253985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
32542c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3255985db425SBarry Smith   for (i=0; i<m; i++) {
3256985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3257d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3258985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3259985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3260985db425SBarry Smith       x[i] = 0.0;
3261985db425SBarry Smith       if (idx) {
3262985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3263985db425SBarry Smith           if (aj[j] > j) {
3264985db425SBarry Smith             idx[i] = j;
3265985db425SBarry Smith             break;
3266985db425SBarry Smith           }
3267985db425SBarry Smith         }
32681a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
32691a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3270985db425SBarry Smith       }
3271985db425SBarry Smith     }
3272985db425SBarry Smith     for (j=0; j<ncols; j++) {
3273985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3274985db425SBarry Smith       aa++; aj++;
3275985db425SBarry Smith     }
3276985db425SBarry Smith   }
3277fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3278ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3279985db425SBarry Smith   PetscFunctionReturn(0);
3280985db425SBarry Smith }
3281985db425SBarry Smith 
3282c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3283c87e5d42SMatthew Knepley {
3284c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3285c87e5d42SMatthew Knepley   PetscErrorCode  ierr;
3286c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3287ce496241SStefano Zampini   PetscScalar     *x;
3288ce496241SStefano Zampini   const MatScalar *aa,*av;
3289c87e5d42SMatthew Knepley 
3290c87e5d42SMatthew Knepley   PetscFunctionBegin;
3291ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3292ce496241SStefano Zampini   aa = av;
3293c87e5d42SMatthew Knepley   ai = a->i;
3294c87e5d42SMatthew Knepley   aj = a->j;
3295c87e5d42SMatthew Knepley 
3296c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3297f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3298c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
32992c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n);
3300c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3301c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3302f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3303f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3304f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3305f07e67edSHong Zhang       x[i] = 0.0;
3306f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3307289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3308f07e67edSHong Zhang           if (aj[j] > j) {
3309f07e67edSHong Zhang             idx[i] = j;
33102205254eSKarl Rupp             break;
33112205254eSKarl Rupp           }
3312289a08f5SMatthew Knepley         }
3313f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3314f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3315f07e67edSHong Zhang       }
3316289a08f5SMatthew Knepley     }
3317c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3318f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3319c87e5d42SMatthew Knepley       aa++; aj++;
3320c87e5d42SMatthew Knepley     }
3321c87e5d42SMatthew Knepley   }
3322f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3323ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3324c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3325c87e5d42SMatthew Knepley }
3326c87e5d42SMatthew Knepley 
3327985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3328985db425SBarry Smith {
3329985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3330985db425SBarry Smith   PetscErrorCode  ierr;
3331d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3332d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3333985db425SBarry Smith   PetscScalar     *x;
3334ce496241SStefano Zampini   const MatScalar *aa,*av;
3335985db425SBarry Smith 
3336985db425SBarry Smith   PetscFunctionBegin;
33372c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3338ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3339ce496241SStefano Zampini   aa = av;
3340985db425SBarry Smith   ai = a->i;
3341985db425SBarry Smith   aj = a->j;
3342985db425SBarry Smith 
3343985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3344fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3345985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
33462c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3347985db425SBarry Smith   for (i=0; i<m; i++) {
3348985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3349d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3350985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3351985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3352985db425SBarry Smith       x[i] = 0.0;
3353985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3354985db425SBarry Smith         for (j=0; j<ncols; j++) {
3355985db425SBarry Smith           if (aj[j] > j) {
3356985db425SBarry Smith             idx[i] = j;
3357985db425SBarry Smith             break;
3358985db425SBarry Smith           }
3359985db425SBarry Smith         }
3360fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3361fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3362985db425SBarry Smith       }
3363985db425SBarry Smith     }
3364985db425SBarry Smith     for (j=0; j<ncols; j++) {
3365985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3366985db425SBarry Smith       aa++; aj++;
3367e34fafa9SBarry Smith     }
3368e34fafa9SBarry Smith   }
3369fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3370ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3371e34fafa9SBarry Smith   PetscFunctionReturn(0);
3372e34fafa9SBarry Smith }
3373bbead8a2SBarry Smith 
3374713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3375bbead8a2SBarry Smith {
3376bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3377bbead8a2SBarry Smith   PetscErrorCode  ierr;
337833d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3379bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33800da83c2eSBarry Smith   const PetscReal shift = 0.0;
33811a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3382bbead8a2SBarry Smith 
3383bbead8a2SBarry Smith   PetscFunctionBegin;
3384a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33854a0d0026SBarry Smith   if (a->ibdiagvalid) {
33864a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33874a0d0026SBarry Smith     PetscFunctionReturn(0);
33884a0d0026SBarry Smith   }
3389bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3390bbead8a2SBarry Smith   if (!a->ibdiag) {
3391785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
33923bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3393bbead8a2SBarry Smith   }
3394bbead8a2SBarry Smith   diag = a->ibdiag;
3395bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3396bbead8a2SBarry Smith   /* factor and invert each block */
3397bbead8a2SBarry Smith   switch (bs) {
3398bbead8a2SBarry Smith   case 1:
3399bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3400bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3401ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3402ec1892c8SHong Zhang         if (allowzeropivot) {
34037b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34047b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34057b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34067d3de750SJacob 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);
340798921bdaSJacob 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);
3408ec1892c8SHong Zhang       }
3409bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3410bbead8a2SBarry Smith     }
3411bbead8a2SBarry Smith     break;
3412bbead8a2SBarry Smith   case 2:
3413bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3414bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3415bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3416a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34177b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
341896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3419bbead8a2SBarry Smith       diag += 4;
3420bbead8a2SBarry Smith     }
3421bbead8a2SBarry Smith     break;
3422bbead8a2SBarry Smith   case 3:
3423bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3424bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3425bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3426a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34277b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
342896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3429bbead8a2SBarry Smith       diag += 9;
3430bbead8a2SBarry Smith     }
3431bbead8a2SBarry Smith     break;
3432bbead8a2SBarry Smith   case 4:
3433bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3434bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3435bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3436a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34377b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
343896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3439bbead8a2SBarry Smith       diag += 16;
3440bbead8a2SBarry Smith     }
3441bbead8a2SBarry Smith     break;
3442bbead8a2SBarry Smith   case 5:
3443bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3444bbead8a2SBarry 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;
3445bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3446a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34477b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
344896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3449bbead8a2SBarry Smith       diag += 25;
3450bbead8a2SBarry Smith     }
3451bbead8a2SBarry Smith     break;
3452bbead8a2SBarry Smith   case 6:
3453bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3454bbead8a2SBarry 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;
3455bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3456a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34577b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3459bbead8a2SBarry Smith       diag += 36;
3460bbead8a2SBarry Smith     }
3461bbead8a2SBarry Smith     break;
3462bbead8a2SBarry Smith   case 7:
3463bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3464bbead8a2SBarry 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;
3465bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3466a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34677b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346896b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3469bbead8a2SBarry Smith       diag += 49;
3470bbead8a2SBarry Smith     }
3471bbead8a2SBarry Smith     break;
3472bbead8a2SBarry Smith   default:
3473dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3474bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3475bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3476bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3477bbead8a2SBarry Smith       }
3478bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
34795f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34807b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
348196b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3482bbead8a2SBarry Smith       diag += bs2;
3483bbead8a2SBarry Smith     }
3484bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3485bbead8a2SBarry Smith   }
3486bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3487bbead8a2SBarry Smith   PetscFunctionReturn(0);
3488bbead8a2SBarry Smith }
3489bbead8a2SBarry Smith 
349073a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
349173a71a0fSBarry Smith {
349273a71a0fSBarry Smith   PetscErrorCode ierr;
349373a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3494fff043a9SJunchao Zhang   PetscScalar    a,*aa;
349573a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
349673a71a0fSBarry Smith 
349773a71a0fSBarry Smith   PetscFunctionBegin;
349873a71a0fSBarry Smith   if (!x->assembled) {
349973a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
350073a71a0fSBarry Smith     for (i=0; i<m; i++) {
350173a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
350273a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
350373a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
350473a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
350573a71a0fSBarry Smith       }
350673a71a0fSBarry Smith     }
3507e2ce353bSJunchao Zhang   } else {
3508fff043a9SJunchao Zhang     ierr = MatSeqAIJGetArrayWrite(x,&aa);CHKERRQ(ierr);
3509fff043a9SJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aa+i);CHKERRQ(ierr);}
3510fff043a9SJunchao Zhang     ierr = MatSeqAIJRestoreArrayWrite(x,&aa);CHKERRQ(ierr);
3511e2ce353bSJunchao Zhang   }
351273a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
351373a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
351473a71a0fSBarry Smith   PetscFunctionReturn(0);
351573a71a0fSBarry Smith }
351673a71a0fSBarry Smith 
3517679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3518679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3519679944adSJunchao Zhang {
3520679944adSJunchao Zhang   PetscErrorCode ierr;
3521679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3522679944adSJunchao Zhang   PetscScalar    a;
3523679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3524679944adSJunchao Zhang 
3525679944adSJunchao Zhang   PetscFunctionBegin;
3526679944adSJunchao Zhang   nskip = high - low;
3527679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3528679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3529679944adSJunchao Zhang   for (i=0; i<m; i++) {
3530679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3531679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3532679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3533679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3534679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3535679944adSJunchao Zhang     }
3536e2ce353bSJunchao Zhang   }
3537679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3538679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3539679944adSJunchao Zhang   PetscFunctionReturn(0);
3540679944adSJunchao Zhang }
3541679944adSJunchao Zhang 
3542682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35430a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3544cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3545cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3546cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
354797304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35487c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35497c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3550f4259b30SLisandro Dalcin                                         NULL,
3551f4259b30SLisandro Dalcin                                         NULL,
3552f4259b30SLisandro Dalcin                                         NULL,
3553f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3554cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3555f4259b30SLisandro Dalcin                                         NULL,
355641f059aeSBarry Smith                                         MatSOR_SeqAIJ,
355791e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
355897304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3559cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3560cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3561cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3562cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3563f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3564cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3565cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3566cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3567d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3568f4259b30SLisandro Dalcin                                         NULL,
3569f4259b30SLisandro Dalcin                                         NULL,
3570f4259b30SLisandro Dalcin                                         NULL,
3571f4259b30SLisandro Dalcin                                         NULL,
35724994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3573f4259b30SLisandro Dalcin                                         NULL,
3574f4259b30SLisandro Dalcin                                         NULL,
3575f4259b30SLisandro Dalcin                                         NULL,
3576f4259b30SLisandro Dalcin                                         NULL,
3577d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3578f4259b30SLisandro Dalcin                                         NULL,
3579f4259b30SLisandro Dalcin                                         NULL,
3580cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3581f4259b30SLisandro Dalcin                                         NULL,
3582d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35837dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3584cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3585cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3586cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3587d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3588cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35897d68702bSBarry Smith                                         MatShift_SeqAIJ,
359079299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
35916e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
359273a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
35933b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
35943b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
35953b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3596a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
359793dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3598f4259b30SLisandro Dalcin                                         NULL,
3599f4259b30SLisandro Dalcin                                         NULL,
3600cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3601f4259b30SLisandro Dalcin                                         NULL,
3602f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3603b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3604b9b97703SBarry Smith                                         MatView_SeqAIJ,
3605f4259b30SLisandro Dalcin                                         NULL,
3606f4259b30SLisandro Dalcin                                         NULL,
3607f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3608321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3609f4259b30SLisandro Dalcin                                         NULL,
3610f4259b30SLisandro Dalcin                                         NULL,
3611f4259b30SLisandro Dalcin                                         NULL,
3612d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3613c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3614f4259b30SLisandro Dalcin                                         NULL,
3615f4259b30SLisandro Dalcin                                         NULL,
3616f4259b30SLisandro Dalcin                                         NULL,
3617f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36183acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3619f4259b30SLisandro Dalcin                                         NULL,
3620f4259b30SLisandro Dalcin                                         NULL,
3621f4259b30SLisandro Dalcin                                         NULL,
36226ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3623f4259b30SLisandro Dalcin                                         NULL,
3624f4259b30SLisandro Dalcin                                         NULL,
3625f4259b30SLisandro Dalcin                                         NULL,
3626bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3627d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36281cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3629f4259b30SLisandro Dalcin                                         NULL,
3630f4259b30SLisandro Dalcin                                         NULL,
3631f4259b30SLisandro Dalcin                                         NULL,
3632f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3633f4259b30SLisandro Dalcin                                         NULL,
363426be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3635f4259b30SLisandro Dalcin                                         NULL,
3636f4259b30SLisandro Dalcin                                         NULL,
36378fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3638f4259b30SLisandro Dalcin                                         NULL,
3639f4259b30SLisandro Dalcin                                         NULL,
36406fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3641f4259b30SLisandro Dalcin                                         NULL,
36424222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3643f4259b30SLisandro Dalcin                                         NULL,
3644f4259b30SLisandro Dalcin                                         NULL,
364587d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3646f4259b30SLisandro Dalcin                                         NULL,
3647d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
364899cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3649f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3650f4259b30SLisandro Dalcin                                         NULL,
3651f4259b30SLisandro Dalcin                                         NULL,
3652cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3653f4259b30SLisandro Dalcin                                         NULL,
36542af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3655f4259b30SLisandro Dalcin                                         NULL,
3656599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3657f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3658f4259b30SLisandro Dalcin                                         NULL,
3659f4259b30SLisandro Dalcin                                         NULL,
3660f4259b30SLisandro Dalcin                                         NULL,
3661f4259b30SLisandro Dalcin                                         NULL,
3662f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3663f4259b30SLisandro Dalcin                                         NULL,
3664f4259b30SLisandro Dalcin                                         NULL,
3665f4259b30SLisandro Dalcin                                         NULL,
3666b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
36670716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3668a873a8cdSSam Reynolds                                         MatGetColumnReductions_SeqAIJ,
366937868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
36700da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3671f4259b30SLisandro Dalcin                                         NULL,
3672f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3673f4259b30SLisandro Dalcin                                         NULL,
3674f4259b30SLisandro Dalcin                                         NULL,
367575648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3676b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3677b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36782b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3679f4259b30SLisandro Dalcin                                         NULL,
3680f4259b30SLisandro Dalcin                                         NULL,
36813964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3682f4259b30SLisandro Dalcin                                  /*139*/NULL,
3683f4259b30SLisandro Dalcin                                         NULL,
3684f4259b30SLisandro Dalcin                                         NULL,
36853a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36869c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36874222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36884222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3689f4259b30SLisandro Dalcin                                         NULL,
3690f4259b30SLisandro Dalcin                                         NULL
36919e29f15eSvictorle };
369217ab2063SBarry Smith 
36937087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3694bef8e0ddSBarry Smith {
3695bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
369697f1f81fSBarry Smith   PetscInt   i,nz,n;
3697bef8e0ddSBarry Smith 
3698bef8e0ddSBarry Smith   PetscFunctionBegin;
3699bef8e0ddSBarry Smith   nz = aij->maxnz;
3700d0f46423SBarry Smith   n  = mat->rmap->n;
3701bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3702bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3703bef8e0ddSBarry Smith   }
3704bef8e0ddSBarry Smith   aij->nz = nz;
3705bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3706bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3707bef8e0ddSBarry Smith   }
3708bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3709bef8e0ddSBarry Smith }
3710bef8e0ddSBarry Smith 
3711a3bb6f32SFande Kong /*
3712ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3713ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3714ddea5d60SJunchao Zhang  */
3715a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3716a3bb6f32SFande Kong {
3717a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3718a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3719a3bb6f32SFande Kong   PetscTablePosition tpos;
372025b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
372125b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3722a3bb6f32SFande Kong   PetscErrorCode     ierr;
3723a3bb6f32SFande Kong 
3724a3bb6f32SFande Kong   PetscFunctionBegin;
3725a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3726a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3727a3bb6f32SFande Kong   /* use a table */
3728a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3729a3bb6f32SFande Kong   ec = 0;
373025b670f0SStefano Zampini   for (i=0; i<nz; i++) {
373125b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3732a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3733a3bb6f32SFande Kong     if (!data) {
3734a3bb6f32SFande Kong       /* one based table */
3735a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3736a3bb6f32SFande Kong     }
3737a3bb6f32SFande Kong   }
3738a3bb6f32SFande Kong   /* form array of columns we need */
3739b3c64f9dSJunchao Zhang   ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr);
3740a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3741a3bb6f32SFande Kong   while (tpos) {
3742a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3743a3bb6f32SFande Kong     gid--;
3744a3bb6f32SFande Kong     lid--;
3745a3bb6f32SFande Kong     garray[lid] = gid;
3746a3bb6f32SFande Kong   }
3747a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3748a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3749a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3750a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3751a3bb6f32SFande Kong   }
3752a3bb6f32SFande Kong   /* compact out the extra columns in B */
375325b670f0SStefano Zampini   for (i=0; i<nz; i++) {
375425b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3755a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3756a3bb6f32SFande Kong     lid--;
375725b670f0SStefano Zampini     jj[i] = lid;
3758a3bb6f32SFande Kong   }
3759ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3760a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
376125b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3762a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3763a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3764a3bb6f32SFande Kong   PetscFunctionReturn(0);
3765a3bb6f32SFande Kong }
3766a3bb6f32SFande Kong 
3767bef8e0ddSBarry Smith /*@
3768bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3769bef8e0ddSBarry Smith        in the matrix.
3770bef8e0ddSBarry Smith 
3771bef8e0ddSBarry Smith   Input Parameters:
3772bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3773bef8e0ddSBarry Smith -  indices - the column indices
3774bef8e0ddSBarry Smith 
377515091d37SBarry Smith   Level: advanced
377615091d37SBarry Smith 
3777bef8e0ddSBarry Smith   Notes:
3778bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3779bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3780bef8e0ddSBarry Smith   of the MatSetValues() operation.
3781bef8e0ddSBarry Smith 
3782bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3783d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3784bef8e0ddSBarry Smith 
3785bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3786bef8e0ddSBarry Smith 
3787b9617806SBarry Smith     The indices should start with zero, not one.
3788b9617806SBarry Smith 
3789bef8e0ddSBarry Smith @*/
37907087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3791bef8e0ddSBarry Smith {
37924ac538c5SBarry Smith   PetscErrorCode ierr;
3793bef8e0ddSBarry Smith 
3794bef8e0ddSBarry Smith   PetscFunctionBegin;
37950700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
37964482741eSBarry Smith   PetscValidPointer(indices,2);
37974ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3798bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3799bef8e0ddSBarry Smith }
3800bef8e0ddSBarry Smith 
3801be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3802be6bf707SBarry Smith 
38037087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3804be6bf707SBarry Smith {
3805be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38066849ba73SBarry Smith   PetscErrorCode ierr;
3807d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3808be6bf707SBarry Smith 
3809be6bf707SBarry Smith   PetscFunctionBegin;
38102c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3811be6bf707SBarry Smith 
3812be6bf707SBarry Smith   /* allocate space for values if not already there */
3813be6bf707SBarry Smith   if (!aij->saved_values) {
3814854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38153bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3816be6bf707SBarry Smith   }
3817be6bf707SBarry Smith 
3818be6bf707SBarry Smith   /* copy values over */
3819580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3820be6bf707SBarry Smith   PetscFunctionReturn(0);
3821be6bf707SBarry Smith }
3822be6bf707SBarry Smith 
3823be6bf707SBarry Smith /*@
3824be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3825be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3826be6bf707SBarry Smith        nonlinear portion.
3827be6bf707SBarry Smith 
3828be6bf707SBarry Smith    Collect on Mat
3829be6bf707SBarry Smith 
3830be6bf707SBarry Smith   Input Parameters:
38310e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3832be6bf707SBarry Smith 
383315091d37SBarry Smith   Level: advanced
383415091d37SBarry Smith 
3835be6bf707SBarry Smith   Common Usage, with SNESSolve():
3836be6bf707SBarry Smith $    Create Jacobian matrix
3837be6bf707SBarry Smith $    Set linear terms into matrix
3838be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3839be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3840be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3841512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3842be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3843be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3844be6bf707SBarry Smith $    In your Jacobian routine
3845be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3846be6bf707SBarry Smith $      Set nonlinear terms in matrix
3847be6bf707SBarry Smith 
3848be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3849be6bf707SBarry Smith $    // build linear portion of Jacobian
3850512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3851be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3852be6bf707SBarry Smith $    loop over nonlinear iterations
3853be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3854be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3855be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3856be6bf707SBarry Smith $       Solve linear system with Jacobian
3857be6bf707SBarry Smith $    endloop
3858be6bf707SBarry Smith 
3859be6bf707SBarry Smith   Notes:
3860be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3861512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3862be6bf707SBarry Smith     calling this routine.
3863be6bf707SBarry Smith 
38640c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38650c468ba9SBarry Smith     and does not allocated additional space.
38660c468ba9SBarry Smith 
3867be6bf707SBarry Smith .seealso: MatRetrieveValues()
3868be6bf707SBarry Smith 
3869be6bf707SBarry Smith @*/
38707087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3871be6bf707SBarry Smith {
38724ac538c5SBarry Smith   PetscErrorCode ierr;
3873be6bf707SBarry Smith 
3874be6bf707SBarry Smith   PetscFunctionBegin;
38750700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38762c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
38772c71b3e2SJacob Faibussowitsch   PetscCheckFalse(mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38784ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3879be6bf707SBarry Smith   PetscFunctionReturn(0);
3880be6bf707SBarry Smith }
3881be6bf707SBarry Smith 
38827087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3883be6bf707SBarry Smith {
3884be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38856849ba73SBarry Smith   PetscErrorCode ierr;
3886d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3887be6bf707SBarry Smith 
3888be6bf707SBarry Smith   PetscFunctionBegin;
38892c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
38902c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!aij->saved_values,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3891be6bf707SBarry Smith   /* copy values over */
3892580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3893be6bf707SBarry Smith   PetscFunctionReturn(0);
3894be6bf707SBarry Smith }
3895be6bf707SBarry Smith 
3896be6bf707SBarry Smith /*@
3897be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3898be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3899be6bf707SBarry Smith        nonlinear portion.
3900be6bf707SBarry Smith 
3901be6bf707SBarry Smith    Collect on Mat
3902be6bf707SBarry Smith 
3903be6bf707SBarry Smith   Input Parameters:
3904386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3905be6bf707SBarry Smith 
390615091d37SBarry Smith   Level: advanced
390715091d37SBarry Smith 
3908be6bf707SBarry Smith .seealso: MatStoreValues()
3909be6bf707SBarry Smith 
3910be6bf707SBarry Smith @*/
39117087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3912be6bf707SBarry Smith {
39134ac538c5SBarry Smith   PetscErrorCode ierr;
3914be6bf707SBarry Smith 
3915be6bf707SBarry Smith   PetscFunctionBegin;
39160700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
39172c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
39182c71b3e2SJacob Faibussowitsch   PetscCheckFalse(mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39194ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3920be6bf707SBarry Smith   PetscFunctionReturn(0);
3921be6bf707SBarry Smith }
3922be6bf707SBarry Smith 
3923be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
392417ab2063SBarry Smith /*@C
3925682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39260d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39276e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
392851c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39292bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
393017ab2063SBarry Smith 
3931d083f849SBarry Smith    Collective
3932db81eaa0SLois Curfman McInnes 
393317ab2063SBarry Smith    Input Parameters:
3934db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
393517ab2063SBarry Smith .  m - number of rows
393617ab2063SBarry Smith .  n - number of columns
393717ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
393851c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39390298fd71SBarry Smith          (possibly different for each row) or NULL
394017ab2063SBarry Smith 
394117ab2063SBarry Smith    Output Parameter:
3942416022c9SBarry Smith .  A - the matrix
394317ab2063SBarry Smith 
3944175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3945f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3946175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3947175b88e8SBarry Smith 
3948b259b22eSLois Curfman McInnes    Notes:
394949a6f317SBarry Smith    If nnz is given then nz is ignored
395049a6f317SBarry Smith 
395117ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
395217ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39530002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
395444cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
395517ab2063SBarry Smith 
395617ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39570298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39583d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39596da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
396017ab2063SBarry Smith 
3961682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39624fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3963682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39646c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39656c7ebb05SLois Curfman McInnes 
39666c7ebb05SLois Curfman McInnes    Options Database Keys:
3967698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
39689db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
396917ab2063SBarry Smith 
3970027ccd11SLois Curfman McInnes    Level: intermediate
3971027ccd11SLois Curfman McInnes 
397269b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
397336db0b34SBarry Smith 
397417ab2063SBarry Smith @*/
39757087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
397617ab2063SBarry Smith {
3977dfbe8321SBarry Smith   PetscErrorCode ierr;
39786945ee14SBarry Smith 
39793a40ed3dSBarry Smith   PetscFunctionBegin;
3980f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3981117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3982c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
3983d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
3984273d9f13SBarry Smith   PetscFunctionReturn(0);
3985273d9f13SBarry Smith }
3986273d9f13SBarry Smith 
3987273d9f13SBarry Smith /*@C
3988273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3989273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3990273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3991273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3992273d9f13SBarry Smith 
3993d083f849SBarry Smith    Collective
3994273d9f13SBarry Smith 
3995273d9f13SBarry Smith    Input Parameters:
39961c4f3114SJed Brown +  B - The matrix
3997273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3998273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39990298fd71SBarry Smith          (possibly different for each row) or NULL
4000273d9f13SBarry Smith 
4001273d9f13SBarry Smith    Notes:
400249a6f317SBarry Smith      If nnz is given then nz is ignored
400349a6f317SBarry Smith 
4004273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4005273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4006273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4007273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4008273d9f13SBarry Smith 
4009273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40100298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4011273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4012273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4013273d9f13SBarry Smith 
4014aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4015aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4016aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4017aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4018aa95bbe8SBarry Smith 
4019a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4020a96a251dSBarry Smith    entries or columns indices
4021a96a251dSBarry Smith 
4022273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4023273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4024273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4025273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4026273d9f13SBarry Smith 
4027273d9f13SBarry Smith    Options Database Keys:
4028698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
402947b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4030273d9f13SBarry Smith 
4031273d9f13SBarry Smith    Level: intermediate
4032273d9f13SBarry Smith 
403319b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
403419b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4035273d9f13SBarry Smith 
4036273d9f13SBarry Smith @*/
40377087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4038273d9f13SBarry Smith {
40394ac538c5SBarry Smith   PetscErrorCode ierr;
4040a23d5eceSKris Buschelman 
4041a23d5eceSKris Buschelman   PetscFunctionBegin;
40426ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40436ba663aaSJed Brown   PetscValidType(B,1);
40444ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4045a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4046a23d5eceSKris Buschelman }
4047a23d5eceSKris Buschelman 
40487087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4049a23d5eceSKris Buschelman {
4050273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40512576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40526849ba73SBarry Smith   PetscErrorCode ierr;
405397f1f81fSBarry Smith   PetscInt       i;
4054273d9f13SBarry Smith 
4055273d9f13SBarry Smith   PetscFunctionBegin;
40562576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4057a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4058c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4059c461c341SBarry Smith     nz             = 0;
4060c461c341SBarry Smith   }
406126283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
406226283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4063899cda47SBarry Smith 
4064435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
40652c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz);
4066cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4067d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
40682c71b3e2SJacob 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]);
40692c71b3e2SJacob 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);
4070b73539f3SBarry Smith     }
4071b73539f3SBarry Smith   }
4072b73539f3SBarry Smith 
4073273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
40742205254eSKarl Rupp 
4075273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4076273d9f13SBarry Smith 
4077ab93d7beSBarry Smith   if (!skipallocation) {
40782ee49352SLisandro Dalcin     if (!b->imax) {
4079071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4080071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4081071fcb05SBarry Smith     }
4082071fcb05SBarry Smith     if (!b->ilen) {
4083071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4084071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4085071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4086071fcb05SBarry Smith     } else {
4087071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
40882ee49352SLisandro Dalcin     }
4089846b4da1SFande Kong     if (!b->ipre) {
4090846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4091846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4092846b4da1SFande Kong     }
4093273d9f13SBarry Smith     if (!nnz) {
4094435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4095c62bd62aSJed Brown       else if (nz < 0) nz = 1;
40965d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4097d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4098d0f46423SBarry Smith       nz = nz*B->rmap->n;
4099273d9f13SBarry Smith     } else {
4100c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4101c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4102c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4103273d9f13SBarry Smith     }
4104ab93d7beSBarry Smith 
4105273d9f13SBarry Smith     /* allocate the matrix space */
410653dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41072ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4108396832f4SHong Zhang     if (B->structure_only) {
41095848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41105848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4111396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4112396832f4SHong Zhang     } else {
4113dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41143bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4115396832f4SHong Zhang     }
4116bfeeae90SHong Zhang     b->i[0] = 0;
4117d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41185da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41195da197adSKris Buschelman     }
4120396832f4SHong Zhang     if (B->structure_only) {
4121396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4122396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4123396832f4SHong Zhang     } else {
4124273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4125e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4126396832f4SHong Zhang     }
4127e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4128c461c341SBarry Smith   } else {
4129e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4130e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4131c461c341SBarry Smith   }
4132273d9f13SBarry Smith 
4133846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4134846b4da1SFande Kong     /* reserve user-requested sparsity */
4135580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4136846b4da1SFande Kong   }
4137846b4da1SFande Kong 
4138273d9f13SBarry Smith   b->nz               = 0;
4139273d9f13SBarry Smith   b->maxnz            = nz;
4140273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41412205254eSKarl Rupp   if (realalloc) {
41422205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41432205254eSKarl Rupp   }
4144cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4145cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4146273d9f13SBarry Smith   PetscFunctionReturn(0);
4147273d9f13SBarry Smith }
4148273d9f13SBarry Smith 
4149846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4150846b4da1SFande Kong {
4151846b4da1SFande Kong   Mat_SeqAIJ     *a;
4152a5bbaf83SFande Kong   PetscInt       i;
4153846b4da1SFande Kong   PetscErrorCode ierr;
4154846b4da1SFande Kong 
4155846b4da1SFande Kong   PetscFunctionBegin;
4156846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
415714d0e64fSAlex Lindsay 
415814d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
415914d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
416014d0e64fSAlex Lindsay 
4161846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41622c814fdeSFande Kong   /* if no saved info, we error out */
41632c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!a->ipre,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info ");
41642c814fdeSFande Kong 
41652c71b3e2SJacob 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 ");
41662c814fdeSFande Kong 
4167580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4168580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4169846b4da1SFande Kong   a->i[0] = 0;
4170846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4171846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4172846b4da1SFande Kong   }
4173846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4174846b4da1SFande Kong   a->nz               = 0;
4175846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4176846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4177846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4178846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4179846b4da1SFande Kong   PetscFunctionReturn(0);
4180846b4da1SFande Kong }
4181846b4da1SFande Kong 
418258d36128SBarry Smith /*@
4183a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4184a1661176SMatthew Knepley 
4185a1661176SMatthew Knepley    Input Parameters:
4186a1661176SMatthew Knepley +  B - the matrix
4187a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4188a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4189a1661176SMatthew Knepley -  v - optional values in the matrix
4190a1661176SMatthew Knepley 
4191a1661176SMatthew Knepley    Level: developer
4192a1661176SMatthew Knepley 
41936a9b8d82SBarry Smith    Notes:
419458d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
419558d36128SBarry Smith 
41966a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
41976a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
41986a9b8d82SBarry Smith 
41996a9b8d82SBarry Smith     Developer Notes:
42006a9b8d82SBarry 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
42016a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
42026a9b8d82SBarry Smith 
42036a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
42046a9b8d82SBarry Smith 
42056a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4206a1661176SMatthew Knepley @*/
4207a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4208a1661176SMatthew Knepley {
4209a1661176SMatthew Knepley   PetscErrorCode ierr;
4210a1661176SMatthew Knepley 
4211a1661176SMatthew Knepley   PetscFunctionBegin;
42120700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42136ba663aaSJed Brown   PetscValidType(B,1);
42144ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4215a1661176SMatthew Knepley   PetscFunctionReturn(0);
4216a1661176SMatthew Knepley }
4217a1661176SMatthew Knepley 
42187087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4219a1661176SMatthew Knepley {
4220a1661176SMatthew Knepley   PetscInt       i;
4221a1661176SMatthew Knepley   PetscInt       m,n;
4222a1661176SMatthew Knepley   PetscInt       nz;
42236a9b8d82SBarry Smith   PetscInt       *nnz;
4224a1661176SMatthew Knepley   PetscErrorCode ierr;
4225a1661176SMatthew Knepley 
4226a1661176SMatthew Knepley   PetscFunctionBegin;
42272c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Ii[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]);
4228779a8d59SSatish Balay 
4229779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4230779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4231779a8d59SSatish Balay 
4232779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4233854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4234a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4235b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
42362c71b3e2SJacob 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);
4237a1661176SMatthew Knepley     nnz[i] = nz;
4238a1661176SMatthew Knepley   }
4239a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4240a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4241a1661176SMatthew Knepley 
4242a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4243071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4244a1661176SMatthew Knepley   }
4245a1661176SMatthew Knepley 
4246a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4247a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4248a1661176SMatthew Knepley 
42497827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4250a1661176SMatthew Knepley   PetscFunctionReturn(0);
4251a1661176SMatthew Knepley }
4252a1661176SMatthew Knepley 
4253ad7e164aSPierre Jolivet /*@
4254ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4255ad7e164aSPierre Jolivet 
4256ad7e164aSPierre Jolivet    Input Parameters:
4257ad7e164aSPierre Jolivet +  A - left-hand side matrix
4258ad7e164aSPierre Jolivet .  B - right-hand side matrix
4259ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4260ad7e164aSPierre Jolivet 
4261ad7e164aSPierre Jolivet    Output Parameter:
4262ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4263ad7e164aSPierre Jolivet 
4264ad7e164aSPierre Jolivet    Level: intermediate
4265ad7e164aSPierre Jolivet 
4266ad7e164aSPierre Jolivet    Notes:
4267ad7e164aSPierre 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().
4268ad7e164aSPierre Jolivet 
4269ad7e164aSPierre Jolivet .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4270ad7e164aSPierre Jolivet @*/
4271ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4272ad7e164aSPierre Jolivet {
4273ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4274ad7e164aSPierre Jolivet 
4275ad7e164aSPierre Jolivet   PetscFunctionBegin;
4276ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4277ad7e164aSPierre Jolivet   PetscValidType(A,1);
4278ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4279ad7e164aSPierre Jolivet   PetscValidType(B,2);
4280ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4281ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4282ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4283ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4284ad7e164aSPierre Jolivet   }
4285ad7e164aSPierre Jolivet   ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr);
4286ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4287ad7e164aSPierre Jolivet }
4288ad7e164aSPierre Jolivet 
4289ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4290ad7e164aSPierre Jolivet {
4291fff043a9SJunchao Zhang   PetscErrorCode     ierr;
4292ad7e164aSPierre Jolivet   Mat                newmat;
4293ad7e164aSPierre Jolivet   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
4294ad7e164aSPierre Jolivet   Mat_SeqAIJ         *b = (Mat_SeqAIJ*)B->data;
4295ad7e164aSPierre Jolivet   PetscScalar        *v;
4296fff043a9SJunchao Zhang   const PetscScalar  *aa,*ba;
4297ad7e164aSPierre 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;
4298ad7e164aSPierre Jolivet   PetscBool          flg;
4299ad7e164aSPierre Jolivet 
4300ad7e164aSPierre Jolivet   PetscFunctionBegin;
43012c71b3e2SJacob Faibussowitsch   PetscCheckFalse(A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
43022c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!A->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
43032c71b3e2SJacob Faibussowitsch   PetscCheckFalse(B->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
43042c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!B->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4305ad7e164aSPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
43062c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
43072c71b3e2SJacob Faibussowitsch   PetscCheckFalse(reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4308ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
4309ad7e164aSPierre Jolivet     ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr);
4310ad7e164aSPierre Jolivet     ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr);
4311ad7e164aSPierre Jolivet     ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr);
4312ad7e164aSPierre Jolivet     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
4313ad7e164aSPierre Jolivet     i[0] = 0;
4314ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4315ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4316ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4317ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4318ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4319ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4320ad7e164aSPierre Jolivet           }
4321ad7e164aSPierre Jolivet         }
4322ad7e164aSPierre Jolivet       }
4323ad7e164aSPierre Jolivet     }
4324ad7e164aSPierre Jolivet     ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr);
4325ad7e164aSPierre Jolivet     *C = newmat;
4326ad7e164aSPierre Jolivet     ierr = PetscFree2(i,j);CHKERRQ(ierr);
4327ad7e164aSPierre Jolivet     nnz = 0;
4328ad7e164aSPierre Jolivet   }
4329ad7e164aSPierre Jolivet   ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr);
4330fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4331fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
4332ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4333ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4334ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4335ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4336fff043a9SJunchao Zhang           v[nnz++] = aa[n] * ba[q];
4337ad7e164aSPierre Jolivet         }
4338ad7e164aSPierre Jolivet       }
4339ad7e164aSPierre Jolivet     }
4340ad7e164aSPierre Jolivet   }
4341ad7e164aSPierre Jolivet   ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr);
4342fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
4343fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
4344ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4345ad7e164aSPierre Jolivet }
4346ad7e164aSPierre Jolivet 
4347c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4348af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4349170fe5c8SBarry Smith 
4350170fe5c8SBarry Smith /*
4351170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4352170fe5c8SBarry Smith 
4353170fe5c8SBarry Smith                n                       p                          p
43542da392ccSBarry Smith         [             ]       [             ]         [                 ]
43552da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
43562da392ccSBarry Smith         [             ]       [             ]         [                 ]
4357170fe5c8SBarry Smith 
4358170fe5c8SBarry Smith */
4359170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4360170fe5c8SBarry Smith {
4361170fe5c8SBarry Smith   PetscErrorCode    ierr;
4362170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4363170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4364170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
436586214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4366170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4367170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4368170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
436986214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
437086214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4371170fe5c8SBarry Smith 
4372170fe5c8SBarry Smith   PetscFunctionBegin;
4373d0f46423SBarry Smith   m    = A->rmap->n;
4374d0f46423SBarry Smith   n    = A->cmap->n;
4375d0f46423SBarry Smith   p    = B->cmap->n;
4376170fe5c8SBarry Smith   a    = sub_a->v;
4377170fe5c8SBarry Smith   b    = sub_b->a;
4378170fe5c8SBarry Smith   c    = sub_c->v;
437986214ceeSStefano Zampini   if (clda == m) {
4380580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
438186214ceeSStefano Zampini   } else {
438286214ceeSStefano Zampini     for (j=0;j<p;j++)
438386214ceeSStefano Zampini       for (i=0;i<m;i++)
438486214ceeSStefano Zampini         c[j*clda + i] = 0.0;
438586214ceeSStefano Zampini   }
4386170fe5c8SBarry Smith   ii  = sub_b->i;
4387170fe5c8SBarry Smith   idx = sub_b->j;
4388170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4389170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4390170fe5c8SBarry Smith     while (q-->0) {
439186214ceeSStefano Zampini       c_q = c + clda*(*idx);
439286214ceeSStefano Zampini       a_q = a + alda*i;
4393854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4394170fe5c8SBarry Smith       idx++;
4395170fe5c8SBarry Smith       b++;
4396170fe5c8SBarry Smith     }
4397170fe5c8SBarry Smith   }
4398170fe5c8SBarry Smith   PetscFunctionReturn(0);
4399170fe5c8SBarry Smith }
4400170fe5c8SBarry Smith 
44014222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4402170fe5c8SBarry Smith {
4403170fe5c8SBarry Smith   PetscErrorCode ierr;
4404d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
440586214ceeSStefano Zampini   PetscBool      cisdense;
4406170fe5c8SBarry Smith 
4407170fe5c8SBarry Smith   PetscFunctionBegin;
44082c71b3e2SJacob 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);
44094222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
44104222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
441186214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
441286214ceeSStefano Zampini   if (!cisdense) {
441386214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
441486214ceeSStefano Zampini   }
441586214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4416d73949e8SHong Zhang 
44174222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4418170fe5c8SBarry Smith   PetscFunctionReturn(0);
4419170fe5c8SBarry Smith }
4420170fe5c8SBarry Smith 
4421170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
44220bad9183SKris Buschelman /*MC
4423fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
44240bad9183SKris Buschelman    based on compressed sparse row format.
44250bad9183SKris Buschelman 
44260bad9183SKris Buschelman    Options Database Keys:
44270bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
44280bad9183SKris Buschelman 
44290bad9183SKris Buschelman    Level: beginner
44300bad9183SKris Buschelman 
44310cd7f59aSBarry Smith    Notes:
44320cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
44330cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
44340cd7f59aSBarry Smith     in the matrix
44350cd7f59aSBarry Smith 
44360cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
44370cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
44380cd7f59aSBarry Smith 
44390cd7f59aSBarry Smith   Developer Notes:
44400cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
44410cd7f59aSBarry Smith 
4442ed73aabaSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType, MATSELL, MATSEQSELL, MATMPISELL
44430bad9183SKris Buschelman M*/
44440bad9183SKris Buschelman 
4445ccd284c7SBarry Smith /*MC
4446ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4447ccd284c7SBarry Smith 
4448ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4449ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
4450ed73aabaSBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4451ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4452ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4453ccd284c7SBarry Smith 
4454ccd284c7SBarry Smith    Options Database Keys:
4455ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4456ccd284c7SBarry Smith 
445795452b02SPatrick Sanan   Developer Notes:
4458ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4459ccd284c7SBarry Smith    enough exist.
4460ccd284c7SBarry Smith 
4461ccd284c7SBarry Smith   Level: beginner
4462ccd284c7SBarry Smith 
4463ed73aabaSBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ, MATMPIAIJ, MATSELL, MATSEQSELL, MATMPISELL
4464ccd284c7SBarry Smith M*/
4465ccd284c7SBarry Smith 
4466ccd284c7SBarry Smith /*MC
4467ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4468ccd284c7SBarry Smith 
4469ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4470ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4471ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4472ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4473ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4474ccd284c7SBarry Smith 
4475ccd284c7SBarry Smith    Options Database Keys:
4476ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4477ccd284c7SBarry Smith 
4478ccd284c7SBarry Smith   Level: beginner
4479ccd284c7SBarry Smith 
4480ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4481ccd284c7SBarry Smith M*/
4482ccd284c7SBarry Smith 
44837906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
44847906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
44857906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
44867906f579SHong Zhang #endif
4487d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4488d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4489d24d4204SJose E. Roman #endif
44907906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
44917906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
44927906f579SHong Zhang #endif
44937906f579SHong Zhang 
4494d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4495c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
44964222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
44977906f579SHong Zhang 
44988c778c55SBarry Smith /*@C
44998f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
45008c778c55SBarry Smith 
45018c778c55SBarry Smith    Not Collective
45028c778c55SBarry Smith 
45038c778c55SBarry Smith    Input Parameter:
4504579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
45058c778c55SBarry Smith 
45068c778c55SBarry Smith    Output Parameter:
45078c778c55SBarry Smith .   array - pointer to the data
45088c778c55SBarry Smith 
45098c778c55SBarry Smith    Level: intermediate
45108c778c55SBarry Smith 
4511774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
45128c778c55SBarry Smith @*/
45138c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
45148c778c55SBarry Smith {
45158c778c55SBarry Smith   PetscErrorCode ierr;
4516d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45178c778c55SBarry Smith 
45188c778c55SBarry Smith   PetscFunctionBegin;
4519d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
4520d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarray)(A,array);CHKERRQ(ierr);
4521d67d9f35SJunchao Zhang   } else {
4522d67d9f35SJunchao Zhang     *array = aij->a;
4523d67d9f35SJunchao Zhang   }
4524d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4525d67d9f35SJunchao Zhang }
4526d67d9f35SJunchao Zhang 
4527d67d9f35SJunchao Zhang /*@C
4528d67d9f35SJunchao Zhang    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
4529d67d9f35SJunchao Zhang 
4530d67d9f35SJunchao Zhang    Not Collective
4531d67d9f35SJunchao Zhang 
4532d67d9f35SJunchao Zhang    Input Parameters:
4533d67d9f35SJunchao Zhang +  mat - a MATSEQAIJ matrix
4534d67d9f35SJunchao Zhang -  array - pointer to the data
4535d67d9f35SJunchao Zhang 
4536d67d9f35SJunchao Zhang    Level: intermediate
4537d67d9f35SJunchao Zhang 
4538d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
4539d67d9f35SJunchao Zhang @*/
4540d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
4541d67d9f35SJunchao Zhang {
4542d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4543d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4544d67d9f35SJunchao Zhang 
4545d67d9f35SJunchao Zhang   PetscFunctionBegin;
4546d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
4547d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearray)(A,array);CHKERRQ(ierr);
4548d67d9f35SJunchao Zhang   } else {
4549d67d9f35SJunchao Zhang     *array = NULL;
4550d67d9f35SJunchao Zhang   }
4551*394ed5ebSJunchao Zhang   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
4552*394ed5ebSJunchao Zhang   ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr);
45538c778c55SBarry Smith   PetscFunctionReturn(0);
45548c778c55SBarry Smith }
45558c778c55SBarry Smith 
455621e72a00SBarry Smith /*@C
45578f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
45588f1ea47aSStefano Zampini 
45598f1ea47aSStefano Zampini    Not Collective
45608f1ea47aSStefano Zampini 
45618f1ea47aSStefano Zampini    Input Parameter:
45628f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45638f1ea47aSStefano Zampini 
45648f1ea47aSStefano Zampini    Output Parameter:
45658f1ea47aSStefano Zampini .   array - pointer to the data
45668f1ea47aSStefano Zampini 
45678f1ea47aSStefano Zampini    Level: intermediate
45688f1ea47aSStefano Zampini 
45698f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
45708f1ea47aSStefano Zampini @*/
45718f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
45728f1ea47aSStefano Zampini {
45738f1ea47aSStefano Zampini   PetscErrorCode ierr;
4574d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45758f1ea47aSStefano Zampini 
45768f1ea47aSStefano Zampini   PetscFunctionBegin;
4577d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
4578d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarrayread)(A,array);CHKERRQ(ierr);
4579d67d9f35SJunchao Zhang   } else {
4580d67d9f35SJunchao Zhang     *array = aij->a;
4581d67d9f35SJunchao Zhang   }
45828f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45838f1ea47aSStefano Zampini }
45848f1ea47aSStefano Zampini 
45858f1ea47aSStefano Zampini /*@C
45868f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
45878f1ea47aSStefano Zampini 
45888f1ea47aSStefano Zampini    Not Collective
45898f1ea47aSStefano Zampini 
45908f1ea47aSStefano Zampini    Input Parameter:
45918f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45928f1ea47aSStefano Zampini 
45938f1ea47aSStefano Zampini    Output Parameter:
45948f1ea47aSStefano Zampini .   array - pointer to the data
45958f1ea47aSStefano Zampini 
45968f1ea47aSStefano Zampini    Level: intermediate
45978f1ea47aSStefano Zampini 
45988f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
45998f1ea47aSStefano Zampini @*/
46008f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
46018f1ea47aSStefano Zampini {
46028f1ea47aSStefano Zampini   PetscErrorCode ierr;
4603d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
46048f1ea47aSStefano Zampini 
46058f1ea47aSStefano Zampini   PetscFunctionBegin;
4606d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
4607d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearrayread)(A,array);CHKERRQ(ierr);
4608d67d9f35SJunchao Zhang   } else {
4609d67d9f35SJunchao Zhang     *array = NULL;
4610d67d9f35SJunchao Zhang   }
4611d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4612d67d9f35SJunchao Zhang }
4613d67d9f35SJunchao Zhang 
4614d67d9f35SJunchao Zhang /*@C
4615d67d9f35SJunchao Zhang    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored
4616d67d9f35SJunchao Zhang 
4617d67d9f35SJunchao Zhang    Not Collective
4618d67d9f35SJunchao Zhang 
4619d67d9f35SJunchao Zhang    Input Parameter:
4620d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4621d67d9f35SJunchao Zhang 
4622d67d9f35SJunchao Zhang    Output Parameter:
4623d67d9f35SJunchao Zhang .   array - pointer to the data
4624d67d9f35SJunchao Zhang 
4625d67d9f35SJunchao Zhang    Level: intermediate
4626d67d9f35SJunchao Zhang 
4627d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
4628d67d9f35SJunchao Zhang @*/
4629d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array)
4630d67d9f35SJunchao Zhang {
4631d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4632d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4633d67d9f35SJunchao Zhang 
4634d67d9f35SJunchao Zhang   PetscFunctionBegin;
4635d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
4636d67d9f35SJunchao Zhang     ierr = (*aij->ops->getarraywrite)(A,array);CHKERRQ(ierr);
4637d67d9f35SJunchao Zhang   } else {
4638d67d9f35SJunchao Zhang     *array = aij->a;
4639d67d9f35SJunchao Zhang   }
4640*394ed5ebSJunchao Zhang   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
4641*394ed5ebSJunchao Zhang   ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr);
4642d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4643d67d9f35SJunchao Zhang }
4644d67d9f35SJunchao Zhang 
4645d67d9f35SJunchao Zhang /*@C
4646d67d9f35SJunchao Zhang    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4647d67d9f35SJunchao Zhang 
4648d67d9f35SJunchao Zhang    Not Collective
4649d67d9f35SJunchao Zhang 
4650d67d9f35SJunchao Zhang    Input Parameter:
4651d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4652d67d9f35SJunchao Zhang 
4653d67d9f35SJunchao Zhang    Output Parameter:
4654d67d9f35SJunchao Zhang .   array - pointer to the data
4655d67d9f35SJunchao Zhang 
4656d67d9f35SJunchao Zhang    Level: intermediate
4657d67d9f35SJunchao Zhang 
4658d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
4659d67d9f35SJunchao Zhang @*/
4660d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array)
4661d67d9f35SJunchao Zhang {
4662d67d9f35SJunchao Zhang   PetscErrorCode ierr;
4663d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4664d67d9f35SJunchao Zhang 
4665d67d9f35SJunchao Zhang   PetscFunctionBegin;
4666d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
4667d67d9f35SJunchao Zhang     ierr = (*aij->ops->restorearraywrite)(A,array);CHKERRQ(ierr);
4668d67d9f35SJunchao Zhang   } else {
4669d67d9f35SJunchao Zhang     *array = NULL;
4670d67d9f35SJunchao Zhang   }
46718f1ea47aSStefano Zampini   PetscFunctionReturn(0);
46728f1ea47aSStefano Zampini }
46738f1ea47aSStefano Zampini 
46748f1ea47aSStefano Zampini /*@C
467521e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
467621e72a00SBarry Smith 
467721e72a00SBarry Smith    Not Collective
467821e72a00SBarry Smith 
467921e72a00SBarry Smith    Input Parameter:
4680579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
468121e72a00SBarry Smith 
468221e72a00SBarry Smith    Output Parameter:
468321e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
468421e72a00SBarry Smith 
468521e72a00SBarry Smith    Level: intermediate
468621e72a00SBarry Smith 
468721e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
468821e72a00SBarry Smith @*/
468921e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
469021e72a00SBarry Smith {
469121e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
469221e72a00SBarry Smith 
469321e72a00SBarry Smith   PetscFunctionBegin;
469421e72a00SBarry Smith   *nz = aij->rmax;
469521e72a00SBarry Smith   PetscFunctionReturn(0);
469621e72a00SBarry Smith }
469721e72a00SBarry Smith 
4698*394ed5ebSJunchao Zhang PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, const PetscInt coo_i[], const PetscInt coo_j[])
4699*394ed5ebSJunchao Zhang {
4700*394ed5ebSJunchao Zhang   PetscErrorCode            ierr;
4701*394ed5ebSJunchao Zhang   MPI_Comm                  comm;
4702*394ed5ebSJunchao Zhang   PetscInt                  *i,*j;
4703*394ed5ebSJunchao Zhang   PetscInt                  M,N,row;
4704*394ed5ebSJunchao Zhang   PetscCount                k,p,q,nneg,nnz,start,end; /* Index the coo array, so use PetscCount as their type */
4705*394ed5ebSJunchao Zhang   PetscInt                  *Ai; /* Change to PetscCount once we use it for row pointers */
4706*394ed5ebSJunchao Zhang   PetscInt                  *Aj;
4707*394ed5ebSJunchao Zhang   PetscScalar               *Aa;
4708*394ed5ebSJunchao Zhang   Mat_SeqAIJ                *seqaij;
4709*394ed5ebSJunchao Zhang   Mat                       newmat;
4710*394ed5ebSJunchao Zhang   PetscCount                *perm,*jmap;
4711*394ed5ebSJunchao Zhang 
4712*394ed5ebSJunchao Zhang   PetscFunctionBegin;
4713*394ed5ebSJunchao Zhang   ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
4714*394ed5ebSJunchao Zhang   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
4715*394ed5ebSJunchao Zhang   ierr = PetscMalloc2(coo_n,&i,coo_n,&j);CHKERRQ(ierr);
4716*394ed5ebSJunchao Zhang   ierr = PetscArraycpy(i,coo_i,coo_n);CHKERRQ(ierr); /* Make a copy since we'll modify it */
4717*394ed5ebSJunchao Zhang   ierr = PetscArraycpy(j,coo_j,coo_n);CHKERRQ(ierr);
4718*394ed5ebSJunchao Zhang   ierr = PetscMalloc1(coo_n,&perm);CHKERRQ(ierr);
4719*394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) { /* Ignore entries with negative row or col indices */
4720*394ed5ebSJunchao Zhang     if (j[k] < 0) i[k] = -1;
4721*394ed5ebSJunchao Zhang     perm[k] = k;
4722*394ed5ebSJunchao Zhang   }
4723*394ed5ebSJunchao Zhang 
4724*394ed5ebSJunchao Zhang   /* Sort by row */
4725*394ed5ebSJunchao Zhang   ierr = PetscSortIntWithIntCountArrayPair(coo_n,i,j,perm);CHKERRQ(ierr);
4726*394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) {if (i[k] >= 0) break;} /* Advance k to the first row with a non-negative index */
4727*394ed5ebSJunchao Zhang   nneg = k;
4728*394ed5ebSJunchao 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 */
4729*394ed5ebSJunchao Zhang   nnz  = 0; /* Total number of unique nonzeros to be counted */
4730*394ed5ebSJunchao Zhang   jmap++; /* Inc jmap by 1 for convinience */
4731*394ed5ebSJunchao Zhang 
4732*394ed5ebSJunchao Zhang   ierr = PetscCalloc1(M+1,&Ai);CHKERRQ(ierr); /* CSR of A */
4733*394ed5ebSJunchao Zhang   ierr = PetscMalloc1(coo_n-nneg,&Aj);CHKERRQ(ierr); /* We have at most coo_n-nneg unique nonzeros */
4734*394ed5ebSJunchao Zhang 
4735*394ed5ebSJunchao Zhang   /* In each row, sort by column, then unique column indices to get row length */
4736*394ed5ebSJunchao Zhang   Ai++; /* Inc by 1 for convinience */
4737*394ed5ebSJunchao Zhang   q = 0; /* q-th unique nonzero, with q starting from 0 */
4738*394ed5ebSJunchao Zhang   while (k<coo_n) {
4739*394ed5ebSJunchao Zhang     row   = i[k];
4740*394ed5ebSJunchao Zhang     start = k; /* [start,end) indices for this row */
4741*394ed5ebSJunchao Zhang     while (k<coo_n && i[k] == row) k++;
4742*394ed5ebSJunchao Zhang     end   = k;
4743*394ed5ebSJunchao Zhang     ierr  = PetscSortIntWithCountArray(end-start,j+start,perm+start);CHKERRQ(ierr);
4744*394ed5ebSJunchao Zhang     /* Find number of unique col entries in this row */
4745*394ed5ebSJunchao Zhang     Aj[q]   = j[start]; /* Log the first nonzero in this row */
4746*394ed5ebSJunchao Zhang     jmap[q] = 1; /* Number of repeats of this nozero entry */
4747*394ed5ebSJunchao Zhang     Ai[row] = 1;
4748*394ed5ebSJunchao Zhang     nnz++;
4749*394ed5ebSJunchao Zhang 
4750*394ed5ebSJunchao Zhang     for (p=start+1; p<end; p++) { /* Scan remaining nonzero in this row */
4751*394ed5ebSJunchao Zhang       if (j[p] != j[p-1]) { /* Meet a new nonzero */
4752*394ed5ebSJunchao Zhang         q++;
4753*394ed5ebSJunchao Zhang         jmap[q] = 1;
4754*394ed5ebSJunchao Zhang         Aj[q]   = j[p];
4755*394ed5ebSJunchao Zhang         Ai[row]++;
4756*394ed5ebSJunchao Zhang         nnz++;
4757*394ed5ebSJunchao Zhang       } else {
4758*394ed5ebSJunchao Zhang         jmap[q]++;
4759*394ed5ebSJunchao Zhang       }
4760*394ed5ebSJunchao Zhang     }
4761*394ed5ebSJunchao Zhang     q++; /* Move to next row and thus next unique nonzero */
4762*394ed5ebSJunchao Zhang   }
4763*394ed5ebSJunchao Zhang   ierr = PetscFree2(i,j);CHKERRQ(ierr);
4764*394ed5ebSJunchao Zhang 
4765*394ed5ebSJunchao Zhang   Ai--; /* Back to the beginning of Ai[] */
4766*394ed5ebSJunchao Zhang   for (k=0; k<M; k++) Ai[k+1] += Ai[k];
4767*394ed5ebSJunchao Zhang   jmap--; /* Back to the beginning of jmap[] */
4768*394ed5ebSJunchao Zhang   jmap[0] = 0;
4769*394ed5ebSJunchao Zhang   for (k=0; k<nnz; k++) jmap[k+1] += jmap[k];
4770*394ed5ebSJunchao Zhang   if (nnz < coo_n-nneg) { /* Realloc with actual number of unique nonzeros */
4771*394ed5ebSJunchao Zhang     PetscCount *jmap_new;
4772*394ed5ebSJunchao Zhang     PetscInt   *Aj_new;
4773*394ed5ebSJunchao Zhang 
4774*394ed5ebSJunchao Zhang     ierr = PetscMalloc1(nnz+1,&jmap_new);CHKERRQ(ierr);
4775*394ed5ebSJunchao Zhang     ierr = PetscArraycpy(jmap_new,jmap,nnz+1);CHKERRQ(ierr);
4776*394ed5ebSJunchao Zhang     ierr = PetscFree(jmap);CHKERRQ(ierr);
4777*394ed5ebSJunchao Zhang     jmap = jmap_new;
4778*394ed5ebSJunchao Zhang 
4779*394ed5ebSJunchao Zhang     ierr = PetscMalloc1(nnz,&Aj_new);CHKERRQ(ierr);
4780*394ed5ebSJunchao Zhang     ierr = PetscArraycpy(Aj_new,Aj,nnz);CHKERRQ(ierr);
4781*394ed5ebSJunchao Zhang     ierr = PetscFree(Aj);CHKERRQ(ierr);
4782*394ed5ebSJunchao Zhang     Aj   = Aj_new;
4783*394ed5ebSJunchao Zhang   }
4784*394ed5ebSJunchao Zhang 
4785*394ed5ebSJunchao Zhang   if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */
4786*394ed5ebSJunchao Zhang     PetscCount *perm_new;
4787*394ed5ebSJunchao Zhang     ierr = PetscMalloc1(coo_n-nneg,&perm_new);CHKERRQ(ierr);
4788*394ed5ebSJunchao Zhang     ierr = PetscArraycpy(perm_new,perm+nneg,coo_n-nneg);CHKERRQ(ierr);
4789*394ed5ebSJunchao Zhang     ierr = PetscFree(perm);CHKERRQ(ierr);
4790*394ed5ebSJunchao Zhang     perm = perm_new;
4791*394ed5ebSJunchao Zhang   }
4792*394ed5ebSJunchao Zhang 
4793*394ed5ebSJunchao Zhang   ierr = PetscCalloc1(nnz,&Aa);CHKERRQ(ierr); /* Zero the matrix */
4794*394ed5ebSJunchao Zhang   ierr = MatCreateSeqAIJWithArrays(comm,M,N,Ai,Aj,Aa,&newmat);CHKERRQ(ierr);
4795*394ed5ebSJunchao Zhang   ierr = MatHeaderMerge(mat,&newmat);CHKERRQ(ierr);
4796*394ed5ebSJunchao Zhang 
4797*394ed5ebSJunchao Zhang   seqaij = (Mat_SeqAIJ*)(mat->data);
4798*394ed5ebSJunchao Zhang   seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */
4799*394ed5ebSJunchao Zhang   seqaij->free_a       = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */
4800*394ed5ebSJunchao Zhang   /* Record COO fields */
4801*394ed5ebSJunchao Zhang   seqaij->coo_n        = coo_n;
4802*394ed5ebSJunchao Zhang   seqaij->Atot         = coo_n-nneg; /* Annz is seqaij->nz, so no need to record that again */
4803*394ed5ebSJunchao Zhang   seqaij->jmap         = jmap; /* of length nnz+1 */
4804*394ed5ebSJunchao Zhang   seqaij->perm         = perm;
4805*394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4806*394ed5ebSJunchao Zhang }
4807*394ed5ebSJunchao Zhang 
4808*394ed5ebSJunchao Zhang static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A,const PetscScalar v[],InsertMode imode)
4809*394ed5ebSJunchao Zhang {
4810*394ed5ebSJunchao Zhang   PetscErrorCode              ierr;
4811*394ed5ebSJunchao Zhang   Mat_SeqAIJ                  *aseq = (Mat_SeqAIJ*)A->data;
4812*394ed5ebSJunchao Zhang   PetscCount                  i,j,Annz = aseq->nz;
4813*394ed5ebSJunchao Zhang   PetscCount                  *perm = aseq->perm,*jmap = aseq->jmap;
4814*394ed5ebSJunchao Zhang   PetscScalar                 *Aa;
4815*394ed5ebSJunchao Zhang 
4816*394ed5ebSJunchao Zhang   PetscFunctionBegin;
4817*394ed5ebSJunchao Zhang   if (imode == INSERT_VALUES) {ierr = MatZeroEntries(A);CHKERRQ(ierr);}
4818*394ed5ebSJunchao Zhang   ierr = MatSeqAIJGetArray(A,&Aa);CHKERRQ(ierr);
4819*394ed5ebSJunchao Zhang   for (i=0; i<Annz; i++) {
4820*394ed5ebSJunchao Zhang     for (j=jmap[i]; j<jmap[i+1]; j++) Aa[i] += v[perm[j]];
4821*394ed5ebSJunchao Zhang   }
4822*394ed5ebSJunchao Zhang   ierr = MatSeqAIJRestoreArray(A,&Aa);CHKERRQ(ierr);
4823*394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4824*394ed5ebSJunchao Zhang }
4825*394ed5ebSJunchao Zhang 
482634b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
48275063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*);
482802fe1965SBarry Smith #endif
48293d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
48305063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*);
48313d0639e7SStefano Zampini #endif
483202fe1965SBarry Smith 
48338cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4834273d9f13SBarry Smith {
4835273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4836dfbe8321SBarry Smith   PetscErrorCode ierr;
483738baddfdSBarry Smith   PetscMPIInt    size;
4838273d9f13SBarry Smith 
4839273d9f13SBarry Smith   PetscFunctionBegin;
4840ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
48412c71b3e2SJacob Faibussowitsch   PetscCheckFalse(size > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4842273d9f13SBarry Smith 
4843b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
48442205254eSKarl Rupp 
4845b0a32e0cSBarry Smith   B->data = (void*)b;
48462205254eSKarl Rupp 
4847549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4848071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
48492205254eSKarl Rupp 
4850f4259b30SLisandro Dalcin   b->row                = NULL;
4851f4259b30SLisandro Dalcin   b->col                = NULL;
4852f4259b30SLisandro Dalcin   b->icol               = NULL;
4853b810aeb4SBarry Smith   b->reallocs           = 0;
485436db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4855f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4856416022c9SBarry Smith   b->nonew              = 0;
4857f4259b30SLisandro Dalcin   b->diag               = NULL;
4858f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4859f4259b30SLisandro Dalcin   B->spptr              = NULL;
4860f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4861f4259b30SLisandro Dalcin   b->idiag              = NULL;
4862f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4863f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
486471f1c65dSBarry Smith   b->omega              = 1.0;
486571f1c65dSBarry Smith   b->fshift             = 0.0;
486671f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4867bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4868a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
486917ab2063SBarry Smith 
487035d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
48718c778c55SBarry Smith 
4872b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4873bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4874bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4875b3866ffcSBarry Smith #endif
487617f1a0eaSHong Zhang 
4877bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4878bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4879bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4880bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4881bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4882bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
48834dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
48849779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
48854a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4886191b95cbSRichard Tran Mills #endif
488734b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
488802fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
48894222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4890fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
489102fe1965SBarry Smith #endif
48923d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
48933d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
48943d0639e7SStefano Zampini #endif
4895bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4896af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4897af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4898af8000cdSHong Zhang #endif
4899d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4900d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4901d24d4204SJose E. Roman #endif
490263c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
490363c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
49044222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
490563c07aadSStefano Zampini #endif
4906b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4907d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4908c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4909bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4910bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4911bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4912846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4913bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4914bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
49154222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
49164222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
49174222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4918ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr);
4919*394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_SeqAIJ);CHKERRQ(ierr);
4920*394ed5ebSJunchao Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSetValuesCOO_C",MatSetValuesCOO_SeqAIJ);CHKERRQ(ierr);
49214108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
492217667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
49234099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
49243a40ed3dSBarry Smith   PetscFunctionReturn(0);
492517ab2063SBarry Smith }
492617ab2063SBarry Smith 
4927b24902e0SBarry Smith /*
4928b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4929b24902e0SBarry Smith */
4930ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
493117ab2063SBarry Smith {
49322a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
49336849ba73SBarry Smith   PetscErrorCode ierr;
4934071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
493517ab2063SBarry Smith 
49363a40ed3dSBarry Smith   PetscFunctionBegin;
49372c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4938273d9f13SBarry Smith 
4939d5f3da31SBarry Smith   C->factortype = A->factortype;
4940f4259b30SLisandro Dalcin   c->row        = NULL;
4941f4259b30SLisandro Dalcin   c->col        = NULL;
4942f4259b30SLisandro Dalcin   c->icol       = NULL;
49436ad4291fSHong Zhang   c->reallocs   = 0;
494417ab2063SBarry Smith 
49456ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
494617ab2063SBarry Smith 
4947aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4948aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4949eec197d1SBarry Smith 
4950071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4951071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4952071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4953071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
49543bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
495517ab2063SBarry Smith 
495617ab2063SBarry Smith   /* allocate the matrix space */
4957f77e22a1SHong Zhang   if (mallocmatspace) {
4958dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
49593bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
49602205254eSKarl Rupp 
4961f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
49622205254eSKarl Rupp 
4963580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
496417ab2063SBarry Smith     if (m > 0) {
4965580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4966be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
49672e5835c6SStefano Zampini         const PetscScalar *aa;
49682e5835c6SStefano Zampini 
49692e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
49702e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
49712e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4972be6bf707SBarry Smith       } else {
4973580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
497417ab2063SBarry Smith       }
497508480c60SBarry Smith     }
4976f77e22a1SHong Zhang   }
497717ab2063SBarry Smith 
49786ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4979416022c9SBarry Smith   c->roworiented       = a->roworiented;
4980416022c9SBarry Smith   c->nonew             = a->nonew;
4981416022c9SBarry Smith   if (a->diag) {
4982854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4983071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
49843bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4985071fcb05SBarry Smith   } else c->diag = NULL;
49862205254eSKarl Rupp 
4987f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4988f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4989f4259b30SLisandro Dalcin   c->idiag              = NULL;
4990f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4991a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4992e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4993e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
49946ad4291fSHong Zhang 
4995893ad86cSHong Zhang   c->rmax         = a->rmax;
4996416022c9SBarry Smith   c->nz           = a->nz;
49978ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4998273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4999754ec7b1SSatish Balay 
50006ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
50016ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
5002cd6b891eSBarry Smith   if (a->compressedrow.use) {
50036ad4291fSHong Zhang     i    = a->compressedrow.nrows;
5004dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
5005580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
5006580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
500727ea64f8SHong Zhang   } else {
500827ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
50090298fd71SBarry Smith     c->compressedrow.i      = NULL;
50100298fd71SBarry Smith     c->compressedrow.rindex = NULL;
50116ad4291fSHong Zhang   }
5012ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
5013e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
50144846f1f5SKris Buschelman 
50152205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
5016140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
50173a40ed3dSBarry Smith   PetscFunctionReturn(0);
501817ab2063SBarry Smith }
501917ab2063SBarry Smith 
5020b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
5021b24902e0SBarry Smith {
5022b24902e0SBarry Smith   PetscErrorCode ierr;
5023b24902e0SBarry Smith 
5024b24902e0SBarry Smith   PetscFunctionBegin;
5025ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
50264b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
5027cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
502833d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
5029cfd3f464SBarry Smith   }
5030a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
5031f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
5032b24902e0SBarry Smith   PetscFunctionReturn(0);
5033b24902e0SBarry Smith }
5034b24902e0SBarry Smith 
5035112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
5036fbdbba38SShri Abhyankar {
503752f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
503852f91c60SVaclav Hapla   PetscErrorCode ierr;
503952f91c60SVaclav Hapla 
504052f91c60SVaclav Hapla   PetscFunctionBegin;
504152f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
504252f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
5043c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
5044c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
504552f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
504652f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
504752f91c60SVaclav Hapla   if (isbinary) {
504852f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
504952f91c60SVaclav Hapla   } else if (ishdf5) {
505052f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
505152f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
505252f91c60SVaclav Hapla #else
505352f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
505452f91c60SVaclav Hapla #endif
505552f91c60SVaclav Hapla   } else {
505698921bdaSJacob 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);
505752f91c60SVaclav Hapla   }
505852f91c60SVaclav Hapla   PetscFunctionReturn(0);
505952f91c60SVaclav Hapla }
506052f91c60SVaclav Hapla 
50613ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
506252f91c60SVaclav Hapla {
50633ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
5064fbdbba38SShri Abhyankar   PetscErrorCode ierr;
50653ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
5066fbdbba38SShri Abhyankar 
5067fbdbba38SShri Abhyankar   PetscFunctionBegin;
50683ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
5069bbead8a2SBarry Smith 
50703ea6fe3dSLisandro Dalcin   /* read in matrix header */
50713ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
50722c71b3e2SJacob Faibussowitsch   PetscCheckFalse(header[0] != MAT_FILE_CLASSID,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
5073fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
50742c71b3e2SJacob Faibussowitsch   PetscCheckFalse(M < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M);
50752c71b3e2SJacob Faibussowitsch   PetscCheckFalse(N < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N);
50762c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
5077fbdbba38SShri Abhyankar 
50783ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
50793ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
50803ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
50813ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
50823ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
50833ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
50843ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
50853ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
50863ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
50873ea6fe3dSLisandro Dalcin 
50883ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
50893ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
50902c71b3e2SJacob 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);
50913ea6fe3dSLisandro Dalcin 
5092fbdbba38SShri Abhyankar   /* read in row lengths */
50933ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
50943ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
50953ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
50963ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
50972c71b3e2SJacob 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);
50983ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
50993ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
51003ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
51012c71b3e2SJacob 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);
51023ea6fe3dSLisandro Dalcin   /* store row lengths */
51033ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
51043ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
5105fbdbba38SShri Abhyankar 
51063ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
51073ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
51083ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
51093ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
51103ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
51113ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
5112fbdbba38SShri Abhyankar 
51133ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
51143ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5115fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
5116fbdbba38SShri Abhyankar }
5117fbdbba38SShri Abhyankar 
5118ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
51197264ac53SSatish Balay {
51207264ac53SSatish Balay   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
5121dfbe8321SBarry Smith   PetscErrorCode    ierr;
5122fff043a9SJunchao Zhang   const PetscScalar *aa,*ba;
5123eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5124eeffb40dSHong Zhang   PetscInt k;
5125eeffb40dSHong Zhang #endif
51267264ac53SSatish Balay 
51273a40ed3dSBarry Smith   PetscFunctionBegin;
5128bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
5129d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
5130ca44d042SBarry Smith     *flg = PETSC_FALSE;
5131ca44d042SBarry Smith     PetscFunctionReturn(0);
5132bcd2baecSBarry Smith   }
51337264ac53SSatish Balay 
51347264ac53SSatish Balay   /* if the a->i are the same */
5135580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
5136abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
51377264ac53SSatish Balay 
51387264ac53SSatish Balay   /* if a->j are the same */
5139580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
5140abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
5141bcd2baecSBarry Smith 
5142fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
5143fff043a9SJunchao Zhang   ierr = MatSeqAIJGetArrayRead(B,&ba);CHKERRQ(ierr);
5144bcd2baecSBarry Smith   /* if a->a are the same */
5145eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5146eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
5147fff043a9SJunchao Zhang     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
5148eeffb40dSHong Zhang       *flg = PETSC_FALSE;
51493a40ed3dSBarry Smith       PetscFunctionReturn(0);
5150eeffb40dSHong Zhang     }
5151eeffb40dSHong Zhang   }
5152eeffb40dSHong Zhang #else
5153fff043a9SJunchao Zhang   ierr = PetscArraycmp(aa,ba,a->nz,flg);CHKERRQ(ierr);
5154eeffb40dSHong Zhang #endif
5155fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
5156fff043a9SJunchao Zhang   ierr = MatSeqAIJRestoreArrayRead(B,&ba);CHKERRQ(ierr);
5157eeffb40dSHong Zhang   PetscFunctionReturn(0);
51587264ac53SSatish Balay }
515936db0b34SBarry Smith 
516005869f15SSatish Balay /*@
516136db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
516236db0b34SBarry Smith               provided by the user.
516336db0b34SBarry Smith 
5164d083f849SBarry Smith       Collective
516536db0b34SBarry Smith 
516636db0b34SBarry Smith    Input Parameters:
516736db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
516836db0b34SBarry Smith .   m - number of rows
516936db0b34SBarry Smith .   n - number of columns
5170483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
517136db0b34SBarry Smith .   j - column indices
517236db0b34SBarry Smith -   a - matrix values
517336db0b34SBarry Smith 
517436db0b34SBarry Smith    Output Parameter:
517536db0b34SBarry Smith .   mat - the matrix
517636db0b34SBarry Smith 
517736db0b34SBarry Smith    Level: intermediate
517836db0b34SBarry Smith 
517936db0b34SBarry Smith    Notes:
51800551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5181292fb18eSBarry Smith     once the matrix is destroyed and not before
518236db0b34SBarry Smith 
518336db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
518436db0b34SBarry Smith 
5185bfeeae90SHong Zhang        The i and j indices are 0 based
518636db0b34SBarry Smith 
5187a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5188a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
51898eef79e4SBarry Smith     as shown
5190a4552177SSatish Balay 
51918eef79e4SBarry Smith $        1 0 0
51928eef79e4SBarry Smith $        2 0 3
51938eef79e4SBarry Smith $        4 5 6
51948eef79e4SBarry Smith $
51958eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
51968eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
51978eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5198a4552177SSatish Balay 
519969b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
520036db0b34SBarry Smith 
520136db0b34SBarry Smith @*/
5202c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
520336db0b34SBarry Smith {
5204dfbe8321SBarry Smith   PetscErrorCode ierr;
5205cbcfb4deSHong Zhang   PetscInt       ii;
520636db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5207cbcfb4deSHong Zhang   PetscInt jj;
520836db0b34SBarry Smith 
520936db0b34SBarry Smith   PetscFunctionBegin;
52102c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m > 0 && i[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5211f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5212f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5213a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
5214ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5215f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
5216ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
5217071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
5218071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
5219ab93d7beSBarry Smith 
522036db0b34SBarry Smith   aij->i            = i;
522136db0b34SBarry Smith   aij->j            = j;
522236db0b34SBarry Smith   aij->a            = a;
522336db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
522436db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5225e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5226e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
522736db0b34SBarry Smith 
522836db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
522936db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
523076bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
52312c71b3e2SJacob 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]);
52329985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
52332c71b3e2SJacob 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);
52342c71b3e2SJacob 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);
52359985e31cSBarry Smith       }
523636db0b34SBarry Smith     }
523776bd3646SJed Brown   }
523876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
523936db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
52402c71b3e2SJacob 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]);
52412c71b3e2SJacob 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]);
524236db0b34SBarry Smith     }
524376bd3646SJed Brown   }
524436db0b34SBarry Smith 
5245b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5246b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
524736db0b34SBarry Smith   PetscFunctionReturn(0);
524836db0b34SBarry Smith }
524980ef6e79SMatthew G Knepley /*@C
5250d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
52518a0b0e6bSVictor Minden               provided by the user.
52528a0b0e6bSVictor Minden 
5253d083f849SBarry Smith       Collective
52548a0b0e6bSVictor Minden 
52558a0b0e6bSVictor Minden    Input Parameters:
52568a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
52578a0b0e6bSVictor Minden .   m   - number of rows
52588a0b0e6bSVictor Minden .   n   - number of columns
52598a0b0e6bSVictor Minden .   i   - row indices
52608a0b0e6bSVictor Minden .   j   - column indices
52611230e6d1SVictor Minden .   a   - matrix values
52621230e6d1SVictor Minden .   nz  - number of nonzeros
52631230e6d1SVictor Minden -   idx - 0 or 1 based
52648a0b0e6bSVictor Minden 
52658a0b0e6bSVictor Minden    Output Parameter:
52668a0b0e6bSVictor Minden .   mat - the matrix
52678a0b0e6bSVictor Minden 
52688a0b0e6bSVictor Minden    Level: intermediate
52698a0b0e6bSVictor Minden 
52708a0b0e6bSVictor Minden    Notes:
52719e99939fSJunchao 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,
52729e99939fSJunchao Zhang        the input data expected is as shown
52739e99939fSJunchao Zhang .vb
52748a0b0e6bSVictor Minden         1 0 0
52758a0b0e6bSVictor Minden         2 0 3
52768a0b0e6bSVictor Minden         4 5 6
52778a0b0e6bSVictor Minden 
52788a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
52798a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
52808a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
52819e99939fSJunchao Zhang .ve
52828a0b0e6bSVictor Minden 
528369b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
52848a0b0e6bSVictor Minden 
52858a0b0e6bSVictor Minden @*/
5286c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
52878a0b0e6bSVictor Minden {
52888a0b0e6bSVictor Minden   PetscErrorCode ierr;
5289d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
52908a0b0e6bSVictor Minden 
52918a0b0e6bSVictor Minden   PetscFunctionBegin;
52921795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
52931230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5294c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
52951230e6d1SVictor Minden   }
52968a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
52978a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
52988a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
52991230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
53001230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
53011230e6d1SVictor Minden     if (idx) {
53021230e6d1SVictor Minden       row = i[ii] - 1;
53031230e6d1SVictor Minden       col = j[ii] - 1;
53041230e6d1SVictor Minden     } else {
53051230e6d1SVictor Minden       row = i[ii];
53061230e6d1SVictor Minden       col = j[ii];
53078a0b0e6bSVictor Minden     }
53081230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
53098a0b0e6bSVictor Minden   }
53108a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
53118a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5312d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
53138a0b0e6bSVictor Minden   PetscFunctionReturn(0);
53148a0b0e6bSVictor Minden }
531536db0b34SBarry Smith 
5316acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5317acf2f550SJed Brown {
5318acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5319acf2f550SJed Brown   PetscErrorCode ierr;
5320acf2f550SJed Brown 
5321acf2f550SJed Brown   PetscFunctionBegin;
5322acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5323acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
53242205254eSKarl Rupp 
5325acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5326acf2f550SJed Brown   PetscFunctionReturn(0);
5327acf2f550SJed Brown }
5328acf2f550SJed Brown 
53299c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
53309c8f2541SHong Zhang {
53319c8f2541SHong Zhang   PetscErrorCode ierr;
53328761c3d6SHong Zhang   PetscMPIInt    size;
53339c8f2541SHong Zhang 
53349c8f2541SHong Zhang   PetscFunctionBegin;
5335ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
53367bbdc51dSHong Zhang   if (size == 1) {
53377bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
53387bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
53397bbdc51dSHong Zhang     } else {
53408761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
53417bbdc51dSHong Zhang     }
53428761c3d6SHong Zhang   } else {
53439c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
53448761c3d6SHong Zhang   }
53459c8f2541SHong Zhang   PetscFunctionReturn(0);
53469c8f2541SHong Zhang }
53479c8f2541SHong Zhang 
534881824310SBarry Smith /*
534953dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
535053dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
535153dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
535253dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
535353dd7562SDmitry Karpeev  */
535453dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
535553dd7562SDmitry Karpeev {
535653dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
535753dd7562SDmitry Karpeev   PetscErrorCode ierr;
535853dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
535953dd7562SDmitry Karpeev   PetscBool      seqaij;
536053dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
536153dd7562SDmitry Karpeev   PetscScalar    v;
536253dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
536353dd7562SDmitry Karpeev 
536453dd7562SDmitry Karpeev   PetscFunctionBegin;
536553dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
536653dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
53674099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
53682c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!seqaij,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
536953dd7562SDmitry Karpeev   if (rowemb) {
537053dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
53712c71b3e2SJacob 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);
537253dd7562SDmitry Karpeev   } else {
53732c71b3e2SJacob Faibussowitsch     PetscCheckFalse(C->rmap->n != B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
537453dd7562SDmitry Karpeev   }
537553dd7562SDmitry Karpeev   if (colemb) {
537653dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
53772c71b3e2SJacob 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);
537853dd7562SDmitry Karpeev   } else {
53792c71b3e2SJacob Faibussowitsch     PetscCheckFalse(C->cmap->n != B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
538053dd7562SDmitry Karpeev   }
538153dd7562SDmitry Karpeev 
538253dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
538353dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
538453dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
538553dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
538653dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
538753dd7562SDmitry Karpeev     }
538853dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
538953dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
539053dd7562SDmitry Karpeev   }
539153dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
539253dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
539353dd7562SDmitry Karpeev   }
539453dd7562SDmitry Karpeev   count = 0;
539553dd7562SDmitry Karpeev   rowindices = NULL;
539653dd7562SDmitry Karpeev   colindices = NULL;
539753dd7562SDmitry Karpeev   if (rowemb) {
539853dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
539953dd7562SDmitry Karpeev   }
540053dd7562SDmitry Karpeev   if (colemb) {
540153dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
540253dd7562SDmitry Karpeev   }
540353dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
540453dd7562SDmitry Karpeev     PetscInt row;
540553dd7562SDmitry Karpeev     row = i;
540653dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
540753dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
540853dd7562SDmitry Karpeev       PetscInt col;
540953dd7562SDmitry Karpeev       col  = Baij->j[count];
541053dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
541153dd7562SDmitry Karpeev       v    = Baij->a[count];
541253dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
541353dd7562SDmitry Karpeev       ++count;
541453dd7562SDmitry Karpeev     }
541553dd7562SDmitry Karpeev   }
541653dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
541753dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
541853dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
541953dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
542053dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
542153dd7562SDmitry Karpeev   PetscFunctionReturn(0);
542253dd7562SDmitry Karpeev }
542353dd7562SDmitry Karpeev 
54244099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
54254099cc6bSBarry Smith 
54264099cc6bSBarry Smith /*@C
54274099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
54284099cc6bSBarry Smith 
54294099cc6bSBarry Smith    Collective on Mat
54304099cc6bSBarry Smith 
54314099cc6bSBarry Smith    Input Parameters:
54324099cc6bSBarry Smith +  mat      - the matrix object
54334099cc6bSBarry Smith -  matype   - matrix type
54344099cc6bSBarry Smith 
54354099cc6bSBarry Smith    Options Database Key:
54364099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
54374099cc6bSBarry Smith 
54384099cc6bSBarry Smith   Level: intermediate
54394099cc6bSBarry Smith 
54404099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
54414099cc6bSBarry Smith @*/
54424099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
54434099cc6bSBarry Smith {
5444fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
54454099cc6bSBarry Smith   PetscBool      sametype;
54464099cc6bSBarry Smith 
54474099cc6bSBarry Smith   PetscFunctionBegin;
54484099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
54494099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
54504099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
54514099cc6bSBarry Smith 
54524099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
54532c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
54544099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
54554099cc6bSBarry Smith   PetscFunctionReturn(0);
54564099cc6bSBarry Smith }
54574099cc6bSBarry Smith 
54584099cc6bSBarry Smith /*@C
54594099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
54604099cc6bSBarry Smith 
54614099cc6bSBarry Smith    Not Collective
54624099cc6bSBarry Smith 
54634099cc6bSBarry Smith    Input Parameters:
54644099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
54654099cc6bSBarry Smith -  function - routine to convert to subtype
54664099cc6bSBarry Smith 
54674099cc6bSBarry Smith    Notes:
54684099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
54694099cc6bSBarry Smith 
54704099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
54714099cc6bSBarry Smith $     -mat_seqaij_type my_mat
54724099cc6bSBarry Smith 
54734099cc6bSBarry Smith    Level: advanced
54744099cc6bSBarry Smith 
54754099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
54764099cc6bSBarry Smith 
54774099cc6bSBarry Smith   Level: advanced
54784099cc6bSBarry Smith @*/
5479388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
54804099cc6bSBarry Smith {
54814099cc6bSBarry Smith   PetscErrorCode ierr;
54824099cc6bSBarry Smith 
54834099cc6bSBarry Smith   PetscFunctionBegin;
54849cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
54854099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
54864099cc6bSBarry Smith   PetscFunctionReturn(0);
54874099cc6bSBarry Smith }
54884099cc6bSBarry Smith 
54894099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
54904099cc6bSBarry Smith 
54914099cc6bSBarry Smith /*@C
54924099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
54934099cc6bSBarry Smith 
54944099cc6bSBarry Smith   Not Collective
54954099cc6bSBarry Smith 
54964099cc6bSBarry Smith   Level: advanced
54974099cc6bSBarry Smith 
54984099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
54994099cc6bSBarry Smith @*/
55004099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
55014099cc6bSBarry Smith {
55024099cc6bSBarry Smith   PetscErrorCode ierr;
55034099cc6bSBarry Smith 
55044099cc6bSBarry Smith   PetscFunctionBegin;
55054099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
55064099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
55074099cc6bSBarry Smith 
55084099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
55094099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
55104dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
55119779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
55126b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5513485f9817SRichard Tran Mills #endif
55145063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
55155063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
55165063d097SStefano Zampini #endif
55175063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
55185063d097SStefano Zampini   ierr = MatSeqAIJRegister(MATSEQAIJKOKKOS,   MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
55195063d097SStefano Zampini #endif
55204099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
55214099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
55224099cc6bSBarry Smith #endif
55234099cc6bSBarry Smith   PetscFunctionReturn(0);
55244099cc6bSBarry Smith }
552553dd7562SDmitry Karpeev 
552653dd7562SDmitry Karpeev /*
552781824310SBarry Smith     Special version for direct calls from Fortran
552881824310SBarry Smith */
5529af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
553081824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
553181824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
553281824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
553381824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
553481824310SBarry Smith #endif
553581824310SBarry Smith 
553681824310SBarry Smith /* Change these macros so can be used in void function */
553798921bdaSJacob Faibussowitsch 
553898921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */
553998921bdaSJacob Faibussowitsch /* Identical to CHKERRV, except it assigns to *_ierr */
554081824310SBarry Smith #undef CHKERRQ
554198921bdaSJacob Faibussowitsch #define CHKERRQ(ierr) do {                                                                     \
554298921bdaSJacob Faibussowitsch     PetscErrorCode ierr_msv_mpiaij = (ierr);                                                   \
554398921bdaSJacob Faibussowitsch     if (PetscUnlikely(ierr_msv_mpiaij)) {                                                      \
554498921bdaSJacob Faibussowitsch       *_ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr_msv_mpiaij,PETSC_ERROR_REPEAT," "); \
554598921bdaSJacob Faibussowitsch       return;                                                                                  \
554698921bdaSJacob Faibussowitsch     }                                                                                          \
554798921bdaSJacob Faibussowitsch   } while (0)
554898921bdaSJacob Faibussowitsch 
554998921bdaSJacob Faibussowitsch #undef SETERRQ
555098921bdaSJacob Faibussowitsch #define SETERRQ(comm,ierr,...) do {                                                            \
555198921bdaSJacob Faibussowitsch     *_ierr = PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr,PETSC_ERROR_INITIAL,__VA_ARGS__); \
555298921bdaSJacob Faibussowitsch     return;                                                                                    \
555398921bdaSJacob Faibussowitsch   } while (0)
555481824310SBarry Smith 
555519caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
555681824310SBarry Smith {
555781824310SBarry Smith   Mat            A  = *AA;
555881824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
555981824310SBarry Smith   InsertMode     is = *isis;
556081824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
556181824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
556281824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
556381824310SBarry Smith   PetscErrorCode ierr;
556481824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
556554f21887SBarry Smith   MatScalar      *ap,value,*aa;
5566ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5567ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
556881824310SBarry Smith 
556981824310SBarry Smith   PetscFunctionBegin;
55704994cf47SJed Brown   MatCheckPreallocated(A,1);
557181824310SBarry Smith   imax  = a->imax;
557281824310SBarry Smith   ai    = a->i;
557381824310SBarry Smith   ailen = a->ilen;
557481824310SBarry Smith   aj    = a->j;
557581824310SBarry Smith   aa    = a->a;
557681824310SBarry Smith 
557781824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
557881824310SBarry Smith     row = im[k];
557981824310SBarry Smith     if (row < 0) continue;
5580cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
558181824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
558281824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
558381824310SBarry Smith     low  = 0;
558481824310SBarry Smith     high = nrow;
558581824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
558681824310SBarry Smith       if (in[l] < 0) continue;
5587cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
558881824310SBarry Smith       col = in[l];
55892205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
55902205254eSKarl Rupp       else value = v[k + l*m];
55912205254eSKarl Rupp 
559281824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
559381824310SBarry Smith 
55942205254eSKarl Rupp       if (col <= lastcol) low = 0;
55952205254eSKarl Rupp       else high = nrow;
559681824310SBarry Smith       lastcol = col;
559781824310SBarry Smith       while (high-low > 5) {
559881824310SBarry Smith         t = (low+high)/2;
559981824310SBarry Smith         if (rp[t] > col) high = t;
560081824310SBarry Smith         else             low  = t;
560181824310SBarry Smith       }
560281824310SBarry Smith       for (i=low; i<high; i++) {
560381824310SBarry Smith         if (rp[i] > col) break;
560481824310SBarry Smith         if (rp[i] == col) {
560581824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
560681824310SBarry Smith           else                  ap[i] = value;
560781824310SBarry Smith           goto noinsert;
560881824310SBarry Smith         }
560981824310SBarry Smith       }
561081824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
561181824310SBarry Smith       if (nonew == 1) goto noinsert;
5612ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5613fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
561481824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
561581824310SBarry Smith       /* shift up all the later entries in this row */
561681824310SBarry Smith       for (ii=N; ii>=i; ii--) {
561781824310SBarry Smith         rp[ii+1] = rp[ii];
561881824310SBarry Smith         ap[ii+1] = ap[ii];
561981824310SBarry Smith       }
562081824310SBarry Smith       rp[i] = col;
562181824310SBarry Smith       ap[i] = value;
5622e56f5c9eSBarry Smith       A->nonzerostate++;
562381824310SBarry Smith noinsert:;
562481824310SBarry Smith       low = i + 1;
562581824310SBarry Smith     }
562681824310SBarry Smith     ailen[row] = nrow;
562781824310SBarry Smith   }
562881824310SBarry Smith   PetscFunctionReturnVoid();
562981824310SBarry Smith }
563098921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No
563198921bdaSJacob Faibussowitsch  * other PETSc functions should be defined past this point, as it is impossible to recover the
563298921bdaSJacob Faibussowitsch  * original definitions */
563398921bdaSJacob Faibussowitsch #undef CHKERRQ
563498921bdaSJacob Faibussowitsch #undef SETERRQ
5635