xref: /petsc/src/mat/impls/aij/seq/aij.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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);
195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg));
205f80ce2aSJacob Faibussowitsch   if (flg) CHKERRQ(MatSeqAIJSetType(A,type));
214099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
224099cc6bSBarry Smith   PetscFunctionReturn(0);
234099cc6bSBarry Smith }
244099cc6bSBarry Smith 
25857cbf51SRichard Tran Mills PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A,PetscInt type,PetscReal *reductions)
260716a85fSBarry Smith {
270716a85fSBarry Smith   PetscInt       i,m,n;
280716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
290716a85fSBarry Smith 
300716a85fSBarry Smith   PetscFunctionBegin;
315f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,&m,&n));
325f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(reductions,n));
330716a85fSBarry Smith   if (type == NORM_2) {
340716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
35a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
360716a85fSBarry Smith     }
370716a85fSBarry Smith   } else if (type == NORM_1) {
380716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
39a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]);
400716a85fSBarry Smith     }
410716a85fSBarry Smith   } else if (type == NORM_INFINITY) {
420716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
43a873a8cdSSam Reynolds       reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),reductions[aij->j[i]]);
440716a85fSBarry Smith     }
45857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
46a873a8cdSSam Reynolds     for (i=0; i<aij->i[m]; i++) {
47857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscRealPart(aij->a[i]);
48a873a8cdSSam Reynolds     }
49857cbf51SRichard Tran Mills   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
50857cbf51SRichard Tran Mills     for (i=0; i<aij->i[m]; i++) {
51857cbf51SRichard Tran Mills       reductions[aij->j[i]] += PetscImaginaryPart(aij->a[i]);
52857cbf51SRichard Tran Mills     }
53857cbf51SRichard Tran Mills   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown reduction type");
540716a85fSBarry Smith 
550716a85fSBarry Smith   if (type == NORM_2) {
56a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
57857cbf51SRichard Tran Mills   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
58a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] /= m;
590716a85fSBarry Smith   }
600716a85fSBarry Smith   PetscFunctionReturn(0);
610716a85fSBarry Smith }
620716a85fSBarry Smith 
633a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
643a062f41SBarry Smith {
653a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
663a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
673a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
683a062f41SBarry Smith   PetscInt        *rows;
693a062f41SBarry Smith 
703a062f41SBarry Smith   PetscFunctionBegin;
713a062f41SBarry Smith   for (i=0; i<m; i++) {
723a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
733a062f41SBarry Smith       cnt++;
743a062f41SBarry Smith     }
753a062f41SBarry Smith   }
765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(cnt,&rows));
773a062f41SBarry Smith   cnt  = 0;
783a062f41SBarry Smith   for (i=0; i<m; i++) {
793a062f41SBarry Smith     if ((ii[i] != ii[i+1]) && ((jj[ii[i]] < bs*(i/bs)) || (jj[ii[i+1]-1] > bs*((i+bs)/bs)-1))) {
803a062f41SBarry Smith       rows[cnt] = i;
813a062f41SBarry Smith       cnt++;
823a062f41SBarry Smith     }
833a062f41SBarry Smith   }
845f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is));
853a062f41SBarry Smith   PetscFunctionReturn(0);
863a062f41SBarry Smith }
873a062f41SBarry Smith 
88f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ_Private(Mat A,PetscInt *nrows,PetscInt **zrows)
896ce1633cSBarry Smith {
906ce1633cSBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
91fff043a9SJunchao Zhang   const MatScalar *aa;
926ce1633cSBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0;
93b2db7409Sstefano_zampini   const PetscInt  *ii = a->i,*jj = a->j,*diag;
946ce1633cSBarry Smith   PetscInt        *rows;
956ce1633cSBarry Smith 
966ce1633cSBarry Smith   PetscFunctionBegin;
975f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
985f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMarkDiagonal_SeqAIJ(A));
996ce1633cSBarry Smith   diag = a->diag;
1006ce1633cSBarry Smith   for (i=0; i<m; i++) {
101b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1026ce1633cSBarry Smith       cnt++;
1036ce1633cSBarry Smith     }
1046ce1633cSBarry Smith   }
1055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(cnt,&rows));
1066ce1633cSBarry Smith   cnt  = 0;
1076ce1633cSBarry Smith   for (i=0; i<m; i++) {
108b2db7409Sstefano_zampini     if ((diag[i] >= ii[i+1]) || (jj[diag[i]] != i) || (aa[diag[i]] == 0.0)) {
1096ce1633cSBarry Smith       rows[cnt++] = i;
1106ce1633cSBarry Smith     }
1116ce1633cSBarry Smith   }
112f1f41ecbSJed Brown   *nrows = cnt;
113f1f41ecbSJed Brown   *zrows = rows;
1145f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
115f1f41ecbSJed Brown   PetscFunctionReturn(0);
116f1f41ecbSJed Brown }
117f1f41ecbSJed Brown 
118f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
119f1f41ecbSJed Brown {
120f1f41ecbSJed Brown   PetscInt       nrows,*rows;
121f1f41ecbSJed Brown 
122f1f41ecbSJed Brown   PetscFunctionBegin;
1230298fd71SBarry Smith   *zrows = NULL;
1245f80ce2aSJacob Faibussowitsch   CHKERRQ(MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows));
1255f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows));
1266ce1633cSBarry Smith   PetscFunctionReturn(0);
1276ce1633cSBarry Smith }
1286ce1633cSBarry Smith 
129b3a44c85SBarry Smith PetscErrorCode MatFindNonzeroRows_SeqAIJ(Mat A,IS *keptrows)
130b3a44c85SBarry Smith {
131b3a44c85SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
132b3a44c85SBarry Smith   const MatScalar *aa;
133b3a44c85SBarry Smith   PetscInt        m=A->rmap->n,cnt = 0;
134b3a44c85SBarry Smith   const PetscInt  *ii;
135b3a44c85SBarry Smith   PetscInt        n,i,j,*rows;
136b3a44c85SBarry Smith 
137b3a44c85SBarry Smith   PetscFunctionBegin;
1385f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
139f4259b30SLisandro Dalcin   *keptrows = NULL;
140b3a44c85SBarry Smith   ii        = a->i;
141b3a44c85SBarry Smith   for (i=0; i<m; i++) {
142b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
143b3a44c85SBarry Smith     if (!n) {
144b3a44c85SBarry Smith       cnt++;
145b3a44c85SBarry Smith       goto ok1;
146b3a44c85SBarry Smith     }
1472e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
148b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
149b3a44c85SBarry Smith     }
150b3a44c85SBarry Smith     cnt++;
151b3a44c85SBarry Smith ok1:;
152b3a44c85SBarry Smith   }
1532e5835c6SStefano Zampini   if (!cnt) {
1545f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
1552e5835c6SStefano Zampini     PetscFunctionReturn(0);
1562e5835c6SStefano Zampini   }
1575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(A->rmap->n-cnt,&rows));
158b3a44c85SBarry Smith   cnt  = 0;
159b3a44c85SBarry Smith   for (i=0; i<m; i++) {
160b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
161b3a44c85SBarry Smith     if (!n) continue;
1622e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
163b3a44c85SBarry Smith       if (aa[j] != 0.0) {
164b3a44c85SBarry Smith         rows[cnt++] = i;
165b3a44c85SBarry Smith         break;
166b3a44c85SBarry Smith       }
167b3a44c85SBarry Smith     }
168b3a44c85SBarry Smith   }
1695f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
1705f80ce2aSJacob Faibussowitsch   CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows));
171b3a44c85SBarry Smith   PetscFunctionReturn(0);
172b3a44c85SBarry Smith }
173b3a44c85SBarry Smith 
1747087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
17579299369SBarry Smith {
17679299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17799e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
17899e65526SBarry Smith   const PetscInt    *diag;
1792e5835c6SStefano Zampini   MatScalar         *aa;
18099e65526SBarry Smith   const PetscScalar *v;
181ace3abfcSBarry Smith   PetscBool         missing;
18279299369SBarry Smith 
18379299369SBarry Smith   PetscFunctionBegin;
18409f38230SBarry Smith   if (Y->assembled) {
1855f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMissingDiagonal_SeqAIJ(Y,&missing,NULL));
18609f38230SBarry Smith     if (!missing) {
18779299369SBarry Smith       diag = aij->diag;
1885f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArrayRead(D,&v));
1895f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSeqAIJGetArray(Y,&aa));
19079299369SBarry Smith       if (is == INSERT_VALUES) {
19179299369SBarry Smith         for (i=0; i<m; i++) {
19279299369SBarry Smith           aa[diag[i]] = v[i];
19379299369SBarry Smith         }
19479299369SBarry Smith       } else {
19579299369SBarry Smith         for (i=0; i<m; i++) {
19679299369SBarry Smith           aa[diag[i]] += v[i];
19779299369SBarry Smith         }
19879299369SBarry Smith       }
1995f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSeqAIJRestoreArray(Y,&aa));
2005f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArrayRead(D,&v));
20179299369SBarry Smith       PetscFunctionReturn(0);
20279299369SBarry Smith     }
2035f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJInvalidateDiagonal(Y));
20409f38230SBarry Smith   }
2055f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDiagonalSet_Default(Y,D,is));
20609f38230SBarry Smith   PetscFunctionReturn(0);
20709f38230SBarry Smith }
20879299369SBarry Smith 
2091a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
21017ab2063SBarry Smith {
211416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
21297f1f81fSBarry Smith   PetscInt       i,ishift;
21317ab2063SBarry Smith 
2143a40ed3dSBarry Smith   PetscFunctionBegin;
215d0f46423SBarry Smith   *m = A->rmap->n;
2163a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
217bfeeae90SHong Zhang   ishift = 0;
21853e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2195f80ce2aSJacob Faibussowitsch     CHKERRQ(MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja));
220bfeeae90SHong Zhang   } else if (oshift == 1) {
2211a83f524SJed Brown     PetscInt *tia;
222d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2233b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
2245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(A->rmap->n+1,&tia));
2251a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2261a83f524SJed Brown     *ia = tia;
227ecc77c7aSBarry Smith     if (ja) {
2281a83f524SJed Brown       PetscInt *tja;
2295f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(nz+1,&tja));
2301a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2311a83f524SJed Brown       *ja = tja;
232ecc77c7aSBarry Smith     }
2336945ee14SBarry Smith   } else {
234ecc77c7aSBarry Smith     *ia = a->i;
235ecc77c7aSBarry Smith     if (ja) *ja = a->j;
236a2ce50c7SBarry Smith   }
2373a40ed3dSBarry Smith   PetscFunctionReturn(0);
238a2744918SBarry Smith }
239a2744918SBarry Smith 
2401a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2416945ee14SBarry Smith {
2423a40ed3dSBarry Smith   PetscFunctionBegin;
2433a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
244bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
2455f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(*ia));
2465f80ce2aSJacob Faibussowitsch     if (ja) CHKERRQ(PetscFree(*ja));
247bcd2baecSBarry Smith   }
2483a40ed3dSBarry Smith   PetscFunctionReturn(0);
24917ab2063SBarry Smith }
25017ab2063SBarry Smith 
2511a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2523b2fbd54SBarry Smith {
2533b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
254d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
25597f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2563b2fbd54SBarry Smith 
2573a40ed3dSBarry Smith   PetscFunctionBegin;
258899cda47SBarry Smith   *nn = n;
2593a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2603b2fbd54SBarry Smith   if (symmetric) {
2615f80ce2aSJacob Faibussowitsch     CHKERRQ(MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja));
2623b2fbd54SBarry Smith   } else {
2635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(n,&collengths));
2645f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(n+1,&cia));
2655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nz,&cja));
2663b2fbd54SBarry Smith     jj   = a->j;
2673b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
268bfeeae90SHong Zhang       collengths[jj[i]]++;
2693b2fbd54SBarry Smith     }
2703b2fbd54SBarry Smith     cia[0] = oshift;
2713b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2723b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2733b2fbd54SBarry Smith     }
2745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(collengths,n));
2753b2fbd54SBarry Smith     jj   = a->j;
276a93ec695SBarry Smith     for (row=0; row<m; row++) {
277a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
278a93ec695SBarry Smith       for (i=0; i<mr; i++) {
279bfeeae90SHong Zhang         col = *jj++;
2802205254eSKarl Rupp 
2813b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
2823b2fbd54SBarry Smith       }
2833b2fbd54SBarry Smith     }
2845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(collengths));
2853b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
2863b2fbd54SBarry Smith   }
2873a40ed3dSBarry Smith   PetscFunctionReturn(0);
2883b2fbd54SBarry Smith }
2893b2fbd54SBarry Smith 
2901a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2913b2fbd54SBarry Smith {
2923a40ed3dSBarry Smith   PetscFunctionBegin;
2933a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2943b2fbd54SBarry Smith 
2955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(*ia));
2965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(*ja));
2973a40ed3dSBarry Smith   PetscFunctionReturn(0);
2983b2fbd54SBarry Smith }
2993b2fbd54SBarry Smith 
3007cee066cSHong Zhang /*
3017cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3027cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
303040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3047cee066cSHong Zhang */
3057cee066cSHong 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)
3067cee066cSHong Zhang {
3077cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3087cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
309071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3107cee066cSHong Zhang   PetscInt       *cspidx;
311071fcb05SBarry Smith   const PetscInt *jj;
3127cee066cSHong Zhang 
3137cee066cSHong Zhang   PetscFunctionBegin;
3147cee066cSHong Zhang   *nn = n;
3157cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
316625f6d37SHong Zhang 
3175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(n,&collengths));
3185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(n+1,&cia));
3195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nz,&cja));
3205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(nz,&cspidx));
3217cee066cSHong Zhang   jj   = a->j;
3227cee066cSHong Zhang   for (i=0; i<nz; i++) {
3237cee066cSHong Zhang     collengths[jj[i]]++;
3247cee066cSHong Zhang   }
3257cee066cSHong Zhang   cia[0] = oshift;
3267cee066cSHong Zhang   for (i=0; i<n; i++) {
3277cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3287cee066cSHong Zhang   }
3295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(collengths,n));
3307cee066cSHong Zhang   jj   = a->j;
3317cee066cSHong Zhang   for (row=0; row<m; row++) {
3327cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3337cee066cSHong Zhang     for (i=0; i<mr; i++) {
3347cee066cSHong Zhang       col         = *jj++;
335071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
336071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
337071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3387cee066cSHong Zhang     }
3397cee066cSHong Zhang   }
3405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(collengths));
341071fcb05SBarry Smith   *ia    = cia;
342071fcb05SBarry Smith   *ja    = cja;
3437cee066cSHong Zhang   *spidx = cspidx;
3447cee066cSHong Zhang   PetscFunctionReturn(0);
3457cee066cSHong Zhang }
3467cee066cSHong Zhang 
3477cee066cSHong Zhang PetscErrorCode MatRestoreColumnIJ_SeqAIJ_Color(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscInt *spidx[],PetscBool  *done)
3487cee066cSHong Zhang {
3497cee066cSHong Zhang   PetscFunctionBegin;
3505f80ce2aSJacob Faibussowitsch   CHKERRQ(MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done));
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(*spidx));
3527cee066cSHong Zhang   PetscFunctionReturn(0);
3537cee066cSHong Zhang }
3547cee066cSHong Zhang 
35587d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
35687d4246cSBarry Smith {
35787d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
35887d4246cSBarry Smith   PetscInt       *ai = a->i;
359fff043a9SJunchao Zhang   PetscScalar    *aa;
36087d4246cSBarry Smith 
36187d4246cSBarry Smith   PetscFunctionBegin;
3625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
3635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(aa+ai[row],v,ai[row+1]-ai[row]));
3645f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
36587d4246cSBarry Smith   PetscFunctionReturn(0);
36687d4246cSBarry Smith }
36787d4246cSBarry Smith 
368bd04181cSBarry Smith /*
369bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
370bd04181cSBarry Smith 
371bd04181cSBarry Smith       -   a single row of values is set with each call
372bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
373bd04181cSBarry Smith       -   the values are always added to the matrix, not set
374bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
375bd04181cSBarry Smith 
3761f763a69SBarry Smith      This does NOT assume the global column indices are sorted
377bd04181cSBarry Smith 
3781f763a69SBarry Smith */
379bd04181cSBarry Smith 
380af0996ceSBarry Smith #include <petsc/private/isimpl.h>
381189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
382189e4007SBarry Smith {
383189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3841f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
3851f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
3861f763a69SBarry Smith   PetscInt       lastcol = -1;
387fff043a9SJunchao Zhang   MatScalar      *ap,value,*aa;
388189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
389189e4007SBarry Smith 
390fff043a9SJunchao Zhang   PetscFunctionBegin;
3915f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
392f38dd0b8SBarry Smith   row  = ridx[im[0]];
3931f763a69SBarry Smith   rp   = aj + ai[row];
3941f763a69SBarry Smith   ap   = aa + ai[row];
3951f763a69SBarry Smith   nrow = ailen[row];
396189e4007SBarry Smith   low  = 0;
397189e4007SBarry Smith   high = nrow;
398189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
399189e4007SBarry Smith     col = cidx[in[l]];
400f38dd0b8SBarry Smith     value = v[l];
401189e4007SBarry Smith 
402189e4007SBarry Smith     if (col <= lastcol) low = 0;
403189e4007SBarry Smith     else high = nrow;
404189e4007SBarry Smith     lastcol = col;
405189e4007SBarry Smith     while (high-low > 5) {
406189e4007SBarry Smith       t = (low+high)/2;
407189e4007SBarry Smith       if (rp[t] > col) high = t;
408189e4007SBarry Smith       else low = t;
409189e4007SBarry Smith     }
410189e4007SBarry Smith     for (i=low; i<high; i++) {
411189e4007SBarry Smith       if (rp[i] == col) {
4121f763a69SBarry Smith         ap[i] += value;
413189e4007SBarry Smith         low = i + 1;
4141f763a69SBarry Smith         break;
415189e4007SBarry Smith       }
416189e4007SBarry Smith     }
417189e4007SBarry Smith   }
4185f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
419f38dd0b8SBarry Smith   return 0;
420189e4007SBarry Smith }
421189e4007SBarry Smith 
42297f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
42317ab2063SBarry Smith {
424416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
425e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
42697f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
427e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
428ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
429ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
430ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
43117ab2063SBarry Smith 
4323a40ed3dSBarry Smith   PetscFunctionBegin;
4335f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
43417ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
435416022c9SBarry Smith     row = im[k];
4365ef9f2a5SBarry Smith     if (row < 0) continue;
4376bdcaf15SBarry Smith     PetscCheck(row < A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,row,A->rmap->n-1);
438720833daSHong Zhang     rp   = aj + ai[row];
439876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
44017ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
441416022c9SBarry Smith     low  = 0;
442c71e6ed7SBarry Smith     high = nrow;
44317ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4445ef9f2a5SBarry Smith       if (in[l] < 0) continue;
4456bdcaf15SBarry Smith       PetscCheck(in[l] < A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[l],A->cmap->n-1);
446bfeeae90SHong Zhang       col = in[l];
447071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
448071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
44936db0b34SBarry Smith 
4502205254eSKarl Rupp       if (col <= lastcol) low = 0;
4512205254eSKarl Rupp       else high = nrow;
452e2ee6c50SBarry Smith       lastcol = col;
453416022c9SBarry Smith       while (high-low > 5) {
454416022c9SBarry Smith         t = (low+high)/2;
455416022c9SBarry Smith         if (rp[t] > col) high = t;
456416022c9SBarry Smith         else low = t;
45717ab2063SBarry Smith       }
458416022c9SBarry Smith       for (i=low; i<high; i++) {
45917ab2063SBarry Smith         if (rp[i] > col) break;
46017ab2063SBarry Smith         if (rp[i] == col) {
461876c6284SHong Zhang           if (!A->structure_only) {
4620c0d7e18SFande Kong             if (is == ADD_VALUES) {
4630c0d7e18SFande Kong               ap[i] += value;
4640c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
4650c0d7e18SFande Kong             }
46617ab2063SBarry Smith             else ap[i] = value;
467720833daSHong Zhang           }
468e44c0bd4SBarry Smith           low = i + 1;
46917ab2063SBarry Smith           goto noinsert;
47017ab2063SBarry Smith         }
47117ab2063SBarry Smith       }
472dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
473c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
4742c71b3e2SJacob 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);
475720833daSHong Zhang       if (A->structure_only) {
476876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
477720833daSHong Zhang       } else {
478fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
479720833daSHong Zhang       }
480c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
481416022c9SBarry Smith       /* shift up all the later entries in this row */
4825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraymove(rp+i+1,rp+i,N-i+1));
48317ab2063SBarry Smith       rp[i] = col;
484580bdb30SBarry Smith       if (!A->structure_only) {
4855f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscArraymove(ap+i+1,ap+i,N-i+1));
486580bdb30SBarry Smith         ap[i] = value;
487580bdb30SBarry Smith       }
488416022c9SBarry Smith       low = i + 1;
489e56f5c9eSBarry Smith       A->nonzerostate++;
490e44c0bd4SBarry Smith noinsert:;
49117ab2063SBarry Smith     }
49217ab2063SBarry Smith     ailen[row] = nrow;
49317ab2063SBarry Smith   }
4945f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
4953a40ed3dSBarry Smith   PetscFunctionReturn(0);
49617ab2063SBarry Smith }
49717ab2063SBarry Smith 
49819b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
49919b08ed1SBarry Smith {
50019b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
50119b08ed1SBarry Smith   PetscInt       *rp,k,row;
50219b08ed1SBarry Smith   PetscInt       *ai = a->i;
50319b08ed1SBarry Smith   PetscInt       *aj = a->j;
504fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
50519b08ed1SBarry Smith 
50619b08ed1SBarry Smith   PetscFunctionBegin;
507*28b400f6SJacob Faibussowitsch   PetscCheck(!A->was_assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
5082c71b3e2SJacob 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);
509fff043a9SJunchao Zhang 
5105f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
51119b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
51219b08ed1SBarry Smith     row  = im[k];
51319b08ed1SBarry Smith     rp   = aj + ai[row];
51419b08ed1SBarry Smith     ap   = aa + ai[row];
51519b08ed1SBarry Smith 
5165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemcpy(rp,in,n*sizeof(PetscInt)));
51719b08ed1SBarry Smith     if (!A->structure_only) {
51819b08ed1SBarry Smith       if (v) {
5195f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMemcpy(ap,v,n*sizeof(PetscScalar)));
52019b08ed1SBarry Smith         v   += n;
52119b08ed1SBarry Smith       } else {
5225f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMemzero(ap,n*sizeof(PetscScalar)));
52319b08ed1SBarry Smith       }
52419b08ed1SBarry Smith     }
52519b08ed1SBarry Smith     a->ilen[row] = n;
52619b08ed1SBarry Smith     a->imax[row] = n;
52719b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
52819b08ed1SBarry Smith     a->nz       += n;
52919b08ed1SBarry Smith   }
5305f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
53119b08ed1SBarry Smith   PetscFunctionReturn(0);
53219b08ed1SBarry Smith }
53319b08ed1SBarry Smith 
53419b08ed1SBarry Smith /*@
53519b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
53619b08ed1SBarry Smith 
53719b08ed1SBarry Smith   Input Parameters:
53819b08ed1SBarry Smith +  A - the SeqAIJ matrix
53919b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
54019b08ed1SBarry Smith 
54119b08ed1SBarry Smith   Level: advanced
54219b08ed1SBarry Smith 
54319b08ed1SBarry Smith   Notes:
54419b08ed1SBarry 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.
54519b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
54619b08ed1SBarry Smith     as always with multiple matrix assemblies.
54719b08ed1SBarry Smith 
54819b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
54919b08ed1SBarry Smith @*/
55019b08ed1SBarry Smith 
55119b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
55219b08ed1SBarry Smith {
55319b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
55419b08ed1SBarry Smith 
55519b08ed1SBarry Smith   PetscFunctionBegin;
5565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(A->rmap));
5575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(A->cmap));
55819b08ed1SBarry Smith   a->maxnz  = nztotal;
55919b08ed1SBarry Smith   if (!a->imax) {
5605f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(A->rmap->n,&a->imax));
5615f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt)));
56219b08ed1SBarry Smith   }
56319b08ed1SBarry Smith   if (!a->ilen) {
5645f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(A->rmap->n,&a->ilen));
5655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt)));
56619b08ed1SBarry Smith   } else {
5675f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt)));
56819b08ed1SBarry Smith   }
56919b08ed1SBarry Smith 
57019b08ed1SBarry Smith   /* allocate the matrix space */
57119b08ed1SBarry Smith   if (A->structure_only) {
5725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nztotal,&a->j));
5735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(A->rmap->n+1,&a->i));
5745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt)));
57519b08ed1SBarry Smith   } else {
5765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i));
5775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt))));
57819b08ed1SBarry Smith   }
57919b08ed1SBarry Smith   a->i[0] = 0;
58019b08ed1SBarry Smith   if (A->structure_only) {
58119b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
58219b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
58319b08ed1SBarry Smith   } else {
58419b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
58519b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
58619b08ed1SBarry Smith   }
58719b08ed1SBarry Smith   a->free_ij        = PETSC_TRUE;
58819b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
58919b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
59019b08ed1SBarry Smith   PetscFunctionReturn(0);
59119b08ed1SBarry Smith }
59219b08ed1SBarry Smith 
593071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
594071fcb05SBarry Smith {
595071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
596071fcb05SBarry Smith   PetscInt       *rp,k,row;
597071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
598071fcb05SBarry Smith   PetscInt       *aj = a->j;
599fff043a9SJunchao Zhang   MatScalar      *aa,*ap;
600071fcb05SBarry Smith 
601071fcb05SBarry Smith   PetscFunctionBegin;
6025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
603071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
604071fcb05SBarry Smith     row  = im[k];
6056bdcaf15SBarry Smith     PetscCheck(n <= a->imax[row],PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Preallocation for row %" PetscInt_FMT " does not match number of columns provided",n);
606071fcb05SBarry Smith     rp   = aj + ai[row];
607071fcb05SBarry Smith     ap   = aa + ai[row];
608071fcb05SBarry Smith     if (!A->was_assembled) {
6095f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMemcpy(rp,in,n*sizeof(PetscInt)));
610071fcb05SBarry Smith     }
611071fcb05SBarry Smith     if (!A->structure_only) {
612071fcb05SBarry Smith       if (v) {
6135f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMemcpy(ap,v,n*sizeof(PetscScalar)));
614071fcb05SBarry Smith         v   += n;
615071fcb05SBarry Smith       } else {
6165f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMemzero(ap,n*sizeof(PetscScalar)));
617071fcb05SBarry Smith       }
618071fcb05SBarry Smith     }
619071fcb05SBarry Smith     ailen[row] = n;
620071fcb05SBarry Smith     a->nz      += n;
621071fcb05SBarry Smith   }
6225f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
623071fcb05SBarry Smith   PetscFunctionReturn(0);
624071fcb05SBarry Smith }
625071fcb05SBarry Smith 
626a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6277eb43aa7SLois Curfman McInnes {
6287eb43aa7SLois Curfman McInnes   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
62997f1f81fSBarry Smith   PetscInt       *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
63097f1f81fSBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
631fff043a9SJunchao Zhang   MatScalar      *ap,*aa;
6327eb43aa7SLois Curfman McInnes 
6333a40ed3dSBarry Smith   PetscFunctionBegin;
6345f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
6357eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6367eb43aa7SLois Curfman McInnes     row = im[k];
63754c59aa7SJacob Faibussowitsch     if (row < 0) {v += n; continue;} /* negative row */
63854c59aa7SJacob Faibussowitsch     PetscCheck(row < A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %" PetscInt_FMT " max %" PetscInt_FMT,row,A->rmap->n-1);
639bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6407eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6417eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
64254c59aa7SJacob Faibussowitsch       if (in[l] < 0) {v++; continue;} /* negative column */
64354c59aa7SJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %" PetscInt_FMT " max %" PetscInt_FMT,in[l],A->cmap->n-1);
644bfeeae90SHong Zhang       col  = in[l];
6457eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6467eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6477eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6487eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6497eb43aa7SLois Curfman McInnes         else low = t;
6507eb43aa7SLois Curfman McInnes       }
6517eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6527eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6537eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
654b49de8d1SLois Curfman McInnes           *v++ = ap[i];
6557eb43aa7SLois Curfman McInnes           goto finished;
6567eb43aa7SLois Curfman McInnes         }
6577eb43aa7SLois Curfman McInnes       }
65897e567efSBarry Smith       *v++ = 0.0;
6597eb43aa7SLois Curfman McInnes finished:;
6607eb43aa7SLois Curfman McInnes     }
6617eb43aa7SLois Curfman McInnes   }
6625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
6633a40ed3dSBarry Smith   PetscFunctionReturn(0);
6647eb43aa7SLois Curfman McInnes }
6657eb43aa7SLois Curfman McInnes 
6663ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
66717ab2063SBarry Smith {
6683ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
669c898d852SStefano Zampini   const PetscScalar *av;
6703ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
6713ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
67217ab2063SBarry Smith 
6733a40ed3dSBarry Smith   PetscFunctionBegin;
6745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetUp(viewer));
6752205254eSKarl Rupp 
6763ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
6773ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
6783ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
6793ea6fe3dSLisandro Dalcin   nz = A->nz;
680416022c9SBarry Smith 
6813ea6fe3dSLisandro Dalcin   /* write matrix header */
6823ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
6833ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
6845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryWrite(viewer,header,4,PETSC_INT));
685416022c9SBarry Smith 
6863ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
6875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m,&rowlens));
6883ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
6895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT));
6905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(rowlens));
6913ea6fe3dSLisandro Dalcin   /* store column indices */
6925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT));
693416022c9SBarry Smith   /* store nonzero values */
6945f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(mat,&av));
6955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR));
6965f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(mat,&av));
697b37d52dbSMark F. Adams 
6983ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
6995f80ce2aSJacob Faibussowitsch   CHKERRQ(MatView_Binary_BlockSizes(mat,viewer));
7003a40ed3dSBarry Smith   PetscFunctionReturn(0);
70117ab2063SBarry Smith }
702416022c9SBarry Smith 
7037dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7047dc0baabSHong Zhang {
7057dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7067dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7077dc0baabSHong Zhang 
7087dc0baabSHong Zhang   PetscFunctionBegin;
7095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
7107dc0baabSHong Zhang   for (i=0; i<m; i++) {
7115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
7127dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7135f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ") ",a->j[k]));
7147dc0baabSHong Zhang     }
7155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
7167dc0baabSHong Zhang   }
7175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
7187dc0baabSHong Zhang   PetscFunctionReturn(0);
7197dc0baabSHong Zhang }
7207dc0baabSHong Zhang 
72109573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
722cd155464SBarry Smith 
723dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
724416022c9SBarry Smith {
725416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
726c898d852SStefano Zampini   const PetscScalar *av;
72760e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
728e060cb09SBarry Smith   const char        *name;
729f3ef73ceSBarry Smith   PetscViewerFormat format;
73017ab2063SBarry Smith 
7313a40ed3dSBarry Smith   PetscFunctionBegin;
7327dc0baabSHong Zhang   if (A->structure_only) {
7335f80ce2aSJacob Faibussowitsch     CHKERRQ(MatView_SeqAIJ_ASCII_structonly(A,viewer));
7347dc0baabSHong Zhang     PetscFunctionReturn(0);
7357dc0baabSHong Zhang   }
73643e49210SHong Zhang 
7375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerGetFormat(viewer,&format));
7382e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7392e5835c6SStefano Zampini 
740c898d852SStefano Zampini   /* trigger copy to CPU if needed */
7415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&av));
7425f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&av));
74371c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
74497f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
74560e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
746c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
747d00d2cf4SBarry Smith       nofinalvalue = 1;
748d00d2cf4SBarry Smith     }
7495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
7505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"%% Size = %" PetscInt_FMT " %" PetscInt_FMT " \n",m,A->cmap->n));
7515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %" PetscInt_FMT " \n",a->nz));
752fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
7535f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",4);\n",a->nz+nofinalvalue));
754fbfe6fa7SJed Brown #else
7555f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"zzz = zeros(%" PetscInt_FMT ",3);\n",a->nz+nofinalvalue));
756fbfe6fa7SJed Brown #endif
7575f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"zzz = [\n"));
75817ab2063SBarry Smith 
75917ab2063SBarry Smith     for (i=0; i<m; i++) {
76060e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
761aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
7625f80ce2aSJacob Faibussowitsch         CHKERRQ(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])));
76317ab2063SBarry Smith #else
7645f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]));
76517ab2063SBarry Smith #endif
76617ab2063SBarry Smith       }
76717ab2063SBarry Smith     }
768d00d2cf4SBarry Smith     if (nofinalvalue) {
769c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
7705f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e %18.16e\n",m,A->cmap->n,0.,0.));
771c337ccceSJed Brown #else
7725f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT "  %18.16e\n",m,A->cmap->n,0.0));
773c337ccceSJed Brown #endif
774d00d2cf4SBarry Smith     }
7755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject)A,&name));
7765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name));
7775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
778fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
7795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
78044cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
7815f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
78260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
783aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
78436db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7855f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
78636db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
7875f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j])));
78836db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
7895f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
7906831982aSBarry Smith         }
79144cd7ae7SLois Curfman McInnes #else
7925f80ce2aSJacob Faibussowitsch         if (a->a[j] != 0.0) CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
79344cd7ae7SLois Curfman McInnes #endif
79444cd7ae7SLois Curfman McInnes       }
7955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
79644cd7ae7SLois Curfman McInnes     }
7975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
798fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
79997f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
8005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
8015f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(m+1,&sptr));
802496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
803496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
80460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
805496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
806aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
80736db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
808496be53dSLois Curfman McInnes #else
809496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
810496be53dSLois Curfman McInnes #endif
811496be53dSLois Curfman McInnes         }
812496be53dSLois Curfman McInnes       }
813496be53dSLois Curfman McInnes     }
8142e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
8155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n\n",m,nzd));
8162e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8172205254eSKarl Rupp       if (i+4<m) {
8185f80ce2aSJacob Faibussowitsch         CHKERRQ(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]));
8192205254eSKarl Rupp       } else if (i+3<m) {
8205f80ce2aSJacob Faibussowitsch         CHKERRQ(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]));
8212205254eSKarl Rupp       } else if (i+2<m) {
8225f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]));
8232205254eSKarl Rupp       } else if (i+1<m) {
8245f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1],sptr[i+2]));
8252205254eSKarl Rupp       } else if (i<m) {
8265f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " %" PetscInt_FMT "\n",sptr[i],sptr[i+1]));
8272205254eSKarl Rupp       } else {
8285f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT "\n",sptr[i]));
8292205254eSKarl Rupp       }
830496be53dSLois Curfman McInnes     }
8315f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
8325f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(sptr));
833496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
83460e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
8355f80ce2aSJacob Faibussowitsch         if (a->j[j] >= i) CHKERRQ(PetscViewerASCIIPrintf(viewer," %" PetscInt_FMT " ",a->j[j]+fshift));
836496be53dSLois Curfman McInnes       }
8375f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
838496be53dSLois Curfman McInnes     }
8395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
840496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
84160e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
842496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
843aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
84436db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
8455f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
8466831982aSBarry Smith           }
847496be53dSLois Curfman McInnes #else
8485f80ce2aSJacob Faibussowitsch           if (a->a[j] != 0.0) CHKERRQ(PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]));
849496be53dSLois Curfman McInnes #endif
850496be53dSLois Curfman McInnes         }
851496be53dSLois Curfman McInnes       }
8525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
853496be53dSLois Curfman McInnes     }
8545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
855fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
85697f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
85787828ca2SBarry Smith     PetscScalar value;
85868f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
85968f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
86068f1ed48SBarry Smith 
86168f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
86268f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
86368f1ed48SBarry Smith         realonly = PETSC_FALSE;
86468f1ed48SBarry Smith         break;
86568f1ed48SBarry Smith       }
86668f1ed48SBarry Smith     }
86768f1ed48SBarry Smith #endif
86802594712SBarry Smith 
8695f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
87002594712SBarry Smith     for (i=0; i<m; i++) {
87102594712SBarry Smith       jcnt = 0;
872d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
873e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
87402594712SBarry Smith           value = a->a[cnt++];
875e24b481bSBarry Smith           jcnt++;
87602594712SBarry Smith         } else {
87702594712SBarry Smith           value = 0.0;
87802594712SBarry Smith         }
879aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
88068f1ed48SBarry Smith         if (realonly) {
8815f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value)));
88268f1ed48SBarry Smith         } else {
8835f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value)));
88468f1ed48SBarry Smith         }
88502594712SBarry Smith #else
8865f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value));
88702594712SBarry Smith #endif
88802594712SBarry Smith       }
8895f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
89002594712SBarry Smith     }
8915f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
8923c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
893150b93efSMatthew G. Knepley     PetscInt fshift=1;
8945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
8953c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
8965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n"));
8973c215bfdSMatthew Knepley #else
8985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n"));
8993c215bfdSMatthew Knepley #endif
9005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT "\n", m, A->cmap->n, a->nz));
9013c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
90260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9033c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
9045f80ce2aSJacob Faibussowitsch         CHKERRQ(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])));
9053c215bfdSMatthew Knepley #else
9065f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"%" PetscInt_FMT " %" PetscInt_FMT " %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]));
9073c215bfdSMatthew Knepley #endif
9083c215bfdSMatthew Knepley       }
9093c215bfdSMatthew Knepley     }
9105f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
9113a40ed3dSBarry Smith   } else {
9125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
913d5f3da31SBarry Smith     if (A->factortype) {
91416cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
9155f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
91616cd7e1dSShri Abhyankar         /* L part */
91760e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
91816cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
91916cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9205f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
92116cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9225f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j]))));
92316cd7e1dSShri Abhyankar           } else {
9245f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
92516cd7e1dSShri Abhyankar           }
92616cd7e1dSShri Abhyankar #else
9275f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
92816cd7e1dSShri Abhyankar #endif
92916cd7e1dSShri Abhyankar         }
93016cd7e1dSShri Abhyankar         /* diagonal */
93116cd7e1dSShri Abhyankar         j = a->diag[i];
93216cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
93316cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
9345f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j])));
93516cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9365f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j]))));
93716cd7e1dSShri Abhyankar         } else {
9385f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j])));
93916cd7e1dSShri Abhyankar         }
94016cd7e1dSShri Abhyankar #else
9415f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)(1.0/a->a[j])));
94216cd7e1dSShri Abhyankar #endif
94316cd7e1dSShri Abhyankar 
94416cd7e1dSShri Abhyankar         /* U part */
94560e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
94616cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
94716cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9485f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
94916cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9505f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j]))));
95116cd7e1dSShri Abhyankar           } else {
9525f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
95316cd7e1dSShri Abhyankar           }
95416cd7e1dSShri Abhyankar #else
9555f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
95616cd7e1dSShri Abhyankar #endif
95716cd7e1dSShri Abhyankar         }
9585f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
95916cd7e1dSShri Abhyankar       }
96016cd7e1dSShri Abhyankar     } else {
96117ab2063SBarry Smith       for (i=0; i<m; i++) {
9625f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"row %" PetscInt_FMT ":",i));
96360e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
964aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
96536db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
9665f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j])));
96736db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9685f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j])));
9693a40ed3dSBarry Smith           } else {
9705f80ce2aSJacob Faibussowitsch             CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)PetscRealPart(a->a[j])));
97117ab2063SBarry Smith           }
97217ab2063SBarry Smith #else
9735f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscViewerASCIIPrintf(viewer," (%" PetscInt_FMT ", %g) ",a->j[j],(double)a->a[j]));
97417ab2063SBarry Smith #endif
97517ab2063SBarry Smith         }
9765f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscViewerASCIIPrintf(viewer,"\n"));
97717ab2063SBarry Smith       }
97816cd7e1dSShri Abhyankar     }
9795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
98017ab2063SBarry Smith   }
9815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFlush(viewer));
9823a40ed3dSBarry Smith   PetscFunctionReturn(0);
983416022c9SBarry Smith }
984416022c9SBarry Smith 
9859804daf3SBarry Smith #include <petscdraw.h>
986dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
987416022c9SBarry Smith {
988480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
989416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
990383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
991383922c3SLisandro Dalcin   int               color;
992b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
993b0a32e0cSBarry Smith   PetscViewer       viewer;
994f3ef73ceSBarry Smith   PetscViewerFormat format;
995fff043a9SJunchao Zhang   const PetscScalar *aa;
996cddf8d76SBarry Smith 
9973a40ed3dSBarry Smith   PetscFunctionBegin;
9985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer));
9995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerGetFormat(viewer,&format));
10005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr));
1001383922c3SLisandro Dalcin 
1002416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10035f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
1004fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
10055f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr;
1006383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10070513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1008b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1009416022c9SBarry Smith     for (i=0; i<m; i++) {
1010cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1011bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1012bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1013fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) >=  0.) continue;
10145f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
1015cddf8d76SBarry Smith       }
1016cddf8d76SBarry Smith     }
1017b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1018cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1019cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1020bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1021bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1022fff043a9SJunchao Zhang         if (aa[j] !=  0.) continue;
10235f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
1024cddf8d76SBarry Smith       }
1025cddf8d76SBarry Smith     }
1026b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1027cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1028cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1029bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1030bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1031fff043a9SJunchao Zhang         if (PetscRealPart(aa[j]) <=  0.) continue;
10325f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
1033416022c9SBarry Smith       }
1034416022c9SBarry Smith     }
1035383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10360513a670SBarry Smith   } else {
10370513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10380513a670SBarry Smith     /* first determine max of all nonzero values */
1039b05fc000SLisandro Dalcin     PetscReal      minv = 0.0, maxv = 0.0;
1040383922c3SLisandro Dalcin     PetscInt       nz   = a->nz, count = 0;
1041b0a32e0cSBarry Smith     PetscDraw      popup;
10425f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr;
10430513a670SBarry Smith 
10440513a670SBarry Smith     for (i=0; i<nz; i++) {
1045fff043a9SJunchao Zhang       if (PetscAbsScalar(aa[i]) > maxv) maxv = PetscAbsScalar(aa[i]);
10460513a670SBarry Smith     }
1047383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
10485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawGetPopup(draw,&popup));
10495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscDrawScalePopup(popup,minv,maxv));
1050383922c3SLisandro Dalcin 
1051383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10520513a670SBarry Smith     for (i=0; i<m; i++) {
1053383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1054383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1055bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1056383922c3SLisandro Dalcin         x_l = a->j[j];
1057383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1058fff043a9SJunchao Zhang         color = PetscDrawRealToColor(PetscAbsScalar(aa[count]),minv,maxv);
10595f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color));
10600513a670SBarry Smith         count++;
10610513a670SBarry Smith       }
10620513a670SBarry Smith     }
1063383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10640513a670SBarry Smith   }
10655f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
1066480ef9eaSBarry Smith   PetscFunctionReturn(0);
1067480ef9eaSBarry Smith }
1068cddf8d76SBarry Smith 
10699804daf3SBarry Smith #include <petscdraw.h>
1070dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1071480ef9eaSBarry Smith {
1072b0a32e0cSBarry Smith   PetscDraw      draw;
107336db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1074ace3abfcSBarry Smith   PetscBool      isnull;
1075480ef9eaSBarry Smith 
1076480ef9eaSBarry Smith   PetscFunctionBegin;
10775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDrawGetDraw(viewer,0,&draw));
10785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawIsNull(draw,&isnull));
1079480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1080480ef9eaSBarry Smith 
1081d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1082480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
10835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawSetCoordinates(draw,xl,yl,xr,yr));
10845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer));
10855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A));
10865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL));
10875f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscDrawSave(draw));
10883a40ed3dSBarry Smith   PetscFunctionReturn(0);
1089416022c9SBarry Smith }
1090416022c9SBarry Smith 
1091dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1092416022c9SBarry Smith {
1093ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1094416022c9SBarry Smith 
10953a40ed3dSBarry Smith   PetscFunctionBegin;
10965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii));
10975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
10985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
1099c45a1595SBarry Smith   if (iascii) {
11005f80ce2aSJacob Faibussowitsch     CHKERRQ(MatView_SeqAIJ_ASCII(A,viewer));
11010f5bd95cSBarry Smith   } else if (isbinary) {
11025f80ce2aSJacob Faibussowitsch     CHKERRQ(MatView_SeqAIJ_Binary(A,viewer));
11030f5bd95cSBarry Smith   } else if (isdraw) {
11045f80ce2aSJacob Faibussowitsch     CHKERRQ(MatView_SeqAIJ_Draw(A,viewer));
110511aeaf0aSBarry Smith   }
11065f80ce2aSJacob Faibussowitsch   CHKERRQ(MatView_SeqAIJ_Inode(A,viewer));
11073a40ed3dSBarry Smith   PetscFunctionReturn(0);
110817ab2063SBarry Smith }
110919bcc07fSBarry Smith 
1110dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
111117ab2063SBarry Smith {
1112416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1113580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1114d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
111554f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11163447b6efSHong Zhang   PetscReal      ratio  = 0.6;
111717ab2063SBarry Smith 
11183a40ed3dSBarry Smith   PetscFunctionBegin;
11193a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
11205f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(A));
1121b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1122b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
11235f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd_SeqAIJ_Inode(A,mode));
1124b215bc84SStefano Zampini     PetscFunctionReturn(0);
1125b215bc84SStefano Zampini   }
112617ab2063SBarry Smith 
112743ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
112817ab2063SBarry Smith   for (i=1; i<m; i++) {
1129416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
113017ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
113194a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
113217ab2063SBarry Smith     if (fshift) {
1133bfeeae90SHong Zhang       ip = aj + ai[i];
1134bfeeae90SHong Zhang       ap = aa + ai[i];
113517ab2063SBarry Smith       N  = ailen[i];
11365f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraymove(ip-fshift,ip,N));
1137580bdb30SBarry Smith       if (!A->structure_only) {
11385f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscArraymove(ap-fshift,ap,N));
113917ab2063SBarry Smith       }
114017ab2063SBarry Smith     }
114117ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
114217ab2063SBarry Smith   }
114317ab2063SBarry Smith   if (m) {
114417ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
114517ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
114617ab2063SBarry Smith   }
11477b083b7cSBarry Smith 
114817ab2063SBarry Smith   /* reset ilen and imax for each row */
11497b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1150396832f4SHong Zhang   if (A->structure_only) {
11515f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(a->imax));
11525f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(a->ilen));
1153396832f4SHong Zhang   } else { /* !A->structure_only */
115417ab2063SBarry Smith     for (i=0; i<m; i++) {
115517ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
11567b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
115717ab2063SBarry Smith     }
1158396832f4SHong Zhang   }
1159bfeeae90SHong Zhang   a->nz = ai[m];
11602c71b3e2SJacob 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);
116117ab2063SBarry Smith 
11625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMarkDiagonal_SeqAIJ(A));
11635f80ce2aSJacob Faibussowitsch   CHKERRQ(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));
11645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(A,"Number of mallocs during MatSetValues() is %" PetscInt_FMT "\n",a->reallocs));
11655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscInfo(A,"Maximum nonzeros in any row is %" PetscInt_FMT "\n",rmax));
11662205254eSKarl Rupp 
11678e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1168dd5f02e7SSatish Balay   a->reallocs         = 0;
11696712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
117036db0b34SBarry Smith   a->rmax             = rmax;
11714e220ebcSLois Curfman McInnes 
1172396832f4SHong Zhang   if (!A->structure_only) {
11735f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio));
1174396832f4SHong Zhang   }
11755f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd_SeqAIJ_Inode(A,mode));
11763a40ed3dSBarry Smith   PetscFunctionReturn(0);
117717ab2063SBarry Smith }
117817ab2063SBarry Smith 
117999cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
118099cafbc1SBarry Smith {
118199cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
118299cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
11832e5835c6SStefano Zampini   MatScalar      *aa;
118499cafbc1SBarry Smith 
118599cafbc1SBarry Smith   PetscFunctionBegin;
11865f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
118799cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
11885f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
11895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(A));
119099cafbc1SBarry Smith   PetscFunctionReturn(0);
119199cafbc1SBarry Smith }
119299cafbc1SBarry Smith 
119399cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
119499cafbc1SBarry Smith {
119599cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
119699cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
11972e5835c6SStefano Zampini   MatScalar      *aa;
119899cafbc1SBarry Smith 
119999cafbc1SBarry Smith   PetscFunctionBegin;
12005f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
120199cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
12035f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(A));
120499cafbc1SBarry Smith   PetscFunctionReturn(0);
120599cafbc1SBarry Smith }
120699cafbc1SBarry Smith 
1207dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
120817ab2063SBarry Smith {
1209fff043a9SJunchao Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1210fff043a9SJunchao Zhang   MatScalar      *aa;
12113a40ed3dSBarry Smith 
12123a40ed3dSBarry Smith   PetscFunctionBegin;
12135f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayWrite(A,&aa));
12145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(aa,a->i[A->rmap->n]));
12155f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayWrite(A,&aa));
12165f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(A));
12173a40ed3dSBarry Smith   PetscFunctionReturn(0);
121817ab2063SBarry Smith }
1219416022c9SBarry Smith 
1220cbc6b225SStefano Zampini PETSC_INTERN PetscErrorCode MatResetPreallocationCOO_SeqAIJ(Mat A)
1221cbc6b225SStefano Zampini {
1222cbc6b225SStefano Zampini   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1223cbc6b225SStefano Zampini 
1224cbc6b225SStefano Zampini   PetscFunctionBegin;
12255f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->perm));
12265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->jmap));
1227cbc6b225SStefano Zampini   PetscFunctionReturn(0);
1228cbc6b225SStefano Zampini }
1229cbc6b225SStefano Zampini 
1230dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
123117ab2063SBarry Smith {
1232416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1233d5d45c9bSBarry Smith 
12343a40ed3dSBarry Smith   PetscFunctionBegin;
1235aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1236c0aa6a63SJacob Faibussowitsch   PetscLogObjectState((PetscObject)A,"Rows=%" PetscInt_FMT ", Cols=%" PetscInt_FMT ", NZ=%" PetscInt_FMT,A->rmap->n,A->cmap->n,a->nz);
123717ab2063SBarry Smith #endif
12385f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i));
12395f80ce2aSJacob Faibussowitsch   CHKERRQ(MatResetPreallocationCOO_SeqAIJ(A));
12405f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&a->row));
12415f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&a->col));
12425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->diag));
12435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->ibdiag));
12445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->imax));
12455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->ilen));
12465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->ipre));
12475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree3(a->idiag,a->mdiag,a->ssor_work));
12485f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->solve_work));
12495f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&a->icol));
12505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(a->saved_values));
12515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(a->compressedrow.i,a->compressedrow.rindex));
12525f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy_SeqAIJ_Inode(A));
12535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(A->data));
1254901853e0SKris Buschelman 
12556718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
12566718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
12576718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
12586718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
12596718818eSStefano Zampini      due to different matrix sizes */
12605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL));
12616718818eSStefano Zampini 
12625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject)A,NULL));
12635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL));
12645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL));
12655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL));
12665f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL));
12675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL));
12685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL));
12694222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
12705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL));
12715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL));
12725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL));
12734222ddf1SHong Zhang #endif
12743d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
12755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL));
12763d0639e7SStefano Zampini #endif
12775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL));
1278af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
12795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL));
1280af8000cdSHong Zhang #endif
1281d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
12825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL));
1283d24d4204SJose E. Roman #endif
128463c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
12855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL));
12865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL));
128763c07aadSStefano Zampini #endif
12885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL));
12895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL));
12905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL));
12915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL));
12925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL));
12935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL));
12945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL));
12955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL));
12965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL));
12975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL));
12985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL));
12995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL));
13005f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetPreallocationCOO_C",NULL));
13015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)A,"MatSetValuesCOO_C",NULL));
13023a40ed3dSBarry Smith   PetscFunctionReturn(0);
130317ab2063SBarry Smith }
130417ab2063SBarry Smith 
1305ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
130617ab2063SBarry Smith {
1307416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13083a40ed3dSBarry Smith 
13093a40ed3dSBarry Smith   PetscFunctionBegin;
1310a65d3064SKris Buschelman   switch (op) {
1311a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13124e0d8c25SBarry Smith     a->roworiented = flg;
1313a65d3064SKris Buschelman     break;
1314a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1315a9817697SBarry Smith     a->keepnonzeropattern = flg;
1316a65d3064SKris Buschelman     break;
1317512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1318512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1319a65d3064SKris Buschelman     break;
1320a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13214e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1322a65d3064SKris Buschelman     break;
1323a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13244e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1325a65d3064SKris Buschelman     break;
132628b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
132728b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
132828b2fa4aSMatthew Knepley     break;
1329a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13304e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13310df259c2SBarry Smith     break;
13323d472b54SHong Zhang   case MAT_SPD:
1333b1646e73SJed Brown   case MAT_SYMMETRIC:
1334b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1335b1646e73SJed Brown   case MAT_HERMITIAN:
1336b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1337957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13385021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13395021d80fSJed Brown     break;
13408c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1341a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1342a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
13435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(A,"Option %s ignored\n",MatOptions[op]));
1344a65d3064SKris Buschelman     break;
1345b87ac2d8SJed Brown   case MAT_USE_INODES:
13465f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg));
1347b87ac2d8SJed Brown     break;
1348c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1349c10200c1SHong Zhang     A->submat_singleis = flg;
1350c10200c1SHong Zhang     break;
1351071fcb05SBarry Smith   case MAT_SORTED_FULL:
1352071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1353071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1354071fcb05SBarry Smith     break;
13551a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
13561a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
13571a2c6b5cSJunchao Zhang     break;
1358a65d3064SKris Buschelman   default:
135998921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1360a65d3064SKris Buschelman   }
13613a40ed3dSBarry Smith   PetscFunctionReturn(0);
136217ab2063SBarry Smith }
136317ab2063SBarry Smith 
1364dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
136517ab2063SBarry Smith {
1366416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1367fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1368c898d852SStefano Zampini   PetscScalar       *x;
1369c898d852SStefano Zampini   const PetscScalar *aa;
137017ab2063SBarry Smith 
13713a40ed3dSBarry Smith   PetscFunctionBegin;
13725f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(v,&n));
13732c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
13745f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
1375d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1376d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
13775f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayWrite(v,&x));
13782c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
13795f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayWrite(v,&x));
13805f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
138135e7444dSHong Zhang     PetscFunctionReturn(0);
138235e7444dSHong Zhang   }
138335e7444dSHong Zhang 
13845f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(v,&x));
138535e7444dSHong Zhang   for (i=0; i<n; i++) {
1386fdc842d1SBarry Smith     x[i] = 0.0;
138735e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
138835e7444dSHong Zhang       if (aj[j] == i) {
138935e7444dSHong Zhang         x[i] = aa[j];
139017ab2063SBarry Smith         break;
139117ab2063SBarry Smith       }
139217ab2063SBarry Smith     }
139317ab2063SBarry Smith   }
13945f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(v,&x));
13955f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
13963a40ed3dSBarry Smith   PetscFunctionReturn(0);
139717ab2063SBarry Smith }
139817ab2063SBarry Smith 
1399c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1400dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
140117ab2063SBarry Smith {
1402416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14035f22a7b3SSebastian Grimberg   const MatScalar   *aa;
1404d9ca1df4SBarry Smith   PetscScalar       *y;
1405d9ca1df4SBarry Smith   const PetscScalar *x;
1406d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14075c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
14085f22a7b3SSebastian Grimberg   const MatScalar   *v;
1409a77337e4SBarry Smith   PetscScalar       alpha;
1410d9ca1df4SBarry Smith   PetscInt          n,i,j;
1411d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14123447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1413ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14145c897100SBarry Smith #endif
141517ab2063SBarry Smith 
14163a40ed3dSBarry Smith   PetscFunctionBegin;
14175f80ce2aSJacob Faibussowitsch   if (zz != yy) CHKERRQ(VecCopy(zz,yy));
14185f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(xx,&x));
14195f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(yy,&y));
14205f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
14215c897100SBarry Smith 
14225c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1423fff043a9SJunchao Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,aa,y);
14245c897100SBarry Smith #else
14253447b6efSHong Zhang   if (usecprow) {
14263447b6efSHong Zhang     m    = cprow.nrows;
14273447b6efSHong Zhang     ii   = cprow.i;
14287b2bb3b9SHong Zhang     ridx = cprow.rindex;
14293447b6efSHong Zhang   } else {
14303447b6efSHong Zhang     ii = a->i;
14313447b6efSHong Zhang   }
143217ab2063SBarry Smith   for (i=0; i<m; i++) {
14333447b6efSHong Zhang     idx = a->j + ii[i];
1434fff043a9SJunchao Zhang     v   = aa + ii[i];
14353447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14363447b6efSHong Zhang     if (usecprow) {
14377b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14383447b6efSHong Zhang     } else {
143917ab2063SBarry Smith       alpha = x[i];
14403447b6efSHong Zhang     }
144104fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
144217ab2063SBarry Smith   }
14435c897100SBarry Smith #endif
14445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogFlops(2.0*a->nz));
14455f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(xx,&x));
14465f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(yy,&y));
14475f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
14483a40ed3dSBarry Smith   PetscFunctionReturn(0);
144917ab2063SBarry Smith }
145017ab2063SBarry Smith 
1451dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14525c897100SBarry Smith {
14535c897100SBarry Smith   PetscFunctionBegin;
14545f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(yy,0.0));
14555f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy));
14565c897100SBarry Smith   PetscFunctionReturn(0);
14575c897100SBarry Smith }
14585c897100SBarry Smith 
1459c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
146078b84d54SShri Abhyankar 
1461dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
146217ab2063SBarry Smith {
1463416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1464d9fead3dSBarry Smith   PetscScalar       *y;
146554f21887SBarry Smith   const PetscScalar *x;
1466fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1467003131ecSBarry Smith   PetscInt          m=A->rmap->n;
14680298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
14697b083b7cSBarry Smith   PetscInt          n,i;
1470362ced78SSatish Balay   PetscScalar       sum;
1471ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
147217ab2063SBarry Smith 
1473b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
147497952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1475fee21e36SBarry Smith #endif
1476fee21e36SBarry Smith 
14773a40ed3dSBarry Smith   PetscFunctionBegin;
1478b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
14795f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMult_SeqAIJ_Inode(A,xx,yy));
1480b215bc84SStefano Zampini     PetscFunctionReturn(0);
1481b215bc84SStefano Zampini   }
14825f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&a_a));
14835f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(xx,&x));
14845f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(yy,&y));
1485416022c9SBarry Smith   ii   = a->i;
14864eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
14875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(y,m));
148897952fefSHong Zhang     m    = a->compressedrow.nrows;
148997952fefSHong Zhang     ii   = a->compressedrow.i;
149097952fefSHong Zhang     ridx = a->compressedrow.rindex;
149197952fefSHong Zhang     for (i=0; i<m; i++) {
149297952fefSHong Zhang       n           = ii[i+1] - ii[i];
149397952fefSHong Zhang       aj          = a->j + ii[i];
1494fff043a9SJunchao Zhang       aa          = a_a + ii[i];
149597952fefSHong Zhang       sum         = 0.0;
1496003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1497003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
149897952fefSHong Zhang       y[*ridx++] = sum;
149997952fefSHong Zhang     }
150097952fefSHong Zhang   } else { /* do not use compressed row format */
1501b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15023d3eaba7SBarry Smith     aj   = a->j;
1503fff043a9SJunchao Zhang     aa   = a_a;
1504b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1505b05257ddSBarry Smith #else
150617ab2063SBarry Smith     for (i=0; i<m; i++) {
1507003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1508003131ecSBarry Smith       aj          = a->j + ii[i];
1509fff043a9SJunchao Zhang       aa          = a_a + ii[i];
151017ab2063SBarry Smith       sum         = 0.0;
1511003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
151217ab2063SBarry Smith       y[i] = sum;
151317ab2063SBarry Smith     }
15148d195f9aSBarry Smith #endif
1515b05257ddSBarry Smith   }
15165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogFlops(2.0*a->nz - a->nonzerorowcnt));
15175f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(xx,&x));
15185f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(yy,&y));
15195f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&a_a));
15203a40ed3dSBarry Smith   PetscFunctionReturn(0);
152117ab2063SBarry Smith }
152217ab2063SBarry Smith 
1523b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1524b434eb95SMatthew G. Knepley {
1525b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1526b434eb95SMatthew G. Knepley   PetscScalar       *y;
1527b434eb95SMatthew G. Knepley   const PetscScalar *x;
1528fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1529b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1530b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1531b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1532b434eb95SMatthew G. Knepley   PetscScalar       sum;
1533b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1534b434eb95SMatthew G. Knepley 
1535b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1536b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1537b434eb95SMatthew G. Knepley #endif
1538b434eb95SMatthew G. Knepley 
1539b434eb95SMatthew G. Knepley   PetscFunctionBegin;
15405f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&a_a));
15415f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(xx,&x));
15425f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(yy,&y));
1543b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1544b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1545b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1546b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1547b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1548b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1549b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1550fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1551b434eb95SMatthew G. Knepley       sum         = 0.0;
1552b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1553b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1554b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1555b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1556b434eb95SMatthew G. Knepley     }
1557b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
15583d3eaba7SBarry Smith     ii = a->i;
1559b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1560b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1561b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1562fff043a9SJunchao Zhang       aa          = a_a + ii[i];
1563b434eb95SMatthew G. Knepley       sum         = 0.0;
1564b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1565b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1566b434eb95SMatthew G. Knepley       y[i] = sum;
1567b434eb95SMatthew G. Knepley     }
1568b434eb95SMatthew G. Knepley   }
15695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogFlops(2.0*a->nz - nonzerorow));
15705f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(xx,&x));
15715f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(yy,&y));
15725f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&a_a));
1573b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1574b434eb95SMatthew G. Knepley }
1575b434eb95SMatthew G. Knepley 
1576b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1577b434eb95SMatthew G. Knepley {
1578b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1579b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1580b434eb95SMatthew G. Knepley   const PetscScalar *x;
1581fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1582b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1583b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1584b434eb95SMatthew G. Knepley   PetscScalar       sum;
1585b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1586b434eb95SMatthew G. Knepley 
1587b434eb95SMatthew G. Knepley   PetscFunctionBegin;
15885f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&a_a));
15895f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(xx,&x));
15905f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayPair(yy,zz,&y,&z));
1591b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1592b434eb95SMatthew G. Knepley     if (zz != yy) {
15935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(z,y,m));
1594b434eb95SMatthew G. Knepley     }
1595b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1596b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1597b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1598b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1599b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1600b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1601fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1602b434eb95SMatthew G. Knepley       sum = y[*ridx];
1603b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1604b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1605b434eb95SMatthew G. Knepley     }
1606b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16073d3eaba7SBarry Smith     ii = a->i;
1608b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1609b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1610b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1611fff043a9SJunchao Zhang       aa  = a_a + ii[i];
1612b434eb95SMatthew G. Knepley       sum = y[i];
1613b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1614b434eb95SMatthew G. Knepley       z[i] = sum;
1615b434eb95SMatthew G. Knepley     }
1616b434eb95SMatthew G. Knepley   }
16175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogFlops(2.0*a->nz));
16185f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(xx,&x));
16195f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayPair(yy,zz,&y,&z));
16205f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&a_a));
1621b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1622b434eb95SMatthew G. Knepley }
1623b434eb95SMatthew G. Knepley 
1624c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1625dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
162617ab2063SBarry Smith {
1627416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1628f15663dcSBarry Smith   PetscScalar       *y,*z;
1629f15663dcSBarry Smith   const PetscScalar *x;
1630fff043a9SJunchao Zhang   const MatScalar   *aa,*a_a;
1631d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1632d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1633362ced78SSatish Balay   PetscScalar       sum;
1634ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16359ea0dfa2SSatish Balay 
16363a40ed3dSBarry Smith   PetscFunctionBegin;
1637b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
16385f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz));
1639b215bc84SStefano Zampini     PetscFunctionReturn(0);
1640b215bc84SStefano Zampini   }
16415f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&a_a));
16425f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(xx,&x));
16435f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayPair(yy,zz,&y,&z));
16444eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16454eb6d288SHong Zhang     if (zz != yy) {
16465f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(z,y,m));
16474eb6d288SHong Zhang     }
164897952fefSHong Zhang     m    = a->compressedrow.nrows;
164997952fefSHong Zhang     ii   = a->compressedrow.i;
165097952fefSHong Zhang     ridx = a->compressedrow.rindex;
165197952fefSHong Zhang     for (i=0; i<m; i++) {
165297952fefSHong Zhang       n   = ii[i+1] - ii[i];
165397952fefSHong Zhang       aj  = a->j + ii[i];
1654fff043a9SJunchao Zhang       aa  = a_a + ii[i];
165597952fefSHong Zhang       sum = y[*ridx];
1656f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
165797952fefSHong Zhang       z[*ridx++] = sum;
165897952fefSHong Zhang     }
165997952fefSHong Zhang   } else { /* do not use compressed row format */
16603d3eaba7SBarry Smith     ii = a->i;
1661f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
16623d3eaba7SBarry Smith     aj = a->j;
1663fff043a9SJunchao Zhang     aa = a_a;
1664f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1665f15663dcSBarry Smith #else
166617ab2063SBarry Smith     for (i=0; i<m; i++) {
1667f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1668f15663dcSBarry Smith       aj  = a->j + ii[i];
1669fff043a9SJunchao Zhang       aa  = a_a + ii[i];
167017ab2063SBarry Smith       sum = y[i];
1671f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
167217ab2063SBarry Smith       z[i] = sum;
167317ab2063SBarry Smith     }
167402ab625aSSatish Balay #endif
1675f15663dcSBarry Smith   }
16765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogFlops(2.0*a->nz));
16775f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(xx,&x));
16785f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayPair(yy,zz,&y,&z));
16795f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&a_a));
16803a40ed3dSBarry Smith   PetscFunctionReturn(0);
168117ab2063SBarry Smith }
168217ab2063SBarry Smith 
168317ab2063SBarry Smith /*
168417ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
168517ab2063SBarry Smith */
1686dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
168717ab2063SBarry Smith {
1688416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1689d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
169017ab2063SBarry Smith 
16913a40ed3dSBarry Smith   PetscFunctionBegin;
169209f38230SBarry Smith   if (!a->diag) {
16935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(m,&a->diag));
16945f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt)));
169509f38230SBarry Smith   }
1696d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
169709f38230SBarry Smith     a->diag[i] = a->i[i+1];
1698bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1699bfeeae90SHong Zhang       if (a->j[j] == i) {
170009f38230SBarry Smith         a->diag[i] = j;
170117ab2063SBarry Smith         break;
170217ab2063SBarry Smith       }
170317ab2063SBarry Smith     }
170417ab2063SBarry Smith   }
17053a40ed3dSBarry Smith   PetscFunctionReturn(0);
170617ab2063SBarry Smith }
170717ab2063SBarry Smith 
170861ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
170961ecd0c6SBarry Smith {
171061ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
171161ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
171261ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
171361ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
171461ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
171561ecd0c6SBarry Smith 
171661ecd0c6SBarry Smith   PetscFunctionBegin;
171761ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
17185f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJSetPreallocation(A,1,NULL));
17195f80ce2aSJacob Faibussowitsch     CHKERRQ(MatShift_Basic(A,v));
172061ecd0c6SBarry Smith     PetscFunctionReturn(0);
172161ecd0c6SBarry Smith   }
172261ecd0c6SBarry Smith 
172361ecd0c6SBarry Smith   if (a->diagonaldense) {
172461ecd0c6SBarry Smith     cnt = 0;
172561ecd0c6SBarry Smith   } else {
17265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(A->rmap->n,&mdiag));
172761ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
172861ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
172961ecd0c6SBarry Smith         cnt++;
173061ecd0c6SBarry Smith         mdiag[i] = 1;
173161ecd0c6SBarry Smith       }
173261ecd0c6SBarry Smith     }
173361ecd0c6SBarry Smith   }
173461ecd0c6SBarry Smith   if (!cnt) {
17355f80ce2aSJacob Faibussowitsch     CHKERRQ(MatShift_Basic(A,v));
173661ecd0c6SBarry Smith   } else {
1737b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1738b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
173961ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
174061ecd0c6SBarry Smith 
174161ecd0c6SBarry Smith     a->a = NULL;
174261ecd0c6SBarry Smith     a->j = NULL;
174361ecd0c6SBarry Smith     a->i = NULL;
174461ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
174561ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
174661ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1747447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
174861ecd0c6SBarry Smith     }
17495f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax));
175061ecd0c6SBarry Smith 
175161ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
175261ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
17535f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES));
1754447d62f5SStefano Zampini       if (i < A->cmap->n) {
17555f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetValue(A,i,i,v,ADD_VALUES));
175661ecd0c6SBarry Smith       }
1757447d62f5SStefano Zampini     }
17585f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
17595f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
176061ecd0c6SBarry Smith     if (singlemalloc) {
17615f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree3(olda,oldj,oldi));
176261ecd0c6SBarry Smith     } else {
17635f80ce2aSJacob Faibussowitsch       if (free_a)  CHKERRQ(PetscFree(olda));
17645f80ce2aSJacob Faibussowitsch       if (free_ij) CHKERRQ(PetscFree(oldj));
17655f80ce2aSJacob Faibussowitsch       if (free_ij) CHKERRQ(PetscFree(oldi));
176661ecd0c6SBarry Smith     }
176761ecd0c6SBarry Smith   }
17685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(mdiag));
176961ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
177061ecd0c6SBarry Smith   PetscFunctionReturn(0);
177161ecd0c6SBarry Smith }
177261ecd0c6SBarry Smith 
1773be5855fcSBarry Smith /*
1774be5855fcSBarry Smith      Checks for missing diagonals
1775be5855fcSBarry Smith */
1776ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1777be5855fcSBarry Smith {
1778be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17797734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1780be5855fcSBarry Smith 
1781be5855fcSBarry Smith   PetscFunctionBegin;
178209f38230SBarry Smith   *missing = PETSC_FALSE;
17837734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
178409f38230SBarry Smith     *missing = PETSC_TRUE;
178509f38230SBarry Smith     if (d) *d = 0;
17865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n"));
178709f38230SBarry Smith   } else {
178801445905SHong Zhang     PetscInt n;
178901445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1790f1e2ffcdSBarry Smith     diag = a->diag;
179101445905SHong Zhang     for (i=0; i<n; i++) {
17927734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
179309f38230SBarry Smith         *missing = PETSC_TRUE;
179409f38230SBarry Smith         if (d) *d = i;
17955f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscInfo(A,"Matrix is missing diagonal number %" PetscInt_FMT "\n",i));
1796358d2f5dSShri Abhyankar         break;
179709f38230SBarry Smith       }
1798be5855fcSBarry Smith     }
1799be5855fcSBarry Smith   }
1800be5855fcSBarry Smith   PetscFunctionReturn(0);
1801be5855fcSBarry Smith }
1802be5855fcSBarry Smith 
18030da83c2eSBarry Smith #include <petscblaslapack.h>
18040da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18050da83c2eSBarry Smith 
18060da83c2eSBarry Smith /*
18070da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18080da83c2eSBarry Smith */
18090da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18100da83c2eSBarry Smith {
18110da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18120da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18130da83c2eSBarry Smith   const PetscReal shift = 0.0;
18140da83c2eSBarry Smith   PetscInt        ipvt[5];
18150da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18160da83c2eSBarry Smith 
18170da83c2eSBarry Smith   PetscFunctionBegin;
18180da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18190da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18202c71b3e2SJacob 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);
18210da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18220da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18230da83c2eSBarry Smith   }
18245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(bsizemax,&indx));
18250da83c2eSBarry Smith   if (bsizemax > 7) {
18265f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots));
18270da83c2eSBarry Smith   }
18280da83c2eSBarry Smith   ncnt = 0;
18290da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18300da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18315f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag));
18320da83c2eSBarry Smith     switch (bsizes[i]) {
18330da83c2eSBarry Smith     case 1:
18340da83c2eSBarry Smith       *diag = 1.0/(*diag);
18350da83c2eSBarry Smith       break;
18360da83c2eSBarry Smith     case 2:
18375f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected));
18380da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18395f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_2(diag));
18400da83c2eSBarry Smith       break;
18410da83c2eSBarry Smith     case 3:
18425f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected));
18430da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18445f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_3(diag));
18450da83c2eSBarry Smith       break;
18460da83c2eSBarry Smith     case 4:
18475f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected));
18480da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18495f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_4(diag));
18500da83c2eSBarry Smith       break;
18510da83c2eSBarry Smith     case 5:
18525f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected));
18530da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18545f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_5(diag));
18550da83c2eSBarry Smith       break;
18560da83c2eSBarry Smith     case 6:
18575f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected));
18580da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_6(diag));
18600da83c2eSBarry Smith       break;
18610da83c2eSBarry Smith     case 7:
18625f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected));
18630da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18645f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_7(diag));
18650da83c2eSBarry Smith       break;
18660da83c2eSBarry Smith     default:
18675f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected));
18680da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18695f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]));
18700da83c2eSBarry Smith     }
18710da83c2eSBarry Smith     ncnt   += bsizes[i];
18720da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
18730da83c2eSBarry Smith   }
18740da83c2eSBarry Smith   if (bsizemax > 7) {
18755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(v_work,v_pivots));
18760da83c2eSBarry Smith   }
18775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(indx));
18780da83c2eSBarry Smith   PetscFunctionReturn(0);
18790da83c2eSBarry Smith }
18800da83c2eSBarry Smith 
1881422a814eSBarry Smith /*
1882422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1883422a814eSBarry Smith */
18847087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
188571f1c65dSBarry Smith {
188671f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
1887d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
18882e5835c6SStefano Zampini   const MatScalar *v;
188954f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
189071f1c65dSBarry Smith 
189171f1c65dSBarry Smith   PetscFunctionBegin;
189271f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
18935f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMarkDiagonal_SeqAIJ(A));
189471f1c65dSBarry Smith   diag = a->diag;
189571f1c65dSBarry Smith   if (!a->idiag) {
18965f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work));
18975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar)));
189871f1c65dSBarry Smith   }
18992e5835c6SStefano Zampini 
190071f1c65dSBarry Smith   mdiag = a->mdiag;
190171f1c65dSBarry Smith   idiag = a->idiag;
19025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&v));
1903422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
190471f1c65dSBarry Smith     for (i=0; i<m; i++) {
190571f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1906899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1907899639b0SHong Zhang         if (PetscRealPart(fshift)) {
19085f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscInfo(A,"Zero diagonal on row %" PetscInt_FMT "\n",i));
19097b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19107b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19117b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
191298921bdaSJacob Faibussowitsch         } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %" PetscInt_FMT,i);
1913899639b0SHong Zhang       }
191471f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
191571f1c65dSBarry Smith     }
19165f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(m));
191771f1c65dSBarry Smith   } else {
191871f1c65dSBarry Smith     for (i=0; i<m; i++) {
191971f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
192071f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
192171f1c65dSBarry Smith     }
19225f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(2.0*m));
192371f1c65dSBarry Smith   }
192471f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&v));
192671f1c65dSBarry Smith   PetscFunctionReturn(0);
192771f1c65dSBarry Smith }
192871f1c65dSBarry Smith 
1929c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
193041f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
193117ab2063SBarry Smith {
1932416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1933e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19342e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
193554f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
19363d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
193797f1f81fSBarry Smith   const PetscInt    *idx,*diag;
193817ab2063SBarry Smith 
19393a40ed3dSBarry Smith   PetscFunctionBegin;
1940b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
19415f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx));
1942b215bc84SStefano Zampini     PetscFunctionReturn(0);
1943b215bc84SStefano Zampini   }
1944b965ef7fSBarry Smith   its = its*lits;
194591723122SBarry Smith 
194671f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
19475f80ce2aSJacob Faibussowitsch   if (!a->idiagvalid) CHKERRQ(MatInvertDiagonal_SeqAIJ(A,omega,fshift));
194871f1c65dSBarry Smith   a->fshift = fshift;
194971f1c65dSBarry Smith   a->omega  = omega;
1950ed480e8bSBarry Smith 
195171f1c65dSBarry Smith   diag  = a->diag;
195271f1c65dSBarry Smith   t     = a->ssor_work;
1953ed480e8bSBarry Smith   idiag = a->idiag;
195471f1c65dSBarry Smith   mdiag = a->mdiag;
1955ed480e8bSBarry Smith 
19565f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
19575f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(xx,&x));
19585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(bb,&b));
1959ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
196017ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
196117ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
1962ed480e8bSBarry Smith     bs = b;
196317ab2063SBarry Smith     for (i=0; i<m; i++) {
196471f1c65dSBarry Smith       d   = fshift + mdiag[i];
1965416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1966ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
19672e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
196817ab2063SBarry Smith       sum = b[i]*d/omega;
1969003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
197017ab2063SBarry Smith       x[i] = sum;
197117ab2063SBarry Smith     }
19725f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(xx,&x));
19735f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(bb,&b));
19745f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
19755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(a->nz));
19763a40ed3dSBarry Smith     PetscFunctionReturn(0);
197717ab2063SBarry Smith   }
1978c783ea89SBarry Smith 
19792c71b3e2SJacob Faibussowitsch   PetscCheckFalse(flag == SOR_APPLY_LOWER,PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
19802205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
19814c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
1982887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
198317ab2063SBarry Smith 
198417ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
198517ab2063SBarry Smith 
1986887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
198717ab2063SBarry Smith     */
198817ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
198917ab2063SBarry Smith 
199017ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
199117ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
1992416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
1993ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
19942e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
199517ab2063SBarry Smith       sum = b[i];
1996e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
1997ed480e8bSBarry Smith       x[i] = sum*idiag[i];
199817ab2063SBarry Smith     }
199917ab2063SBarry Smith 
200017ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20012e5835c6SStefano Zampini     v = aa;
20022205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
200317ab2063SBarry Smith 
200417ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2005ed480e8bSBarry Smith     ts   = t;
2006416022c9SBarry Smith     diag = a->diag;
200717ab2063SBarry Smith     for (i=0; i<m; i++) {
2008416022c9SBarry Smith       n   = diag[i] - a->i[i];
2009ed480e8bSBarry Smith       idx = a->j + a->i[i];
20102e5835c6SStefano Zampini       v   = aa + a->i[i];
201117ab2063SBarry Smith       sum = t[i];
2012003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2013ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2014733d66baSBarry Smith       /*  x = x + t */
2015733d66baSBarry Smith       x[i] += t[i];
201617ab2063SBarry Smith     }
201717ab2063SBarry Smith 
20185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(6.0*m-1 + 2.0*a->nz));
20195f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(xx,&x));
20205f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(bb,&b));
20213a40ed3dSBarry Smith     PetscFunctionReturn(0);
202217ab2063SBarry Smith   }
202317ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
202417ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
202517ab2063SBarry Smith       for (i=0; i<m; i++) {
2026416022c9SBarry Smith         n   = diag[i] - a->i[i];
2027ed480e8bSBarry Smith         idx = a->j + a->i[i];
20282e5835c6SStefano Zampini         v   = aa + a->i[i];
202917ab2063SBarry Smith         sum = b[i];
2030e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20315c99c7daSBarry Smith         t[i] = sum;
2032ed480e8bSBarry Smith         x[i] = sum*idiag[i];
203317ab2063SBarry Smith       }
20345c99c7daSBarry Smith       xb   = t;
20355f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogFlops(a->nz));
20363a40ed3dSBarry Smith     } else xb = b;
203717ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
203817ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2039416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2040ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20412e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
204217ab2063SBarry Smith         sum = xb[i];
2043e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20445c99c7daSBarry Smith         if (xb == b) {
2045ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20465c99c7daSBarry Smith         } else {
2047b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
204817ab2063SBarry Smith         }
20495c99c7daSBarry Smith       }
20505f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
205117ab2063SBarry Smith     }
205217ab2063SBarry Smith     its--;
205317ab2063SBarry Smith   }
205417ab2063SBarry Smith   while (its--) {
205517ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
205617ab2063SBarry Smith       for (i=0; i<m; i++) {
2057b19a5dc2SMark Adams         /* lower */
2058b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2059ed480e8bSBarry Smith         idx = a->j + a->i[i];
20602e5835c6SStefano Zampini         v   = aa + a->i[i];
206117ab2063SBarry Smith         sum = b[i];
2062e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2063b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2064b19a5dc2SMark Adams         /* upper */
2065b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2066b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
20672e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2068b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2069b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
207017ab2063SBarry Smith       }
2071b19a5dc2SMark Adams       xb   = t;
20725f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogFlops(2.0*a->nz));
2073b19a5dc2SMark Adams     } else xb = b;
207417ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
207517ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2076b19a5dc2SMark Adams         sum = xb[i];
2077b19a5dc2SMark Adams         if (xb == b) {
2078b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2079416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2080ed480e8bSBarry Smith           idx = a->j + a->i[i];
20812e5835c6SStefano Zampini           v   = aa + a->i[i];
2082e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2083ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2084b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2085b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2086b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
20872e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2088b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2089b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
209017ab2063SBarry Smith         }
2091b19a5dc2SMark Adams       }
2092b19a5dc2SMark Adams       if (xb == b) {
20935f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscLogFlops(2.0*a->nz));
2094b19a5dc2SMark Adams       } else {
20955f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscLogFlops(a->nz)); /* assumes 1/2 in upper */
2096b19a5dc2SMark Adams       }
209717ab2063SBarry Smith     }
209817ab2063SBarry Smith   }
20995f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
21005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(xx,&x));
21015f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(bb,&b));
2102365a8a9eSBarry Smith   PetscFunctionReturn(0);
210317ab2063SBarry Smith }
210417ab2063SBarry Smith 
2105dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
210617ab2063SBarry Smith {
2107416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21084e220ebcSLois Curfman McInnes 
21093a40ed3dSBarry Smith   PetscFunctionBegin;
21104e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21113966268fSBarry Smith   info->nz_allocated = a->maxnz;
21123966268fSBarry Smith   info->nz_used      = a->nz;
21133966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21143966268fSBarry Smith   info->assemblies   = A->num_ass;
21153966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21167adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2117d5f3da31SBarry Smith   if (A->factortype) {
21184e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21194e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21204e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21214e220ebcSLois Curfman McInnes   } else {
21224e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21234e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21244e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21254e220ebcSLois Curfman McInnes   }
21263a40ed3dSBarry Smith   PetscFunctionReturn(0);
212717ab2063SBarry Smith }
212817ab2063SBarry Smith 
21292b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
213017ab2063SBarry Smith {
2131416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2132c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
213397b48c8fSBarry Smith   const PetscScalar *xx;
21342e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2135c7da8527SEric Chamberland   PetscInt          d = 0;
213617ab2063SBarry Smith 
21373a40ed3dSBarry Smith   PetscFunctionBegin;
213897b48c8fSBarry Smith   if (x && b) {
21395f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(x,&xx));
21405f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(b,&bb));
214197b48c8fSBarry Smith     for (i=0; i<N; i++) {
21422c71b3e2SJacob Faibussowitsch       PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2143447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
214497b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
214597b48c8fSBarry Smith     }
21465f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(x,&xx));
21475f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(b,&bb));
214897b48c8fSBarry Smith   }
214997b48c8fSBarry Smith 
21505f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
2151a9817697SBarry Smith   if (a->keepnonzeropattern) {
2152f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
21532c71b3e2SJacob Faibussowitsch       PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
21545f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]));
2155f1e2ffcdSBarry Smith     }
2156f4df32b1SMatthew Knepley     if (diag != 0.0) {
2157c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2158c7da8527SEric Chamberland         d = rows[i];
2159447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
21602c71b3e2SJacob 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);
2161c7da8527SEric Chamberland       }
2162f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2163447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
21642e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2165f1e2ffcdSBarry Smith       }
2166f1e2ffcdSBarry Smith     }
2167f1e2ffcdSBarry Smith   } else {
2168f4df32b1SMatthew Knepley     if (diag != 0.0) {
216917ab2063SBarry Smith       for (i=0; i<N; i++) {
21702c71b3e2SJacob Faibussowitsch         PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
21717ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2172447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2173447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2174447d62f5SStefano Zampini           } else {
2175416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
21762e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2177bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2178447d62f5SStefano Zampini           }
2179447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
21805f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES));
218117ab2063SBarry Smith         }
218217ab2063SBarry Smith       }
21833a40ed3dSBarry Smith     } else {
218417ab2063SBarry Smith       for (i=0; i<N; i++) {
21852c71b3e2SJacob Faibussowitsch         PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
2186416022c9SBarry Smith         a->ilen[rows[i]] = 0;
218717ab2063SBarry Smith       }
218817ab2063SBarry Smith     }
2189e56f5c9eSBarry Smith     A->nonzerostate++;
2190f1e2ffcdSBarry Smith   }
21915f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
21925f80ce2aSJacob Faibussowitsch   CHKERRQ((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY));
21933a40ed3dSBarry Smith   PetscFunctionReturn(0);
219417ab2063SBarry Smith }
219517ab2063SBarry Smith 
21966e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
21976e169961SBarry Smith {
21986e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
21996e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22002b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22016e169961SBarry Smith   const PetscScalar *xx;
22022e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22036e169961SBarry Smith 
22046e169961SBarry Smith   PetscFunctionBegin;
22052e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22065f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&aa));
22076e169961SBarry Smith   if (x && b) {
22085f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(x,&xx));
22095f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(b,&bb));
22102b40b63fSBarry Smith     vecs = PETSC_TRUE;
22116e169961SBarry Smith   }
22125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(A->rmap->n,&zeroed));
22136e169961SBarry Smith   for (i=0; i<N; i++) {
22142c71b3e2SJacob Faibussowitsch     PetscCheckFalse(rows[i] < 0 || rows[i] > m,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %" PetscInt_FMT " out of range", rows[i]);
22155f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]));
22162205254eSKarl Rupp 
22176e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22186e169961SBarry Smith   }
22196e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22206e169961SBarry Smith     if (!zeroed[i]) {
22216e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22224cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22232e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22242e5835c6SStefano Zampini           aa[j] = 0.0;
22256e169961SBarry Smith         }
22266e169961SBarry Smith       }
22274cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22286e169961SBarry Smith   }
22296e169961SBarry Smith   if (x && b) {
22305f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(x,&xx));
22315f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(b,&bb));
22326e169961SBarry Smith   }
22335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(zeroed));
22346e169961SBarry Smith   if (diag != 0.0) {
22355f80ce2aSJacob Faibussowitsch     CHKERRQ(MatMissingDiagonal_SeqAIJ(A,&missing,&d));
22361d5a398dSstefano_zampini     if (missing) {
22371d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22384cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22392c71b3e2SJacob 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]);
22405f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES));
22411d5a398dSstefano_zampini       }
22421d5a398dSstefano_zampini     } else {
22436e169961SBarry Smith       for (i=0; i<N; i++) {
22442e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
22456e169961SBarry Smith       }
22466e169961SBarry Smith     }
22471d5a398dSstefano_zampini   }
22485f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&aa));
22495f80ce2aSJacob Faibussowitsch   CHKERRQ((*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY));
22506e169961SBarry Smith   PetscFunctionReturn(0);
22516e169961SBarry Smith }
22526e169961SBarry Smith 
2253a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
225417ab2063SBarry Smith {
2255fff043a9SJunchao Zhang   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2256fff043a9SJunchao Zhang   const PetscScalar *aa;
2257fff043a9SJunchao Zhang   PetscInt          *itmp;
225817ab2063SBarry Smith 
22593a40ed3dSBarry Smith   PetscFunctionBegin;
22605f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
2261416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
22622e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
226317ab2063SBarry Smith   if (idx) {
2264bfeeae90SHong Zhang     itmp = a->j + a->i[row];
226526fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2266f4259b30SLisandro Dalcin     else *idx = NULL;
226717ab2063SBarry Smith   }
22685f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
22693a40ed3dSBarry Smith   PetscFunctionReturn(0);
227017ab2063SBarry Smith }
227117ab2063SBarry Smith 
2272a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
227317ab2063SBarry Smith {
22743a40ed3dSBarry Smith   PetscFunctionBegin;
2275cb4a9cd9SHong Zhang   if (nz)  *nz = 0;
22762e5835c6SStefano Zampini   if (idx) *idx = NULL;
22772e5835c6SStefano Zampini   if (v)   *v = NULL;
22783a40ed3dSBarry Smith   PetscFunctionReturn(0);
227917ab2063SBarry Smith }
228017ab2063SBarry Smith 
2281dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
228217ab2063SBarry Smith {
2283416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
22842e5835c6SStefano Zampini   const MatScalar *v;
228536db0b34SBarry Smith   PetscReal       sum = 0.0;
228697f1f81fSBarry Smith   PetscInt        i,j;
228717ab2063SBarry Smith 
22883a40ed3dSBarry Smith   PetscFunctionBegin;
22895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&v));
229017ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2291570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2292570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
229373cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2294570b7f6dSBarry Smith #else
2295416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
229636db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
229717ab2063SBarry Smith     }
22988f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2299570b7f6dSBarry Smith #endif
23005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(2.0*a->nz));
23013a40ed3dSBarry Smith   } else if (type == NORM_1) {
230236db0b34SBarry Smith     PetscReal *tmp;
230397f1f81fSBarry Smith     PetscInt  *jj = a->j;
23045f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(A->cmap->n+1,&tmp));
2305064f8208SBarry Smith     *nrm = 0.0;
2306416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2307bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
230817ab2063SBarry Smith     }
2309d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2310064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
231117ab2063SBarry Smith     }
23125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(tmp));
23135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(PetscMax(a->nz-1,0)));
23143a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2315064f8208SBarry Smith     *nrm = 0.0;
2316d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23172e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
231817ab2063SBarry Smith       sum = 0.0;
2319416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23202e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
232117ab2063SBarry Smith       }
2322064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
232317ab2063SBarry Smith     }
23245f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(PetscMax(a->nz-1,0)));
2325f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23265f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&v));
23273a40ed3dSBarry Smith   PetscFunctionReturn(0);
232817ab2063SBarry Smith }
232917ab2063SBarry Smith 
23304e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
23314e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
23324e938277SHong Zhang {
23334e938277SHong Zhang   PetscInt       i,j,anzj;
23344e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
23354e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
23364e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
23374e938277SHong Zhang 
23384e938277SHong Zhang   PetscFunctionBegin;
23394e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
23405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(an+1,&ati));
23415f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(ai[am],&atj));
23425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(an,&atfill));
23434e938277SHong Zhang 
23444e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
23454e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
234626fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
23474e938277SHong Zhang   /* Form ati for csr format of A^T. */
234826fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
23494e938277SHong Zhang 
23504e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
23515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(atfill,ati,an));
23524e938277SHong Zhang 
23534e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
23544e938277SHong Zhang   for (i=0;i<am;i++) {
23554e938277SHong Zhang     anzj = ai[i+1] - ai[i];
23564e938277SHong Zhang     for (j=0;j<anzj;j++) {
23574e938277SHong Zhang       atj[atfill[*aj]] = i;
23584e938277SHong Zhang       atfill[*aj++]   += 1;
23594e938277SHong Zhang     }
23604e938277SHong Zhang   }
23614e938277SHong Zhang 
23624e938277SHong Zhang   /* Clean up temporary space and complete requests. */
23635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(atfill));
23645f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B));
23655f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs)));
23665f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*B,((PetscObject)A)->type_name));
2367a2f3521dSMark F. Adams 
23684e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
23694e938277SHong Zhang   b->free_a  = PETSC_FALSE;
23704e938277SHong Zhang   b->free_ij = PETSC_TRUE;
23714e938277SHong Zhang   b->nonew   = 0;
23724e938277SHong Zhang   PetscFunctionReturn(0);
23734e938277SHong Zhang }
23744e938277SHong Zhang 
23757087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2376cd0d46ebSvictorle {
23773d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
237854f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
23792e5835c6SStefano Zampini   const MatScalar *va,*vb;
238097f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2381cd0d46ebSvictorle 
2382cd0d46ebSvictorle   PetscFunctionBegin;
23835f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,&ma,&na));
23845f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(B,&mb,&nb));
23855485867bSBarry Smith   if (ma!=nb || na!=mb) {
23865485867bSBarry Smith     *f = PETSC_FALSE;
23875485867bSBarry Smith     PetscFunctionReturn(0);
23885485867bSBarry Smith   }
23895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&va));
23905f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(B,&vb));
2391cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2392cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
23935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(ma,&aptr));
23945f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(mb,&bptr));
2395cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2396cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2397cd0d46ebSvictorle 
2398cd0d46ebSvictorle   *f = PETSC_TRUE;
2399cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2400cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
240197f1f81fSBarry Smith       PetscInt    idc,idr;
24025485867bSBarry Smith       PetscScalar vc,vr;
2403cd0d46ebSvictorle       /* column/row index/value */
24045485867bSBarry Smith       idc = adx[aptr[i]];
24055485867bSBarry Smith       idr = bdx[bptr[idc]];
24065485867bSBarry Smith       vc  = va[aptr[i]];
24075485867bSBarry Smith       vr  = vb[bptr[idc]];
24085485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24095485867bSBarry Smith         *f = PETSC_FALSE;
24105485867bSBarry Smith         goto done;
2411cd0d46ebSvictorle       } else {
24125485867bSBarry Smith         aptr[i]++;
24135485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2414cd0d46ebSvictorle       }
2415cd0d46ebSvictorle     }
2416cd0d46ebSvictorle   }
2417cd0d46ebSvictorle done:
24185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(aptr));
24195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(bptr));
24205f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&va));
24215f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(B,&vb));
2422cd0d46ebSvictorle   PetscFunctionReturn(0);
2423cd0d46ebSvictorle }
2424cd0d46ebSvictorle 
24257087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
24261cbb95d3SBarry Smith {
24273d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
242854f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
242954f21887SBarry Smith   MatScalar      *va,*vb;
24301cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
24311cbb95d3SBarry Smith 
24321cbb95d3SBarry Smith   PetscFunctionBegin;
24335f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(A,&ma,&na));
24345f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(B,&mb,&nb));
24351cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
24361cbb95d3SBarry Smith     *f = PETSC_FALSE;
24371cbb95d3SBarry Smith     PetscFunctionReturn(0);
24381cbb95d3SBarry Smith   }
24391cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
24401cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
24411cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
24425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(ma,&aptr));
24435f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(mb,&bptr));
24441cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
24451cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
24461cbb95d3SBarry Smith 
24471cbb95d3SBarry Smith   *f = PETSC_TRUE;
24481cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
24491cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
24501cbb95d3SBarry Smith       PetscInt    idc,idr;
24511cbb95d3SBarry Smith       PetscScalar vc,vr;
24521cbb95d3SBarry Smith       /* column/row index/value */
24531cbb95d3SBarry Smith       idc = adx[aptr[i]];
24541cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
24551cbb95d3SBarry Smith       vc  = va[aptr[i]];
24561cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
24571cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
24581cbb95d3SBarry Smith         *f = PETSC_FALSE;
24591cbb95d3SBarry Smith         goto done;
24601cbb95d3SBarry Smith       } else {
24611cbb95d3SBarry Smith         aptr[i]++;
24621cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
24631cbb95d3SBarry Smith       }
24641cbb95d3SBarry Smith     }
24651cbb95d3SBarry Smith   }
24661cbb95d3SBarry Smith done:
24675f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(aptr));
24685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(bptr));
24691cbb95d3SBarry Smith   PetscFunctionReturn(0);
24701cbb95d3SBarry Smith }
24711cbb95d3SBarry Smith 
2472ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24739e29f15eSvictorle {
24749e29f15eSvictorle   PetscFunctionBegin;
24755f80ce2aSJacob Faibussowitsch   CHKERRQ(MatIsTranspose_SeqAIJ(A,A,tol,f));
24769e29f15eSvictorle   PetscFunctionReturn(0);
24779e29f15eSvictorle }
24789e29f15eSvictorle 
2479ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
24801cbb95d3SBarry Smith {
24811cbb95d3SBarry Smith   PetscFunctionBegin;
24825f80ce2aSJacob Faibussowitsch   CHKERRQ(MatIsHermitianTranspose_SeqAIJ(A,A,tol,f));
24831cbb95d3SBarry Smith   PetscFunctionReturn(0);
24841cbb95d3SBarry Smith }
24851cbb95d3SBarry Smith 
2486dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
248717ab2063SBarry Smith {
2488416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2489fff8e43fSBarry Smith   const PetscScalar *l,*r;
2490fff8e43fSBarry Smith   PetscScalar       x;
249154f21887SBarry Smith   MatScalar         *v;
2492fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2493fff8e43fSBarry Smith   const PetscInt    *jj;
249417ab2063SBarry Smith 
24953a40ed3dSBarry Smith   PetscFunctionBegin;
249617ab2063SBarry Smith   if (ll) {
24973ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
24983ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
24995f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(ll,&m));
25002c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
25015f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(ll,&l));
25025f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArray(A,&v));
250317ab2063SBarry Smith     for (i=0; i<m; i++) {
250417ab2063SBarry Smith       x = l[i];
2505416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25062205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
250717ab2063SBarry Smith     }
25085f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(ll,&l));
25095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(nz));
25105f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArray(A,&v));
251117ab2063SBarry Smith   }
251217ab2063SBarry Smith   if (rr) {
25135f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetLocalSize(rr,&n));
25142c71b3e2SJacob Faibussowitsch     PetscCheckFalse(n != A->cmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
25155f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(rr,&r));
25165f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArray(A,&v));
25172e5835c6SStefano Zampini     jj = a->j;
25182205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
25195f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArray(A,&v));
25205f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(rr,&r));
25215f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(nz));
252217ab2063SBarry Smith   }
25235f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(A));
25243a40ed3dSBarry Smith   PetscFunctionReturn(0);
252517ab2063SBarry Smith }
252617ab2063SBarry Smith 
25277dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
252817ab2063SBarry Smith {
2529db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
2530d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
253197f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
25325d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
25332e5835c6SStefano Zampini   const PetscScalar *aa;
25345d0c19d7SBarry Smith   PetscInt          nrows,ncols;
253597f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
253654f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2537416022c9SBarry Smith   Mat               C;
2538cdc6f3adSToby Isaac   PetscBool         stride;
253917ab2063SBarry Smith 
25403a40ed3dSBarry Smith   PetscFunctionBegin;
25415f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(isrow,&irow));
25425f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(isrow,&nrows));
25435f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetLocalSize(iscol,&ncols));
254417ab2063SBarry Smith 
25455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride));
2546ff718158SBarry Smith   if (stride) {
25475f80ce2aSJacob Faibussowitsch     CHKERRQ(ISStrideGetInfo(iscol,&first,&step));
2548ff718158SBarry Smith   } else {
2549ff718158SBarry Smith     first = 0;
2550ff718158SBarry Smith     step  = 0;
2551ff718158SBarry Smith   }
2552fee21e36SBarry Smith   if (stride && step == 1) {
255302834360SBarry Smith     /* special case of contiguous rows */
25545f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(nrows,&lens,nrows,&starts));
255502834360SBarry Smith     /* loop over new rows determining lens and starting points */
255602834360SBarry Smith     for (i=0; i<nrows; i++) {
2557bfeeae90SHong Zhang       kstart = ai[irow[i]];
2558a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2559a91a9bebSLisandro Dalcin       starts[i] = kstart;
256002834360SBarry Smith       for (k=kstart; k<kend; k++) {
2561bfeeae90SHong Zhang         if (aj[k] >= first) {
256202834360SBarry Smith           starts[i] = k;
256302834360SBarry Smith           break;
256402834360SBarry Smith         }
256502834360SBarry Smith       }
2566a2744918SBarry Smith       sum = 0;
256702834360SBarry Smith       while (k < kend) {
2568bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2569a2744918SBarry Smith         sum++;
257002834360SBarry Smith       }
2571a2744918SBarry Smith       lens[i] = sum;
257202834360SBarry Smith     }
257302834360SBarry Smith     /* create submatrix */
2574cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
257597f1f81fSBarry Smith       PetscInt n_cols,n_rows;
25765f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetSize(*B,&n_rows,&n_cols));
25772c71b3e2SJacob Faibussowitsch       PetscCheckFalse(n_rows != nrows || n_cols != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
25785f80ce2aSJacob Faibussowitsch       CHKERRQ(MatZeroEntries(*B));
257908480c60SBarry Smith       C    = *B;
25803a40ed3dSBarry Smith     } else {
25813bef6203SJed Brown       PetscInt rbs,cbs;
25825f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),&C));
25835f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE));
25845f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetBlockSize(isrow,&rbs));
25855f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetBlockSize(iscol,&cbs));
25865f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetBlockSizes(C,rbs,cbs));
25875f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetType(C,((PetscObject)A)->type_name));
25885f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens));
258908480c60SBarry Smith     }
2590db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2591db02288aSLois Curfman McInnes 
259202834360SBarry Smith     /* loop over rows inserting into submatrix */
2593db02288aSLois Curfman McInnes     a_new = c->a;
2594db02288aSLois Curfman McInnes     j_new = c->j;
2595db02288aSLois Curfman McInnes     i_new = c->i;
25965f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
259702834360SBarry Smith     for (i=0; i<nrows; i++) {
2598a2744918SBarry Smith       ii    = starts[i];
2599a2744918SBarry Smith       lensi = lens[i];
2600a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2601a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
260202834360SBarry Smith       }
26035f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(a_new,aa + starts[i],lensi));
2604a2744918SBarry Smith       a_new     += lensi;
2605a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2606a2744918SBarry Smith       c->ilen[i] = lensi;
260702834360SBarry Smith     }
26085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
26095f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(lens,starts));
26103a40ed3dSBarry Smith   } else {
26115f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(iscol,&icol));
26125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(oldcols,&smap));
26135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(1+nrows,&lens));
26144dcab191SBarry Smith     for (i=0; i<ncols; i++) {
26156bdcaf15SBarry Smith       PetscCheck(icol[i] < oldcols,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%" PetscInt_FMT "] %" PetscInt_FMT " >= A->cmap->n %" PetscInt_FMT,i,icol[i],oldcols);
26164dcab191SBarry Smith       smap[icol[i]] = i+1;
26174dcab191SBarry Smith     }
26184dcab191SBarry Smith 
261902834360SBarry Smith     /* determine lens of each row */
262002834360SBarry Smith     for (i=0; i<nrows; i++) {
2621bfeeae90SHong Zhang       kstart  = ai[irow[i]];
262202834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
262302834360SBarry Smith       lens[i] = 0;
262402834360SBarry Smith       for (k=kstart; k<kend; k++) {
2625bfeeae90SHong Zhang         if (smap[aj[k]]) {
262602834360SBarry Smith           lens[i]++;
262702834360SBarry Smith         }
262802834360SBarry Smith       }
262902834360SBarry Smith     }
263017ab2063SBarry Smith     /* Create and fill new matrix */
2631a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2632ace3abfcSBarry Smith       PetscBool equal;
26330f5bd95cSBarry Smith 
263499141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
26352c71b3e2SJacob Faibussowitsch       PetscCheckFalse((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
26365f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal));
2637*28b400f6SJacob Faibussowitsch       PetscCheck(equal,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
26385f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(c->ilen,(*B)->rmap->n));
263908480c60SBarry Smith       C    = *B;
26403a40ed3dSBarry Smith     } else {
26413bef6203SJed Brown       PetscInt rbs,cbs;
26425f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),&C));
26435f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE));
26445f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetBlockSize(isrow,&rbs));
26455f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetBlockSize(iscol,&cbs));
26465f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetBlockSizes(C,rbs,cbs));
26475f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetType(C,((PetscObject)A)->type_name));
26485f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens));
264908480c60SBarry Smith     }
26505f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
265199141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
265217ab2063SBarry Smith     for (i=0; i<nrows; i++) {
265399141d43SSatish Balay       row      = irow[i];
2654bfeeae90SHong Zhang       kstart   = ai[row];
265599141d43SSatish Balay       kend     = kstart + a->ilen[row];
2656bfeeae90SHong Zhang       mat_i    = c->i[i];
265799141d43SSatish Balay       mat_j    = c->j + mat_i;
265899141d43SSatish Balay       mat_a    = c->a + mat_i;
265999141d43SSatish Balay       mat_ilen = c->ilen + i;
266017ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2661bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2662ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
26632e5835c6SStefano Zampini           *mat_a++ = aa[k];
266499141d43SSatish Balay           (*mat_ilen)++;
266599141d43SSatish Balay 
266617ab2063SBarry Smith         }
266717ab2063SBarry Smith       }
266817ab2063SBarry Smith     }
26695f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
267002834360SBarry Smith     /* Free work space */
26715f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(iscol,&icol));
26725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(smap));
26735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(lens));
2674cdc6f3adSToby Isaac     /* sort */
2675cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2676cdc6f3adSToby Isaac       PetscInt ilen;
2677cdc6f3adSToby Isaac 
2678cdc6f3adSToby Isaac       mat_i = c->i[i];
2679cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2680cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2681cdc6f3adSToby Isaac       ilen  = c->ilen[i];
26825f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSortIntWithScalarArray(ilen,mat_j,mat_a));
2683cdc6f3adSToby Isaac     }
268402834360SBarry Smith   }
26858c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
26865f80ce2aSJacob Faibussowitsch   CHKERRQ(MatBindToCPU(C,A->boundtocpu));
2687305c6ccfSStefano Zampini #endif
26885f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
26895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));
269017ab2063SBarry Smith 
26915f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(isrow,&irow));
2692416022c9SBarry Smith   *B   = C;
26933a40ed3dSBarry Smith   PetscFunctionReturn(0);
269417ab2063SBarry Smith }
269517ab2063SBarry Smith 
2696fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
269782d44351SHong Zhang {
269882d44351SHong Zhang   Mat            B;
269982d44351SHong Zhang 
270082d44351SHong Zhang   PetscFunctionBegin;
2701c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
27025f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(subComm,&B));
27035f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n));
27045f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSizesFromMats(B,mat,mat));
27055f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(B,MATSEQAIJ));
27065f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE));
270782d44351SHong Zhang     *subMat = B;
2708c2d650bdSHong Zhang   } else {
27095f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN));
2710c2d650bdSHong Zhang   }
271182d44351SHong Zhang   PetscFunctionReturn(0);
271282d44351SHong Zhang }
271382d44351SHong Zhang 
27149a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2715a871dcd8SBarry Smith {
271663b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
271763b91edcSBarry Smith   Mat            outA;
2718ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
271963b91edcSBarry Smith 
27203a40ed3dSBarry Smith   PetscFunctionBegin;
27212c71b3e2SJacob Faibussowitsch   PetscCheckFalse(info->levels != 0,PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
27221df811f5SHong Zhang 
27235f80ce2aSJacob Faibussowitsch   CHKERRQ(ISIdentity(row,&row_identity));
27245f80ce2aSJacob Faibussowitsch   CHKERRQ(ISIdentity(col,&col_identity));
2725a871dcd8SBarry Smith 
272663b91edcSBarry Smith   outA             = inA;
2727d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
27285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(inA->solvertype));
27295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype));
27302205254eSKarl Rupp 
27315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)row));
27325f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&a->row));
27332205254eSKarl Rupp 
2734c3122656SLisandro Dalcin   a->row = row;
27352205254eSKarl Rupp 
27365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectReference((PetscObject)col));
27375f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&a->col));
27382205254eSKarl Rupp 
2739c3122656SLisandro Dalcin   a->col = col;
274063b91edcSBarry Smith 
274136db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
27425f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&a->icol));
27435f80ce2aSJacob Faibussowitsch   CHKERRQ(ISInvertPermutation(col,PETSC_DECIDE,&a->icol));
27445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol));
2745f0ec6fceSSatish Balay 
274694a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
27475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(inA->rmap->n+1,&a->solve_work));
27485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar)));
274994a9d846SBarry Smith   }
275063b91edcSBarry Smith 
27515f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMarkDiagonal_SeqAIJ(inA));
2752137fb511SHong Zhang   if (row_identity && col_identity) {
27535f80ce2aSJacob Faibussowitsch     CHKERRQ(MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info));
2754137fb511SHong Zhang   } else {
27555f80ce2aSJacob Faibussowitsch     CHKERRQ(MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info));
2756137fb511SHong Zhang   }
27573a40ed3dSBarry Smith   PetscFunctionReturn(0);
2758a871dcd8SBarry Smith }
2759a871dcd8SBarry Smith 
2760f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2761f0b747eeSBarry Smith {
2762f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2763dfa0f9e5SStefano Zampini   PetscScalar    *v;
2764c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
27653a40ed3dSBarry Smith 
27663a40ed3dSBarry Smith   PetscFunctionBegin;
27675f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(inA,&v));
27685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBLASIntCast(a->nz,&bnz));
2769dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
27705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogFlops(a->nz));
27715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(inA,&v));
27725f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(inA));
27733a40ed3dSBarry Smith   PetscFunctionReturn(0);
2774f0b747eeSBarry Smith }
2775f0b747eeSBarry Smith 
2776f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
277716b64355SHong Zhang {
277816b64355SHong Zhang   PetscInt       i;
277916b64355SHong Zhang 
278016b64355SHong Zhang   PetscFunctionBegin;
278116b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
27825f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr));
278316b64355SHong Zhang 
278416b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
27855f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(submatj->sbuf2[i]));
278616b64355SHong Zhang     }
27875f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1));
278816b64355SHong Zhang 
278916b64355SHong Zhang     if (submatj->rbuf1) {
27905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(submatj->rbuf1[0]));
27915f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(submatj->rbuf1));
279216b64355SHong Zhang     }
279316b64355SHong Zhang 
279416b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
27955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(submatj->rbuf3[i]));
279616b64355SHong Zhang     }
27975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3));
27985f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(submatj->pa));
279916b64355SHong Zhang   }
280016b64355SHong Zhang 
280116b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
28025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTableDestroy((PetscTable*)&submatj->rmap));
28035f80ce2aSJacob Faibussowitsch   if (submatj->cmap_loc) CHKERRQ(PetscFree(submatj->cmap_loc));
28045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(submatj->rmap_loc));
280516b64355SHong Zhang #else
28065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(submatj->rmap));
280716b64355SHong Zhang #endif
280816b64355SHong Zhang 
280916b64355SHong Zhang   if (!submatj->allcolumns) {
281016b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
28115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTableDestroy((PetscTable*)&submatj->cmap));
281216b64355SHong Zhang #else
28135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(submatj->cmap));
281416b64355SHong Zhang #endif
281516b64355SHong Zhang   }
28165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(submatj->row2proc));
281716b64355SHong Zhang 
28185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(submatj));
281916b64355SHong Zhang   PetscFunctionReturn(0);
282016b64355SHong Zhang }
282116b64355SHong Zhang 
28220fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
282316b64355SHong Zhang {
282416b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
28255c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
282616b64355SHong Zhang 
282716b64355SHong Zhang   PetscFunctionBegin;
28285f80ce2aSJacob Faibussowitsch   CHKERRQ((*submatj->destroy)(C));
28295f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroySubMatrix_Private(submatj));
283016b64355SHong Zhang   PetscFunctionReturn(0);
283116b64355SHong Zhang }
283216b64355SHong Zhang 
28332d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
28342d033e1fSHong Zhang {
28352d033e1fSHong Zhang   PetscInt       i;
28360fb991dcSHong Zhang   Mat            C;
28370fb991dcSHong Zhang   Mat_SeqAIJ     *c;
28380fb991dcSHong Zhang   Mat_SubSppt    *submatj;
28392d033e1fSHong Zhang 
28402d033e1fSHong Zhang   PetscFunctionBegin;
28412d033e1fSHong Zhang   for (i=0; i<n; i++) {
28420fb991dcSHong Zhang     C       = (*mat)[i];
28430fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
28440fb991dcSHong Zhang     submatj = c->submatis1;
28452d033e1fSHong Zhang     if (submatj) {
2846682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
28475f80ce2aSJacob Faibussowitsch         CHKERRQ((*submatj->destroy)(C));
28485f80ce2aSJacob Faibussowitsch         CHKERRQ(MatDestroySubMatrix_Private(submatj));
28495f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(C->defaultvectype));
28505f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscLayoutDestroy(&C->rmap));
28515f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscLayoutDestroy(&C->cmap));
28525f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscHeaderDestroy(&C));
2853682e4c99SStefano Zampini       }
28542d033e1fSHong Zhang     } else {
28555f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDestroy(&C));
28562d033e1fSHong Zhang     }
28572d033e1fSHong Zhang   }
285886e85357SHong Zhang 
285963a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
28605f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroySubMatrices_Dummy(n,mat));
286163a75b2aSHong Zhang 
28625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(*mat));
28632d033e1fSHong Zhang   PetscFunctionReturn(0);
28642d033e1fSHong Zhang }
28652d033e1fSHong Zhang 
28667dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2867cddf8d76SBarry Smith {
286897f1f81fSBarry Smith   PetscInt       i;
2869cddf8d76SBarry Smith 
28703a40ed3dSBarry Smith   PetscFunctionBegin;
2871cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
28725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscCalloc1(n+1,B));
2873cddf8d76SBarry Smith   }
2874cddf8d76SBarry Smith 
2875cddf8d76SBarry Smith   for (i=0; i<n; i++) {
28765f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]));
2877cddf8d76SBarry Smith   }
28783a40ed3dSBarry Smith   PetscFunctionReturn(0);
2879cddf8d76SBarry Smith }
2880cddf8d76SBarry Smith 
288197f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
28824dcbc457SBarry Smith {
2883e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
28845d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
28855d0c19d7SBarry Smith   const PetscInt *idx;
288697f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2887f1af5d2fSBarry Smith   PetscBT        table;
2888bbd702dbSSatish Balay 
28893a40ed3dSBarry Smith   PetscFunctionBegin;
2890d0f46423SBarry Smith   m  = A->rmap->n;
2891e4d965acSSatish Balay   ai = a->i;
2892bfeeae90SHong Zhang   aj = a->j;
28938a047759SSatish Balay 
28942c71b3e2SJacob Faibussowitsch   PetscCheckFalse(ov < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
289506763907SSatish Balay 
28965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m+1,&nidx));
28975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTCreate(m,&table));
289806763907SSatish Balay 
2899e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2900b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2901e4d965acSSatish Balay     isz  = 0;
29025f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBTMemzero(m,table));
2903e4d965acSSatish Balay 
2904e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29055f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(is[i],&idx));
29065f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(is[i],&n));
2907e4d965acSSatish Balay 
2908dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
2909e4d965acSSatish Balay     for (j=0; j<n; ++j) {
29102205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
29114dcbc457SBarry Smith     }
29125f80ce2aSJacob Faibussowitsch     CHKERRQ(ISRestoreIndices(is[i],&idx));
29135f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&is[i]));
2914e4d965acSSatish Balay 
291504a348a9SBarry Smith     k = 0;
291604a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
291704a348a9SBarry Smith       n = isz;
291806763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
2919e4d965acSSatish Balay         row   = nidx[k];
2920e4d965acSSatish Balay         start = ai[row];
2921e4d965acSSatish Balay         end   = ai[row+1];
292204a348a9SBarry Smith         for (l = start; l<end; l++) {
2923efb16452SHong Zhang           val = aj[l];
29242205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
2925e4d965acSSatish Balay         }
2926e4d965acSSatish Balay       }
2927e4d965acSSatish Balay     }
29285f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i)));
2929e4d965acSSatish Balay   }
29305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscBTDestroy(&table));
29315f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(nidx));
29323a40ed3dSBarry Smith   PetscFunctionReturn(0);
29334dcbc457SBarry Smith }
293417ab2063SBarry Smith 
29350513a670SBarry Smith /* -------------------------------------------------------------- */
2936dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
29370513a670SBarry Smith {
29380513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29393b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
29405d0c19d7SBarry Smith   const PetscInt *row,*col;
29415d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
294256cd22aeSBarry Smith   IS             icolp,irowp;
29430298fd71SBarry Smith   PetscInt       *cwork = NULL;
29440298fd71SBarry Smith   PetscScalar    *vwork = NULL;
29450513a670SBarry Smith 
29463a40ed3dSBarry Smith   PetscFunctionBegin;
29475f80ce2aSJacob Faibussowitsch   CHKERRQ(ISInvertPermutation(rowp,PETSC_DECIDE,&irowp));
29485f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(irowp,&row));
29495f80ce2aSJacob Faibussowitsch   CHKERRQ(ISInvertPermutation(colp,PETSC_DECIDE,&icolp));
29505f80ce2aSJacob Faibussowitsch   CHKERRQ(ISGetIndices(icolp,&col));
29510513a670SBarry Smith 
29520513a670SBarry Smith   /* determine lengths of permuted rows */
29535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m+1,&lens));
29542205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
29555f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),B));
29565f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*B,m,n,m,n));
29575f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSizesFromMats(*B,A,A));
29585f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*B,((PetscObject)A)->type_name));
29595f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens));
29605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(lens));
29610513a670SBarry Smith 
29625f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(n,&cnew));
29630513a670SBarry Smith   for (i=0; i<m; i++) {
29645f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork));
29652205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
29665f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES));
29675f80ce2aSJacob Faibussowitsch     CHKERRQ(MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork));
29680513a670SBarry Smith   }
29695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(cnew));
29702205254eSKarl Rupp 
29713c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
29722205254eSKarl Rupp 
29738c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
29745f80ce2aSJacob Faibussowitsch   CHKERRQ(MatBindToCPU(*B,A->boundtocpu));
29759fe5e383SStefano Zampini #endif
29765f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY));
29775f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY));
29785f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(irowp,&row));
29795f80ce2aSJacob Faibussowitsch   CHKERRQ(ISRestoreIndices(icolp,&col));
29805f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&irowp));
29815f80ce2aSJacob Faibussowitsch   CHKERRQ(ISDestroy(&icolp));
29826768869dSprj-   if (rowp == colp) {
29835f80ce2aSJacob Faibussowitsch     CHKERRQ(MatPropagateSymmetryOptions(A,*B));
29846768869dSprj-   }
29853a40ed3dSBarry Smith   PetscFunctionReturn(0);
29860513a670SBarry Smith }
29870513a670SBarry Smith 
2988dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
2989cb5b572fSBarry Smith {
2990cb5b572fSBarry Smith   PetscFunctionBegin;
299133f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
299233f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
2993be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2994be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
29952e5835c6SStefano Zampini     const PetscScalar *aa;
2996be6bf707SBarry Smith 
29975f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
29982c71b3e2SJacob 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]);
29995f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(b->a,aa,a->i[A->rmap->n]));
30005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectStateIncrease((PetscObject)B));
30015f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
3002cb5b572fSBarry Smith   } else {
30035f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCopy_Basic(A,B,str));
3004cb5b572fSBarry Smith   }
3005cb5b572fSBarry Smith   PetscFunctionReturn(0);
3006cb5b572fSBarry Smith }
3007cb5b572fSBarry Smith 
30084994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3009273d9f13SBarry Smith {
3010273d9f13SBarry Smith   PetscFunctionBegin;
30115f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL));
3012273d9f13SBarry Smith   PetscFunctionReturn(0);
3013273d9f13SBarry Smith }
3014273d9f13SBarry Smith 
3015f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
30166c0721eeSBarry Smith {
30176c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
30186e111a19SKarl Rupp 
30196c0721eeSBarry Smith   PetscFunctionBegin;
30206c0721eeSBarry Smith   *array = a->a;
30216c0721eeSBarry Smith   PetscFunctionReturn(0);
30226c0721eeSBarry Smith }
30236c0721eeSBarry Smith 
3024f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
30256c0721eeSBarry Smith {
30266c0721eeSBarry Smith   PetscFunctionBegin;
3027f38c1e66SStefano Zampini   *array = NULL;
30286c0721eeSBarry Smith   PetscFunctionReturn(0);
30296c0721eeSBarry Smith }
3030273d9f13SBarry Smith 
30318229c054SShri Abhyankar /*
30328229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
30338229c054SShri Abhyankar    have different nonzero structure.
30348229c054SShri Abhyankar */
3035b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3036ec7775f6SShri Abhyankar {
3037b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3038ec7775f6SShri Abhyankar 
3039ec7775f6SShri Abhyankar   PetscFunctionBegin;
3040ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3041ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3042b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3043b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3044b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
30458af7cee1SJed Brown     nnz[i] = 0;
30468af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3047b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3048b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
30498af7cee1SJed Brown       nnz[i]++;
30508af7cee1SJed Brown     }
30518af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3052ec7775f6SShri Abhyankar   }
3053ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3054ec7775f6SShri Abhyankar }
3055ec7775f6SShri Abhyankar 
3056b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3057b264fe52SHong Zhang {
3058b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3059b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3060b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3061b264fe52SHong Zhang 
3062b264fe52SHong Zhang   PetscFunctionBegin;
3063b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
30645f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz));
3065b264fe52SHong Zhang   PetscFunctionReturn(0);
3066b264fe52SHong Zhang }
3067b264fe52SHong Zhang 
3068f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3069ac90fabeSBarry Smith {
3070ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3071ac90fabeSBarry Smith 
3072ac90fabeSBarry Smith   PetscFunctionBegin;
3073134adf20SPierre Jolivet   if (str == UNKNOWN_NONZERO_PATTERN || (PetscDefined(USE_DEBUG) && str == SAME_NONZERO_PATTERN)) {
3074134adf20SPierre Jolivet     PetscBool e = x->nz == y->nz ? PETSC_TRUE : PETSC_FALSE;
3075134adf20SPierre Jolivet     if (e) {
30765f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e));
307781fa06acSBarry Smith       if (e) {
30785f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscArraycmp(x->j,y->j,y->nz,&e));
3079134adf20SPierre Jolivet         if (e) str = SAME_NONZERO_PATTERN;
308081fa06acSBarry Smith       }
308181fa06acSBarry Smith     }
308254c59aa7SJacob Faibussowitsch     if (!e) PetscCheck(str != SAME_NONZERO_PATTERN,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"MatStructure is not SAME_NONZERO_PATTERN");
308381fa06acSBarry Smith   }
3084ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
30852e5835c6SStefano Zampini     const PetscScalar *xa;
30862e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
308781fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
308881fa06acSBarry Smith 
30895f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscBLASIntCast(x->nz,&bnz));
30905f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArray(Y,&ya));
30915f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArrayRead(X,&xa));
30922e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
30935f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayRead(X,&xa));
30945f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArray(Y,&ya));
30955f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogFlops(2.0*bnz));
30965f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJInvalidateDiagonal(Y));
30975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectStateIncrease((PetscObject)Y));
3098ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
30995f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAXPY_Basic(Y,a,X,str));
3100ac90fabeSBarry Smith   } else {
31018229c054SShri Abhyankar     Mat      B;
31028229c054SShri Abhyankar     PetscInt *nnz;
31035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(Y->rmap->N,&nnz));
31045f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(PetscObjectComm((PetscObject)Y),&B));
31055f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name));
31065f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetLayouts(B,Y->rmap,Y->cmap));
31075f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(B,((PetscObject)Y)->type_name));
31085f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz));
31095f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJSetPreallocation(B,0,nnz));
31105f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAXPY_BasicWithPreallocation(B,Y,a,X,str));
31115f80ce2aSJacob Faibussowitsch     CHKERRQ(MatHeaderMerge(Y,&B));
31125f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(nnz));
3113ac90fabeSBarry Smith   }
3114ac90fabeSBarry Smith   PetscFunctionReturn(0);
3115ac90fabeSBarry Smith }
3116ac90fabeSBarry Smith 
31172726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3118354c94deSBarry Smith {
3119354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3120354c94deSBarry Smith   Mat_SeqAIJ  *aij = (Mat_SeqAIJ*)mat->data;
3121354c94deSBarry Smith   PetscInt     i,nz;
3122354c94deSBarry Smith   PetscScalar *a;
3123354c94deSBarry Smith 
3124354c94deSBarry Smith   PetscFunctionBegin;
3125354c94deSBarry Smith   nz = aij->nz;
31265f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(mat,&a));
31272205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
31285f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(mat,&a));
3129354c94deSBarry Smith #else
3130354c94deSBarry Smith   PetscFunctionBegin;
3131354c94deSBarry Smith #endif
3132354c94deSBarry Smith   PetscFunctionReturn(0);
3133354c94deSBarry Smith }
3134354c94deSBarry Smith 
3135985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3136e34fafa9SBarry Smith {
3137e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3138d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3139e34fafa9SBarry Smith   PetscReal       atmp;
3140985db425SBarry Smith   PetscScalar     *x;
3141ce496241SStefano Zampini   const MatScalar *aa,*av;
3142e34fafa9SBarry Smith 
3143e34fafa9SBarry Smith   PetscFunctionBegin;
3144*28b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
31455f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&av));
3146ce496241SStefano Zampini   aa = av;
3147e34fafa9SBarry Smith   ai = a->i;
3148e34fafa9SBarry Smith   aj = a->j;
3149e34fafa9SBarry Smith 
31505f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(v,0.0));
31515f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(v,&x));
31525f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(v,&n));
31532c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3154e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3155e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3156e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3157985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3158985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3159985db425SBarry Smith       aa++; aj++;
3160985db425SBarry Smith     }
3161985db425SBarry Smith   }
31625f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(v,&x));
31635f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&av));
3164985db425SBarry Smith   PetscFunctionReturn(0);
3165985db425SBarry Smith }
3166985db425SBarry Smith 
3167985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3168985db425SBarry Smith {
3169985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3170d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3171985db425SBarry Smith   PetscScalar     *x;
3172ce496241SStefano Zampini   const MatScalar *aa,*av;
3173985db425SBarry Smith 
3174985db425SBarry Smith   PetscFunctionBegin;
3175*28b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
31765f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&av));
3177ce496241SStefano Zampini   aa = av;
3178985db425SBarry Smith   ai = a->i;
3179985db425SBarry Smith   aj = a->j;
3180985db425SBarry Smith 
31815f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(v,0.0));
31825f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(v,&x));
31835f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(v,&n));
31842c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != A->rmap->n,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3185985db425SBarry Smith   for (i=0; i<m; i++) {
3186985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3187d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3188985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3189985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3190985db425SBarry Smith       x[i] = 0.0;
3191985db425SBarry Smith       if (idx) {
3192985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3193985db425SBarry Smith           if (aj[j] > j) {
3194985db425SBarry Smith             idx[i] = j;
3195985db425SBarry Smith             break;
3196985db425SBarry Smith           }
3197985db425SBarry Smith         }
31981a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
31991a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3200985db425SBarry Smith       }
3201985db425SBarry Smith     }
3202985db425SBarry Smith     for (j=0; j<ncols; j++) {
3203985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3204985db425SBarry Smith       aa++; aj++;
3205985db425SBarry Smith     }
3206985db425SBarry Smith   }
32075f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(v,&x));
32085f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&av));
3209985db425SBarry Smith   PetscFunctionReturn(0);
3210985db425SBarry Smith }
3211985db425SBarry Smith 
3212c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3213c87e5d42SMatthew Knepley {
3214c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3215c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3216ce496241SStefano Zampini   PetscScalar     *x;
3217ce496241SStefano Zampini   const MatScalar *aa,*av;
3218c87e5d42SMatthew Knepley 
3219c87e5d42SMatthew Knepley   PetscFunctionBegin;
32205f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&av));
3221ce496241SStefano Zampini   aa = av;
3222c87e5d42SMatthew Knepley   ai = a->i;
3223c87e5d42SMatthew Knepley   aj = a->j;
3224c87e5d42SMatthew Knepley 
32255f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(v,0.0));
32265f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(v,&x));
32275f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(v,&n));
32282c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %" PetscInt_FMT " vs. %" PetscInt_FMT " rows", m, n);
3229c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3230c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3231f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3232f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3233f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3234f07e67edSHong Zhang       x[i] = 0.0;
3235f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3236289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3237f07e67edSHong Zhang           if (aj[j] > j) {
3238f07e67edSHong Zhang             idx[i] = j;
32392205254eSKarl Rupp             break;
32402205254eSKarl Rupp           }
3241289a08f5SMatthew Knepley         }
3242f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3243f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3244f07e67edSHong Zhang       }
3245289a08f5SMatthew Knepley     }
3246c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3247f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3248c87e5d42SMatthew Knepley       aa++; aj++;
3249c87e5d42SMatthew Knepley     }
3250c87e5d42SMatthew Knepley   }
32515f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(v,&x));
32525f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&av));
3253c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3254c87e5d42SMatthew Knepley }
3255c87e5d42SMatthew Knepley 
3256985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3257985db425SBarry Smith {
3258985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3259d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3260d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3261985db425SBarry Smith   PetscScalar     *x;
3262ce496241SStefano Zampini   const MatScalar *aa,*av;
3263985db425SBarry Smith 
3264985db425SBarry Smith   PetscFunctionBegin;
3265*28b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
32665f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&av));
3267ce496241SStefano Zampini   aa = av;
3268985db425SBarry Smith   ai = a->i;
3269985db425SBarry Smith   aj = a->j;
3270985db425SBarry Smith 
32715f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(v,0.0));
32725f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayWrite(v,&x));
32735f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetLocalSize(v,&n));
32742c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n != m,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3275985db425SBarry Smith   for (i=0; i<m; i++) {
3276985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3277d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3278985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3279985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3280985db425SBarry Smith       x[i] = 0.0;
3281985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3282985db425SBarry Smith         for (j=0; j<ncols; j++) {
3283985db425SBarry Smith           if (aj[j] > j) {
3284985db425SBarry Smith             idx[i] = j;
3285985db425SBarry Smith             break;
3286985db425SBarry Smith           }
3287985db425SBarry Smith         }
3288fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3289fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3290985db425SBarry Smith       }
3291985db425SBarry Smith     }
3292985db425SBarry Smith     for (j=0; j<ncols; j++) {
3293985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3294985db425SBarry Smith       aa++; aj++;
3295e34fafa9SBarry Smith     }
3296e34fafa9SBarry Smith   }
32975f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayWrite(v,&x));
32985f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&av));
3299e34fafa9SBarry Smith   PetscFunctionReturn(0);
3300e34fafa9SBarry Smith }
3301bbead8a2SBarry Smith 
3302713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3303bbead8a2SBarry Smith {
3304bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
330533d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3306bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
33070da83c2eSBarry Smith   const PetscReal shift = 0.0;
33081a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3309bbead8a2SBarry Smith 
3310bbead8a2SBarry Smith   PetscFunctionBegin;
3311a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
33124a0d0026SBarry Smith   if (a->ibdiagvalid) {
33134a0d0026SBarry Smith     if (values) *values = a->ibdiag;
33144a0d0026SBarry Smith     PetscFunctionReturn(0);
33154a0d0026SBarry Smith   }
33165f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMarkDiagonal_SeqAIJ(A));
3317bbead8a2SBarry Smith   if (!a->ibdiag) {
33185f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(bs2*mbs,&a->ibdiag));
33195f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar)));
3320bbead8a2SBarry Smith   }
3321bbead8a2SBarry Smith   diag = a->ibdiag;
3322bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3323bbead8a2SBarry Smith   /* factor and invert each block */
3324bbead8a2SBarry Smith   switch (bs) {
3325bbead8a2SBarry Smith   case 1:
3326bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
33275f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,1,&i,1,&i,diag+i));
3328ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3329ec1892c8SHong Zhang         if (allowzeropivot) {
33307b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33317b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
33327b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
33335f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscInfo(A,"Zero pivot, row %" PetscInt_FMT " pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON));
333498921bdaSJacob 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);
3335ec1892c8SHong Zhang       }
3336bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3337bbead8a2SBarry Smith     }
3338bbead8a2SBarry Smith     break;
3339bbead8a2SBarry Smith   case 2:
3340bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3341bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
33425f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,2,ij,2,ij,diag));
33435f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected));
33447b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33455f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_2(diag));
3346bbead8a2SBarry Smith       diag += 4;
3347bbead8a2SBarry Smith     }
3348bbead8a2SBarry Smith     break;
3349bbead8a2SBarry Smith   case 3:
3350bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3351bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
33525f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,3,ij,3,ij,diag));
33535f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected));
33547b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33555f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_3(diag));
3356bbead8a2SBarry Smith       diag += 9;
3357bbead8a2SBarry Smith     }
3358bbead8a2SBarry Smith     break;
3359bbead8a2SBarry Smith   case 4:
3360bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3361bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
33625f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,4,ij,4,ij,diag));
33635f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected));
33647b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33655f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_4(diag));
3366bbead8a2SBarry Smith       diag += 16;
3367bbead8a2SBarry Smith     }
3368bbead8a2SBarry Smith     break;
3369bbead8a2SBarry Smith   case 5:
3370bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3371bbead8a2SBarry 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;
33725f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,5,ij,5,ij,diag));
33735f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected));
33747b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33755f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_5(diag));
3376bbead8a2SBarry Smith       diag += 25;
3377bbead8a2SBarry Smith     }
3378bbead8a2SBarry Smith     break;
3379bbead8a2SBarry Smith   case 6:
3380bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3381bbead8a2SBarry 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;
33825f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,6,ij,6,ij,diag));
33835f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected));
33847b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33855f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_6(diag));
3386bbead8a2SBarry Smith       diag += 36;
3387bbead8a2SBarry Smith     }
3388bbead8a2SBarry Smith     break;
3389bbead8a2SBarry Smith   case 7:
3390bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3391bbead8a2SBarry 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;
33925f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,7,ij,7,ij,diag));
33935f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected));
33947b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
33955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_7(diag));
3396bbead8a2SBarry Smith       diag += 49;
3397bbead8a2SBarry Smith     }
3398bbead8a2SBarry Smith     break;
3399bbead8a2SBarry Smith   default:
34005f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ));
3401bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3402bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3403bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3404bbead8a2SBarry Smith       }
34055f80ce2aSJacob Faibussowitsch       CHKERRQ(MatGetValues(A,bs,IJ,bs,IJ,diag));
34065f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected));
34077b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34085f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscKernel_A_gets_transpose_A_N(diag,bs));
3409bbead8a2SBarry Smith       diag += bs2;
3410bbead8a2SBarry Smith     }
34115f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree3(v_work,v_pivots,IJ));
3412bbead8a2SBarry Smith   }
3413bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3414bbead8a2SBarry Smith   PetscFunctionReturn(0);
3415bbead8a2SBarry Smith }
3416bbead8a2SBarry Smith 
341773a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
341873a71a0fSBarry Smith {
341973a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3420fff043a9SJunchao Zhang   PetscScalar    a,*aa;
342173a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
342273a71a0fSBarry Smith 
342373a71a0fSBarry Smith   PetscFunctionBegin;
342473a71a0fSBarry Smith   if (!x->assembled) {
34255f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetSize(x,&m,&n));
342673a71a0fSBarry Smith     for (i=0; i<m; i++) {
342773a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
34285f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscRandomGetValue(rctx,&a));
342973a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
34305f80ce2aSJacob Faibussowitsch         CHKERRQ(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES));
343173a71a0fSBarry Smith       }
343273a71a0fSBarry Smith     }
3433e2ce353bSJunchao Zhang   } else {
34345f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJGetArrayWrite(x,&aa));
34355f80ce2aSJacob Faibussowitsch     for (i=0; i<aij->nz; i++) CHKERRQ(PetscRandomGetValue(rctx,aa+i));
34365f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJRestoreArrayWrite(x,&aa));
3437e2ce353bSJunchao Zhang   }
34385f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
34395f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
344073a71a0fSBarry Smith   PetscFunctionReturn(0);
344173a71a0fSBarry Smith }
344273a71a0fSBarry Smith 
3443679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3444679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3445679944adSJunchao Zhang {
3446679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3447679944adSJunchao Zhang   PetscScalar    a;
3448679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3449679944adSJunchao Zhang 
3450679944adSJunchao Zhang   PetscFunctionBegin;
3451679944adSJunchao Zhang   nskip = high - low;
34525f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(x,&m,&n));
3453679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3454679944adSJunchao Zhang   for (i=0; i<m; i++) {
3455679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
34565f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscRandomGetValue(rctx,&a));
3457679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3458679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
34595f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES));
3460679944adSJunchao Zhang     }
3461e2ce353bSJunchao Zhang   }
34625f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY));
34635f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY));
3464679944adSJunchao Zhang   PetscFunctionReturn(0);
3465679944adSJunchao Zhang }
3466679944adSJunchao Zhang 
3467682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
34680a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3469cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3470cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3471cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
347297304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
34737c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
34747c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3475f4259b30SLisandro Dalcin                                         NULL,
3476f4259b30SLisandro Dalcin                                         NULL,
3477f4259b30SLisandro Dalcin                                         NULL,
3478f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3479cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3480f4259b30SLisandro Dalcin                                         NULL,
348141f059aeSBarry Smith                                         MatSOR_SeqAIJ,
348291e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
348397304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3484cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3485cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3486cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3487cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3488f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3489cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3490cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3491cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3492d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3493f4259b30SLisandro Dalcin                                         NULL,
3494f4259b30SLisandro Dalcin                                         NULL,
3495f4259b30SLisandro Dalcin                                         NULL,
3496f4259b30SLisandro Dalcin                                         NULL,
34974994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3498f4259b30SLisandro Dalcin                                         NULL,
3499f4259b30SLisandro Dalcin                                         NULL,
3500f4259b30SLisandro Dalcin                                         NULL,
3501f4259b30SLisandro Dalcin                                         NULL,
3502d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3503f4259b30SLisandro Dalcin                                         NULL,
3504f4259b30SLisandro Dalcin                                         NULL,
3505cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3506f4259b30SLisandro Dalcin                                         NULL,
3507d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
35087dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3509cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3510cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3511cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3512d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3513cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
35147d68702bSBarry Smith                                         MatShift_SeqAIJ,
351579299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
35166e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
351773a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
35183b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
35193b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
35203b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3521a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
352293dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3523f4259b30SLisandro Dalcin                                         NULL,
3524f4259b30SLisandro Dalcin                                         NULL,
3525cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3526f4259b30SLisandro Dalcin                                         NULL,
3527f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3528b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3529b9b97703SBarry Smith                                         MatView_SeqAIJ,
3530f4259b30SLisandro Dalcin                                         NULL,
3531f4259b30SLisandro Dalcin                                         NULL,
3532f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3533321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3534f4259b30SLisandro Dalcin                                         NULL,
3535f4259b30SLisandro Dalcin                                         NULL,
3536f4259b30SLisandro Dalcin                                         NULL,
3537d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3538c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3539f4259b30SLisandro Dalcin                                         NULL,
3540f4259b30SLisandro Dalcin                                         NULL,
3541f4259b30SLisandro Dalcin                                         NULL,
3542f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
35433acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3544f4259b30SLisandro Dalcin                                         NULL,
3545f4259b30SLisandro Dalcin                                         NULL,
3546f4259b30SLisandro Dalcin                                         NULL,
35476ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3548f4259b30SLisandro Dalcin                                         NULL,
3549f4259b30SLisandro Dalcin                                         NULL,
3550f4259b30SLisandro Dalcin                                         NULL,
3551bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3552d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
35531cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3554f4259b30SLisandro Dalcin                                         NULL,
3555f4259b30SLisandro Dalcin                                         NULL,
3556f4259b30SLisandro Dalcin                                         NULL,
3557f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3558f4259b30SLisandro Dalcin                                         NULL,
355926be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3560f4259b30SLisandro Dalcin                                         NULL,
3561f4259b30SLisandro Dalcin                                         NULL,
35628fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3563f4259b30SLisandro Dalcin                                         NULL,
3564f4259b30SLisandro Dalcin                                         NULL,
35656fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3566f4259b30SLisandro Dalcin                                         NULL,
35674222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3568f4259b30SLisandro Dalcin                                         NULL,
3569f4259b30SLisandro Dalcin                                         NULL,
357087d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3571f4259b30SLisandro Dalcin                                         NULL,
3572d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
357399cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3574f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3575f4259b30SLisandro Dalcin                                         NULL,
3576f4259b30SLisandro Dalcin                                         NULL,
3577cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3578f4259b30SLisandro Dalcin                                         NULL,
35792af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3580f4259b30SLisandro Dalcin                                         NULL,
3581599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3582f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3583f4259b30SLisandro Dalcin                                         NULL,
3584f4259b30SLisandro Dalcin                                         NULL,
3585f4259b30SLisandro Dalcin                                         NULL,
3586f4259b30SLisandro Dalcin                                         NULL,
3587f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3588f4259b30SLisandro Dalcin                                         NULL,
3589f4259b30SLisandro Dalcin                                         NULL,
3590f4259b30SLisandro Dalcin                                         NULL,
3591b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
35920716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3593a873a8cdSSam Reynolds                                         MatGetColumnReductions_SeqAIJ,
359437868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
35950da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3596f4259b30SLisandro Dalcin                                         NULL,
3597f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3598f4259b30SLisandro Dalcin                                         NULL,
3599f4259b30SLisandro Dalcin                                         NULL,
360075648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3601b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3602b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
36032b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3604f4259b30SLisandro Dalcin                                         NULL,
3605f4259b30SLisandro Dalcin                                         NULL,
36063964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3607f4259b30SLisandro Dalcin                                  /*139*/NULL,
3608f4259b30SLisandro Dalcin                                         NULL,
3609f4259b30SLisandro Dalcin                                         NULL,
36103a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
36119c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
36124222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
36134222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3614f4259b30SLisandro Dalcin                                         NULL,
3615f4259b30SLisandro Dalcin                                         NULL
36169e29f15eSvictorle };
361717ab2063SBarry Smith 
36187087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3619bef8e0ddSBarry Smith {
3620bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
362197f1f81fSBarry Smith   PetscInt   i,nz,n;
3622bef8e0ddSBarry Smith 
3623bef8e0ddSBarry Smith   PetscFunctionBegin;
3624bef8e0ddSBarry Smith   nz = aij->maxnz;
3625d0f46423SBarry Smith   n  = mat->rmap->n;
3626bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3627bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3628bef8e0ddSBarry Smith   }
3629bef8e0ddSBarry Smith   aij->nz = nz;
3630bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3631bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3632bef8e0ddSBarry Smith   }
3633bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3634bef8e0ddSBarry Smith }
3635bef8e0ddSBarry Smith 
3636a3bb6f32SFande Kong /*
3637ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3638ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3639ddea5d60SJunchao Zhang  */
3640a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3641a3bb6f32SFande Kong {
3642a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3643a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3644a3bb6f32SFande Kong   PetscTablePosition tpos;
364525b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
364625b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3647a3bb6f32SFande Kong 
3648a3bb6f32SFande Kong   PetscFunctionBegin;
3649a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3650a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3651a3bb6f32SFande Kong   /* use a table */
36525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1));
3653a3bb6f32SFande Kong   ec = 0;
365425b670f0SStefano Zampini   for (i=0; i<nz; i++) {
365525b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
36565f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTableFind(gid1_lid1,gid1,&data));
3657a3bb6f32SFande Kong     if (!data) {
3658a3bb6f32SFande Kong       /* one based table */
36595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES));
3660a3bb6f32SFande Kong     }
3661a3bb6f32SFande Kong   }
3662a3bb6f32SFande Kong   /* form array of columns we need */
36635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(ec,&garray));
36645f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTableGetHeadPosition(gid1_lid1,&tpos));
3665a3bb6f32SFande Kong   while (tpos) {
36665f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid));
3667a3bb6f32SFande Kong     gid--;
3668a3bb6f32SFande Kong     lid--;
3669a3bb6f32SFande Kong     garray[lid] = gid;
3670a3bb6f32SFande Kong   }
36715f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortInt(ec,garray)); /* sort, and rebuild */
36725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTableRemoveAll(gid1_lid1));
3673a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
36745f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES));
3675a3bb6f32SFande Kong   }
3676a3bb6f32SFande Kong   /* compact out the extra columns in B */
367725b670f0SStefano Zampini   for (i=0; i<nz; i++) {
367825b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
36795f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscTableFind(gid1_lid1,gid1,&lid));
3680a3bb6f32SFande Kong     lid--;
368125b670f0SStefano Zampini     jj[i] = lid;
3682a3bb6f32SFande Kong   }
36835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutDestroy(&mat->cmap));
36845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTableDestroy(&gid1_lid1));
36855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap));
36865f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping));
36875f80ce2aSJacob Faibussowitsch   CHKERRQ(ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH));
3688a3bb6f32SFande Kong   PetscFunctionReturn(0);
3689a3bb6f32SFande Kong }
3690a3bb6f32SFande Kong 
3691bef8e0ddSBarry Smith /*@
3692bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3693bef8e0ddSBarry Smith        in the matrix.
3694bef8e0ddSBarry Smith 
3695bef8e0ddSBarry Smith   Input Parameters:
3696bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3697bef8e0ddSBarry Smith -  indices - the column indices
3698bef8e0ddSBarry Smith 
369915091d37SBarry Smith   Level: advanced
370015091d37SBarry Smith 
3701bef8e0ddSBarry Smith   Notes:
3702bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3703bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3704bef8e0ddSBarry Smith   of the MatSetValues() operation.
3705bef8e0ddSBarry Smith 
3706bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3707d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3708bef8e0ddSBarry Smith 
3709bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3710bef8e0ddSBarry Smith 
3711b9617806SBarry Smith     The indices should start with zero, not one.
3712b9617806SBarry Smith 
3713bef8e0ddSBarry Smith @*/
37147087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3715bef8e0ddSBarry Smith {
3716bef8e0ddSBarry Smith   PetscFunctionBegin;
37170700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
37184482741eSBarry Smith   PetscValidPointer(indices,2);
37195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices)));
3720bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3721bef8e0ddSBarry Smith }
3722bef8e0ddSBarry Smith 
3723be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3724be6bf707SBarry Smith 
37257087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3726be6bf707SBarry Smith {
3727be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3728d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3729be6bf707SBarry Smith 
3730be6bf707SBarry Smith   PetscFunctionBegin;
3731*28b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3732be6bf707SBarry Smith 
3733be6bf707SBarry Smith   /* allocate space for values if not already there */
3734be6bf707SBarry Smith   if (!aij->saved_values) {
37355f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nz+1,&aij->saved_values));
37365f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar)));
3737be6bf707SBarry Smith   }
3738be6bf707SBarry Smith 
3739be6bf707SBarry Smith   /* copy values over */
37405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(aij->saved_values,aij->a,nz));
3741be6bf707SBarry Smith   PetscFunctionReturn(0);
3742be6bf707SBarry Smith }
3743be6bf707SBarry Smith 
3744be6bf707SBarry Smith /*@
3745be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3746be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3747be6bf707SBarry Smith        nonlinear portion.
3748be6bf707SBarry Smith 
3749be6bf707SBarry Smith    Collect on Mat
3750be6bf707SBarry Smith 
3751be6bf707SBarry Smith   Input Parameters:
37520e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3753be6bf707SBarry Smith 
375415091d37SBarry Smith   Level: advanced
375515091d37SBarry Smith 
3756be6bf707SBarry Smith   Common Usage, with SNESSolve():
3757be6bf707SBarry Smith $    Create Jacobian matrix
3758be6bf707SBarry Smith $    Set linear terms into matrix
3759be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3760be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3761be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3762512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3763be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3764be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3765be6bf707SBarry Smith $    In your Jacobian routine
3766be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3767be6bf707SBarry Smith $      Set nonlinear terms in matrix
3768be6bf707SBarry Smith 
3769be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3770be6bf707SBarry Smith $    // build linear portion of Jacobian
3771512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3772be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3773be6bf707SBarry Smith $    loop over nonlinear iterations
3774be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3775be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3776be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3777be6bf707SBarry Smith $       Solve linear system with Jacobian
3778be6bf707SBarry Smith $    endloop
3779be6bf707SBarry Smith 
3780be6bf707SBarry Smith   Notes:
3781be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3782512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3783be6bf707SBarry Smith     calling this routine.
3784be6bf707SBarry Smith 
37850c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
37860c468ba9SBarry Smith     and does not allocated additional space.
37870c468ba9SBarry Smith 
3788be6bf707SBarry Smith .seealso: MatRetrieveValues()
3789be6bf707SBarry Smith 
3790be6bf707SBarry Smith @*/
37917087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3792be6bf707SBarry Smith {
3793be6bf707SBarry Smith   PetscFunctionBegin;
37940700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3795*28b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3796*28b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
37975f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat)));
3798be6bf707SBarry Smith   PetscFunctionReturn(0);
3799be6bf707SBarry Smith }
3800be6bf707SBarry Smith 
38017087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3802be6bf707SBarry Smith {
3803be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3804d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3805be6bf707SBarry Smith 
3806be6bf707SBarry Smith   PetscFunctionBegin;
3807*28b400f6SJacob Faibussowitsch   PetscCheck(aij->nonew,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3808*28b400f6SJacob Faibussowitsch   PetscCheck(aij->saved_values,PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3809be6bf707SBarry Smith   /* copy values over */
38105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(aij->a,aij->saved_values,nz));
3811be6bf707SBarry Smith   PetscFunctionReturn(0);
3812be6bf707SBarry Smith }
3813be6bf707SBarry Smith 
3814be6bf707SBarry Smith /*@
3815be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3816be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3817be6bf707SBarry Smith        nonlinear portion.
3818be6bf707SBarry Smith 
3819be6bf707SBarry Smith    Collect on Mat
3820be6bf707SBarry Smith 
3821be6bf707SBarry Smith   Input Parameters:
3822386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3823be6bf707SBarry Smith 
382415091d37SBarry Smith   Level: advanced
382515091d37SBarry Smith 
3826be6bf707SBarry Smith .seealso: MatStoreValues()
3827be6bf707SBarry Smith 
3828be6bf707SBarry Smith @*/
38297087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3830be6bf707SBarry Smith {
3831be6bf707SBarry Smith   PetscFunctionBegin;
38320700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3833*28b400f6SJacob Faibussowitsch   PetscCheck(mat->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3834*28b400f6SJacob Faibussowitsch   PetscCheck(!mat->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
38355f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat)));
3836be6bf707SBarry Smith   PetscFunctionReturn(0);
3837be6bf707SBarry Smith }
3838be6bf707SBarry Smith 
3839be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
384017ab2063SBarry Smith /*@C
3841682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
38420d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
38436e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
384451c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
38452bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
384617ab2063SBarry Smith 
3847d083f849SBarry Smith    Collective
3848db81eaa0SLois Curfman McInnes 
384917ab2063SBarry Smith    Input Parameters:
3850db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
385117ab2063SBarry Smith .  m - number of rows
385217ab2063SBarry Smith .  n - number of columns
385317ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
385451c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
38550298fd71SBarry Smith          (possibly different for each row) or NULL
385617ab2063SBarry Smith 
385717ab2063SBarry Smith    Output Parameter:
3858416022c9SBarry Smith .  A - the matrix
385917ab2063SBarry Smith 
3860175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3861f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3862175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3863175b88e8SBarry Smith 
3864b259b22eSLois Curfman McInnes    Notes:
386549a6f317SBarry Smith    If nnz is given then nz is ignored
386649a6f317SBarry Smith 
386717ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
386817ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
38690002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
387044cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
387117ab2063SBarry Smith 
387217ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
38730298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
38743d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
38756da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
387617ab2063SBarry Smith 
3877682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
38784fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3879682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
38806c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
38816c7ebb05SLois Curfman McInnes 
38826c7ebb05SLois Curfman McInnes    Options Database Keys:
3883698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
38849db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
388517ab2063SBarry Smith 
3886027ccd11SLois Curfman McInnes    Level: intermediate
3887027ccd11SLois Curfman McInnes 
388869b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
388936db0b34SBarry Smith 
389017ab2063SBarry Smith @*/
38917087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
389217ab2063SBarry Smith {
38933a40ed3dSBarry Smith   PetscFunctionBegin;
38945f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,A));
38955f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*A,m,n,m,n));
38965f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*A,MATSEQAIJ));
38975f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz));
3898273d9f13SBarry Smith   PetscFunctionReturn(0);
3899273d9f13SBarry Smith }
3900273d9f13SBarry Smith 
3901273d9f13SBarry Smith /*@C
3902273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
3903273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
3904273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
3905273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
3906273d9f13SBarry Smith 
3907d083f849SBarry Smith    Collective
3908273d9f13SBarry Smith 
3909273d9f13SBarry Smith    Input Parameters:
39101c4f3114SJed Brown +  B - The matrix
3911273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
3912273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39130298fd71SBarry Smith          (possibly different for each row) or NULL
3914273d9f13SBarry Smith 
3915273d9f13SBarry Smith    Notes:
391649a6f317SBarry Smith      If nnz is given then nz is ignored
391749a6f317SBarry Smith 
3918273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
3919273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
3920273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
3921273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
3922273d9f13SBarry Smith 
3923273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39240298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
3925273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
3926273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
3927273d9f13SBarry Smith 
3928aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
3929aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
3930aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
3931aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
3932aa95bbe8SBarry Smith 
3933a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
3934a96a251dSBarry Smith    entries or columns indices
3935a96a251dSBarry Smith 
3936273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
3937273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
3938273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
3939273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
3940273d9f13SBarry Smith 
3941273d9f13SBarry Smith    Options Database Keys:
3942698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
394347b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
3944273d9f13SBarry Smith 
3945273d9f13SBarry Smith    Level: intermediate
3946273d9f13SBarry Smith 
394719b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
394819b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
3949273d9f13SBarry Smith 
3950273d9f13SBarry Smith @*/
39517087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
3952273d9f13SBarry Smith {
3953a23d5eceSKris Buschelman   PetscFunctionBegin;
39546ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
39556ba663aaSJed Brown   PetscValidType(B,1);
39565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz)));
3957a23d5eceSKris Buschelman   PetscFunctionReturn(0);
3958a23d5eceSKris Buschelman }
3959a23d5eceSKris Buschelman 
39607087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
3961a23d5eceSKris Buschelman {
3962273d9f13SBarry Smith   Mat_SeqAIJ     *b;
39632576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
396497f1f81fSBarry Smith   PetscInt       i;
3965273d9f13SBarry Smith 
3966273d9f13SBarry Smith   PetscFunctionBegin;
39672576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
3968a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
3969c461c341SBarry Smith     skipallocation = PETSC_TRUE;
3970c461c341SBarry Smith     nz             = 0;
3971c461c341SBarry Smith   }
39725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(B->rmap));
39735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(B->cmap));
3974899cda47SBarry Smith 
3975435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
39762c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %" PetscInt_FMT,nz);
3977cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
3978d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
39792c71b3e2SJacob 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]);
39802c71b3e2SJacob 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);
3981b73539f3SBarry Smith     }
3982b73539f3SBarry Smith   }
3983b73539f3SBarry Smith 
3984273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
39852205254eSKarl Rupp 
3986273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
3987273d9f13SBarry Smith 
3988ab93d7beSBarry Smith   if (!skipallocation) {
39892ee49352SLisandro Dalcin     if (!b->imax) {
39905f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(B->rmap->n,&b->imax));
39915f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt)));
3992071fcb05SBarry Smith     }
3993071fcb05SBarry Smith     if (!b->ilen) {
3994071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
39955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc1(B->rmap->n,&b->ilen));
39965f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt)));
3997071fcb05SBarry Smith     } else {
39985f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt)));
39992ee49352SLisandro Dalcin     }
4000846b4da1SFande Kong     if (!b->ipre) {
40015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(B->rmap->n,&b->ipre));
40025f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt)));
4003846b4da1SFande Kong     }
4004273d9f13SBarry Smith     if (!nnz) {
4005435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4006c62bd62aSJed Brown       else if (nz < 0) nz = 1;
40075d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4008d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4009d0f46423SBarry Smith       nz = nz*B->rmap->n;
4010273d9f13SBarry Smith     } else {
4011c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4012c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
40135f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscIntCast(nz64,&nz));
4014273d9f13SBarry Smith     }
4015ab93d7beSBarry Smith 
4016273d9f13SBarry Smith     /* allocate the matrix space */
401753dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
40185f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i));
4019396832f4SHong Zhang     if (B->structure_only) {
40205f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(nz,&b->j));
40215f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(B->rmap->n+1,&b->i));
40225f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt)));
4023396832f4SHong Zhang     } else {
40245f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i));
40255f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt))));
4026396832f4SHong Zhang     }
4027bfeeae90SHong Zhang     b->i[0] = 0;
4028d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
40295da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
40305da197adSKris Buschelman     }
4031396832f4SHong Zhang     if (B->structure_only) {
4032396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4033396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4034396832f4SHong Zhang     } else {
4035273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4036e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4037396832f4SHong Zhang     }
4038e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4039c461c341SBarry Smith   } else {
4040e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4041e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4042c461c341SBarry Smith   }
4043273d9f13SBarry Smith 
4044846b4da1SFande Kong   if (b->ipre && nnz != b->ipre && b->imax) {
4045846b4da1SFande Kong     /* reserve user-requested sparsity */
40465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(b->ipre,b->imax,B->rmap->n));
4047846b4da1SFande Kong   }
4048846b4da1SFande Kong 
4049273d9f13SBarry Smith   b->nz               = 0;
4050273d9f13SBarry Smith   b->maxnz            = nz;
4051273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
40522205254eSKarl Rupp   if (realalloc) {
40535f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE));
40542205254eSKarl Rupp   }
4055cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4056cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4057273d9f13SBarry Smith   PetscFunctionReturn(0);
4058273d9f13SBarry Smith }
4059273d9f13SBarry Smith 
4060846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4061846b4da1SFande Kong {
4062846b4da1SFande Kong   Mat_SeqAIJ     *a;
4063a5bbaf83SFande Kong   PetscInt       i;
4064846b4da1SFande Kong 
4065846b4da1SFande Kong   PetscFunctionBegin;
4066846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
406714d0e64fSAlex Lindsay 
406814d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
406914d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
407014d0e64fSAlex Lindsay 
4071846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
40722c814fdeSFande Kong   /* if no saved info, we error out */
4073*28b400f6SJacob Faibussowitsch   PetscCheck(a->ipre,PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info ");
40742c814fdeSFande Kong 
40752c71b3e2SJacob 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 ");
40762c814fdeSFande Kong 
40775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(a->imax,a->ipre,A->rmap->n));
40785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArrayzero(a->ilen,A->rmap->n));
4079846b4da1SFande Kong   a->i[0] = 0;
4080846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4081846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4082846b4da1SFande Kong   }
4083846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4084846b4da1SFande Kong   a->nz               = 0;
4085846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4086846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4087846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4088846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4089846b4da1SFande Kong   PetscFunctionReturn(0);
4090846b4da1SFande Kong }
4091846b4da1SFande Kong 
409258d36128SBarry Smith /*@
4093a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4094a1661176SMatthew Knepley 
4095a1661176SMatthew Knepley    Input Parameters:
4096a1661176SMatthew Knepley +  B - the matrix
4097a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4098a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4099a1661176SMatthew Knepley -  v - optional values in the matrix
4100a1661176SMatthew Knepley 
4101a1661176SMatthew Knepley    Level: developer
4102a1661176SMatthew Knepley 
41036a9b8d82SBarry Smith    Notes:
410458d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
410558d36128SBarry Smith 
41066a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
41076a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
41086a9b8d82SBarry Smith 
41096a9b8d82SBarry Smith     Developer Notes:
41106a9b8d82SBarry 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
41116a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
41126a9b8d82SBarry Smith 
41136a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
41146a9b8d82SBarry Smith 
41156a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4116a1661176SMatthew Knepley @*/
4117a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4118a1661176SMatthew Knepley {
4119a1661176SMatthew Knepley   PetscFunctionBegin;
41200700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
41216ba663aaSJed Brown   PetscValidType(B,1);
41225f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v)));
4123a1661176SMatthew Knepley   PetscFunctionReturn(0);
4124a1661176SMatthew Knepley }
4125a1661176SMatthew Knepley 
41267087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4127a1661176SMatthew Knepley {
4128a1661176SMatthew Knepley   PetscInt       i;
4129a1661176SMatthew Knepley   PetscInt       m,n;
4130a1661176SMatthew Knepley   PetscInt       nz;
41316a9b8d82SBarry Smith   PetscInt       *nnz;
4132a1661176SMatthew Knepley 
4133a1661176SMatthew Knepley   PetscFunctionBegin;
41342c71b3e2SJacob Faibussowitsch   PetscCheckFalse(Ii[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %" PetscInt_FMT, Ii[0]);
4135779a8d59SSatish Balay 
41365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(B->rmap));
41375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(B->cmap));
4138779a8d59SSatish Balay 
41395f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(B, &m, &n));
41405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m+1, &nnz));
4141a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4142b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
41432c71b3e2SJacob 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);
4144a1661176SMatthew Knepley     nnz[i] = nz;
4145a1661176SMatthew Knepley   }
41465f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(B, 0, nnz));
41475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(nnz));
4148a1661176SMatthew Knepley 
4149a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
41505f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES));
4151a1661176SMatthew Knepley   }
4152a1661176SMatthew Knepley 
41535f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
41545f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
4155a1661176SMatthew Knepley 
41565f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE));
4157a1661176SMatthew Knepley   PetscFunctionReturn(0);
4158a1661176SMatthew Knepley }
4159a1661176SMatthew Knepley 
4160ad7e164aSPierre Jolivet /*@
4161ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4162ad7e164aSPierre Jolivet 
4163ad7e164aSPierre Jolivet    Input Parameters:
4164ad7e164aSPierre Jolivet +  A - left-hand side matrix
4165ad7e164aSPierre Jolivet .  B - right-hand side matrix
4166ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4167ad7e164aSPierre Jolivet 
4168ad7e164aSPierre Jolivet    Output Parameter:
4169ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4170ad7e164aSPierre Jolivet 
4171ad7e164aSPierre Jolivet    Level: intermediate
4172ad7e164aSPierre Jolivet 
4173ad7e164aSPierre Jolivet    Notes:
4174ad7e164aSPierre 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().
4175ad7e164aSPierre Jolivet 
4176ad7e164aSPierre Jolivet .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4177ad7e164aSPierre Jolivet @*/
4178ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4179ad7e164aSPierre Jolivet {
4180ad7e164aSPierre Jolivet   PetscFunctionBegin;
4181ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4182ad7e164aSPierre Jolivet   PetscValidType(A,1);
4183ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4184ad7e164aSPierre Jolivet   PetscValidType(B,2);
4185ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4186ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4187ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4188ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4189ad7e164aSPierre Jolivet   }
41905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C)));
4191ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4192ad7e164aSPierre Jolivet }
4193ad7e164aSPierre Jolivet 
4194ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4195ad7e164aSPierre Jolivet {
4196ad7e164aSPierre Jolivet   Mat                newmat;
4197ad7e164aSPierre Jolivet   Mat_SeqAIJ         *a = (Mat_SeqAIJ*)A->data;
4198ad7e164aSPierre Jolivet   Mat_SeqAIJ         *b = (Mat_SeqAIJ*)B->data;
4199ad7e164aSPierre Jolivet   PetscScalar        *v;
4200fff043a9SJunchao Zhang   const PetscScalar  *aa,*ba;
4201ad7e164aSPierre 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;
4202ad7e164aSPierre Jolivet   PetscBool          flg;
4203ad7e164aSPierre Jolivet 
4204ad7e164aSPierre Jolivet   PetscFunctionBegin;
4205*28b400f6SJacob Faibussowitsch   PetscCheck(!A->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4206*28b400f6SJacob Faibussowitsch   PetscCheck(A->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4207*28b400f6SJacob Faibussowitsch   PetscCheck(!B->factortype,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4208*28b400f6SJacob Faibussowitsch   PetscCheck(B->assembled,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
42095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg));
4210*28b400f6SJacob Faibussowitsch   PetscCheck(flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
42112c71b3e2SJacob Faibussowitsch   PetscCheckFalse(reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX,PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4212ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
42135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j));
42145f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreate(PETSC_COMM_SELF,&newmat));
42155f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn));
42165f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(newmat,MATAIJ));
4217ad7e164aSPierre Jolivet     i[0] = 0;
4218ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4219ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4220ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4221ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4222ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4223ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4224ad7e164aSPierre Jolivet           }
4225ad7e164aSPierre Jolivet         }
4226ad7e164aSPierre Jolivet       }
4227ad7e164aSPierre Jolivet     }
42285f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL));
4229ad7e164aSPierre Jolivet     *C = newmat;
42305f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(i,j));
4231ad7e164aSPierre Jolivet     nnz = 0;
4232ad7e164aSPierre Jolivet   }
42335f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(*C,&v));
42345f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
42355f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(B,&ba));
4236ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4237ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4238ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4239ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4240fff043a9SJunchao Zhang           v[nnz++] = aa[n] * ba[q];
4241ad7e164aSPierre Jolivet         }
4242ad7e164aSPierre Jolivet       }
4243ad7e164aSPierre Jolivet     }
4244ad7e164aSPierre Jolivet   }
42455f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(*C,&v));
42465f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
42475f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(B,&ba));
4248ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4249ad7e164aSPierre Jolivet }
4250ad7e164aSPierre Jolivet 
4251c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4252af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4253170fe5c8SBarry Smith 
4254170fe5c8SBarry Smith /*
4255170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4256170fe5c8SBarry Smith 
4257170fe5c8SBarry Smith                n                       p                          p
42582da392ccSBarry Smith         [             ]       [             ]         [                 ]
42592da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
42602da392ccSBarry Smith         [             ]       [             ]         [                 ]
4261170fe5c8SBarry Smith 
4262170fe5c8SBarry Smith */
4263170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4264170fe5c8SBarry Smith {
4265170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4266170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4267170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
426886214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4269170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4270170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4271170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
427286214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
427386214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4274170fe5c8SBarry Smith 
4275170fe5c8SBarry Smith   PetscFunctionBegin;
4276d0f46423SBarry Smith   m    = A->rmap->n;
4277d0f46423SBarry Smith   n    = A->cmap->n;
4278d0f46423SBarry Smith   p    = B->cmap->n;
4279170fe5c8SBarry Smith   a    = sub_a->v;
4280170fe5c8SBarry Smith   b    = sub_b->a;
4281170fe5c8SBarry Smith   c    = sub_c->v;
428286214ceeSStefano Zampini   if (clda == m) {
42835f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArrayzero(c,m*p));
428486214ceeSStefano Zampini   } else {
428586214ceeSStefano Zampini     for (j=0;j<p;j++)
428686214ceeSStefano Zampini       for (i=0;i<m;i++)
428786214ceeSStefano Zampini         c[j*clda + i] = 0.0;
428886214ceeSStefano Zampini   }
4289170fe5c8SBarry Smith   ii  = sub_b->i;
4290170fe5c8SBarry Smith   idx = sub_b->j;
4291170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4292170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4293170fe5c8SBarry Smith     while (q-->0) {
429486214ceeSStefano Zampini       c_q = c + clda*(*idx);
429586214ceeSStefano Zampini       a_q = a + alda*i;
4296854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4297170fe5c8SBarry Smith       idx++;
4298170fe5c8SBarry Smith       b++;
4299170fe5c8SBarry Smith     }
4300170fe5c8SBarry Smith   }
4301170fe5c8SBarry Smith   PetscFunctionReturn(0);
4302170fe5c8SBarry Smith }
4303170fe5c8SBarry Smith 
43044222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4305170fe5c8SBarry Smith {
4306d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
430786214ceeSStefano Zampini   PetscBool      cisdense;
4308170fe5c8SBarry Smith 
4309170fe5c8SBarry Smith   PetscFunctionBegin;
43102c71b3e2SJacob 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);
43115f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(C,m,n,m,n));
43125f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetBlockSizesFromMats(C,A,B));
43135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,""));
431486214ceeSStefano Zampini   if (!cisdense) {
43155f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetType(C,MATDENSE));
431686214ceeSStefano Zampini   }
43175f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(C));
4318d73949e8SHong Zhang 
43194222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4320170fe5c8SBarry Smith   PetscFunctionReturn(0);
4321170fe5c8SBarry Smith }
4322170fe5c8SBarry Smith 
4323170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
43240bad9183SKris Buschelman /*MC
4325fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
43260bad9183SKris Buschelman    based on compressed sparse row format.
43270bad9183SKris Buschelman 
43280bad9183SKris Buschelman    Options Database Keys:
43290bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
43300bad9183SKris Buschelman 
43310bad9183SKris Buschelman    Level: beginner
43320bad9183SKris Buschelman 
43330cd7f59aSBarry Smith    Notes:
43340cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
43350cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
43360cd7f59aSBarry Smith     in the matrix
43370cd7f59aSBarry Smith 
43380cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
43390cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
43400cd7f59aSBarry Smith 
43410cd7f59aSBarry Smith   Developer Notes:
43420cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
43430cd7f59aSBarry Smith 
4344ed73aabaSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType, MATSELL, MATSEQSELL, MATMPISELL
43450bad9183SKris Buschelman M*/
43460bad9183SKris Buschelman 
4347ccd284c7SBarry Smith /*MC
4348ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4349ccd284c7SBarry Smith 
4350ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4351ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
4352ed73aabaSBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4353ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4354ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4355ccd284c7SBarry Smith 
4356ccd284c7SBarry Smith    Options Database Keys:
4357ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4358ccd284c7SBarry Smith 
435995452b02SPatrick Sanan   Developer Notes:
4360ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4361ccd284c7SBarry Smith    enough exist.
4362ccd284c7SBarry Smith 
4363ccd284c7SBarry Smith   Level: beginner
4364ccd284c7SBarry Smith 
4365ed73aabaSBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ, MATMPIAIJ, MATSELL, MATSEQSELL, MATMPISELL
4366ccd284c7SBarry Smith M*/
4367ccd284c7SBarry Smith 
4368ccd284c7SBarry Smith /*MC
4369ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4370ccd284c7SBarry Smith 
4371ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4372ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4373ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4374ccd284c7SBarry Smith    for communicators controlling multiple processes.  It is recommended that you call both of
4375ccd284c7SBarry Smith    the above preallocation routines for simplicity.
4376ccd284c7SBarry Smith 
4377ccd284c7SBarry Smith    Options Database Keys:
4378ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4379ccd284c7SBarry Smith 
4380ccd284c7SBarry Smith   Level: beginner
4381ccd284c7SBarry Smith 
4382ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4383ccd284c7SBarry Smith M*/
4384ccd284c7SBarry Smith 
43857906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
43867906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
43877906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
43887906f579SHong Zhang #endif
4389d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4390d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4391d24d4204SJose E. Roman #endif
43927906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
43937906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
43947906f579SHong Zhang #endif
43957906f579SHong Zhang 
4396d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4397c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
43984222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
43997906f579SHong Zhang 
44008c778c55SBarry Smith /*@C
44018f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
44028c778c55SBarry Smith 
44038c778c55SBarry Smith    Not Collective
44048c778c55SBarry Smith 
44058c778c55SBarry Smith    Input Parameter:
4406579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
44078c778c55SBarry Smith 
44088c778c55SBarry Smith    Output Parameter:
44098c778c55SBarry Smith .   array - pointer to the data
44108c778c55SBarry Smith 
44118c778c55SBarry Smith    Level: intermediate
44128c778c55SBarry Smith 
4413774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
44148c778c55SBarry Smith @*/
44158c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
44168c778c55SBarry Smith {
4417d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
44188c778c55SBarry Smith 
44198c778c55SBarry Smith   PetscFunctionBegin;
4420d67d9f35SJunchao Zhang   if (aij->ops->getarray) {
44215f80ce2aSJacob Faibussowitsch     CHKERRQ((*aij->ops->getarray)(A,array));
4422d67d9f35SJunchao Zhang   } else {
4423d67d9f35SJunchao Zhang     *array = aij->a;
4424d67d9f35SJunchao Zhang   }
4425d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4426d67d9f35SJunchao Zhang }
4427d67d9f35SJunchao Zhang 
4428d67d9f35SJunchao Zhang /*@C
4429d67d9f35SJunchao Zhang    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
4430d67d9f35SJunchao Zhang 
4431d67d9f35SJunchao Zhang    Not Collective
4432d67d9f35SJunchao Zhang 
4433d67d9f35SJunchao Zhang    Input Parameters:
4434d67d9f35SJunchao Zhang +  mat - a MATSEQAIJ matrix
4435d67d9f35SJunchao Zhang -  array - pointer to the data
4436d67d9f35SJunchao Zhang 
4437d67d9f35SJunchao Zhang    Level: intermediate
4438d67d9f35SJunchao Zhang 
4439d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
4440d67d9f35SJunchao Zhang @*/
4441d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
4442d67d9f35SJunchao Zhang {
4443d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4444d67d9f35SJunchao Zhang 
4445d67d9f35SJunchao Zhang   PetscFunctionBegin;
4446d67d9f35SJunchao Zhang   if (aij->ops->restorearray) {
44475f80ce2aSJacob Faibussowitsch     CHKERRQ((*aij->ops->restorearray)(A,array));
4448d67d9f35SJunchao Zhang   } else {
4449d67d9f35SJunchao Zhang     *array = NULL;
4450d67d9f35SJunchao Zhang   }
44515f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(A));
44525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateIncrease((PetscObject)A));
44538c778c55SBarry Smith   PetscFunctionReturn(0);
44548c778c55SBarry Smith }
44558c778c55SBarry Smith 
445621e72a00SBarry Smith /*@C
44578f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
44588f1ea47aSStefano Zampini 
44598f1ea47aSStefano Zampini    Not Collective
44608f1ea47aSStefano Zampini 
44618f1ea47aSStefano Zampini    Input Parameter:
44628f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44638f1ea47aSStefano Zampini 
44648f1ea47aSStefano Zampini    Output Parameter:
44658f1ea47aSStefano Zampini .   array - pointer to the data
44668f1ea47aSStefano Zampini 
44678f1ea47aSStefano Zampini    Level: intermediate
44688f1ea47aSStefano Zampini 
44698f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
44708f1ea47aSStefano Zampini @*/
44718f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
44728f1ea47aSStefano Zampini {
4473d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
44748f1ea47aSStefano Zampini 
44758f1ea47aSStefano Zampini   PetscFunctionBegin;
4476d67d9f35SJunchao Zhang   if (aij->ops->getarrayread) {
44775f80ce2aSJacob Faibussowitsch     CHKERRQ((*aij->ops->getarrayread)(A,array));
4478d67d9f35SJunchao Zhang   } else {
4479d67d9f35SJunchao Zhang     *array = aij->a;
4480d67d9f35SJunchao Zhang   }
44818f1ea47aSStefano Zampini   PetscFunctionReturn(0);
44828f1ea47aSStefano Zampini }
44838f1ea47aSStefano Zampini 
44848f1ea47aSStefano Zampini /*@C
44858f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
44868f1ea47aSStefano Zampini 
44878f1ea47aSStefano Zampini    Not Collective
44888f1ea47aSStefano Zampini 
44898f1ea47aSStefano Zampini    Input Parameter:
44908f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
44918f1ea47aSStefano Zampini 
44928f1ea47aSStefano Zampini    Output Parameter:
44938f1ea47aSStefano Zampini .   array - pointer to the data
44948f1ea47aSStefano Zampini 
44958f1ea47aSStefano Zampini    Level: intermediate
44968f1ea47aSStefano Zampini 
44978f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
44988f1ea47aSStefano Zampini @*/
44998f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
45008f1ea47aSStefano Zampini {
4501d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
45028f1ea47aSStefano Zampini 
45038f1ea47aSStefano Zampini   PetscFunctionBegin;
4504d67d9f35SJunchao Zhang   if (aij->ops->restorearrayread) {
45055f80ce2aSJacob Faibussowitsch     CHKERRQ((*aij->ops->restorearrayread)(A,array));
4506d67d9f35SJunchao Zhang   } else {
4507d67d9f35SJunchao Zhang     *array = NULL;
4508d67d9f35SJunchao Zhang   }
4509d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4510d67d9f35SJunchao Zhang }
4511d67d9f35SJunchao Zhang 
4512d67d9f35SJunchao Zhang /*@C
4513d67d9f35SJunchao Zhang    MatSeqAIJGetArrayWrite - gives write-only access to the array where the data for a MATSEQAIJ matrix is stored
4514d67d9f35SJunchao Zhang 
4515d67d9f35SJunchao Zhang    Not Collective
4516d67d9f35SJunchao Zhang 
4517d67d9f35SJunchao Zhang    Input Parameter:
4518d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4519d67d9f35SJunchao Zhang 
4520d67d9f35SJunchao Zhang    Output Parameter:
4521d67d9f35SJunchao Zhang .   array - pointer to the data
4522d67d9f35SJunchao Zhang 
4523d67d9f35SJunchao Zhang    Level: intermediate
4524d67d9f35SJunchao Zhang 
4525d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
4526d67d9f35SJunchao Zhang @*/
4527d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJGetArrayWrite(Mat A,PetscScalar **array)
4528d67d9f35SJunchao Zhang {
4529d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4530d67d9f35SJunchao Zhang 
4531d67d9f35SJunchao Zhang   PetscFunctionBegin;
4532d67d9f35SJunchao Zhang   if (aij->ops->getarraywrite) {
45335f80ce2aSJacob Faibussowitsch     CHKERRQ((*aij->ops->getarraywrite)(A,array));
4534d67d9f35SJunchao Zhang   } else {
4535d67d9f35SJunchao Zhang     *array = aij->a;
4536d67d9f35SJunchao Zhang   }
45375f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal(A));
45385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectStateIncrease((PetscObject)A));
4539d67d9f35SJunchao Zhang   PetscFunctionReturn(0);
4540d67d9f35SJunchao Zhang }
4541d67d9f35SJunchao Zhang 
4542d67d9f35SJunchao Zhang /*@C
4543d67d9f35SJunchao Zhang    MatSeqAIJRestoreArrayWrite - restore the read-only access array obtained from MatSeqAIJGetArrayRead
4544d67d9f35SJunchao Zhang 
4545d67d9f35SJunchao Zhang    Not Collective
4546d67d9f35SJunchao Zhang 
4547d67d9f35SJunchao Zhang    Input Parameter:
4548d67d9f35SJunchao Zhang .  mat - a MATSEQAIJ matrix
4549d67d9f35SJunchao Zhang 
4550d67d9f35SJunchao Zhang    Output Parameter:
4551d67d9f35SJunchao Zhang .   array - pointer to the data
4552d67d9f35SJunchao Zhang 
4553d67d9f35SJunchao Zhang    Level: intermediate
4554d67d9f35SJunchao Zhang 
4555d67d9f35SJunchao Zhang .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
4556d67d9f35SJunchao Zhang @*/
4557d67d9f35SJunchao Zhang PetscErrorCode  MatSeqAIJRestoreArrayWrite(Mat A,PetscScalar **array)
4558d67d9f35SJunchao Zhang {
4559d67d9f35SJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
4560d67d9f35SJunchao Zhang 
4561d67d9f35SJunchao Zhang   PetscFunctionBegin;
4562d67d9f35SJunchao Zhang   if (aij->ops->restorearraywrite) {
45635f80ce2aSJacob Faibussowitsch     CHKERRQ((*aij->ops->restorearraywrite)(A,array));
4564d67d9f35SJunchao Zhang   } else {
4565d67d9f35SJunchao Zhang     *array = NULL;
4566d67d9f35SJunchao Zhang   }
45678f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45688f1ea47aSStefano Zampini }
45698f1ea47aSStefano Zampini 
45708f1ea47aSStefano Zampini /*@C
457121e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
457221e72a00SBarry Smith 
457321e72a00SBarry Smith    Not Collective
457421e72a00SBarry Smith 
457521e72a00SBarry Smith    Input Parameter:
4576579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
457721e72a00SBarry Smith 
457821e72a00SBarry Smith    Output Parameter:
457921e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
458021e72a00SBarry Smith 
458121e72a00SBarry Smith    Level: intermediate
458221e72a00SBarry Smith 
458321e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
458421e72a00SBarry Smith @*/
458521e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
458621e72a00SBarry Smith {
458721e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
458821e72a00SBarry Smith 
458921e72a00SBarry Smith   PetscFunctionBegin;
459021e72a00SBarry Smith   *nz = aij->rmax;
459121e72a00SBarry Smith   PetscFunctionReturn(0);
459221e72a00SBarry Smith }
459321e72a00SBarry Smith 
4594394ed5ebSJunchao Zhang PetscErrorCode MatSetPreallocationCOO_SeqAIJ(Mat mat, PetscCount coo_n, const PetscInt coo_i[], const PetscInt coo_j[])
4595394ed5ebSJunchao Zhang {
4596394ed5ebSJunchao Zhang   MPI_Comm                  comm;
4597394ed5ebSJunchao Zhang   PetscInt                  *i,*j;
4598394ed5ebSJunchao Zhang   PetscInt                  M,N,row;
4599394ed5ebSJunchao Zhang   PetscCount                k,p,q,nneg,nnz,start,end; /* Index the coo array, so use PetscCount as their type */
4600394ed5ebSJunchao Zhang   PetscInt                  *Ai; /* Change to PetscCount once we use it for row pointers */
4601394ed5ebSJunchao Zhang   PetscInt                  *Aj;
4602394ed5ebSJunchao Zhang   PetscScalar               *Aa;
4603cbc6b225SStefano Zampini   Mat_SeqAIJ                *seqaij = (Mat_SeqAIJ*)(mat->data);
4604cbc6b225SStefano Zampini   MatType                   rtype;
4605394ed5ebSJunchao Zhang   PetscCount                *perm,*jmap;
4606394ed5ebSJunchao Zhang 
4607394ed5ebSJunchao Zhang   PetscFunctionBegin;
46085f80ce2aSJacob Faibussowitsch   CHKERRQ(MatResetPreallocationCOO_SeqAIJ(mat));
46095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)mat,&comm));
46105f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(mat,&M,&N));
46115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(coo_n,&i,coo_n,&j));
46125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(i,coo_i,coo_n)); /* Make a copy since we'll modify it */
46135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(j,coo_j,coo_n));
46145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(coo_n,&perm));
4615394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) { /* Ignore entries with negative row or col indices */
4616394ed5ebSJunchao Zhang     if (j[k] < 0) i[k] = -1;
4617394ed5ebSJunchao Zhang     perm[k] = k;
4618394ed5ebSJunchao Zhang   }
4619394ed5ebSJunchao Zhang 
4620394ed5ebSJunchao Zhang   /* Sort by row */
46215f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSortIntWithIntCountArrayPair(coo_n,i,j,perm));
4622394ed5ebSJunchao Zhang   for (k=0; k<coo_n; k++) {if (i[k] >= 0) break;} /* Advance k to the first row with a non-negative index */
4623394ed5ebSJunchao Zhang   nneg = k;
46245f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(coo_n-nneg+1,&jmap)); /* +1 to make a CSR-like data structure. jmap[i] originally is the number of repeats for i-th nonzero */
4625394ed5ebSJunchao Zhang   nnz  = 0; /* Total number of unique nonzeros to be counted */
4626394ed5ebSJunchao Zhang   jmap++; /* Inc jmap by 1 for convinience */
4627394ed5ebSJunchao Zhang 
46285f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(M+1,&Ai)); /* CSR of A */
46295f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(coo_n-nneg,&Aj)); /* We have at most coo_n-nneg unique nonzeros */
4630394ed5ebSJunchao Zhang 
4631394ed5ebSJunchao Zhang   /* In each row, sort by column, then unique column indices to get row length */
4632394ed5ebSJunchao Zhang   Ai++; /* Inc by 1 for convinience */
4633394ed5ebSJunchao Zhang   q = 0; /* q-th unique nonzero, with q starting from 0 */
4634394ed5ebSJunchao Zhang   while (k<coo_n) {
4635394ed5ebSJunchao Zhang     row   = i[k];
4636394ed5ebSJunchao Zhang     start = k; /* [start,end) indices for this row */
4637394ed5ebSJunchao Zhang     while (k<coo_n && i[k] == row) k++;
4638394ed5ebSJunchao Zhang     end   = k;
46395f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSortIntWithCountArray(end-start,j+start,perm+start));
4640394ed5ebSJunchao Zhang     /* Find number of unique col entries in this row */
4641394ed5ebSJunchao Zhang     Aj[q]   = j[start]; /* Log the first nonzero in this row */
4642394ed5ebSJunchao Zhang     jmap[q] = 1; /* Number of repeats of this nozero entry */
4643394ed5ebSJunchao Zhang     Ai[row] = 1;
4644394ed5ebSJunchao Zhang     nnz++;
4645394ed5ebSJunchao Zhang 
4646394ed5ebSJunchao Zhang     for (p=start+1; p<end; p++) { /* Scan remaining nonzero in this row */
4647394ed5ebSJunchao Zhang       if (j[p] != j[p-1]) { /* Meet a new nonzero */
4648394ed5ebSJunchao Zhang         q++;
4649394ed5ebSJunchao Zhang         jmap[q] = 1;
4650394ed5ebSJunchao Zhang         Aj[q]   = j[p];
4651394ed5ebSJunchao Zhang         Ai[row]++;
4652394ed5ebSJunchao Zhang         nnz++;
4653394ed5ebSJunchao Zhang       } else {
4654394ed5ebSJunchao Zhang         jmap[q]++;
4655394ed5ebSJunchao Zhang       }
4656394ed5ebSJunchao Zhang     }
4657394ed5ebSJunchao Zhang     q++; /* Move to next row and thus next unique nonzero */
4658394ed5ebSJunchao Zhang   }
46595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(i,j));
4660394ed5ebSJunchao Zhang 
4661394ed5ebSJunchao Zhang   Ai--; /* Back to the beginning of Ai[] */
4662394ed5ebSJunchao Zhang   for (k=0; k<M; k++) Ai[k+1] += Ai[k];
4663394ed5ebSJunchao Zhang   jmap--; /* Back to the beginning of jmap[] */
4664394ed5ebSJunchao Zhang   jmap[0] = 0;
4665394ed5ebSJunchao Zhang   for (k=0; k<nnz; k++) jmap[k+1] += jmap[k];
4666394ed5ebSJunchao Zhang   if (nnz < coo_n-nneg) { /* Realloc with actual number of unique nonzeros */
4667394ed5ebSJunchao Zhang     PetscCount *jmap_new;
4668394ed5ebSJunchao Zhang     PetscInt   *Aj_new;
4669394ed5ebSJunchao Zhang 
46705f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nnz+1,&jmap_new));
46715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(jmap_new,jmap,nnz+1));
46725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(jmap));
4673394ed5ebSJunchao Zhang     jmap = jmap_new;
4674394ed5ebSJunchao Zhang 
46755f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(nnz,&Aj_new));
46765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(Aj_new,Aj,nnz));
46775f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(Aj));
4678394ed5ebSJunchao Zhang     Aj   = Aj_new;
4679394ed5ebSJunchao Zhang   }
4680394ed5ebSJunchao Zhang 
4681394ed5ebSJunchao Zhang   if (nneg) { /* Discard heading entries with negative indices in perm[], as we'll access it from index 0 in MatSetValuesCOO */
4682394ed5ebSJunchao Zhang     PetscCount *perm_new;
4683cbc6b225SStefano Zampini 
46845f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(coo_n-nneg,&perm_new));
46855f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscArraycpy(perm_new,perm+nneg,coo_n-nneg));
46865f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(perm));
4687394ed5ebSJunchao Zhang     perm = perm_new;
4688394ed5ebSJunchao Zhang   }
4689394ed5ebSJunchao Zhang 
46905f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetRootType_Private(mat,&rtype));
46915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(nnz,&Aa)); /* Zero the matrix */
46925f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSeqAIJWithArrays_private(PETSC_COMM_SELF,M,N,Ai,Aj,Aa,rtype,mat));
4693394ed5ebSJunchao Zhang 
4694394ed5ebSJunchao Zhang   seqaij->singlemalloc = PETSC_FALSE; /* Ai, Aj and Aa are not allocated in one big malloc */
4695394ed5ebSJunchao Zhang   seqaij->free_a       = seqaij->free_ij = PETSC_TRUE; /* Let newmat own Ai, Aj and Aa */
4696394ed5ebSJunchao Zhang   /* Record COO fields */
4697394ed5ebSJunchao Zhang   seqaij->coo_n        = coo_n;
4698394ed5ebSJunchao Zhang   seqaij->Atot         = coo_n-nneg; /* Annz is seqaij->nz, so no need to record that again */
4699394ed5ebSJunchao Zhang   seqaij->jmap         = jmap; /* of length nnz+1 */
4700394ed5ebSJunchao Zhang   seqaij->perm         = perm;
4701394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4702394ed5ebSJunchao Zhang }
4703394ed5ebSJunchao Zhang 
4704394ed5ebSJunchao Zhang static PetscErrorCode MatSetValuesCOO_SeqAIJ(Mat A,const PetscScalar v[],InsertMode imode)
4705394ed5ebSJunchao Zhang {
4706394ed5ebSJunchao Zhang   Mat_SeqAIJ                  *aseq = (Mat_SeqAIJ*)A->data;
4707394ed5ebSJunchao Zhang   PetscCount                  i,j,Annz = aseq->nz;
4708394ed5ebSJunchao Zhang   PetscCount                  *perm = aseq->perm,*jmap = aseq->jmap;
4709394ed5ebSJunchao Zhang   PetscScalar                 *Aa;
4710394ed5ebSJunchao Zhang 
4711394ed5ebSJunchao Zhang   PetscFunctionBegin;
47125f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArray(A,&Aa));
4713394ed5ebSJunchao Zhang   for (i=0; i<Annz; i++) {
4714b6c38306SJunchao Zhang     PetscScalar sum = 0.0;
4715b6c38306SJunchao Zhang     for (j=jmap[i]; j<jmap[i+1]; j++) sum += v[perm[j]];
4716b6c38306SJunchao Zhang     Aa[i] = (imode == INSERT_VALUES? 0.0 : Aa[i]) + sum;
4717394ed5ebSJunchao Zhang   }
47185f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArray(A,&Aa));
4719394ed5ebSJunchao Zhang   PetscFunctionReturn(0);
4720394ed5ebSJunchao Zhang }
4721394ed5ebSJunchao Zhang 
472234b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
47235063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat,MatType,MatReuse,Mat*);
472402fe1965SBarry Smith #endif
47253d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47265063d097SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat,MatType,MatReuse,Mat*);
47273d0639e7SStefano Zampini #endif
472802fe1965SBarry Smith 
47298cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4730273d9f13SBarry Smith {
4731273d9f13SBarry Smith   Mat_SeqAIJ     *b;
473238baddfdSBarry Smith   PetscMPIInt    size;
4733273d9f13SBarry Smith 
4734273d9f13SBarry Smith   PetscFunctionBegin;
47355f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PetscObjectComm((PetscObject)B),&size));
47362c71b3e2SJacob Faibussowitsch   PetscCheckFalse(size > 1,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4737273d9f13SBarry Smith 
47385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(B,&b));
47392205254eSKarl Rupp 
4740b0a32e0cSBarry Smith   B->data = (void*)b;
47412205254eSKarl Rupp 
47425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps)));
4743071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
47442205254eSKarl Rupp 
4745f4259b30SLisandro Dalcin   b->row                = NULL;
4746f4259b30SLisandro Dalcin   b->col                = NULL;
4747f4259b30SLisandro Dalcin   b->icol               = NULL;
4748b810aeb4SBarry Smith   b->reallocs           = 0;
474936db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4750f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4751416022c9SBarry Smith   b->nonew              = 0;
4752f4259b30SLisandro Dalcin   b->diag               = NULL;
4753f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4754f4259b30SLisandro Dalcin   B->spptr              = NULL;
4755f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4756f4259b30SLisandro Dalcin   b->idiag              = NULL;
4757f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4758f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
475971f1c65dSBarry Smith   b->omega              = 1.0;
476071f1c65dSBarry Smith   b->fshift             = 0.0;
476171f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4762bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4763a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
476417ab2063SBarry Smith 
47655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ));
47668c778c55SBarry Smith 
4767b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
47685f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ));
47695f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ));
4770b3866ffcSBarry Smith #endif
477117f1a0eaSHong Zhang 
47725f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ));
47735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ));
47745f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ));
47755f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ));
47765f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ));
47775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM));
47785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL));
47799779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
47805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL));
4781191b95cbSRichard Tran Mills #endif
478234b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
47835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE));
47845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ));
47855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ));
478602fe1965SBarry Smith #endif
47873d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos));
47893d0639e7SStefano Zampini #endif
47905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL));
4791af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
47925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental));
4793af8000cdSHong Zhang #endif
4794d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
47955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK));
4796d24d4204SJose E. Roman #endif
479763c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
47985f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE));
47995f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ));
480063c07aadSStefano Zampini #endif
48015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense));
48025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL));
48035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS));
48045f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ));
48055f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ));
48065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ));
48075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ));
48085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ));
48095f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ));
48105f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ));
48115f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ));
48125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ));
48135f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ));
48145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatSetPreallocationCOO_C",MatSetPreallocationCOO_SeqAIJ));
48155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)B,"MatSetValuesCOO_C",MatSetValuesCOO_SeqAIJ));
48165f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate_SeqAIJ_Inode(B));
48175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ));
48185f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetTypeFromOptions(B));  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
48193a40ed3dSBarry Smith   PetscFunctionReturn(0);
482017ab2063SBarry Smith }
482117ab2063SBarry Smith 
4822b24902e0SBarry Smith /*
4823b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4824b24902e0SBarry Smith */
4825ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
482617ab2063SBarry Smith {
48272a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
4828071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
482917ab2063SBarry Smith 
48303a40ed3dSBarry Smith   PetscFunctionBegin;
48312c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4832273d9f13SBarry Smith 
4833d5f3da31SBarry Smith   C->factortype = A->factortype;
4834f4259b30SLisandro Dalcin   c->row        = NULL;
4835f4259b30SLisandro Dalcin   c->col        = NULL;
4836f4259b30SLisandro Dalcin   c->icol       = NULL;
48376ad4291fSHong Zhang   c->reallocs   = 0;
483817ab2063SBarry Smith 
483969272f91SPierre Jolivet   C->assembled    = A->assembled;
484069272f91SPierre Jolivet   C->preallocated = A->preallocated;
484117ab2063SBarry Smith 
484269272f91SPierre Jolivet   if (A->preallocated) {
48435f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutReference(A->rmap,&C->rmap));
48445f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLayoutReference(A->cmap,&C->cmap));
4845eec197d1SBarry Smith 
48465f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(m,&c->imax));
48475f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt)));
48485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(m,&c->ilen));
48495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt)));
48505f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt)));
485117ab2063SBarry Smith 
485217ab2063SBarry Smith     /* allocate the matrix space */
4853f77e22a1SHong Zhang     if (mallocmatspace) {
48545f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i));
48555f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt)));
48562205254eSKarl Rupp 
4857f1e2ffcdSBarry Smith       c->singlemalloc = PETSC_TRUE;
48582205254eSKarl Rupp 
48595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(c->i,a->i,m+1));
486017ab2063SBarry Smith       if (m > 0) {
48615f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscArraycpy(c->j,a->j,a->i[m]));
4862be6bf707SBarry Smith         if (cpvalues == MAT_COPY_VALUES) {
48632e5835c6SStefano Zampini           const PetscScalar *aa;
48642e5835c6SStefano Zampini 
48655f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
48665f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscArraycpy(c->a,aa,a->i[m]));
48675f80ce2aSJacob Faibussowitsch           CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
4868be6bf707SBarry Smith         } else {
48695f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscArrayzero(c->a,a->i[m]));
487017ab2063SBarry Smith         }
487108480c60SBarry Smith       }
4872f77e22a1SHong Zhang     }
487317ab2063SBarry Smith 
48746ad4291fSHong Zhang     c->ignorezeroentries = a->ignorezeroentries;
4875416022c9SBarry Smith     c->roworiented       = a->roworiented;
4876416022c9SBarry Smith     c->nonew             = a->nonew;
4877416022c9SBarry Smith     if (a->diag) {
48785f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(m+1,&c->diag));
48795f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt)));
48805f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt)));
4881071fcb05SBarry Smith     } else c->diag = NULL;
48822205254eSKarl Rupp 
4883f4259b30SLisandro Dalcin     c->solve_work         = NULL;
4884f4259b30SLisandro Dalcin     c->saved_values       = NULL;
4885f4259b30SLisandro Dalcin     c->idiag              = NULL;
4886f4259b30SLisandro Dalcin     c->ssor_work          = NULL;
4887a9817697SBarry Smith     c->keepnonzeropattern = a->keepnonzeropattern;
4888e6b907acSBarry Smith     c->free_a             = PETSC_TRUE;
4889e6b907acSBarry Smith     c->free_ij            = PETSC_TRUE;
48906ad4291fSHong Zhang 
4891893ad86cSHong Zhang     c->rmax         = a->rmax;
4892416022c9SBarry Smith     c->nz           = a->nz;
48938ed568f8SMatthew G Knepley     c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4894754ec7b1SSatish Balay 
48956ad4291fSHong Zhang     c->compressedrow.use   = a->compressedrow.use;
48966ad4291fSHong Zhang     c->compressedrow.nrows = a->compressedrow.nrows;
4897cd6b891eSBarry Smith     if (a->compressedrow.use) {
48986ad4291fSHong Zhang       i    = a->compressedrow.nrows;
48995f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex));
49005f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1));
49015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i));
490227ea64f8SHong Zhang     } else {
490327ea64f8SHong Zhang       c->compressedrow.use    = PETSC_FALSE;
49040298fd71SBarry Smith       c->compressedrow.i      = NULL;
49050298fd71SBarry Smith       c->compressedrow.rindex = NULL;
49066ad4291fSHong Zhang     }
4907ea632784SBarry Smith     c->nonzerorowcnt = a->nonzerorowcnt;
4908e56f5c9eSBarry Smith     C->nonzerostate  = A->nonzerostate;
49094846f1f5SKris Buschelman 
49105f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C));
491169272f91SPierre Jolivet   }
49125f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist));
49133a40ed3dSBarry Smith   PetscFunctionReturn(0);
491417ab2063SBarry Smith }
491517ab2063SBarry Smith 
4916b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4917b24902e0SBarry Smith {
4918b24902e0SBarry Smith   PetscFunctionBegin;
49195f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PetscObjectComm((PetscObject)A),B));
49205f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n));
4921cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
49225f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetBlockSizesFromMats(*B,A,A));
4923cfd3f464SBarry Smith   }
49245f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*B,((PetscObject)A)->type_name));
49255f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE));
4926b24902e0SBarry Smith   PetscFunctionReturn(0);
4927b24902e0SBarry Smith }
4928b24902e0SBarry Smith 
4929112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4930fbdbba38SShri Abhyankar {
493152f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
493252f91c60SVaclav Hapla 
493352f91c60SVaclav Hapla   PetscFunctionBegin;
493452f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
493552f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4936c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
49375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetUp(viewer));
49385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
49395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5));
494052f91c60SVaclav Hapla   if (isbinary) {
49415f80ce2aSJacob Faibussowitsch     CHKERRQ(MatLoad_SeqAIJ_Binary(newMat,viewer));
494252f91c60SVaclav Hapla   } else if (ishdf5) {
494352f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
49445f80ce2aSJacob Faibussowitsch     CHKERRQ(MatLoad_AIJ_HDF5(newMat,viewer));
494552f91c60SVaclav Hapla #else
494652f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
494752f91c60SVaclav Hapla #endif
494852f91c60SVaclav Hapla   } else {
494998921bdaSJacob 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);
495052f91c60SVaclav Hapla   }
495152f91c60SVaclav Hapla   PetscFunctionReturn(0);
495252f91c60SVaclav Hapla }
495352f91c60SVaclav Hapla 
49543ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
495552f91c60SVaclav Hapla {
49563ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
49573ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4958fbdbba38SShri Abhyankar 
4959fbdbba38SShri Abhyankar   PetscFunctionBegin;
49605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetUp(viewer));
4961bbead8a2SBarry Smith 
49623ea6fe3dSLisandro Dalcin   /* read in matrix header */
49635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT));
49642c71b3e2SJacob Faibussowitsch   PetscCheckFalse(header[0] != MAT_FILE_CLASSID,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4965fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
49662c71b3e2SJacob Faibussowitsch   PetscCheckFalse(M < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%" PetscInt_FMT ") in file is negative",M);
49672c71b3e2SJacob Faibussowitsch   PetscCheckFalse(N < 0,PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%" PetscInt_FMT ") in file is negative",N);
49682c71b3e2SJacob Faibussowitsch   PetscCheckFalse(nz < 0,PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4969fbdbba38SShri Abhyankar 
49703ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
49715f80ce2aSJacob Faibussowitsch   CHKERRQ(MatLoad_Binary_BlockSizes(mat,viewer));
49723ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
49733ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
49743ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
49753ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
49763ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
49775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(mat->rmap));
49785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLayoutSetUp(mat->cmap));
49793ea6fe3dSLisandro Dalcin 
49803ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
49815f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(mat,&rows,&cols));
49822c71b3e2SJacob 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);
49833ea6fe3dSLisandro Dalcin 
4984fbdbba38SShri Abhyankar   /* read in row lengths */
49855f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(M,&rowlens));
49865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT));
49873ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
49883ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
49892c71b3e2SJacob 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);
49903ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
49915f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens));
49925f80ce2aSJacob Faibussowitsch   CHKERRQ(MatGetSize(mat,&rows,&cols));
49932c71b3e2SJacob 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);
49943ea6fe3dSLisandro Dalcin   /* store row lengths */
49955f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycpy(a->ilen,rowlens,M));
49965f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(rowlens));
4997fbdbba38SShri Abhyankar 
49983ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
49993ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
50003ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
50015f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT));
50023ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
50035f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR));
5004fbdbba38SShri Abhyankar 
50055f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY));
50065f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY));
5007fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
5008fbdbba38SShri Abhyankar }
5009fbdbba38SShri Abhyankar 
5010ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
50117264ac53SSatish Balay {
50127264ac53SSatish Balay   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
5013fff043a9SJunchao Zhang   const PetscScalar *aa,*ba;
5014eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5015eeffb40dSHong Zhang   PetscInt k;
5016eeffb40dSHong Zhang #endif
50177264ac53SSatish Balay 
50183a40ed3dSBarry Smith   PetscFunctionBegin;
5019bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
5020d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
5021ca44d042SBarry Smith     *flg = PETSC_FALSE;
5022ca44d042SBarry Smith     PetscFunctionReturn(0);
5023bcd2baecSBarry Smith   }
50247264ac53SSatish Balay 
50257264ac53SSatish Balay   /* if the a->i are the same */
50265f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycmp(a->i,b->i,A->rmap->n+1,flg));
5027abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
50287264ac53SSatish Balay 
50297264ac53SSatish Balay   /* if a->j are the same */
50305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycmp(a->j,b->j,a->nz,flg));
5031abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
5032bcd2baecSBarry Smith 
50335f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(A,&aa));
50345f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJGetArrayRead(B,&ba));
5035bcd2baecSBarry Smith   /* if a->a are the same */
5036eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
5037eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
5038fff043a9SJunchao Zhang     if (PetscRealPart(aa[k]) != PetscRealPart(ba[k]) || PetscImaginaryPart(aa[k]) != PetscImaginaryPart(ba[k])) {
5039eeffb40dSHong Zhang       *flg = PETSC_FALSE;
50403a40ed3dSBarry Smith       PetscFunctionReturn(0);
5041eeffb40dSHong Zhang     }
5042eeffb40dSHong Zhang   }
5043eeffb40dSHong Zhang #else
50445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscArraycmp(aa,ba,a->nz,flg));
5045eeffb40dSHong Zhang #endif
50465f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(A,&aa));
50475f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRestoreArrayRead(B,&ba));
5048eeffb40dSHong Zhang   PetscFunctionReturn(0);
50497264ac53SSatish Balay }
505036db0b34SBarry Smith 
505105869f15SSatish Balay /*@
505236db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
505336db0b34SBarry Smith               provided by the user.
505436db0b34SBarry Smith 
5055d083f849SBarry Smith       Collective
505636db0b34SBarry Smith 
505736db0b34SBarry Smith    Input Parameters:
505836db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
505936db0b34SBarry Smith .   m - number of rows
506036db0b34SBarry Smith .   n - number of columns
5061483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
506236db0b34SBarry Smith .   j - column indices
506336db0b34SBarry Smith -   a - matrix values
506436db0b34SBarry Smith 
506536db0b34SBarry Smith    Output Parameter:
506636db0b34SBarry Smith .   mat - the matrix
506736db0b34SBarry Smith 
506836db0b34SBarry Smith    Level: intermediate
506936db0b34SBarry Smith 
507036db0b34SBarry Smith    Notes:
50710551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5072292fb18eSBarry Smith     once the matrix is destroyed and not before
507336db0b34SBarry Smith 
507436db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
507536db0b34SBarry Smith 
5076bfeeae90SHong Zhang        The i and j indices are 0 based
507736db0b34SBarry Smith 
5078a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5079a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
50808eef79e4SBarry Smith     as shown
5081a4552177SSatish Balay 
50828eef79e4SBarry Smith $        1 0 0
50838eef79e4SBarry Smith $        2 0 3
50848eef79e4SBarry Smith $        4 5 6
50858eef79e4SBarry Smith $
50868eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
50878eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
50888eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5089a4552177SSatish Balay 
509069b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
509136db0b34SBarry Smith 
509236db0b34SBarry Smith @*/
5093c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
509436db0b34SBarry Smith {
5095cbcfb4deSHong Zhang   PetscInt       ii;
509636db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5097cbcfb4deSHong Zhang   PetscInt jj;
509836db0b34SBarry Smith 
509936db0b34SBarry Smith   PetscFunctionBegin;
51002c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m > 0 && i[0],PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
51015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,mat));
51025f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*mat,m,n,m,n));
51035f80ce2aSJacob Faibussowitsch   /* CHKERRQ(MatSetBlockSizes(*mat,,)); */
51045f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*mat,MATSEQAIJ));
51055f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL));
5106ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
51075f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m,&aij->imax));
51085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(m,&aij->ilen));
5109ab93d7beSBarry Smith 
511036db0b34SBarry Smith   aij->i            = i;
511136db0b34SBarry Smith   aij->j            = j;
511236db0b34SBarry Smith   aij->a            = a;
511336db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
511436db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5115e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5116e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
511736db0b34SBarry Smith 
5118cbc6b225SStefano Zampini   for (ii=0,aij->nonzerorowcnt=0,aij->rmax=0; ii<m; ii++) {
511936db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
512076bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
51212c71b3e2SJacob 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]);
51229985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
51232c71b3e2SJacob 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);
51242c71b3e2SJacob 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);
51259985e31cSBarry Smith       }
512636db0b34SBarry Smith     }
512776bd3646SJed Brown   }
512876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
512936db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
51302c71b3e2SJacob 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]);
51312c71b3e2SJacob 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]);
513236db0b34SBarry Smith     }
513376bd3646SJed Brown   }
513436db0b34SBarry Smith 
51355f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY));
51365f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY));
513736db0b34SBarry Smith   PetscFunctionReturn(0);
513836db0b34SBarry Smith }
5139cbc6b225SStefano Zampini 
514080ef6e79SMatthew G Knepley /*@C
5141d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
51428a0b0e6bSVictor Minden               provided by the user.
51438a0b0e6bSVictor Minden 
5144d083f849SBarry Smith       Collective
51458a0b0e6bSVictor Minden 
51468a0b0e6bSVictor Minden    Input Parameters:
51478a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
51488a0b0e6bSVictor Minden .   m   - number of rows
51498a0b0e6bSVictor Minden .   n   - number of columns
51508a0b0e6bSVictor Minden .   i   - row indices
51518a0b0e6bSVictor Minden .   j   - column indices
51521230e6d1SVictor Minden .   a   - matrix values
51531230e6d1SVictor Minden .   nz  - number of nonzeros
51541230e6d1SVictor Minden -   idx - 0 or 1 based
51558a0b0e6bSVictor Minden 
51568a0b0e6bSVictor Minden    Output Parameter:
51578a0b0e6bSVictor Minden .   mat - the matrix
51588a0b0e6bSVictor Minden 
51598a0b0e6bSVictor Minden    Level: intermediate
51608a0b0e6bSVictor Minden 
51618a0b0e6bSVictor Minden    Notes:
51629e99939fSJunchao 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,
51639e99939fSJunchao Zhang        the input data expected is as shown
51649e99939fSJunchao Zhang .vb
51658a0b0e6bSVictor Minden         1 0 0
51668a0b0e6bSVictor Minden         2 0 3
51678a0b0e6bSVictor Minden         4 5 6
51688a0b0e6bSVictor Minden 
51698a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
51708a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
51718a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
51729e99939fSJunchao Zhang .ve
51738a0b0e6bSVictor Minden 
517469b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
51758a0b0e6bSVictor Minden 
51768a0b0e6bSVictor Minden @*/
5177c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
51788a0b0e6bSVictor Minden {
5179d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
51808a0b0e6bSVictor Minden 
51818a0b0e6bSVictor Minden   PetscFunctionBegin;
51825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscCalloc1(m,&nnz));
51831230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5184c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
51851230e6d1SVictor Minden   }
51865f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,mat));
51875f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(*mat,m,n,m,n));
51885f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(*mat,MATSEQAIJ));
51895f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz));
51901230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
51911230e6d1SVictor Minden     if (idx) {
51921230e6d1SVictor Minden       row = i[ii] - 1;
51931230e6d1SVictor Minden       col = j[ii] - 1;
51941230e6d1SVictor Minden     } else {
51951230e6d1SVictor Minden       row = i[ii];
51961230e6d1SVictor Minden       col = j[ii];
51978a0b0e6bSVictor Minden     }
51985f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES));
51998a0b0e6bSVictor Minden   }
52005f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY));
52015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY));
52025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(nnz));
52038a0b0e6bSVictor Minden   PetscFunctionReturn(0);
52048a0b0e6bSVictor Minden }
520536db0b34SBarry Smith 
5206acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5207acf2f550SJed Brown {
5208acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5209acf2f550SJed Brown 
5210acf2f550SJed Brown   PetscFunctionBegin;
5211acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5212acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
52132205254eSKarl Rupp 
52145f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJInvalidateDiagonal_Inode(A));
5215acf2f550SJed Brown   PetscFunctionReturn(0);
5216acf2f550SJed Brown }
5217acf2f550SJed Brown 
52189c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
52199c8f2541SHong Zhang {
52208761c3d6SHong Zhang   PetscMPIInt    size;
52219c8f2541SHong Zhang 
52229c8f2541SHong Zhang   PetscFunctionBegin;
52235f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
52247bbdc51dSHong Zhang   if (size == 1) {
52257bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
52265f80ce2aSJacob Faibussowitsch       CHKERRQ(MatDuplicate(inmat,MAT_COPY_VALUES,outmat));
52277bbdc51dSHong Zhang     } else {
52285f80ce2aSJacob Faibussowitsch       CHKERRQ(MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN));
52297bbdc51dSHong Zhang     }
52308761c3d6SHong Zhang   } else {
52315f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat));
52328761c3d6SHong Zhang   }
52339c8f2541SHong Zhang   PetscFunctionReturn(0);
52349c8f2541SHong Zhang }
52359c8f2541SHong Zhang 
523681824310SBarry Smith /*
523753dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
523853dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
523953dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
524053dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
524153dd7562SDmitry Karpeev  */
524253dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
524353dd7562SDmitry Karpeev {
524453dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
524553dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
524653dd7562SDmitry Karpeev   PetscBool      seqaij;
524753dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
524853dd7562SDmitry Karpeev   PetscScalar    v;
524953dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
525053dd7562SDmitry Karpeev 
525153dd7562SDmitry Karpeev   PetscFunctionBegin;
525253dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
525353dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
52545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij));
5255*28b400f6SJacob Faibussowitsch   PetscCheck(seqaij,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
525653dd7562SDmitry Karpeev   if (rowemb) {
52575f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(rowemb,&m));
52582c71b3e2SJacob 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);
525953dd7562SDmitry Karpeev   } else {
52602c71b3e2SJacob Faibussowitsch     PetscCheckFalse(C->rmap->n != B->rmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
526153dd7562SDmitry Karpeev   }
526253dd7562SDmitry Karpeev   if (colemb) {
52635f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetLocalSize(colemb,&n));
52642c71b3e2SJacob 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);
526553dd7562SDmitry Karpeev   } else {
52662c71b3e2SJacob Faibussowitsch     PetscCheckFalse(C->cmap->n != B->cmap->n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
526753dd7562SDmitry Karpeev   }
526853dd7562SDmitry Karpeev 
526953dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
527053dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
52715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(B->rmap->n,&nz));
527253dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
527353dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
527453dd7562SDmitry Karpeev     }
52755f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSeqAIJSetPreallocation(C,0,nz));
52765f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(nz));
527753dd7562SDmitry Karpeev   }
527853dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
52795f80ce2aSJacob Faibussowitsch     CHKERRQ(MatZeroEntries(C));
528053dd7562SDmitry Karpeev   }
528153dd7562SDmitry Karpeev   count = 0;
528253dd7562SDmitry Karpeev   rowindices = NULL;
528353dd7562SDmitry Karpeev   colindices = NULL;
528453dd7562SDmitry Karpeev   if (rowemb) {
52855f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(rowemb,&rowindices));
528653dd7562SDmitry Karpeev   }
528753dd7562SDmitry Karpeev   if (colemb) {
52885f80ce2aSJacob Faibussowitsch     CHKERRQ(ISGetIndices(colemb,&colindices));
528953dd7562SDmitry Karpeev   }
529053dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
529153dd7562SDmitry Karpeev     PetscInt row;
529253dd7562SDmitry Karpeev     row = i;
529353dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
529453dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
529553dd7562SDmitry Karpeev       PetscInt col;
529653dd7562SDmitry Karpeev       col  = Baij->j[count];
529753dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
529853dd7562SDmitry Karpeev       v    = Baij->a[count];
52995f80ce2aSJacob Faibussowitsch       CHKERRQ(MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES));
530053dd7562SDmitry Karpeev       ++count;
530153dd7562SDmitry Karpeev     }
530253dd7562SDmitry Karpeev   }
530353dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
530453dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
530553dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
530653dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
530753dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
530853dd7562SDmitry Karpeev   PetscFunctionReturn(0);
530953dd7562SDmitry Karpeev }
531053dd7562SDmitry Karpeev 
53114099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
53124099cc6bSBarry Smith 
53134099cc6bSBarry Smith /*@C
53144099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
53154099cc6bSBarry Smith 
53164099cc6bSBarry Smith    Collective on Mat
53174099cc6bSBarry Smith 
53184099cc6bSBarry Smith    Input Parameters:
53194099cc6bSBarry Smith +  mat      - the matrix object
53204099cc6bSBarry Smith -  matype   - matrix type
53214099cc6bSBarry Smith 
53224099cc6bSBarry Smith    Options Database Key:
53234099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
53244099cc6bSBarry Smith 
53254099cc6bSBarry Smith   Level: intermediate
53264099cc6bSBarry Smith 
53274099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
53284099cc6bSBarry Smith @*/
53294099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
53304099cc6bSBarry Smith {
53314099cc6bSBarry Smith   PetscBool      sametype;
53325f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Mat,MatType,MatReuse,Mat*);
53334099cc6bSBarry Smith 
53344099cc6bSBarry Smith   PetscFunctionBegin;
53354099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
53365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectTypeCompare((PetscObject)mat,matype,&sametype));
53374099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
53384099cc6bSBarry Smith 
53395f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFunctionListFind(MatSeqAIJList,matype,&r));
53405f80ce2aSJacob Faibussowitsch   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
53415f80ce2aSJacob Faibussowitsch   CHKERRQ((*r)(mat,matype,MAT_INPLACE_MATRIX,&mat));
53424099cc6bSBarry Smith   PetscFunctionReturn(0);
53434099cc6bSBarry Smith }
53444099cc6bSBarry Smith 
53454099cc6bSBarry Smith /*@C
53464099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
53474099cc6bSBarry Smith 
53484099cc6bSBarry Smith    Not Collective
53494099cc6bSBarry Smith 
53504099cc6bSBarry Smith    Input Parameters:
53514099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
53524099cc6bSBarry Smith -  function - routine to convert to subtype
53534099cc6bSBarry Smith 
53544099cc6bSBarry Smith    Notes:
53554099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
53564099cc6bSBarry Smith 
53574099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
53584099cc6bSBarry Smith $     -mat_seqaij_type my_mat
53594099cc6bSBarry Smith 
53604099cc6bSBarry Smith    Level: advanced
53614099cc6bSBarry Smith 
53624099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
53634099cc6bSBarry Smith 
53644099cc6bSBarry Smith   Level: advanced
53654099cc6bSBarry Smith @*/
5366388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
53674099cc6bSBarry Smith {
53684099cc6bSBarry Smith   PetscFunctionBegin;
53695f80ce2aSJacob Faibussowitsch   CHKERRQ(MatInitializePackage());
53705f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFunctionListAdd(&MatSeqAIJList,sname,function));
53714099cc6bSBarry Smith   PetscFunctionReturn(0);
53724099cc6bSBarry Smith }
53734099cc6bSBarry Smith 
53744099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
53754099cc6bSBarry Smith 
53764099cc6bSBarry Smith /*@C
53774099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
53784099cc6bSBarry Smith 
53794099cc6bSBarry Smith   Not Collective
53804099cc6bSBarry Smith 
53814099cc6bSBarry Smith   Level: advanced
53824099cc6bSBarry Smith 
53834099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
53844099cc6bSBarry Smith @*/
53854099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
53864099cc6bSBarry Smith {
53874099cc6bSBarry Smith   PetscFunctionBegin;
53884099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
53894099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
53904099cc6bSBarry Smith 
53915f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL));
53925f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM));
53935f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL));
53949779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
53955f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL));
5396485f9817SRichard Tran Mills #endif
53975063d097SStefano Zampini #if defined(PETSC_HAVE_CUDA)
53985f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRegister(MATSEQAIJCUSPARSE, MatConvert_SeqAIJ_SeqAIJCUSPARSE));
53995063d097SStefano Zampini #endif
54005063d097SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
54015f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRegister(MATSEQAIJKOKKOS,   MatConvert_SeqAIJ_SeqAIJKokkos));
54025063d097SStefano Zampini #endif
54034099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
54045f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL));
54054099cc6bSBarry Smith #endif
54064099cc6bSBarry Smith   PetscFunctionReturn(0);
54074099cc6bSBarry Smith }
540853dd7562SDmitry Karpeev 
540953dd7562SDmitry Karpeev /*
541081824310SBarry Smith     Special version for direct calls from Fortran
541181824310SBarry Smith */
5412af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
541381824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
541481824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
541581824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
541681824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
541781824310SBarry Smith #endif
541881824310SBarry Smith 
541981824310SBarry Smith /* Change these macros so can be used in void function */
542098921bdaSJacob Faibussowitsch 
542198921bdaSJacob Faibussowitsch /* Change these macros so can be used in void function */
542298921bdaSJacob Faibussowitsch /* Identical to CHKERRV, except it assigns to *_ierr */
542381824310SBarry Smith #undef CHKERRQ
54245f80ce2aSJacob Faibussowitsch #define CHKERRQ(...) do {                                                                      \
54255f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr_msv_mpiaij = __VA_ARGS__;                                              \
542698921bdaSJacob Faibussowitsch     if (PetscUnlikely(ierr_msv_mpiaij)) {                                                      \
542798921bdaSJacob Faibussowitsch       *_ierr = PetscError(PETSC_COMM_SELF,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr_msv_mpiaij,PETSC_ERROR_REPEAT," "); \
542898921bdaSJacob Faibussowitsch       return;                                                                                  \
542998921bdaSJacob Faibussowitsch     }                                                                                          \
543098921bdaSJacob Faibussowitsch   } while (0)
543198921bdaSJacob Faibussowitsch 
543298921bdaSJacob Faibussowitsch #undef SETERRQ
543398921bdaSJacob Faibussowitsch #define SETERRQ(comm,ierr,...) do {                                                            \
543498921bdaSJacob Faibussowitsch     *_ierr = PetscError(comm,__LINE__,PETSC_FUNCTION_NAME,__FILE__,ierr,PETSC_ERROR_INITIAL,__VA_ARGS__); \
543598921bdaSJacob Faibussowitsch     return;                                                                                    \
543698921bdaSJacob Faibussowitsch   } while (0)
543781824310SBarry Smith 
543819caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
543981824310SBarry Smith {
544081824310SBarry Smith   Mat            A  = *AA;
544181824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
544281824310SBarry Smith   InsertMode     is = *isis;
544381824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
544481824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
544581824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
544681824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
544754f21887SBarry Smith   MatScalar      *ap,value,*aa;
5448ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5449ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
545081824310SBarry Smith 
545181824310SBarry Smith   PetscFunctionBegin;
54524994cf47SJed Brown   MatCheckPreallocated(A,1);
545381824310SBarry Smith   imax  = a->imax;
545481824310SBarry Smith   ai    = a->i;
545581824310SBarry Smith   ailen = a->ilen;
545681824310SBarry Smith   aj    = a->j;
545781824310SBarry Smith   aa    = a->a;
545881824310SBarry Smith 
545981824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
546081824310SBarry Smith     row = im[k];
546181824310SBarry Smith     if (row < 0) continue;
54625f80ce2aSJacob Faibussowitsch     PetscCheck(row < A->rmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
546381824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
546481824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
546581824310SBarry Smith     low  = 0;
546681824310SBarry Smith     high = nrow;
546781824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
546881824310SBarry Smith       if (in[l] < 0) continue;
54695f80ce2aSJacob Faibussowitsch       PetscCheck(in[l] < A->cmap->n,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
547081824310SBarry Smith       col = in[l];
54712205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
54722205254eSKarl Rupp       else value = v[k + l*m];
54732205254eSKarl Rupp 
547481824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
547581824310SBarry Smith 
54762205254eSKarl Rupp       if (col <= lastcol) low = 0;
54772205254eSKarl Rupp       else high = nrow;
547881824310SBarry Smith       lastcol = col;
547981824310SBarry Smith       while (high-low > 5) {
548081824310SBarry Smith         t = (low+high)/2;
548181824310SBarry Smith         if (rp[t] > col) high = t;
548281824310SBarry Smith         else             low  = t;
548381824310SBarry Smith       }
548481824310SBarry Smith       for (i=low; i<high; i++) {
548581824310SBarry Smith         if (rp[i] > col) break;
548681824310SBarry Smith         if (rp[i] == col) {
548781824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
548881824310SBarry Smith           else                  ap[i] = value;
548981824310SBarry Smith           goto noinsert;
549081824310SBarry Smith         }
549181824310SBarry Smith       }
549281824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
549381824310SBarry Smith       if (nonew == 1) goto noinsert;
54945f80ce2aSJacob Faibussowitsch       PetscCheck(nonew != -1,PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5495fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
549681824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
549781824310SBarry Smith       /* shift up all the later entries in this row */
549881824310SBarry Smith       for (ii=N; ii>=i; ii--) {
549981824310SBarry Smith         rp[ii+1] = rp[ii];
550081824310SBarry Smith         ap[ii+1] = ap[ii];
550181824310SBarry Smith       }
550281824310SBarry Smith       rp[i] = col;
550381824310SBarry Smith       ap[i] = value;
5504e56f5c9eSBarry Smith       A->nonzerostate++;
550581824310SBarry Smith noinsert:;
550681824310SBarry Smith       low = i + 1;
550781824310SBarry Smith     }
550881824310SBarry Smith     ailen[row] = nrow;
550981824310SBarry Smith   }
551081824310SBarry Smith   PetscFunctionReturnVoid();
551181824310SBarry Smith }
551298921bdaSJacob Faibussowitsch /* Undefining these here since they were redefined from their original definition above! No
551398921bdaSJacob Faibussowitsch  * other PETSc functions should be defined past this point, as it is impossible to recover the
551498921bdaSJacob Faibussowitsch  * original definitions */
551598921bdaSJacob Faibussowitsch #undef CHKERRQ
551698921bdaSJacob Faibussowitsch #undef SETERRQ
5517