xref: /petsc/src/mat/impls/aij/seq/aij.c (revision a873a8cd69acc6fd9b12ad3d6b30ee1bf0a81da9)
1d5d45c9bSBarry Smith /*
23369ce9aSBarry Smith     Defines the basic matrix operations for the AIJ (compressed row)
3d5d45c9bSBarry Smith   matrix storage format.
4d5d45c9bSBarry Smith */
53369ce9aSBarry Smith 
6c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/aij.h>          /*I "petscmat.h" I*/
7c6db04a5SJed Brown #include <petscblaslapack.h>
8c6db04a5SJed Brown #include <petscbt.h>
9af0996ceSBarry Smith #include <petsc/private/kernels/blocktranspose.h>
100716a85fSBarry Smith 
114099cc6bSBarry Smith PetscErrorCode MatSeqAIJSetTypeFromOptions(Mat A)
124099cc6bSBarry Smith {
134099cc6bSBarry Smith   PetscErrorCode       ierr;
144099cc6bSBarry Smith   PetscBool            flg;
154099cc6bSBarry Smith   char                 type[256];
164099cc6bSBarry Smith 
174099cc6bSBarry Smith   PetscFunctionBegin;
181e1ea65dSPierre Jolivet   ierr = PetscObjectOptionsBegin((PetscObject)A);CHKERRQ(ierr);
194099cc6bSBarry Smith   ierr = PetscOptionsFList("-mat_seqaij_type","Matrix SeqAIJ type","MatSeqAIJSetType",MatSeqAIJList,"seqaij",type,256,&flg);CHKERRQ(ierr);
204099cc6bSBarry Smith   if (flg) {
214099cc6bSBarry Smith     ierr = MatSeqAIJSetType(A,type);CHKERRQ(ierr);
224099cc6bSBarry Smith   }
234099cc6bSBarry Smith   ierr = PetscOptionsEnd();CHKERRQ(ierr);
244099cc6bSBarry Smith   PetscFunctionReturn(0);
254099cc6bSBarry Smith }
264099cc6bSBarry Smith 
27*a873a8cdSSam Reynolds PetscErrorCode MatGetColumnReductions_SeqAIJ(Mat A,ReductionType type,PetscReal *reductions)
280716a85fSBarry Smith {
290716a85fSBarry Smith   PetscErrorCode ierr;
300716a85fSBarry Smith   PetscInt       i,m,n;
310716a85fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
320716a85fSBarry Smith 
330716a85fSBarry Smith   PetscFunctionBegin;
340716a85fSBarry Smith   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
35*a873a8cdSSam Reynolds   ierr = PetscArrayzero(reductions,n);CHKERRQ(ierr);
36*a873a8cdSSam Reynolds   if (type == REDUCTION_NORM_2) {
370716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
38*a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]*aij->a[i]);
390716a85fSBarry Smith     }
40*a873a8cdSSam Reynolds   } else if (type == REDUCTION_NORM_1) {
410716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
42*a873a8cdSSam Reynolds       reductions[aij->j[i]] += PetscAbsScalar(aij->a[i]);
430716a85fSBarry Smith     }
44*a873a8cdSSam Reynolds   } else if (type == REDUCTION_NORM_INFINITY) {
450716a85fSBarry Smith     for (i=0; i<aij->i[m]; i++) {
46*a873a8cdSSam Reynolds       reductions[aij->j[i]] = PetscMax(PetscAbsScalar(aij->a[i]),reductions[aij->j[i]]);
470716a85fSBarry Smith     }
48*a873a8cdSSam Reynolds   } else if (type == REDUCTION_SUM || type == REDUCTION_MEAN) {
49*a873a8cdSSam Reynolds     for (i=0; i<aij->i[m]; i++) {
50*a873a8cdSSam Reynolds       reductions[aij->j[i]] += aij->a[i];
51*a873a8cdSSam Reynolds     }
52*a873a8cdSSam Reynolds   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Unknown ReductionType");
530716a85fSBarry Smith 
54*a873a8cdSSam Reynolds   if (type == REDUCTION_NORM_2) {
55*a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
56*a873a8cdSSam Reynolds   } else if (type == REDUCTION_MEAN) {
57*a873a8cdSSam Reynolds     for (i=0; i<n; i++) reductions[i] /= m;
580716a85fSBarry Smith   }
590716a85fSBarry Smith   PetscFunctionReturn(0);
600716a85fSBarry Smith }
610716a85fSBarry Smith 
623a062f41SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_SeqAIJ(Mat A,IS *is)
633a062f41SBarry Smith {
643a062f41SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
653a062f41SBarry Smith   PetscInt        i,m=A->rmap->n,cnt = 0, bs = A->rmap->bs;
663a062f41SBarry Smith   const PetscInt  *jj = a->j,*ii = a->i;
673a062f41SBarry Smith   PetscInt        *rows;
683a062f41SBarry Smith   PetscErrorCode  ierr;
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   }
763a062f41SBarry Smith   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
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   }
843a062f41SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,is);CHKERRQ(ierr);
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;
916ce1633cSBarry Smith   const MatScalar *aa = a->a;
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   PetscErrorCode  ierr;
966ce1633cSBarry Smith 
976ce1633cSBarry Smith   PetscFunctionBegin;
986ce1633cSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
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   }
105785e854fSJed Brown   ierr = PetscMalloc1(cnt,&rows);CHKERRQ(ierr);
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;
114f1f41ecbSJed Brown   PetscFunctionReturn(0);
115f1f41ecbSJed Brown }
116f1f41ecbSJed Brown 
117f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_SeqAIJ(Mat A,IS *zrows)
118f1f41ecbSJed Brown {
119f1f41ecbSJed Brown   PetscInt       nrows,*rows;
120f1f41ecbSJed Brown   PetscErrorCode ierr;
121f1f41ecbSJed Brown 
122f1f41ecbSJed Brown   PetscFunctionBegin;
1230298fd71SBarry Smith   *zrows = NULL;
124f1f41ecbSJed Brown   ierr   = MatFindZeroDiagonals_SeqAIJ_Private(A,&nrows,&rows);CHKERRQ(ierr);
125ce94432eSBarry Smith   ierr   = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr);
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   PetscErrorCode  ierr;
137b3a44c85SBarry Smith 
138b3a44c85SBarry Smith   PetscFunctionBegin;
1392e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
140f4259b30SLisandro Dalcin   *keptrows = NULL;
141b3a44c85SBarry Smith   ii        = a->i;
142b3a44c85SBarry Smith   for (i=0; i<m; i++) {
143b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
144b3a44c85SBarry Smith     if (!n) {
145b3a44c85SBarry Smith       cnt++;
146b3a44c85SBarry Smith       goto ok1;
147b3a44c85SBarry Smith     }
1482e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
149b3a44c85SBarry Smith       if (aa[j] != 0.0) goto ok1;
150b3a44c85SBarry Smith     }
151b3a44c85SBarry Smith     cnt++;
152b3a44c85SBarry Smith ok1:;
153b3a44c85SBarry Smith   }
1542e5835c6SStefano Zampini   if (!cnt) {
1552e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
1562e5835c6SStefano Zampini     PetscFunctionReturn(0);
1572e5835c6SStefano Zampini   }
158854ce69bSBarry Smith   ierr = PetscMalloc1(A->rmap->n-cnt,&rows);CHKERRQ(ierr);
159b3a44c85SBarry Smith   cnt  = 0;
160b3a44c85SBarry Smith   for (i=0; i<m; i++) {
161b3a44c85SBarry Smith     n = ii[i+1] - ii[i];
162b3a44c85SBarry Smith     if (!n) continue;
1632e5835c6SStefano Zampini     for (j=ii[i]; j<ii[i+1]; j++) {
164b3a44c85SBarry Smith       if (aa[j] != 0.0) {
165b3a44c85SBarry Smith         rows[cnt++] = i;
166b3a44c85SBarry Smith         break;
167b3a44c85SBarry Smith       }
168b3a44c85SBarry Smith     }
169b3a44c85SBarry Smith   }
1702e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
171b3a44c85SBarry Smith   ierr = ISCreateGeneral(PETSC_COMM_SELF,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr);
172b3a44c85SBarry Smith   PetscFunctionReturn(0);
173b3a44c85SBarry Smith }
174b3a44c85SBarry Smith 
1757087cfbeSBarry Smith PetscErrorCode  MatDiagonalSet_SeqAIJ(Mat Y,Vec D,InsertMode is)
17679299369SBarry Smith {
17779299369SBarry Smith   PetscErrorCode    ierr;
17879299369SBarry Smith   Mat_SeqAIJ        *aij = (Mat_SeqAIJ*) Y->data;
17999e65526SBarry Smith   PetscInt          i,m = Y->rmap->n;
18099e65526SBarry Smith   const PetscInt    *diag;
1812e5835c6SStefano Zampini   MatScalar         *aa;
18299e65526SBarry Smith   const PetscScalar *v;
183ace3abfcSBarry Smith   PetscBool         missing;
1848c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
185837a59e1SRichard Tran Mills   PetscBool         inserted = PETSC_FALSE;
186837a59e1SRichard Tran Mills #endif
18779299369SBarry Smith 
18879299369SBarry Smith   PetscFunctionBegin;
18909f38230SBarry Smith   if (Y->assembled) {
1900298fd71SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(Y,&missing,NULL);CHKERRQ(ierr);
19109f38230SBarry Smith     if (!missing) {
19279299369SBarry Smith       diag = aij->diag;
19399e65526SBarry Smith       ierr = VecGetArrayRead(D,&v);CHKERRQ(ierr);
1942e5835c6SStefano Zampini       ierr = MatSeqAIJGetArray(Y,&aa);CHKERRQ(ierr);
19579299369SBarry Smith       if (is == INSERT_VALUES) {
1968c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
197837a59e1SRichard Tran Mills         inserted = PETSC_TRUE;
198837a59e1SRichard Tran Mills #endif
19979299369SBarry Smith         for (i=0; i<m; i++) {
20079299369SBarry Smith           aa[diag[i]] = v[i];
20179299369SBarry Smith         }
20279299369SBarry Smith       } else {
20379299369SBarry Smith         for (i=0; i<m; i++) {
2048c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
205837a59e1SRichard Tran Mills           if (v[i] != 0.0) inserted = PETSC_TRUE;
206837a59e1SRichard Tran Mills #endif
20779299369SBarry Smith           aa[diag[i]] += v[i];
20879299369SBarry Smith         }
20979299369SBarry Smith       }
2102e5835c6SStefano Zampini       ierr = MatSeqAIJRestoreArray(Y,&aa);CHKERRQ(ierr);
2118c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
212837a59e1SRichard Tran Mills       if (inserted) Y->offloadmask = PETSC_OFFLOAD_CPU;
213837a59e1SRichard Tran Mills #endif
21499e65526SBarry Smith       ierr = VecRestoreArrayRead(D,&v);CHKERRQ(ierr);
21579299369SBarry Smith       PetscFunctionReturn(0);
21679299369SBarry Smith     }
217acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
21809f38230SBarry Smith   }
21909f38230SBarry Smith   ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr);
22009f38230SBarry Smith   PetscFunctionReturn(0);
22109f38230SBarry Smith }
22279299369SBarry Smith 
2231a83f524SJed Brown PetscErrorCode MatGetRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *m,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
22417ab2063SBarry Smith {
225416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
226dfbe8321SBarry Smith   PetscErrorCode ierr;
22797f1f81fSBarry Smith   PetscInt       i,ishift;
22817ab2063SBarry Smith 
2293a40ed3dSBarry Smith   PetscFunctionBegin;
230d0f46423SBarry Smith   *m = A->rmap->n;
2313a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
232bfeeae90SHong Zhang   ishift = 0;
23353e63a63SBarry Smith   if (symmetric && !A->structurally_symmetric) {
2342462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,ishift,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
235bfeeae90SHong Zhang   } else if (oshift == 1) {
2361a83f524SJed Brown     PetscInt *tia;
237d0f46423SBarry Smith     PetscInt nz = a->i[A->rmap->n];
2383b2fbd54SBarry Smith     /* malloc space and  add 1 to i and j indices */
239854ce69bSBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&tia);CHKERRQ(ierr);
2401a83f524SJed Brown     for (i=0; i<A->rmap->n+1; i++) tia[i] = a->i[i] + 1;
2411a83f524SJed Brown     *ia = tia;
242ecc77c7aSBarry Smith     if (ja) {
2431a83f524SJed Brown       PetscInt *tja;
244854ce69bSBarry Smith       ierr = PetscMalloc1(nz+1,&tja);CHKERRQ(ierr);
2451a83f524SJed Brown       for (i=0; i<nz; i++) tja[i] = a->j[i] + 1;
2461a83f524SJed Brown       *ja = tja;
247ecc77c7aSBarry Smith     }
2486945ee14SBarry Smith   } else {
249ecc77c7aSBarry Smith     *ia = a->i;
250ecc77c7aSBarry Smith     if (ja) *ja = a->j;
251a2ce50c7SBarry Smith   }
2523a40ed3dSBarry Smith   PetscFunctionReturn(0);
253a2744918SBarry Smith }
254a2744918SBarry Smith 
2551a83f524SJed Brown PetscErrorCode MatRestoreRowIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2566945ee14SBarry Smith {
257dfbe8321SBarry Smith   PetscErrorCode ierr;
2586945ee14SBarry Smith 
2593a40ed3dSBarry Smith   PetscFunctionBegin;
2603a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
261bfeeae90SHong Zhang   if ((symmetric && !A->structurally_symmetric) || oshift == 1) {
262606d414cSSatish Balay     ierr = PetscFree(*ia);CHKERRQ(ierr);
263ecc77c7aSBarry Smith     if (ja) {ierr = PetscFree(*ja);CHKERRQ(ierr);}
264bcd2baecSBarry Smith   }
2653a40ed3dSBarry Smith   PetscFunctionReturn(0);
26617ab2063SBarry Smith }
26717ab2063SBarry Smith 
2681a83f524SJed Brown PetscErrorCode MatGetColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *nn,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
2693b2fbd54SBarry Smith {
2703b2fbd54SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
271dfbe8321SBarry Smith   PetscErrorCode ierr;
272d0f46423SBarry Smith   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
27397f1f81fSBarry Smith   PetscInt       nz = a->i[m],row,*jj,mr,col;
2743b2fbd54SBarry Smith 
2753a40ed3dSBarry Smith   PetscFunctionBegin;
276899cda47SBarry Smith   *nn = n;
2773a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
2783b2fbd54SBarry Smith   if (symmetric) {
2792462f5fdSStefano Zampini     ierr = MatToSymmetricIJ_SeqAIJ(A->rmap->n,a->i,a->j,PETSC_TRUE,0,oshift,(PetscInt**)ia,(PetscInt**)ja);CHKERRQ(ierr);
2803b2fbd54SBarry Smith   } else {
281b9e7e5c1SBarry Smith     ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
282854ce69bSBarry Smith     ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
283b9e7e5c1SBarry Smith     ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
2843b2fbd54SBarry Smith     jj   = a->j;
2853b2fbd54SBarry Smith     for (i=0; i<nz; i++) {
286bfeeae90SHong Zhang       collengths[jj[i]]++;
2873b2fbd54SBarry Smith     }
2883b2fbd54SBarry Smith     cia[0] = oshift;
2893b2fbd54SBarry Smith     for (i=0; i<n; i++) {
2903b2fbd54SBarry Smith       cia[i+1] = cia[i] + collengths[i];
2913b2fbd54SBarry Smith     }
292580bdb30SBarry Smith     ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
2933b2fbd54SBarry Smith     jj   = a->j;
294a93ec695SBarry Smith     for (row=0; row<m; row++) {
295a93ec695SBarry Smith       mr = a->i[row+1] - a->i[row];
296a93ec695SBarry Smith       for (i=0; i<mr; i++) {
297bfeeae90SHong Zhang         col = *jj++;
2982205254eSKarl Rupp 
2993b2fbd54SBarry Smith         cja[cia[col] + collengths[col]++ - oshift] = row + oshift;
3003b2fbd54SBarry Smith       }
3013b2fbd54SBarry Smith     }
302606d414cSSatish Balay     ierr = PetscFree(collengths);CHKERRQ(ierr);
3033b2fbd54SBarry Smith     *ia  = cia; *ja = cja;
3043b2fbd54SBarry Smith   }
3053a40ed3dSBarry Smith   PetscFunctionReturn(0);
3063b2fbd54SBarry Smith }
3073b2fbd54SBarry Smith 
3081a83f524SJed Brown PetscErrorCode MatRestoreColumnIJ_SeqAIJ(Mat A,PetscInt oshift,PetscBool symmetric,PetscBool inodecompressed,PetscInt *n,const PetscInt *ia[],const PetscInt *ja[],PetscBool  *done)
3093b2fbd54SBarry Smith {
310dfbe8321SBarry Smith   PetscErrorCode ierr;
311606d414cSSatish Balay 
3123a40ed3dSBarry Smith   PetscFunctionBegin;
3133a40ed3dSBarry Smith   if (!ia) PetscFunctionReturn(0);
3143b2fbd54SBarry Smith 
315606d414cSSatish Balay   ierr = PetscFree(*ia);CHKERRQ(ierr);
316606d414cSSatish Balay   ierr = PetscFree(*ja);CHKERRQ(ierr);
3173a40ed3dSBarry Smith   PetscFunctionReturn(0);
3183b2fbd54SBarry Smith }
3193b2fbd54SBarry Smith 
3207cee066cSHong Zhang /*
3217cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ_Color() and MatRestoreColumnIJ_SeqAIJ_Color() are customized from
3227cee066cSHong Zhang  MatGetColumnIJ_SeqAIJ() and MatRestoreColumnIJ_SeqAIJ() by adding an output
323040ebd07SHong Zhang  spidx[], index of a->a, to be used in MatTransposeColoringCreate_SeqAIJ() and MatFDColoringCreate_SeqXAIJ()
3247cee066cSHong Zhang */
3257cee066cSHong 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)
3267cee066cSHong Zhang {
3277cee066cSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
3287cee066cSHong Zhang   PetscErrorCode ierr;
3297cee066cSHong Zhang   PetscInt       i,*collengths,*cia,*cja,n = A->cmap->n,m = A->rmap->n;
330071fcb05SBarry Smith   PetscInt       nz = a->i[m],row,mr,col,tmp;
3317cee066cSHong Zhang   PetscInt       *cspidx;
332071fcb05SBarry Smith   const PetscInt *jj;
3337cee066cSHong Zhang 
3347cee066cSHong Zhang   PetscFunctionBegin;
3357cee066cSHong Zhang   *nn = n;
3367cee066cSHong Zhang   if (!ia) PetscFunctionReturn(0);
337625f6d37SHong Zhang 
338b9e7e5c1SBarry Smith   ierr = PetscCalloc1(n,&collengths);CHKERRQ(ierr);
339854ce69bSBarry Smith   ierr = PetscMalloc1(n+1,&cia);CHKERRQ(ierr);
340b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cja);CHKERRQ(ierr);
341b9e7e5c1SBarry Smith   ierr = PetscMalloc1(nz,&cspidx);CHKERRQ(ierr);
3427cee066cSHong Zhang   jj   = a->j;
3437cee066cSHong Zhang   for (i=0; i<nz; i++) {
3447cee066cSHong Zhang     collengths[jj[i]]++;
3457cee066cSHong Zhang   }
3467cee066cSHong Zhang   cia[0] = oshift;
3477cee066cSHong Zhang   for (i=0; i<n; i++) {
3487cee066cSHong Zhang     cia[i+1] = cia[i] + collengths[i];
3497cee066cSHong Zhang   }
350580bdb30SBarry Smith   ierr = PetscArrayzero(collengths,n);CHKERRQ(ierr);
3517cee066cSHong Zhang   jj   = a->j;
3527cee066cSHong Zhang   for (row=0; row<m; row++) {
3537cee066cSHong Zhang     mr = a->i[row+1] - a->i[row];
3547cee066cSHong Zhang     for (i=0; i<mr; i++) {
3557cee066cSHong Zhang       col         = *jj++;
356071fcb05SBarry Smith       tmp         = cia[col] + collengths[col]++ - oshift;
357071fcb05SBarry Smith       cspidx[tmp] = a->i[row] + i; /* index of a->j */
358071fcb05SBarry Smith       cja[tmp]    = row + oshift;
3597cee066cSHong Zhang     }
3607cee066cSHong Zhang   }
3617cee066cSHong Zhang   ierr   = PetscFree(collengths);CHKERRQ(ierr);
362071fcb05SBarry Smith   *ia    = cia;
363071fcb05SBarry Smith   *ja    = cja;
3647cee066cSHong Zhang   *spidx = cspidx;
3657cee066cSHong Zhang   PetscFunctionReturn(0);
3667cee066cSHong Zhang }
3677cee066cSHong Zhang 
3687cee066cSHong 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)
3697cee066cSHong Zhang {
3707cee066cSHong Zhang   PetscErrorCode ierr;
3717cee066cSHong Zhang 
3727cee066cSHong Zhang   PetscFunctionBegin;
3735243ef75SHong Zhang   ierr = MatRestoreColumnIJ_SeqAIJ(A,oshift,symmetric,inodecompressed,n,ia,ja,done);CHKERRQ(ierr);
3747cee066cSHong Zhang   ierr = PetscFree(*spidx);CHKERRQ(ierr);
3757cee066cSHong Zhang   PetscFunctionReturn(0);
3767cee066cSHong Zhang }
3777cee066cSHong Zhang 
37887d4246cSBarry Smith PetscErrorCode MatSetValuesRow_SeqAIJ(Mat A,PetscInt row,const PetscScalar v[])
37987d4246cSBarry Smith {
38087d4246cSBarry Smith   Mat_SeqAIJ     *a  = (Mat_SeqAIJ*)A->data;
38187d4246cSBarry Smith   PetscInt       *ai = a->i;
38287d4246cSBarry Smith   PetscErrorCode ierr;
38387d4246cSBarry Smith 
38487d4246cSBarry Smith   PetscFunctionBegin;
385580bdb30SBarry Smith   ierr = PetscArraycpy(a->a+ai[row],v,ai[row+1]-ai[row]);CHKERRQ(ierr);
3868c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
387c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && ai[row+1]-ai[row]) A->offloadmask = PETSC_OFFLOAD_CPU;
388e2cf4d64SStefano Zampini #endif
38987d4246cSBarry Smith   PetscFunctionReturn(0);
39087d4246cSBarry Smith }
39187d4246cSBarry Smith 
392bd04181cSBarry Smith /*
393bd04181cSBarry Smith     MatSeqAIJSetValuesLocalFast - An optimized version of MatSetValuesLocal() for SeqAIJ matrices with several assumptions
394bd04181cSBarry Smith 
395bd04181cSBarry Smith       -   a single row of values is set with each call
396bd04181cSBarry Smith       -   no row or column indices are negative or (in error) larger than the number of rows or columns
397bd04181cSBarry Smith       -   the values are always added to the matrix, not set
398bd04181cSBarry Smith       -   no new locations are introduced in the nonzero structure of the matrix
399bd04181cSBarry Smith 
4001f763a69SBarry Smith      This does NOT assume the global column indices are sorted
401bd04181cSBarry Smith 
4021f763a69SBarry Smith */
403bd04181cSBarry Smith 
404af0996ceSBarry Smith #include <petsc/private/isimpl.h>
405189e4007SBarry Smith PetscErrorCode MatSeqAIJSetValuesLocalFast(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
406189e4007SBarry Smith {
407189e4007SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4081f763a69SBarry Smith   PetscInt       low,high,t,row,nrow,i,col,l;
4091f763a69SBarry Smith   const PetscInt *rp,*ai = a->i,*ailen = a->ilen,*aj = a->j;
4101f763a69SBarry Smith   PetscInt       lastcol = -1;
411189e4007SBarry Smith   MatScalar      *ap,value,*aa = a->a;
412189e4007SBarry Smith   const PetscInt *ridx = A->rmap->mapping->indices,*cidx = A->cmap->mapping->indices;
413189e4007SBarry Smith 
414f38dd0b8SBarry Smith   row  = ridx[im[0]];
4151f763a69SBarry Smith   rp   = aj + ai[row];
4161f763a69SBarry Smith   ap   = aa + ai[row];
4171f763a69SBarry Smith   nrow = ailen[row];
418189e4007SBarry Smith   low  = 0;
419189e4007SBarry Smith   high = nrow;
420189e4007SBarry Smith   for (l=0; l<n; l++) { /* loop over added columns */
421189e4007SBarry Smith     col = cidx[in[l]];
422f38dd0b8SBarry Smith     value = v[l];
423189e4007SBarry Smith 
424189e4007SBarry Smith     if (col <= lastcol) low = 0;
425189e4007SBarry Smith     else high = nrow;
426189e4007SBarry Smith     lastcol = col;
427189e4007SBarry Smith     while (high-low > 5) {
428189e4007SBarry Smith       t = (low+high)/2;
429189e4007SBarry Smith       if (rp[t] > col) high = t;
430189e4007SBarry Smith       else low = t;
431189e4007SBarry Smith     }
432189e4007SBarry Smith     for (i=low; i<high; i++) {
433189e4007SBarry Smith       if (rp[i] == col) {
4341f763a69SBarry Smith         ap[i] += value;
435189e4007SBarry Smith         low = i + 1;
4361f763a69SBarry Smith         break;
437189e4007SBarry Smith       }
438189e4007SBarry Smith     }
439189e4007SBarry Smith   }
4408c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
441c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
442e2cf4d64SStefano Zampini #endif
443f38dd0b8SBarry Smith   return 0;
444189e4007SBarry Smith }
445189e4007SBarry Smith 
44697f1f81fSBarry Smith PetscErrorCode MatSetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
44717ab2063SBarry Smith {
448416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
449e2ee6c50SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
45097f1f81fSBarry Smith   PetscInt       *imax = a->imax,*ai = a->i,*ailen = a->ilen;
4516849ba73SBarry Smith   PetscErrorCode ierr;
452e2ee6c50SBarry Smith   PetscInt       *aj = a->j,nonew = a->nonew,lastcol = -1;
453ce496241SStefano Zampini   MatScalar      *ap=NULL,value=0.0,*aa;
454ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
455ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
4568c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
457e2cf4d64SStefano Zampini   PetscBool      inserted          = PETSC_FALSE;
458e2cf4d64SStefano Zampini #endif
45917ab2063SBarry Smith 
4603a40ed3dSBarry Smith   PetscFunctionBegin;
461ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
462ce496241SStefano Zampini   if (A->offloadmask == PETSC_OFFLOAD_GPU) {
463ce496241SStefano Zampini     const PetscScalar *dummy;
464ce496241SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&dummy);CHKERRQ(ierr);
465ce496241SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&dummy);CHKERRQ(ierr);
466ce496241SStefano Zampini   }
467ce496241SStefano Zampini #endif
468ce496241SStefano Zampini   aa = a->a;
46917ab2063SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
470416022c9SBarry Smith     row = im[k];
4715ef9f2a5SBarry Smith     if (row < 0) continue;
472cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
473720833daSHong Zhang     rp   = aj + ai[row];
474876c6284SHong Zhang     if (!A->structure_only) ap = aa + ai[row];
47517ab2063SBarry Smith     rmax = imax[row]; nrow = ailen[row];
476416022c9SBarry Smith     low  = 0;
477c71e6ed7SBarry Smith     high = nrow;
47817ab2063SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
4795ef9f2a5SBarry Smith       if (in[l] < 0) continue;
480cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
481bfeeae90SHong Zhang       col = in[l];
482071fcb05SBarry Smith       if (v && !A->structure_only) value = roworiented ? v[l + k*n] : v[k + l*m];
483071fcb05SBarry Smith       if (!A->structure_only && value == 0.0 && ignorezeroentries && is == ADD_VALUES && row != col) continue;
48436db0b34SBarry Smith 
4852205254eSKarl Rupp       if (col <= lastcol) low = 0;
4862205254eSKarl Rupp       else high = nrow;
487e2ee6c50SBarry Smith       lastcol = col;
488416022c9SBarry Smith       while (high-low > 5) {
489416022c9SBarry Smith         t = (low+high)/2;
490416022c9SBarry Smith         if (rp[t] > col) high = t;
491416022c9SBarry Smith         else low = t;
49217ab2063SBarry Smith       }
493416022c9SBarry Smith       for (i=low; i<high; i++) {
49417ab2063SBarry Smith         if (rp[i] > col) break;
49517ab2063SBarry Smith         if (rp[i] == col) {
496876c6284SHong Zhang           if (!A->structure_only) {
4970c0d7e18SFande Kong             if (is == ADD_VALUES) {
4980c0d7e18SFande Kong               ap[i] += value;
4990c0d7e18SFande Kong               (void)PetscLogFlops(1.0);
5000c0d7e18SFande Kong             }
50117ab2063SBarry Smith             else ap[i] = value;
5028c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
503e2cf4d64SStefano Zampini             inserted = PETSC_TRUE;
504e2cf4d64SStefano Zampini #endif
505720833daSHong Zhang           }
506e44c0bd4SBarry Smith           low = i + 1;
50717ab2063SBarry Smith           goto noinsert;
50817ab2063SBarry Smith         }
50917ab2063SBarry Smith       }
510dcd36c23SBarry Smith       if (value == 0.0 && ignorezeroentries && row != col) goto noinsert;
511c2653b3dSLois Curfman McInnes       if (nonew == 1) goto noinsert;
512e32f2f54SBarry Smith       if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at (%D,%D) in the matrix",row,col);
513720833daSHong Zhang       if (A->structure_only) {
514876c6284SHong Zhang         MatSeqXAIJReallocateAIJ_structure_only(A,A->rmap->n,1,nrow,row,col,rmax,ai,aj,rp,imax,nonew,MatScalar);
515720833daSHong Zhang       } else {
516fef13f97SBarry Smith         MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
517720833daSHong Zhang       }
518c03d1d03SSatish Balay       N = nrow++ - 1; a->nz++; high++;
519416022c9SBarry Smith       /* shift up all the later entries in this row */
520580bdb30SBarry Smith       ierr  = PetscArraymove(rp+i+1,rp+i,N-i+1);CHKERRQ(ierr);
52117ab2063SBarry Smith       rp[i] = col;
522580bdb30SBarry Smith       if (!A->structure_only) {
523580bdb30SBarry Smith         ierr  = PetscArraymove(ap+i+1,ap+i,N-i+1);CHKERRQ(ierr);
524580bdb30SBarry Smith         ap[i] = value;
525580bdb30SBarry Smith       }
526416022c9SBarry Smith       low = i + 1;
527e56f5c9eSBarry Smith       A->nonzerostate++;
5288c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
529e2cf4d64SStefano Zampini       inserted = PETSC_TRUE;
530e2cf4d64SStefano Zampini #endif
531e44c0bd4SBarry Smith noinsert:;
53217ab2063SBarry Smith     }
53317ab2063SBarry Smith     ailen[row] = nrow;
53417ab2063SBarry Smith   }
5358c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
536c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && inserted) A->offloadmask = PETSC_OFFLOAD_CPU;
537e2cf4d64SStefano Zampini #endif
5383a40ed3dSBarry Smith   PetscFunctionReturn(0);
53917ab2063SBarry Smith }
54017ab2063SBarry Smith 
54119b08ed1SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFullNoPreallocation(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
54219b08ed1SBarry Smith {
54319b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
54419b08ed1SBarry Smith   PetscInt       *rp,k,row;
54519b08ed1SBarry Smith   PetscInt       *ai = a->i;
54619b08ed1SBarry Smith   PetscErrorCode ierr;
54719b08ed1SBarry Smith   PetscInt       *aj = a->j;
54819b08ed1SBarry Smith   MatScalar      *aa = a->a,*ap;
54919b08ed1SBarry Smith 
55019b08ed1SBarry Smith   PetscFunctionBegin;
55119b08ed1SBarry Smith   if (A->was_assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot call on assembled matrix.");
55219b08ed1SBarry Smith   if (m*n+a->nz > a->maxnz) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of entries in matrix will be larger than maximum nonzeros allocated for %D in MatSeqAIJSetTotalPreallocation()",a->maxnz);
55319b08ed1SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
55419b08ed1SBarry Smith     row  = im[k];
55519b08ed1SBarry Smith     rp   = aj + ai[row];
55619b08ed1SBarry Smith     ap   = aa + ai[row];
55719b08ed1SBarry Smith 
55819b08ed1SBarry Smith     ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
55919b08ed1SBarry Smith     if (!A->structure_only) {
56019b08ed1SBarry Smith       if (v) {
56119b08ed1SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
56219b08ed1SBarry Smith         v   += n;
56319b08ed1SBarry Smith       } else {
56419b08ed1SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
56519b08ed1SBarry Smith       }
56619b08ed1SBarry Smith     }
56719b08ed1SBarry Smith     a->ilen[row] = n;
56819b08ed1SBarry Smith     a->imax[row] = n;
56919b08ed1SBarry Smith     a->i[row+1]  = a->i[row]+n;
57019b08ed1SBarry Smith     a->nz       += n;
57119b08ed1SBarry Smith   }
5728c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
57319b08ed1SBarry Smith   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
57419b08ed1SBarry Smith #endif
57519b08ed1SBarry Smith   PetscFunctionReturn(0);
57619b08ed1SBarry Smith }
57719b08ed1SBarry Smith 
57819b08ed1SBarry Smith /*@
57919b08ed1SBarry Smith     MatSeqAIJSetTotalPreallocation - Sets an upper bound on the total number of expected nonzeros in the matrix.
58019b08ed1SBarry Smith 
58119b08ed1SBarry Smith   Input Parameters:
58219b08ed1SBarry Smith +  A - the SeqAIJ matrix
58319b08ed1SBarry Smith -  nztotal - bound on the number of nonzeros
58419b08ed1SBarry Smith 
58519b08ed1SBarry Smith   Level: advanced
58619b08ed1SBarry Smith 
58719b08ed1SBarry Smith   Notes:
58819b08ed1SBarry 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.
58919b08ed1SBarry Smith     Simply call MatSetValues() after this call to provide the matrix entries in the usual manner. This matrix may be used
59019b08ed1SBarry Smith     as always with multiple matrix assemblies.
59119b08ed1SBarry Smith 
59219b08ed1SBarry Smith .seealso: MatSetOption(), MAT_SORTED_FULL, MatSetValues(), MatSeqAIJSetPreallocation()
59319b08ed1SBarry Smith @*/
59419b08ed1SBarry Smith 
59519b08ed1SBarry Smith PetscErrorCode MatSeqAIJSetTotalPreallocation(Mat A,PetscInt nztotal)
59619b08ed1SBarry Smith {
59719b08ed1SBarry Smith   PetscErrorCode ierr;
59819b08ed1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
59919b08ed1SBarry Smith 
60019b08ed1SBarry Smith   PetscFunctionBegin;
60119b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
60219b08ed1SBarry Smith   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
60319b08ed1SBarry Smith   a->maxnz  = nztotal;
60419b08ed1SBarry Smith   if (!a->imax) {
60519b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->imax);CHKERRQ(ierr);
60619b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
60719b08ed1SBarry Smith   }
60819b08ed1SBarry Smith   if (!a->ilen) {
60919b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n,&a->ilen);CHKERRQ(ierr);
61019b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
61119b08ed1SBarry Smith   } else {
61219b08ed1SBarry Smith     ierr = PetscMemzero(a->ilen,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
61319b08ed1SBarry Smith   }
61419b08ed1SBarry Smith 
61519b08ed1SBarry Smith   /* allocate the matrix space */
61619b08ed1SBarry Smith   if (A->structure_only) {
61719b08ed1SBarry Smith     ierr = PetscMalloc1(nztotal,&a->j);CHKERRQ(ierr);
61819b08ed1SBarry Smith     ierr = PetscMalloc1(A->rmap->n+1,&a->i);CHKERRQ(ierr);
61919b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*sizeof(PetscInt));CHKERRQ(ierr);
62019b08ed1SBarry Smith   } else {
62119b08ed1SBarry Smith     ierr = PetscMalloc3(nztotal,&a->a,nztotal,&a->j,A->rmap->n+1,&a->i);CHKERRQ(ierr);
62219b08ed1SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,(A->rmap->n+1)*sizeof(PetscInt)+nztotal*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
62319b08ed1SBarry Smith   }
62419b08ed1SBarry Smith   a->i[0] = 0;
62519b08ed1SBarry Smith   if (A->structure_only) {
62619b08ed1SBarry Smith     a->singlemalloc = PETSC_FALSE;
62719b08ed1SBarry Smith     a->free_a       = PETSC_FALSE;
62819b08ed1SBarry Smith   } else {
62919b08ed1SBarry Smith     a->singlemalloc = PETSC_TRUE;
63019b08ed1SBarry Smith     a->free_a       = PETSC_TRUE;
63119b08ed1SBarry Smith   }
63219b08ed1SBarry Smith   a->free_ij         = PETSC_TRUE;
63319b08ed1SBarry Smith   A->ops->setvalues = MatSetValues_SeqAIJ_SortedFullNoPreallocation;
63419b08ed1SBarry Smith   A->preallocated   = PETSC_TRUE;
63519b08ed1SBarry Smith   PetscFunctionReturn(0);
63619b08ed1SBarry Smith }
63719b08ed1SBarry Smith 
638071fcb05SBarry Smith PetscErrorCode MatSetValues_SeqAIJ_SortedFull(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode is)
639071fcb05SBarry Smith {
640071fcb05SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
641071fcb05SBarry Smith   PetscInt       *rp,k,row;
642071fcb05SBarry Smith   PetscInt       *ai = a->i,*ailen = a->ilen;
643071fcb05SBarry Smith   PetscErrorCode ierr;
644071fcb05SBarry Smith   PetscInt       *aj = a->j;
645071fcb05SBarry Smith   MatScalar      *aa = a->a,*ap;
646071fcb05SBarry Smith 
647071fcb05SBarry Smith   PetscFunctionBegin;
648071fcb05SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
649071fcb05SBarry Smith     row  = im[k];
65019b08ed1SBarry Smith     if (PetscUnlikelyDebug(n > a->imax[row])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Preallocation for row %D does not match number of columns provided",n);
651071fcb05SBarry Smith     rp   = aj + ai[row];
652071fcb05SBarry Smith     ap   = aa + ai[row];
653071fcb05SBarry Smith     if (!A->was_assembled) {
654071fcb05SBarry Smith       ierr = PetscMemcpy(rp,in,n*sizeof(PetscInt));CHKERRQ(ierr);
655071fcb05SBarry Smith     }
656071fcb05SBarry Smith     if (!A->structure_only) {
657071fcb05SBarry Smith       if (v) {
658071fcb05SBarry Smith         ierr = PetscMemcpy(ap,v,n*sizeof(PetscScalar));CHKERRQ(ierr);
659071fcb05SBarry Smith         v   += n;
660071fcb05SBarry Smith       } else {
661071fcb05SBarry Smith         ierr = PetscMemzero(ap,n*sizeof(PetscScalar));CHKERRQ(ierr);
662071fcb05SBarry Smith       }
663071fcb05SBarry Smith     }
664071fcb05SBarry Smith     ailen[row] = n;
665071fcb05SBarry Smith     a->nz      += n;
666071fcb05SBarry Smith   }
6678c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
668c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED && m && n) A->offloadmask = PETSC_OFFLOAD_CPU;
669e2cf4d64SStefano Zampini #endif
670071fcb05SBarry Smith   PetscFunctionReturn(0);
671071fcb05SBarry Smith }
672071fcb05SBarry Smith 
673a77337e4SBarry Smith PetscErrorCode MatGetValues_SeqAIJ(Mat A,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],PetscScalar v[])
6747eb43aa7SLois Curfman McInnes {
6757eb43aa7SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
67697f1f81fSBarry Smith   PetscInt   *rp,k,low,high,t,row,nrow,i,col,l,*aj = a->j;
67797f1f81fSBarry Smith   PetscInt   *ai = a->i,*ailen = a->ilen;
67854f21887SBarry Smith   MatScalar  *ap,*aa = a->a;
6797eb43aa7SLois Curfman McInnes 
6803a40ed3dSBarry Smith   PetscFunctionBegin;
6817eb43aa7SLois Curfman McInnes   for (k=0; k<m; k++) { /* loop over rows */
6827eb43aa7SLois Curfman McInnes     row = im[k];
683e32f2f54SBarry Smith     if (row < 0) {v += n; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",row); */
684e32f2f54SBarry Smith     if (row >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",row,A->rmap->n-1);
685bfeeae90SHong Zhang     rp   = aj + ai[row]; ap = aa + ai[row];
6867eb43aa7SLois Curfman McInnes     nrow = ailen[row];
6877eb43aa7SLois Curfman McInnes     for (l=0; l<n; l++) { /* loop over columns */
688e32f2f54SBarry Smith       if (in[l] < 0) {v++; continue;} /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",in[l]); */
689e32f2f54SBarry Smith       if (in[l] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[l],A->cmap->n-1);
690bfeeae90SHong Zhang       col  = in[l];
6917eb43aa7SLois Curfman McInnes       high = nrow; low = 0; /* assume unsorted */
6927eb43aa7SLois Curfman McInnes       while (high-low > 5) {
6937eb43aa7SLois Curfman McInnes         t = (low+high)/2;
6947eb43aa7SLois Curfman McInnes         if (rp[t] > col) high = t;
6957eb43aa7SLois Curfman McInnes         else low = t;
6967eb43aa7SLois Curfman McInnes       }
6977eb43aa7SLois Curfman McInnes       for (i=low; i<high; i++) {
6987eb43aa7SLois Curfman McInnes         if (rp[i] > col) break;
6997eb43aa7SLois Curfman McInnes         if (rp[i] == col) {
700b49de8d1SLois Curfman McInnes           *v++ = ap[i];
7017eb43aa7SLois Curfman McInnes           goto finished;
7027eb43aa7SLois Curfman McInnes         }
7037eb43aa7SLois Curfman McInnes       }
70497e567efSBarry Smith       *v++ = 0.0;
7057eb43aa7SLois Curfman McInnes finished:;
7067eb43aa7SLois Curfman McInnes     }
7077eb43aa7SLois Curfman McInnes   }
7083a40ed3dSBarry Smith   PetscFunctionReturn(0);
7097eb43aa7SLois Curfman McInnes }
7107eb43aa7SLois Curfman McInnes 
7113ea6fe3dSLisandro Dalcin PetscErrorCode MatView_SeqAIJ_Binary(Mat mat,PetscViewer viewer)
71217ab2063SBarry Smith {
7133ea6fe3dSLisandro Dalcin   Mat_SeqAIJ        *A = (Mat_SeqAIJ*)mat->data;
714c898d852SStefano Zampini   const PetscScalar *av;
7153ea6fe3dSLisandro Dalcin   PetscInt          header[4],M,N,m,nz,i;
7163ea6fe3dSLisandro Dalcin   PetscInt          *rowlens;
7176849ba73SBarry Smith   PetscErrorCode    ierr;
71817ab2063SBarry Smith 
7193a40ed3dSBarry Smith   PetscFunctionBegin;
7203ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
7212205254eSKarl Rupp 
7223ea6fe3dSLisandro Dalcin   M  = mat->rmap->N;
7233ea6fe3dSLisandro Dalcin   N  = mat->cmap->N;
7243ea6fe3dSLisandro Dalcin   m  = mat->rmap->n;
7253ea6fe3dSLisandro Dalcin   nz = A->nz;
726416022c9SBarry Smith 
7273ea6fe3dSLisandro Dalcin   /* write matrix header */
7283ea6fe3dSLisandro Dalcin   header[0] = MAT_FILE_CLASSID;
7293ea6fe3dSLisandro Dalcin   header[1] = M; header[2] = N; header[3] = nz;
7303ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);
731416022c9SBarry Smith 
7323ea6fe3dSLisandro Dalcin   /* fill in and store row lengths */
7333ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(m,&rowlens);CHKERRQ(ierr);
7343ea6fe3dSLisandro Dalcin   for (i=0; i<m; i++) rowlens[i] = A->i[i+1] - A->i[i];
7353ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,rowlens,m,PETSC_INT);CHKERRQ(ierr);
7363ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
7373ea6fe3dSLisandro Dalcin   /* store column indices */
7383ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryWrite(viewer,A->j,nz,PETSC_INT);CHKERRQ(ierr);
739416022c9SBarry Smith   /* store nonzero values */
740c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(mat,&av);CHKERRQ(ierr);
741c898d852SStefano Zampini   ierr = PetscViewerBinaryWrite(viewer,av,nz,PETSC_SCALAR);CHKERRQ(ierr);
742c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(mat,&av);CHKERRQ(ierr);
743b37d52dbSMark F. Adams 
7443ea6fe3dSLisandro Dalcin   /* write block size option to the viewer's .info file */
7453ea6fe3dSLisandro Dalcin   ierr = MatView_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
7463a40ed3dSBarry Smith   PetscFunctionReturn(0);
74717ab2063SBarry Smith }
748416022c9SBarry Smith 
7497dc0baabSHong Zhang static PetscErrorCode MatView_SeqAIJ_ASCII_structonly(Mat A,PetscViewer viewer)
7507dc0baabSHong Zhang {
7517dc0baabSHong Zhang   PetscErrorCode ierr;
7527dc0baabSHong Zhang   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
7537dc0baabSHong Zhang   PetscInt       i,k,m=A->rmap->N;
7547dc0baabSHong Zhang 
7557dc0baabSHong Zhang   PetscFunctionBegin;
7567dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
7577dc0baabSHong Zhang   for (i=0; i<m; i++) {
7587dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
7597dc0baabSHong Zhang     for (k=a->i[i]; k<a->i[i+1]; k++) {
7607dc0baabSHong Zhang       ierr = PetscViewerASCIIPrintf(viewer," (%D) ",a->j[k]);CHKERRQ(ierr);
7617dc0baabSHong Zhang     }
7627dc0baabSHong Zhang     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
7637dc0baabSHong Zhang   }
7647dc0baabSHong Zhang   ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
7657dc0baabSHong Zhang   PetscFunctionReturn(0);
7667dc0baabSHong Zhang }
7677dc0baabSHong Zhang 
76809573ac7SBarry Smith extern PetscErrorCode MatSeqAIJFactorInfo_Matlab(Mat,PetscViewer);
769cd155464SBarry Smith 
770dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_ASCII(Mat A,PetscViewer viewer)
771416022c9SBarry Smith {
772416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
773c898d852SStefano Zampini   const PetscScalar *av;
774dfbe8321SBarry Smith   PetscErrorCode    ierr;
77560e0710aSBarry Smith   PetscInt          i,j,m = A->rmap->n;
776e060cb09SBarry Smith   const char        *name;
777f3ef73ceSBarry Smith   PetscViewerFormat format;
77817ab2063SBarry Smith 
7793a40ed3dSBarry Smith   PetscFunctionBegin;
7807dc0baabSHong Zhang   if (A->structure_only) {
7817dc0baabSHong Zhang     ierr = MatView_SeqAIJ_ASCII_structonly(A,viewer);CHKERRQ(ierr);
7827dc0baabSHong Zhang     PetscFunctionReturn(0);
7837dc0baabSHong Zhang   }
78443e49210SHong Zhang 
785b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
7862e5835c6SStefano Zampini   if (format == PETSC_VIEWER_ASCII_FACTOR_INFO || format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscFunctionReturn(0);
7872e5835c6SStefano Zampini 
788c898d852SStefano Zampini   /* trigger copy to CPU if needed */
789c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
790c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
79171c2f376SKris Buschelman   if (format == PETSC_VIEWER_ASCII_MATLAB) {
79297f1f81fSBarry Smith     PetscInt nofinalvalue = 0;
79360e0710aSBarry Smith     if (m && ((a->i[m] == a->i[m-1]) || (a->j[a->nz-1] != A->cmap->n-1))) {
794c337ccceSJed Brown       /* Need a dummy value to ensure the dimension of the matrix. */
795d00d2cf4SBarry Smith       nofinalvalue = 1;
796d00d2cf4SBarry Smith     }
797d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
798d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",m,A->cmap->n);CHKERRQ(ierr);
79977431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%% Nonzeros = %D \n",a->nz);CHKERRQ(ierr);
800fbfe6fa7SJed Brown #if defined(PETSC_USE_COMPLEX)
801fbfe6fa7SJed Brown     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,4);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
802fbfe6fa7SJed Brown #else
80377431f27SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",a->nz+nofinalvalue);CHKERRQ(ierr);
804fbfe6fa7SJed Brown #endif
805b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
80617ab2063SBarry Smith 
80717ab2063SBarry Smith     for (i=0; i<m; i++) {
80860e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
809aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
810a9bf72d8SJed Brown         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",i+1,a->j[j]+1,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
81117ab2063SBarry Smith #else
81260e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,a->j[j]+1,(double)a->a[j]);CHKERRQ(ierr);
81317ab2063SBarry Smith #endif
81417ab2063SBarry Smith       }
81517ab2063SBarry Smith     }
816d00d2cf4SBarry Smith     if (nofinalvalue) {
817c337ccceSJed Brown #if defined(PETSC_USE_COMPLEX)
818c337ccceSJed Brown       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e %18.16e\n",m,A->cmap->n,0.,0.);CHKERRQ(ierr);
819c337ccceSJed Brown #else
820d0f46423SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",m,A->cmap->n,0.0);CHKERRQ(ierr);
821c337ccceSJed Brown #endif
822d00d2cf4SBarry Smith     }
823317d6ea6SBarry Smith     ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
824fb9695e5SSatish Balay     ierr = PetscViewerASCIIPrintf(viewer,"];\n %s = spconvert(zzz);\n",name);CHKERRQ(ierr);
825d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
826fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
827d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
82844cd7ae7SLois Curfman McInnes     for (i=0; i<m; i++) {
82977431f27SBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
83060e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
831aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
83236db0b34SBarry Smith         if (PetscImaginaryPart(a->a[j]) > 0.0 && PetscRealPart(a->a[j]) != 0.0) {
83360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
83436db0b34SBarry Smith         } else if (PetscImaginaryPart(a->a[j]) < 0.0 && PetscRealPart(a->a[j]) != 0.0) {
83560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
83636db0b34SBarry Smith         } else if (PetscRealPart(a->a[j]) != 0.0) {
83760e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
8386831982aSBarry Smith         }
83944cd7ae7SLois Curfman McInnes #else
84060e0710aSBarry Smith         if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);}
84144cd7ae7SLois Curfman McInnes #endif
84244cd7ae7SLois Curfman McInnes       }
843b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
84444cd7ae7SLois Curfman McInnes     }
845d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
846fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_SYMMODU) {
84797f1f81fSBarry Smith     PetscInt nzd=0,fshift=1,*sptr;
848d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
849854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&sptr);CHKERRQ(ierr);
850496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
851496be53dSLois Curfman McInnes       sptr[i] = nzd+1;
85260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
853496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
854aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
85536db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) nzd++;
856496be53dSLois Curfman McInnes #else
857496be53dSLois Curfman McInnes           if (a->a[j] != 0.0) nzd++;
858496be53dSLois Curfman McInnes #endif
859496be53dSLois Curfman McInnes         }
860496be53dSLois Curfman McInnes       }
861496be53dSLois Curfman McInnes     }
8622e44a96cSLois Curfman McInnes     sptr[m] = nzd+1;
86377431f27SBarry Smith     ierr    = PetscViewerASCIIPrintf(viewer," %D %D\n\n",m,nzd);CHKERRQ(ierr);
8642e44a96cSLois Curfman McInnes     for (i=0; i<m+1; i+=6) {
8652205254eSKarl Rupp       if (i+4<m) {
8662205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4],sptr[i+5]);CHKERRQ(ierr);
8672205254eSKarl Rupp       } else if (i+3<m) {
8682205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3],sptr[i+4]);CHKERRQ(ierr);
8692205254eSKarl Rupp       } else if (i+2<m) {
8702205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2],sptr[i+3]);CHKERRQ(ierr);
8712205254eSKarl Rupp       } else if (i+1<m) {
8722205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D %D\n",sptr[i],sptr[i+1],sptr[i+2]);CHKERRQ(ierr);
8732205254eSKarl Rupp       } else if (i<m) {
8742205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D %D\n",sptr[i],sptr[i+1]);CHKERRQ(ierr);
8752205254eSKarl Rupp       } else {
8762205254eSKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer," %D\n",sptr[i]);CHKERRQ(ierr);
8772205254eSKarl Rupp       }
878496be53dSLois Curfman McInnes     }
879b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
880606d414cSSatish Balay     ierr = PetscFree(sptr);CHKERRQ(ierr);
881496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
88260e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
88377431f27SBarry Smith         if (a->j[j] >= i) {ierr = PetscViewerASCIIPrintf(viewer," %D ",a->j[j]+fshift);CHKERRQ(ierr);}
884496be53dSLois Curfman McInnes       }
885b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
886496be53dSLois Curfman McInnes     }
887b0a32e0cSBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
888496be53dSLois Curfman McInnes     for (i=0; i<m; i++) {
88960e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
890496be53dSLois Curfman McInnes         if (a->j[j] >= i) {
891aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
89236db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) != 0.0 || PetscRealPart(a->a[j]) != 0.0) {
89360e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," %18.16e %18.16e ",(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
8946831982aSBarry Smith           }
895496be53dSLois Curfman McInnes #else
89660e0710aSBarry Smith           if (a->a[j] != 0.0) {ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",(double)a->a[j]);CHKERRQ(ierr);}
897496be53dSLois Curfman McInnes #endif
898496be53dSLois Curfman McInnes         }
899496be53dSLois Curfman McInnes       }
900b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
901496be53dSLois Curfman McInnes     }
902d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
903fb9695e5SSatish Balay   } else if (format == PETSC_VIEWER_ASCII_DENSE) {
90497f1f81fSBarry Smith     PetscInt    cnt = 0,jcnt;
90587828ca2SBarry Smith     PetscScalar value;
90668f1ed48SBarry Smith #if defined(PETSC_USE_COMPLEX)
90768f1ed48SBarry Smith     PetscBool   realonly = PETSC_TRUE;
90868f1ed48SBarry Smith 
90968f1ed48SBarry Smith     for (i=0; i<a->i[m]; i++) {
91068f1ed48SBarry Smith       if (PetscImaginaryPart(a->a[i]) != 0.0) {
91168f1ed48SBarry Smith         realonly = PETSC_FALSE;
91268f1ed48SBarry Smith         break;
91368f1ed48SBarry Smith       }
91468f1ed48SBarry Smith     }
91568f1ed48SBarry Smith #endif
91602594712SBarry Smith 
917d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
91802594712SBarry Smith     for (i=0; i<m; i++) {
91902594712SBarry Smith       jcnt = 0;
920d0f46423SBarry Smith       for (j=0; j<A->cmap->n; j++) {
921e24b481bSBarry Smith         if (jcnt < a->i[i+1]-a->i[i] && j == a->j[cnt]) {
92202594712SBarry Smith           value = a->a[cnt++];
923e24b481bSBarry Smith           jcnt++;
92402594712SBarry Smith         } else {
92502594712SBarry Smith           value = 0.0;
92602594712SBarry Smith         }
927aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
92868f1ed48SBarry Smith         if (realonly) {
92960e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)PetscRealPart(value));CHKERRQ(ierr);
93068f1ed48SBarry Smith         } else {
93160e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," %7.5e+%7.5e i ",(double)PetscRealPart(value),(double)PetscImaginaryPart(value));CHKERRQ(ierr);
93268f1ed48SBarry Smith         }
93302594712SBarry Smith #else
93460e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," %7.5e ",(double)value);CHKERRQ(ierr);
93502594712SBarry Smith #endif
93602594712SBarry Smith       }
937b0a32e0cSBarry Smith       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
93802594712SBarry Smith     }
939d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9403c215bfdSMatthew Knepley   } else if (format == PETSC_VIEWER_ASCII_MATRIXMARKET) {
941150b93efSMatthew G. Knepley     PetscInt fshift=1;
942d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
9433c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
94419303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate complex general\n");CHKERRQ(ierr);
9453c215bfdSMatthew Knepley #else
94619303e72SJonathan Guyer     ierr = PetscViewerASCIIPrintf(viewer,"%%%%MatrixMarket matrix coordinate real general\n");CHKERRQ(ierr);
9473c215bfdSMatthew Knepley #endif
948d0f46423SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"%D %D %D\n", m, A->cmap->n, a->nz);CHKERRQ(ierr);
9493c215bfdSMatthew Knepley     for (i=0; i<m; i++) {
95060e0710aSBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
9513c215bfdSMatthew Knepley #if defined(PETSC_USE_COMPLEX)
952a9a0e077SKarl Rupp         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g %g\n", i+fshift,a->j[j]+fshift,(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
9533c215bfdSMatthew Knepley #else
954150b93efSMatthew G. Knepley         ierr = PetscViewerASCIIPrintf(viewer,"%D %D %g\n", i+fshift, a->j[j]+fshift, (double)a->a[j]);CHKERRQ(ierr);
9553c215bfdSMatthew Knepley #endif
9563c215bfdSMatthew Knepley       }
9573c215bfdSMatthew Knepley     }
958d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
9593a40ed3dSBarry Smith   } else {
960d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
961d5f3da31SBarry Smith     if (A->factortype) {
96216cd7e1dSShri Abhyankar       for (i=0; i<m; i++) {
96316cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
96416cd7e1dSShri Abhyankar         /* L part */
96560e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
96616cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
96716cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
96860e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
96916cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9706712e2f1SBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
97116cd7e1dSShri Abhyankar           } else {
97260e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
97316cd7e1dSShri Abhyankar           }
97416cd7e1dSShri Abhyankar #else
97560e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
97616cd7e1dSShri Abhyankar #endif
97716cd7e1dSShri Abhyankar         }
97816cd7e1dSShri Abhyankar         /* diagonal */
97916cd7e1dSShri Abhyankar         j = a->diag[i];
98016cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
98116cd7e1dSShri Abhyankar         if (PetscImaginaryPart(a->a[j]) > 0.0) {
98260e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)PetscImaginaryPart(1.0/a->a[j]));CHKERRQ(ierr);
98316cd7e1dSShri Abhyankar         } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
9846712e2f1SBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(1.0/a->a[j]),(double)(-PetscImaginaryPart(1.0/a->a[j])));CHKERRQ(ierr);
98516cd7e1dSShri Abhyankar         } else {
98660e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(1.0/a->a[j]));CHKERRQ(ierr);
98716cd7e1dSShri Abhyankar         }
98816cd7e1dSShri Abhyankar #else
98960e0710aSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)(1.0/a->a[j]));CHKERRQ(ierr);
99016cd7e1dSShri Abhyankar #endif
99116cd7e1dSShri Abhyankar 
99216cd7e1dSShri Abhyankar         /* U part */
99360e0710aSBarry Smith         for (j=a->diag[i+1]+1; j<a->diag[i]; j++) {
99416cd7e1dSShri Abhyankar #if defined(PETSC_USE_COMPLEX)
99516cd7e1dSShri Abhyankar           if (PetscImaginaryPart(a->a[j]) > 0.0) {
99660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
99716cd7e1dSShri Abhyankar           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
99822ab088eSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)(-PetscImaginaryPart(a->a[j])));CHKERRQ(ierr);
99916cd7e1dSShri Abhyankar           } else {
100060e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
100116cd7e1dSShri Abhyankar           }
100216cd7e1dSShri Abhyankar #else
100360e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
100416cd7e1dSShri Abhyankar #endif
100516cd7e1dSShri Abhyankar         }
100616cd7e1dSShri Abhyankar         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
100716cd7e1dSShri Abhyankar       }
100816cd7e1dSShri Abhyankar     } else {
100917ab2063SBarry Smith       for (i=0; i<m; i++) {
101077431f27SBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
101160e0710aSBarry Smith         for (j=a->i[i]; j<a->i[i+1]; j++) {
1012aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX)
101336db0b34SBarry Smith           if (PetscImaginaryPart(a->a[j]) > 0.0) {
101460e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
101536db0b34SBarry Smith           } else if (PetscImaginaryPart(a->a[j]) < 0.0) {
101660e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g - %g i)",a->j[j],(double)PetscRealPart(a->a[j]),(double)-PetscImaginaryPart(a->a[j]));CHKERRQ(ierr);
10173a40ed3dSBarry Smith           } else {
101860e0710aSBarry Smith             ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)PetscRealPart(a->a[j]));CHKERRQ(ierr);
101917ab2063SBarry Smith           }
102017ab2063SBarry Smith #else
102160e0710aSBarry Smith           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",a->j[j],(double)a->a[j]);CHKERRQ(ierr);
102217ab2063SBarry Smith #endif
102317ab2063SBarry Smith         }
1024b0a32e0cSBarry Smith         ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
102517ab2063SBarry Smith       }
102616cd7e1dSShri Abhyankar     }
1027d00279f6SBarry Smith     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
102817ab2063SBarry Smith   }
1029b0a32e0cSBarry Smith   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
10303a40ed3dSBarry Smith   PetscFunctionReturn(0);
1031416022c9SBarry Smith }
1032416022c9SBarry Smith 
10339804daf3SBarry Smith #include <petscdraw.h>
1034dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw_Zoom(PetscDraw draw,void *Aa)
1035416022c9SBarry Smith {
1036480ef9eaSBarry Smith   Mat               A  = (Mat) Aa;
1037416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1038dfbe8321SBarry Smith   PetscErrorCode    ierr;
1039383922c3SLisandro Dalcin   PetscInt          i,j,m = A->rmap->n;
1040383922c3SLisandro Dalcin   int               color;
1041b05fc000SLisandro Dalcin   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1042b0a32e0cSBarry Smith   PetscViewer       viewer;
1043f3ef73ceSBarry Smith   PetscViewerFormat format;
1044cddf8d76SBarry Smith 
10453a40ed3dSBarry Smith   PetscFunctionBegin;
1046480ef9eaSBarry Smith   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1047b0a32e0cSBarry Smith   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1048b0a32e0cSBarry Smith   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1049383922c3SLisandro Dalcin 
1050416022c9SBarry Smith   /* loop over matrix elements drawing boxes */
10510513a670SBarry Smith 
1052fb9695e5SSatish Balay   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1053383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10540513a670SBarry Smith     /* Blue for negative, Cyan for zero and  Red for positive */
1055b0a32e0cSBarry Smith     color = PETSC_DRAW_BLUE;
1056416022c9SBarry Smith     for (i=0; i<m; i++) {
1057cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1058bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1059bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
106036db0b34SBarry Smith         if (PetscRealPart(a->a[j]) >=  0.) continue;
1061b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1062cddf8d76SBarry Smith       }
1063cddf8d76SBarry Smith     }
1064b0a32e0cSBarry Smith     color = PETSC_DRAW_CYAN;
1065cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1066cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1067bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1068bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
1069cddf8d76SBarry Smith         if (a->a[j] !=  0.) continue;
1070b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1071cddf8d76SBarry Smith       }
1072cddf8d76SBarry Smith     }
1073b0a32e0cSBarry Smith     color = PETSC_DRAW_RED;
1074cddf8d76SBarry Smith     for (i=0; i<m; i++) {
1075cddf8d76SBarry Smith       y_l = m - i - 1.0; y_r = y_l + 1.0;
1076bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1077bfeeae90SHong Zhang         x_l = a->j[j]; x_r = x_l + 1.0;
107836db0b34SBarry Smith         if (PetscRealPart(a->a[j]) <=  0.) continue;
1079b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1080416022c9SBarry Smith       }
1081416022c9SBarry Smith     }
1082383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
10830513a670SBarry Smith   } else {
10840513a670SBarry Smith     /* use contour shading to indicate magnitude of values */
10850513a670SBarry Smith     /* first determine max of all nonzero values */
1086b05fc000SLisandro Dalcin     PetscReal minv = 0.0, maxv = 0.0;
1087383922c3SLisandro Dalcin     PetscInt  nz = a->nz, count = 0;
1088b0a32e0cSBarry Smith     PetscDraw popup;
10890513a670SBarry Smith 
10900513a670SBarry Smith     for (i=0; i<nz; i++) {
10910513a670SBarry Smith       if (PetscAbsScalar(a->a[i]) > maxv) maxv = PetscAbsScalar(a->a[i]);
10920513a670SBarry Smith     }
1093383922c3SLisandro Dalcin     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1094b0a32e0cSBarry Smith     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
109545f3bb6eSLisandro Dalcin     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1096383922c3SLisandro Dalcin 
1097383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
10980513a670SBarry Smith     for (i=0; i<m; i++) {
1099383922c3SLisandro Dalcin       y_l = m - i - 1.0;
1100383922c3SLisandro Dalcin       y_r = y_l + 1.0;
1101bfeeae90SHong Zhang       for (j=a->i[i]; j<a->i[i+1]; j++) {
1102383922c3SLisandro Dalcin         x_l = a->j[j];
1103383922c3SLisandro Dalcin         x_r = x_l + 1.0;
1104b05fc000SLisandro Dalcin         color = PetscDrawRealToColor(PetscAbsScalar(a->a[count]),minv,maxv);
1105b0a32e0cSBarry Smith         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
11060513a670SBarry Smith         count++;
11070513a670SBarry Smith       }
11080513a670SBarry Smith     }
1109383922c3SLisandro Dalcin     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
11100513a670SBarry Smith   }
1111480ef9eaSBarry Smith   PetscFunctionReturn(0);
1112480ef9eaSBarry Smith }
1113cddf8d76SBarry Smith 
11149804daf3SBarry Smith #include <petscdraw.h>
1115dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ_Draw(Mat A,PetscViewer viewer)
1116480ef9eaSBarry Smith {
1117dfbe8321SBarry Smith   PetscErrorCode ierr;
1118b0a32e0cSBarry Smith   PetscDraw      draw;
111936db0b34SBarry Smith   PetscReal      xr,yr,xl,yl,h,w;
1120ace3abfcSBarry Smith   PetscBool      isnull;
1121480ef9eaSBarry Smith 
1122480ef9eaSBarry Smith   PetscFunctionBegin;
1123b0a32e0cSBarry Smith   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1124b0a32e0cSBarry Smith   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1125480ef9eaSBarry Smith   if (isnull) PetscFunctionReturn(0);
1126480ef9eaSBarry Smith 
1127d0f46423SBarry Smith   xr   = A->cmap->n; yr  = A->rmap->n; h = yr/10.0; w = xr/10.0;
1128480ef9eaSBarry Smith   xr  += w;          yr += h;         xl = -w;     yl = -h;
1129b0a32e0cSBarry Smith   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1130832b7cebSLisandro Dalcin   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1131b0a32e0cSBarry Smith   ierr = PetscDrawZoom(draw,MatView_SeqAIJ_Draw_Zoom,A);CHKERRQ(ierr);
11320298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1133832b7cebSLisandro Dalcin   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
11343a40ed3dSBarry Smith   PetscFunctionReturn(0);
1135416022c9SBarry Smith }
1136416022c9SBarry Smith 
1137dfbe8321SBarry Smith PetscErrorCode MatView_SeqAIJ(Mat A,PetscViewer viewer)
1138416022c9SBarry Smith {
1139dfbe8321SBarry Smith   PetscErrorCode ierr;
1140ace3abfcSBarry Smith   PetscBool      iascii,isbinary,isdraw;
1141416022c9SBarry Smith 
11423a40ed3dSBarry Smith   PetscFunctionBegin;
1143251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1144251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1145251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1146c45a1595SBarry Smith   if (iascii) {
11473a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_ASCII(A,viewer);CHKERRQ(ierr);
11480f5bd95cSBarry Smith   } else if (isbinary) {
11493a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Binary(A,viewer);CHKERRQ(ierr);
11500f5bd95cSBarry Smith   } else if (isdraw) {
11513a40ed3dSBarry Smith     ierr = MatView_SeqAIJ_Draw(A,viewer);CHKERRQ(ierr);
115211aeaf0aSBarry Smith   }
11534108e4d5SBarry Smith   ierr = MatView_SeqAIJ_Inode(A,viewer);CHKERRQ(ierr);
11543a40ed3dSBarry Smith   PetscFunctionReturn(0);
115517ab2063SBarry Smith }
115619bcc07fSBarry Smith 
1157dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_SeqAIJ(Mat A,MatAssemblyType mode)
115817ab2063SBarry Smith {
1159416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
11606849ba73SBarry Smith   PetscErrorCode ierr;
1161580bdb30SBarry Smith   PetscInt       fshift = 0,i,*ai = a->i,*aj = a->j,*imax = a->imax;
1162d0f46423SBarry Smith   PetscInt       m      = A->rmap->n,*ip,N,*ailen = a->ilen,rmax = 0;
116354f21887SBarry Smith   MatScalar      *aa    = a->a,*ap;
11643447b6efSHong Zhang   PetscReal      ratio  = 0.6;
116517ab2063SBarry Smith 
11663a40ed3dSBarry Smith   PetscFunctionBegin;
11673a40ed3dSBarry Smith   if (mode == MAT_FLUSH_ASSEMBLY) PetscFunctionReturn(0);
1168071fcb05SBarry Smith   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
1169b215bc84SStefano Zampini   if (A->was_assembled && A->ass_nonzerostate == A->nonzerostate) {
1170b215bc84SStefano Zampini     /* we need to respect users asking to use or not the inodes routine in between matrix assemblies */
1171b215bc84SStefano Zampini     ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
1172b215bc84SStefano Zampini     PetscFunctionReturn(0);
1173b215bc84SStefano Zampini   }
117417ab2063SBarry Smith 
117543ee02c3SBarry Smith   if (m) rmax = ailen[0]; /* determine row with most nonzeros */
117617ab2063SBarry Smith   for (i=1; i<m; i++) {
1177416022c9SBarry Smith     /* move each row back by the amount of empty slots (fshift) before it*/
117817ab2063SBarry Smith     fshift += imax[i-1] - ailen[i-1];
117994a9d846SBarry Smith     rmax    = PetscMax(rmax,ailen[i]);
118017ab2063SBarry Smith     if (fshift) {
1181bfeeae90SHong Zhang       ip = aj + ai[i];
1182bfeeae90SHong Zhang       ap = aa + ai[i];
118317ab2063SBarry Smith       N  = ailen[i];
1184580bdb30SBarry Smith       ierr = PetscArraymove(ip-fshift,ip,N);CHKERRQ(ierr);
1185580bdb30SBarry Smith       if (!A->structure_only) {
1186580bdb30SBarry Smith         ierr = PetscArraymove(ap-fshift,ap,N);CHKERRQ(ierr);
118717ab2063SBarry Smith       }
118817ab2063SBarry Smith     }
118917ab2063SBarry Smith     ai[i] = ai[i-1] + ailen[i-1];
119017ab2063SBarry Smith   }
119117ab2063SBarry Smith   if (m) {
119217ab2063SBarry Smith     fshift += imax[m-1] - ailen[m-1];
119317ab2063SBarry Smith     ai[m]   = ai[m-1] + ailen[m-1];
119417ab2063SBarry Smith   }
11957b083b7cSBarry Smith 
119617ab2063SBarry Smith   /* reset ilen and imax for each row */
11977b083b7cSBarry Smith   a->nonzerorowcnt = 0;
1198396832f4SHong Zhang   if (A->structure_only) {
1199071fcb05SBarry Smith     ierr = PetscFree(a->imax);CHKERRQ(ierr);
1200071fcb05SBarry Smith     ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1201396832f4SHong Zhang   } else { /* !A->structure_only */
120217ab2063SBarry Smith     for (i=0; i<m; i++) {
120317ab2063SBarry Smith       ailen[i] = imax[i] = ai[i+1] - ai[i];
12047b083b7cSBarry Smith       a->nonzerorowcnt += ((ai[i+1] - ai[i]) > 0);
120517ab2063SBarry Smith     }
1206396832f4SHong Zhang   }
1207bfeeae90SHong Zhang   a->nz = ai[m];
120865e19b50SBarry Smith   if (fshift && a->nounused == -1) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Unused space detected in matrix: %D X %D, %D unneeded", m, A->cmap->n, fshift);
120917ab2063SBarry Smith 
121009f38230SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
1211d0f46423SBarry Smith   ierr = PetscInfo4(A,"Matrix size: %D X %D; storage space: %D unneeded,%D used\n",m,A->cmap->n,fshift,a->nz);CHKERRQ(ierr);
1212ae15b995SBarry Smith   ierr = PetscInfo1(A,"Number of mallocs during MatSetValues() is %D\n",a->reallocs);CHKERRQ(ierr);
1213ae15b995SBarry Smith   ierr = PetscInfo1(A,"Maximum nonzeros in any row is %D\n",rmax);CHKERRQ(ierr);
12142205254eSKarl Rupp 
12158e58a170SBarry Smith   A->info.mallocs    += a->reallocs;
1216dd5f02e7SSatish Balay   a->reallocs         = 0;
12176712e2f1SBarry Smith   A->info.nz_unneeded = (PetscReal)fshift;
121836db0b34SBarry Smith   a->rmax             = rmax;
12194e220ebcSLois Curfman McInnes 
1220396832f4SHong Zhang   if (!A->structure_only) {
122111e456e1SBarry Smith     ierr = MatCheckCompressedRow(A,a->nonzerorowcnt,&a->compressedrow,a->i,m,ratio);CHKERRQ(ierr);
1222396832f4SHong Zhang   }
12234108e4d5SBarry Smith   ierr = MatAssemblyEnd_SeqAIJ_Inode(A,mode);CHKERRQ(ierr);
12243a40ed3dSBarry Smith   PetscFunctionReturn(0);
122517ab2063SBarry Smith }
122617ab2063SBarry Smith 
122799cafbc1SBarry Smith PetscErrorCode MatRealPart_SeqAIJ(Mat A)
122899cafbc1SBarry Smith {
122999cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
123099cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12312e5835c6SStefano Zampini   MatScalar      *aa;
1232acf2f550SJed Brown   PetscErrorCode ierr;
123399cafbc1SBarry Smith 
123499cafbc1SBarry Smith   PetscFunctionBegin;
12352e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
123699cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
12372e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1238acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12398c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1240c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1241e2cf4d64SStefano Zampini #endif
124299cafbc1SBarry Smith   PetscFunctionReturn(0);
124399cafbc1SBarry Smith }
124499cafbc1SBarry Smith 
124599cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_SeqAIJ(Mat A)
124699cafbc1SBarry Smith {
124799cafbc1SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
124899cafbc1SBarry Smith   PetscInt       i,nz = a->nz;
12492e5835c6SStefano Zampini   MatScalar      *aa;
1250acf2f550SJed Brown   PetscErrorCode ierr;
125199cafbc1SBarry Smith 
125299cafbc1SBarry Smith   PetscFunctionBegin;
12532e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
125499cafbc1SBarry Smith   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
12552e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
1256acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12578c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1258c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1259e2cf4d64SStefano Zampini #endif
126099cafbc1SBarry Smith   PetscFunctionReturn(0);
126199cafbc1SBarry Smith }
126299cafbc1SBarry Smith 
1263dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_SeqAIJ(Mat A)
126417ab2063SBarry Smith {
1265416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1266dfbe8321SBarry Smith   PetscErrorCode ierr;
12673a40ed3dSBarry Smith 
12683a40ed3dSBarry Smith   PetscFunctionBegin;
1269580bdb30SBarry Smith   ierr = PetscArrayzero(a->a,a->i[A->rmap->n]);CHKERRQ(ierr);
1270acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
12718c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
1272c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
1273e2cf4d64SStefano Zampini #endif
12743a40ed3dSBarry Smith   PetscFunctionReturn(0);
127517ab2063SBarry Smith }
1276416022c9SBarry Smith 
1277dfbe8321SBarry Smith PetscErrorCode MatDestroy_SeqAIJ(Mat A)
127817ab2063SBarry Smith {
1279416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
1280dfbe8321SBarry Smith   PetscErrorCode ierr;
1281d5d45c9bSBarry Smith 
12823a40ed3dSBarry Smith   PetscFunctionBegin;
1283aa482453SBarry Smith #if defined(PETSC_USE_LOG)
1284d0f46423SBarry Smith   PetscLogObjectState((PetscObject)A,"Rows=%D, Cols=%D, NZ=%D",A->rmap->n,A->cmap->n,a->nz);
128517ab2063SBarry Smith #endif
1286e6b907acSBarry Smith   ierr = MatSeqXAIJFreeAIJ(A,&a->a,&a->j,&a->i);CHKERRQ(ierr);
12876bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
12886bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
128905b42c5fSBarry Smith   ierr = PetscFree(a->diag);CHKERRQ(ierr);
1290d48dcb14SBarry Smith   ierr = PetscFree(a->ibdiag);CHKERRQ(ierr);
1291071fcb05SBarry Smith   ierr = PetscFree(a->imax);CHKERRQ(ierr);
1292071fcb05SBarry Smith   ierr = PetscFree(a->ilen);CHKERRQ(ierr);
1293846b4da1SFande Kong   ierr = PetscFree(a->ipre);CHKERRQ(ierr);
129471f1c65dSBarry Smith   ierr = PetscFree3(a->idiag,a->mdiag,a->ssor_work);CHKERRQ(ierr);
129505b42c5fSBarry Smith   ierr = PetscFree(a->solve_work);CHKERRQ(ierr);
12966bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
129705b42c5fSBarry Smith   ierr = PetscFree(a->saved_values);CHKERRQ(ierr);
1298cd6b891eSBarry Smith   ierr = PetscFree2(a->compressedrow.i,a->compressedrow.rindex);CHKERRQ(ierr);
1299a30b2313SHong Zhang 
13004108e4d5SBarry Smith   ierr = MatDestroy_SeqAIJ_Inode(A);CHKERRQ(ierr);
1301bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
1302901853e0SKris Buschelman 
13036718818eSStefano Zampini   /* MatMatMultNumeric_SeqAIJ_SeqAIJ_Sorted may allocate this.
13046718818eSStefano Zampini      That function is so heavily used (sometimes in an hidden way through multnumeric function pointers)
13056718818eSStefano Zampini      that is hard to properly add this data to the MatProduct data. We free it here to avoid
13066718818eSStefano Zampini      users reusing the matrix object with different data to incur in obscure segmentation faults
13076718818eSStefano Zampini      due to different matrix sizes */
13086718818eSStefano Zampini   ierr = PetscObjectCompose((PetscObject)A,"__PETSc__ab_dense",NULL);CHKERRQ(ierr);
13096718818eSStefano Zampini 
1310f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
1311bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetColumnIndices_C",NULL);CHKERRQ(ierr);
1312bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatStoreValues_C",NULL);CHKERRQ(ierr);
1313bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatRetrieveValues_C",NULL);CHKERRQ(ierr);
1314bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsbaij_C",NULL);CHKERRQ(ierr);
1315bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqbaij_C",NULL);CHKERRQ(ierr);
1316bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijperm_C",NULL);CHKERRQ(ierr);
13174222ddf1SHong Zhang #if defined(PETSC_HAVE_CUDA)
13184222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
1319e6e9a74fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",NULL);CHKERRQ(ierr);
1320fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",NULL);CHKERRQ(ierr);
13214222ddf1SHong Zhang #endif
13223d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
13233d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijkokkos_C",NULL);CHKERRQ(ierr);
13243d0639e7SStefano Zampini #endif
13254222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqaijcrl_C",NULL);CHKERRQ(ierr);
1326af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
1327af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_elemental_C",NULL);CHKERRQ(ierr);
1328af8000cdSHong Zhang #endif
1329d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
1330d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_scalapack_C",NULL);CHKERRQ(ierr);
1331d24d4204SJose E. Roman #endif
133263c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
133363c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_hypre_C",NULL);CHKERRQ(ierr);
13344222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
133563c07aadSStefano Zampini #endif
1336b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1337c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_seqsell_C",NULL);CHKERRQ(ierr);
1338c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_seqaij_is_C",NULL);CHKERRQ(ierr);
1339bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatIsTranspose_C",NULL);CHKERRQ(ierr);
1340bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocation_C",NULL);CHKERRQ(ierr);
1341846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)A,"MatResetPreallocation_C",NULL);CHKERRQ(ierr);
1342bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr);
1343bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatReorderForNonzeroDiagonal_C",NULL);CHKERRQ(ierr);
13444222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_is_seqaij_C",NULL);CHKERRQ(ierr);
13454222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
13464222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)A,"MatProductSetFromOptions_seqaij_seqaij_C",NULL);CHKERRQ(ierr);
1347ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)A,"MatSeqAIJKron_C",NULL);CHKERRQ(ierr);
13483a40ed3dSBarry Smith   PetscFunctionReturn(0);
134917ab2063SBarry Smith }
135017ab2063SBarry Smith 
1351ace3abfcSBarry Smith PetscErrorCode MatSetOption_SeqAIJ(Mat A,MatOption op,PetscBool flg)
135217ab2063SBarry Smith {
1353416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
13544846f1f5SKris Buschelman   PetscErrorCode ierr;
13553a40ed3dSBarry Smith 
13563a40ed3dSBarry Smith   PetscFunctionBegin;
1357a65d3064SKris Buschelman   switch (op) {
1358a65d3064SKris Buschelman   case MAT_ROW_ORIENTED:
13594e0d8c25SBarry Smith     a->roworiented = flg;
1360a65d3064SKris Buschelman     break;
1361a9817697SBarry Smith   case MAT_KEEP_NONZERO_PATTERN:
1362a9817697SBarry Smith     a->keepnonzeropattern = flg;
1363a65d3064SKris Buschelman     break;
1364512a5fc5SBarry Smith   case MAT_NEW_NONZERO_LOCATIONS:
1365512a5fc5SBarry Smith     a->nonew = (flg ? 0 : 1);
1366a65d3064SKris Buschelman     break;
1367a65d3064SKris Buschelman   case MAT_NEW_NONZERO_LOCATION_ERR:
13684e0d8c25SBarry Smith     a->nonew = (flg ? -1 : 0);
1369a65d3064SKris Buschelman     break;
1370a65d3064SKris Buschelman   case MAT_NEW_NONZERO_ALLOCATION_ERR:
13714e0d8c25SBarry Smith     a->nonew = (flg ? -2 : 0);
1372a65d3064SKris Buschelman     break;
137328b2fa4aSMatthew Knepley   case MAT_UNUSED_NONZERO_LOCATION_ERR:
137428b2fa4aSMatthew Knepley     a->nounused = (flg ? -1 : 0);
137528b2fa4aSMatthew Knepley     break;
1376a65d3064SKris Buschelman   case MAT_IGNORE_ZERO_ENTRIES:
13774e0d8c25SBarry Smith     a->ignorezeroentries = flg;
13780df259c2SBarry Smith     break;
13793d472b54SHong Zhang   case MAT_SPD:
1380b1646e73SJed Brown   case MAT_SYMMETRIC:
1381b1646e73SJed Brown   case MAT_STRUCTURALLY_SYMMETRIC:
1382b1646e73SJed Brown   case MAT_HERMITIAN:
1383b1646e73SJed Brown   case MAT_SYMMETRY_ETERNAL:
1384957cac9fSHong Zhang   case MAT_STRUCTURE_ONLY:
13855021d80fSJed Brown     /* These options are handled directly by MatSetOption() */
13865021d80fSJed Brown     break;
13878c78258cSHong Zhang   case MAT_FORCE_DIAGONAL_ENTRIES:
1388a65d3064SKris Buschelman   case MAT_IGNORE_OFF_PROC_ENTRIES:
1389a65d3064SKris Buschelman   case MAT_USE_HASH_TABLE:
1390290bbb0aSBarry Smith     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1391a65d3064SKris Buschelman     break;
1392b87ac2d8SJed Brown   case MAT_USE_INODES:
1393b215bc84SStefano Zampini     ierr = MatSetOption_SeqAIJ_Inode(A,MAT_USE_INODES,flg);CHKERRQ(ierr);
1394b87ac2d8SJed Brown     break;
1395c10200c1SHong Zhang   case MAT_SUBMAT_SINGLEIS:
1396c10200c1SHong Zhang     A->submat_singleis = flg;
1397c10200c1SHong Zhang     break;
1398071fcb05SBarry Smith   case MAT_SORTED_FULL:
1399071fcb05SBarry Smith     if (flg) A->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
1400071fcb05SBarry Smith     else     A->ops->setvalues = MatSetValues_SeqAIJ;
1401071fcb05SBarry Smith     break;
14021a2c6b5cSJunchao Zhang   case MAT_FORM_EXPLICIT_TRANSPOSE:
14031a2c6b5cSJunchao Zhang     A->form_explicit_transpose = flg;
14041a2c6b5cSJunchao Zhang     break;
1405a65d3064SKris Buschelman   default:
1406e32f2f54SBarry Smith     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op);
1407a65d3064SKris Buschelman   }
14083a40ed3dSBarry Smith   PetscFunctionReturn(0);
140917ab2063SBarry Smith }
141017ab2063SBarry Smith 
1411dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_SeqAIJ(Mat A,Vec v)
141217ab2063SBarry Smith {
1413416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
14146849ba73SBarry Smith   PetscErrorCode    ierr;
1415fdc842d1SBarry Smith   PetscInt          i,j,n,*ai=a->i,*aj=a->j;
1416c898d852SStefano Zampini   PetscScalar       *x;
1417c898d852SStefano Zampini   const PetscScalar *aa;
141817ab2063SBarry Smith 
14193a40ed3dSBarry Smith   PetscFunctionBegin;
1420d3e70bfaSHong Zhang   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1421e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1422c898d852SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
1423d5f3da31SBarry Smith   if (A->factortype == MAT_FACTOR_ILU || A->factortype == MAT_FACTOR_LU) {
1424d3e70bfaSHong Zhang     PetscInt *diag=a->diag;
1425fdc842d1SBarry Smith     ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
14262c990fa1SHong Zhang     for (i=0; i<n; i++) x[i] = 1.0/aa[diag[i]];
1427fdc842d1SBarry Smith     ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1428c898d852SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
142935e7444dSHong Zhang     PetscFunctionReturn(0);
143035e7444dSHong Zhang   }
143135e7444dSHong Zhang 
1432fdc842d1SBarry Smith   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
143335e7444dSHong Zhang   for (i=0; i<n; i++) {
1434fdc842d1SBarry Smith     x[i] = 0.0;
143535e7444dSHong Zhang     for (j=ai[i]; j<ai[i+1]; j++) {
143635e7444dSHong Zhang       if (aj[j] == i) {
143735e7444dSHong Zhang         x[i] = aa[j];
143817ab2063SBarry Smith         break;
143917ab2063SBarry Smith       }
144017ab2063SBarry Smith     }
144117ab2063SBarry Smith   }
1442fdc842d1SBarry Smith   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
1443c898d852SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
14443a40ed3dSBarry Smith   PetscFunctionReturn(0);
144517ab2063SBarry Smith }
144617ab2063SBarry Smith 
1447c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
1448dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_SeqAIJ(Mat A,Vec xx,Vec zz,Vec yy)
144917ab2063SBarry Smith {
1450416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1451d9ca1df4SBarry Smith   PetscScalar       *y;
1452d9ca1df4SBarry Smith   const PetscScalar *x;
1453dfbe8321SBarry Smith   PetscErrorCode    ierr;
1454d0f46423SBarry Smith   PetscInt          m = A->rmap->n;
14555c897100SBarry Smith #if !defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1456d9ca1df4SBarry Smith   const MatScalar   *v;
1457a77337e4SBarry Smith   PetscScalar       alpha;
1458d9ca1df4SBarry Smith   PetscInt          n,i,j;
1459d9ca1df4SBarry Smith   const PetscInt    *idx,*ii,*ridx=NULL;
14603447b6efSHong Zhang   Mat_CompressedRow cprow    = a->compressedrow;
1461ace3abfcSBarry Smith   PetscBool         usecprow = cprow.use;
14625c897100SBarry Smith #endif
146317ab2063SBarry Smith 
14643a40ed3dSBarry Smith   PetscFunctionBegin;
14652e8a6d31SBarry Smith   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
1466d9ca1df4SBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
14671ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
14685c897100SBarry Smith 
14695c897100SBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTTRANSPOSEAIJ)
1470bfeeae90SHong Zhang   fortranmulttransposeaddaij_(&m,x,a->i,a->j,a->a,y);
14715c897100SBarry Smith #else
14723447b6efSHong Zhang   if (usecprow) {
14733447b6efSHong Zhang     m    = cprow.nrows;
14743447b6efSHong Zhang     ii   = cprow.i;
14757b2bb3b9SHong Zhang     ridx = cprow.rindex;
14763447b6efSHong Zhang   } else {
14773447b6efSHong Zhang     ii = a->i;
14783447b6efSHong Zhang   }
147917ab2063SBarry Smith   for (i=0; i<m; i++) {
14803447b6efSHong Zhang     idx = a->j + ii[i];
14813447b6efSHong Zhang     v   = a->a + ii[i];
14823447b6efSHong Zhang     n   = ii[i+1] - ii[i];
14833447b6efSHong Zhang     if (usecprow) {
14847b2bb3b9SHong Zhang       alpha = x[ridx[i]];
14853447b6efSHong Zhang     } else {
148617ab2063SBarry Smith       alpha = x[i];
14873447b6efSHong Zhang     }
148804fbf559SBarry Smith     for (j=0; j<n; j++) y[idx[j]] += alpha*v[j];
148917ab2063SBarry Smith   }
14905c897100SBarry Smith #endif
1491dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1492d9ca1df4SBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
14931ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
14943a40ed3dSBarry Smith   PetscFunctionReturn(0);
149517ab2063SBarry Smith }
149617ab2063SBarry Smith 
1497dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_SeqAIJ(Mat A,Vec xx,Vec yy)
14985c897100SBarry Smith {
1499dfbe8321SBarry Smith   PetscErrorCode ierr;
15005c897100SBarry Smith 
15015c897100SBarry Smith   PetscFunctionBegin;
1502170fe5c8SBarry Smith   ierr = VecSet(yy,0.0);CHKERRQ(ierr);
15035c897100SBarry Smith   ierr = MatMultTransposeAdd_SeqAIJ(A,xx,yy,yy);CHKERRQ(ierr);
15045c897100SBarry Smith   PetscFunctionReturn(0);
15055c897100SBarry Smith }
15065c897100SBarry Smith 
1507c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmult.h>
150878b84d54SShri Abhyankar 
1509dfbe8321SBarry Smith PetscErrorCode MatMult_SeqAIJ(Mat A,Vec xx,Vec yy)
151017ab2063SBarry Smith {
1511416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1512d9fead3dSBarry Smith   PetscScalar       *y;
151354f21887SBarry Smith   const PetscScalar *x;
151454f21887SBarry Smith   const MatScalar   *aa;
1515dfbe8321SBarry Smith   PetscErrorCode    ierr;
1516003131ecSBarry Smith   PetscInt          m=A->rmap->n;
15170298fd71SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
15187b083b7cSBarry Smith   PetscInt          n,i;
1519362ced78SSatish Balay   PetscScalar       sum;
1520ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
152117ab2063SBarry Smith 
1522b6410449SSatish Balay #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
152397952fefSHong Zhang #pragma disjoint(*x,*y,*aa)
1524fee21e36SBarry Smith #endif
1525fee21e36SBarry Smith 
15263a40ed3dSBarry Smith   PetscFunctionBegin;
1527b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1528b215bc84SStefano Zampini     ierr = MatMult_SeqAIJ_Inode(A,xx,yy);CHKERRQ(ierr);
1529b215bc84SStefano Zampini     PetscFunctionReturn(0);
1530b215bc84SStefano Zampini   }
15313649974fSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
15321ebc52fbSHong Zhang   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1533416022c9SBarry Smith   ii   = a->i;
15344eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
1535580bdb30SBarry Smith     ierr = PetscArrayzero(y,m);CHKERRQ(ierr);
153697952fefSHong Zhang     m    = a->compressedrow.nrows;
153797952fefSHong Zhang     ii   = a->compressedrow.i;
153897952fefSHong Zhang     ridx = a->compressedrow.rindex;
153997952fefSHong Zhang     for (i=0; i<m; i++) {
154097952fefSHong Zhang       n           = ii[i+1] - ii[i];
154197952fefSHong Zhang       aj          = a->j + ii[i];
154297952fefSHong Zhang       aa          = a->a + ii[i];
154397952fefSHong Zhang       sum         = 0.0;
1544003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
1545003131ecSBarry Smith       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
154697952fefSHong Zhang       y[*ridx++] = sum;
154797952fefSHong Zhang     }
154897952fefSHong Zhang   } else { /* do not use compressed row format */
1549b05257ddSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTAIJ)
15503d3eaba7SBarry Smith     aj   = a->j;
15513d3eaba7SBarry Smith     aa   = a->a;
1552b05257ddSBarry Smith     fortranmultaij_(&m,x,ii,aj,aa,y);
1553b05257ddSBarry Smith #else
155417ab2063SBarry Smith     for (i=0; i<m; i++) {
1555003131ecSBarry Smith       n           = ii[i+1] - ii[i];
1556003131ecSBarry Smith       aj          = a->j + ii[i];
1557003131ecSBarry Smith       aa          = a->a + ii[i];
155817ab2063SBarry Smith       sum         = 0.0;
1559003131ecSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
156017ab2063SBarry Smith       y[i] = sum;
156117ab2063SBarry Smith     }
15628d195f9aSBarry Smith #endif
1563b05257ddSBarry Smith   }
15647b083b7cSBarry Smith   ierr = PetscLogFlops(2.0*a->nz - a->nonzerorowcnt);CHKERRQ(ierr);
15653649974fSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
15661ebc52fbSHong Zhang   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
15673a40ed3dSBarry Smith   PetscFunctionReturn(0);
156817ab2063SBarry Smith }
156917ab2063SBarry Smith 
1570b434eb95SMatthew G. Knepley PetscErrorCode MatMultMax_SeqAIJ(Mat A,Vec xx,Vec yy)
1571b434eb95SMatthew G. Knepley {
1572b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1573b434eb95SMatthew G. Knepley   PetscScalar       *y;
1574b434eb95SMatthew G. Knepley   const PetscScalar *x;
1575b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1576b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1577b434eb95SMatthew G. Knepley   PetscInt          m=A->rmap->n;
1578b434eb95SMatthew G. Knepley   const PetscInt    *aj,*ii,*ridx=NULL;
1579b434eb95SMatthew G. Knepley   PetscInt          n,i,nonzerorow=0;
1580b434eb95SMatthew G. Knepley   PetscScalar       sum;
1581b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1582b434eb95SMatthew G. Knepley 
1583b434eb95SMatthew G. Knepley #if defined(PETSC_HAVE_PRAGMA_DISJOINT)
1584b434eb95SMatthew G. Knepley #pragma disjoint(*x,*y,*aa)
1585b434eb95SMatthew G. Knepley #endif
1586b434eb95SMatthew G. Knepley 
1587b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1588b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1589b434eb95SMatthew G. Knepley   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1590b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1591b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1592b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1593b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1594b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1595b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1596b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1597b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1598b434eb95SMatthew G. Knepley       sum         = 0.0;
1599b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1600b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1601b434eb95SMatthew G. Knepley       /* for (j=0; j<n; j++) sum += (*aa++)*x[*aj++]; */
1602b434eb95SMatthew G. Knepley       y[*ridx++] = sum;
1603b434eb95SMatthew G. Knepley     }
1604b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16053d3eaba7SBarry Smith     ii = a->i;
1606b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1607b434eb95SMatthew G. Knepley       n           = ii[i+1] - ii[i];
1608b434eb95SMatthew G. Knepley       aj          = a->j + ii[i];
1609b434eb95SMatthew G. Knepley       aa          = a->a + ii[i];
1610b434eb95SMatthew G. Knepley       sum         = 0.0;
1611b434eb95SMatthew G. Knepley       nonzerorow += (n>0);
1612b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1613b434eb95SMatthew G. Knepley       y[i] = sum;
1614b434eb95SMatthew G. Knepley     }
1615b434eb95SMatthew G. Knepley   }
1616b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz - nonzerorow);CHKERRQ(ierr);
1617b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1618b434eb95SMatthew G. Knepley   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1619b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1620b434eb95SMatthew G. Knepley }
1621b434eb95SMatthew G. Knepley 
1622b434eb95SMatthew G. Knepley PetscErrorCode MatMultAddMax_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
1623b434eb95SMatthew G. Knepley {
1624b434eb95SMatthew G. Knepley   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1625b434eb95SMatthew G. Knepley   PetscScalar       *y,*z;
1626b434eb95SMatthew G. Knepley   const PetscScalar *x;
1627b434eb95SMatthew G. Knepley   const MatScalar   *aa;
1628b434eb95SMatthew G. Knepley   PetscErrorCode    ierr;
1629b434eb95SMatthew G. Knepley   PetscInt          m = A->rmap->n,*aj,*ii;
1630b434eb95SMatthew G. Knepley   PetscInt          n,i,*ridx=NULL;
1631b434eb95SMatthew G. Knepley   PetscScalar       sum;
1632b434eb95SMatthew G. Knepley   PetscBool         usecprow=a->compressedrow.use;
1633b434eb95SMatthew G. Knepley 
1634b434eb95SMatthew G. Knepley   PetscFunctionBegin;
1635b434eb95SMatthew G. Knepley   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1636d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1637b434eb95SMatthew G. Knepley   if (usecprow) { /* use compressed row format */
1638b434eb95SMatthew G. Knepley     if (zz != yy) {
1639580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
1640b434eb95SMatthew G. Knepley     }
1641b434eb95SMatthew G. Knepley     m    = a->compressedrow.nrows;
1642b434eb95SMatthew G. Knepley     ii   = a->compressedrow.i;
1643b434eb95SMatthew G. Knepley     ridx = a->compressedrow.rindex;
1644b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1645b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1646b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1647b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1648b434eb95SMatthew G. Knepley       sum = y[*ridx];
1649b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1650b434eb95SMatthew G. Knepley       z[*ridx++] = sum;
1651b434eb95SMatthew G. Knepley     }
1652b434eb95SMatthew G. Knepley   } else { /* do not use compressed row format */
16533d3eaba7SBarry Smith     ii = a->i;
1654b434eb95SMatthew G. Knepley     for (i=0; i<m; i++) {
1655b434eb95SMatthew G. Knepley       n   = ii[i+1] - ii[i];
1656b434eb95SMatthew G. Knepley       aj  = a->j + ii[i];
1657b434eb95SMatthew G. Knepley       aa  = a->a + ii[i];
1658b434eb95SMatthew G. Knepley       sum = y[i];
1659b434eb95SMatthew G. Knepley       PetscSparseDenseMaxDot(sum,x,aa,aj,n);
1660b434eb95SMatthew G. Knepley       z[i] = sum;
1661b434eb95SMatthew G. Knepley     }
1662b434eb95SMatthew G. Knepley   }
1663b434eb95SMatthew G. Knepley   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1664b434eb95SMatthew G. Knepley   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1665d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
1666b434eb95SMatthew G. Knepley   PetscFunctionReturn(0);
1667b434eb95SMatthew G. Knepley }
1668b434eb95SMatthew G. Knepley 
1669c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/fmultadd.h>
1670dfbe8321SBarry Smith PetscErrorCode MatMultAdd_SeqAIJ(Mat A,Vec xx,Vec yy,Vec zz)
167117ab2063SBarry Smith {
1672416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1673f15663dcSBarry Smith   PetscScalar       *y,*z;
1674f15663dcSBarry Smith   const PetscScalar *x;
167554f21887SBarry Smith   const MatScalar   *aa;
1676dfbe8321SBarry Smith   PetscErrorCode    ierr;
1677d9ca1df4SBarry Smith   const PetscInt    *aj,*ii,*ridx=NULL;
1678d9ca1df4SBarry Smith   PetscInt          m = A->rmap->n,n,i;
1679362ced78SSatish Balay   PetscScalar       sum;
1680ace3abfcSBarry Smith   PetscBool         usecprow=a->compressedrow.use;
16819ea0dfa2SSatish Balay 
16823a40ed3dSBarry Smith   PetscFunctionBegin;
1683b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked) {
1684b215bc84SStefano Zampini     ierr = MatMultAdd_SeqAIJ_Inode(A,xx,yy,zz);CHKERRQ(ierr);
1685b215bc84SStefano Zampini     PetscFunctionReturn(0);
1686b215bc84SStefano Zampini   }
1687f15663dcSBarry Smith   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1688d9ca1df4SBarry Smith   ierr = VecGetArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
16894eb6d288SHong Zhang   if (usecprow) { /* use compressed row format */
16904eb6d288SHong Zhang     if (zz != yy) {
1691580bdb30SBarry Smith       ierr = PetscArraycpy(z,y,m);CHKERRQ(ierr);
16924eb6d288SHong Zhang     }
169397952fefSHong Zhang     m    = a->compressedrow.nrows;
169497952fefSHong Zhang     ii   = a->compressedrow.i;
169597952fefSHong Zhang     ridx = a->compressedrow.rindex;
169697952fefSHong Zhang     for (i=0; i<m; i++) {
169797952fefSHong Zhang       n   = ii[i+1] - ii[i];
169897952fefSHong Zhang       aj  = a->j + ii[i];
169997952fefSHong Zhang       aa  = a->a + ii[i];
170097952fefSHong Zhang       sum = y[*ridx];
1701f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
170297952fefSHong Zhang       z[*ridx++] = sum;
170397952fefSHong Zhang     }
170497952fefSHong Zhang   } else { /* do not use compressed row format */
17053d3eaba7SBarry Smith     ii = a->i;
1706f15663dcSBarry Smith #if defined(PETSC_USE_FORTRAN_KERNEL_MULTADDAIJ)
17073d3eaba7SBarry Smith     aj = a->j;
17083d3eaba7SBarry Smith     aa = a->a;
1709f15663dcSBarry Smith     fortranmultaddaij_(&m,x,ii,aj,aa,y,z);
1710f15663dcSBarry Smith #else
171117ab2063SBarry Smith     for (i=0; i<m; i++) {
1712f15663dcSBarry Smith       n   = ii[i+1] - ii[i];
1713f15663dcSBarry Smith       aj  = a->j + ii[i];
1714f15663dcSBarry Smith       aa  = a->a + ii[i];
171517ab2063SBarry Smith       sum = y[i];
1716f15663dcSBarry Smith       PetscSparseDensePlusDot(sum,x,aa,aj,n);
171717ab2063SBarry Smith       z[i] = sum;
171817ab2063SBarry Smith     }
171902ab625aSSatish Balay #endif
1720f15663dcSBarry Smith   }
1721dc0b31edSSatish Balay   ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
1722f15663dcSBarry Smith   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1723d9ca1df4SBarry Smith   ierr = VecRestoreArrayPair(yy,zz,&y,&z);CHKERRQ(ierr);
17243a40ed3dSBarry Smith   PetscFunctionReturn(0);
172517ab2063SBarry Smith }
172617ab2063SBarry Smith 
172717ab2063SBarry Smith /*
172817ab2063SBarry Smith      Adds diagonal pointers to sparse matrix structure.
172917ab2063SBarry Smith */
1730dfbe8321SBarry Smith PetscErrorCode MatMarkDiagonal_SeqAIJ(Mat A)
173117ab2063SBarry Smith {
1732416022c9SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
17336849ba73SBarry Smith   PetscErrorCode ierr;
1734d0f46423SBarry Smith   PetscInt       i,j,m = A->rmap->n;
173517ab2063SBarry Smith 
17363a40ed3dSBarry Smith   PetscFunctionBegin;
173709f38230SBarry Smith   if (!a->diag) {
1738785e854fSJed Brown     ierr = PetscMalloc1(m,&a->diag);CHKERRQ(ierr);
17393bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A, m*sizeof(PetscInt));CHKERRQ(ierr);
174009f38230SBarry Smith   }
1741d0f46423SBarry Smith   for (i=0; i<A->rmap->n; i++) {
174209f38230SBarry Smith     a->diag[i] = a->i[i+1];
1743bfeeae90SHong Zhang     for (j=a->i[i]; j<a->i[i+1]; j++) {
1744bfeeae90SHong Zhang       if (a->j[j] == i) {
174509f38230SBarry Smith         a->diag[i] = j;
174617ab2063SBarry Smith         break;
174717ab2063SBarry Smith       }
174817ab2063SBarry Smith     }
174917ab2063SBarry Smith   }
17503a40ed3dSBarry Smith   PetscFunctionReturn(0);
175117ab2063SBarry Smith }
175217ab2063SBarry Smith 
175361ecd0c6SBarry Smith PetscErrorCode MatShift_SeqAIJ(Mat A,PetscScalar v)
175461ecd0c6SBarry Smith {
175561ecd0c6SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
175661ecd0c6SBarry Smith   const PetscInt    *diag = (const PetscInt*)a->diag;
175761ecd0c6SBarry Smith   const PetscInt    *ii = (const PetscInt*) a->i;
175861ecd0c6SBarry Smith   PetscInt          i,*mdiag = NULL;
175961ecd0c6SBarry Smith   PetscErrorCode    ierr;
176061ecd0c6SBarry Smith   PetscInt          cnt = 0; /* how many diagonals are missing */
176161ecd0c6SBarry Smith 
176261ecd0c6SBarry Smith   PetscFunctionBegin;
176361ecd0c6SBarry Smith   if (!A->preallocated || !a->nz) {
176461ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
176561ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
176661ecd0c6SBarry Smith     PetscFunctionReturn(0);
176761ecd0c6SBarry Smith   }
176861ecd0c6SBarry Smith 
176961ecd0c6SBarry Smith   if (a->diagonaldense) {
177061ecd0c6SBarry Smith     cnt = 0;
177161ecd0c6SBarry Smith   } else {
177261ecd0c6SBarry Smith     ierr = PetscCalloc1(A->rmap->n,&mdiag);CHKERRQ(ierr);
177361ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
177461ecd0c6SBarry Smith       if (diag[i] >= ii[i+1]) {
177561ecd0c6SBarry Smith         cnt++;
177661ecd0c6SBarry Smith         mdiag[i] = 1;
177761ecd0c6SBarry Smith       }
177861ecd0c6SBarry Smith     }
177961ecd0c6SBarry Smith   }
178061ecd0c6SBarry Smith   if (!cnt) {
178161ecd0c6SBarry Smith     ierr = MatShift_Basic(A,v);CHKERRQ(ierr);
178261ecd0c6SBarry Smith   } else {
1783b6f2aa54SBarry Smith     PetscScalar *olda = a->a;  /* preserve pointers to current matrix nonzeros structure and values */
1784b6f2aa54SBarry Smith     PetscInt    *oldj = a->j, *oldi = a->i;
178561ecd0c6SBarry Smith     PetscBool   singlemalloc = a->singlemalloc,free_a = a->free_a,free_ij = a->free_ij;
178661ecd0c6SBarry Smith 
178761ecd0c6SBarry Smith     a->a = NULL;
178861ecd0c6SBarry Smith     a->j = NULL;
178961ecd0c6SBarry Smith     a->i = NULL;
179061ecd0c6SBarry Smith     /* increase the values in imax for each row where a diagonal is being inserted then reallocate the matrix data structures */
179161ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
179261ecd0c6SBarry Smith       a->imax[i] += mdiag[i];
1793447d62f5SStefano Zampini       a->imax[i] = PetscMin(a->imax[i],A->cmap->n);
179461ecd0c6SBarry Smith     }
179561ecd0c6SBarry Smith     ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,0,a->imax);CHKERRQ(ierr);
179661ecd0c6SBarry Smith 
179761ecd0c6SBarry Smith     /* copy old values into new matrix data structure */
179861ecd0c6SBarry Smith     for (i=0; i<A->rmap->n; i++) {
179961ecd0c6SBarry Smith       ierr = MatSetValues(A,1,&i,a->imax[i] - mdiag[i],&oldj[oldi[i]],&olda[oldi[i]],ADD_VALUES);CHKERRQ(ierr);
1800447d62f5SStefano Zampini       if (i < A->cmap->n) {
180161ecd0c6SBarry Smith         ierr = MatSetValue(A,i,i,v,ADD_VALUES);CHKERRQ(ierr);
180261ecd0c6SBarry Smith       }
1803447d62f5SStefano Zampini     }
180461ecd0c6SBarry Smith     ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180561ecd0c6SBarry Smith     ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
180661ecd0c6SBarry Smith     if (singlemalloc) {
180761ecd0c6SBarry Smith       ierr = PetscFree3(olda,oldj,oldi);CHKERRQ(ierr);
180861ecd0c6SBarry Smith     } else {
180961ecd0c6SBarry Smith       if (free_a)  {ierr = PetscFree(olda);CHKERRQ(ierr);}
181061ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldj);CHKERRQ(ierr);}
181161ecd0c6SBarry Smith       if (free_ij) {ierr = PetscFree(oldi);CHKERRQ(ierr);}
181261ecd0c6SBarry Smith     }
181361ecd0c6SBarry Smith   }
181461ecd0c6SBarry Smith   ierr = PetscFree(mdiag);CHKERRQ(ierr);
181561ecd0c6SBarry Smith   a->diagonaldense = PETSC_TRUE;
181661ecd0c6SBarry Smith   PetscFunctionReturn(0);
181761ecd0c6SBarry Smith }
181861ecd0c6SBarry Smith 
1819be5855fcSBarry Smith /*
1820be5855fcSBarry Smith      Checks for missing diagonals
1821be5855fcSBarry Smith */
1822ace3abfcSBarry Smith PetscErrorCode MatMissingDiagonal_SeqAIJ(Mat A,PetscBool  *missing,PetscInt *d)
1823be5855fcSBarry Smith {
1824be5855fcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
18257734d3b5SMatthew G. Knepley   PetscInt       *diag,*ii = a->i,i;
1826994fe344SLisandro Dalcin   PetscErrorCode ierr;
1827be5855fcSBarry Smith 
1828be5855fcSBarry Smith   PetscFunctionBegin;
182909f38230SBarry Smith   *missing = PETSC_FALSE;
18307734d3b5SMatthew G. Knepley   if (A->rmap->n > 0 && !ii) {
183109f38230SBarry Smith     *missing = PETSC_TRUE;
183209f38230SBarry Smith     if (d) *d = 0;
1833994fe344SLisandro Dalcin     ierr = PetscInfo(A,"Matrix has no entries therefore is missing diagonal\n");CHKERRQ(ierr);
183409f38230SBarry Smith   } else {
183501445905SHong Zhang     PetscInt n;
183601445905SHong Zhang     n = PetscMin(A->rmap->n, A->cmap->n);
1837f1e2ffcdSBarry Smith     diag = a->diag;
183801445905SHong Zhang     for (i=0; i<n; i++) {
18397734d3b5SMatthew G. Knepley       if (diag[i] >= ii[i+1]) {
184009f38230SBarry Smith         *missing = PETSC_TRUE;
184109f38230SBarry Smith         if (d) *d = i;
1842994fe344SLisandro Dalcin         ierr = PetscInfo1(A,"Matrix is missing diagonal number %D\n",i);CHKERRQ(ierr);
1843358d2f5dSShri Abhyankar         break;
184409f38230SBarry Smith       }
1845be5855fcSBarry Smith     }
1846be5855fcSBarry Smith   }
1847be5855fcSBarry Smith   PetscFunctionReturn(0);
1848be5855fcSBarry Smith }
1849be5855fcSBarry Smith 
18500da83c2eSBarry Smith #include <petscblaslapack.h>
18510da83c2eSBarry Smith #include <petsc/private/kernels/blockinvert.h>
18520da83c2eSBarry Smith 
18530da83c2eSBarry Smith /*
18540da83c2eSBarry Smith     Note that values is allocated externally by the PC and then passed into this routine
18550da83c2eSBarry Smith */
18560da83c2eSBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_SeqAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag)
18570da83c2eSBarry Smith {
18580da83c2eSBarry Smith   PetscErrorCode  ierr;
18590da83c2eSBarry Smith   PetscInt        n = A->rmap->n, i, ncnt = 0, *indx,j,bsizemax = 0,*v_pivots;
18600da83c2eSBarry Smith   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
18610da83c2eSBarry Smith   const PetscReal shift = 0.0;
18620da83c2eSBarry Smith   PetscInt        ipvt[5];
18630da83c2eSBarry Smith   PetscScalar     work[25],*v_work;
18640da83c2eSBarry Smith 
18650da83c2eSBarry Smith   PetscFunctionBegin;
18660da83c2eSBarry Smith   allowzeropivot = PetscNot(A->erroriffailure);
18670da83c2eSBarry Smith   for (i=0; i<nblocks; i++) ncnt += bsizes[i];
18680da83c2eSBarry Smith   if (ncnt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Total blocksizes %D doesn't match number matrix rows %D",ncnt,n);
18690da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18700da83c2eSBarry Smith     bsizemax = PetscMax(bsizemax,bsizes[i]);
18710da83c2eSBarry Smith   }
18720da83c2eSBarry Smith   ierr = PetscMalloc1(bsizemax,&indx);CHKERRQ(ierr);
18730da83c2eSBarry Smith   if (bsizemax > 7) {
18740da83c2eSBarry Smith     ierr = PetscMalloc2(bsizemax,&v_work,bsizemax,&v_pivots);CHKERRQ(ierr);
18750da83c2eSBarry Smith   }
18760da83c2eSBarry Smith   ncnt = 0;
18770da83c2eSBarry Smith   for (i=0; i<nblocks; i++) {
18780da83c2eSBarry Smith     for (j=0; j<bsizes[i]; j++) indx[j] = ncnt+j;
18790da83c2eSBarry Smith     ierr    = MatGetValues(A,bsizes[i],indx,bsizes[i],indx,diag);CHKERRQ(ierr);
18800da83c2eSBarry Smith     switch (bsizes[i]) {
18810da83c2eSBarry Smith     case 1:
18820da83c2eSBarry Smith       *diag = 1.0/(*diag);
18830da83c2eSBarry Smith       break;
18840da83c2eSBarry Smith     case 2:
18850da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18860da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18870da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
18880da83c2eSBarry Smith       break;
18890da83c2eSBarry Smith     case 3:
18900da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18910da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18920da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
18930da83c2eSBarry Smith       break;
18940da83c2eSBarry Smith     case 4:
18950da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
18960da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
18970da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
18980da83c2eSBarry Smith       break;
18990da83c2eSBarry Smith     case 5:
19000da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19010da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19020da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
19030da83c2eSBarry Smith       break;
19040da83c2eSBarry Smith     case 6:
19050da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19060da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19070da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
19080da83c2eSBarry Smith       break;
19090da83c2eSBarry Smith     case 7:
19100da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19110da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19120da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
19130da83c2eSBarry Smith       break;
19140da83c2eSBarry Smith     default:
19150da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_inverse_A(bsizes[i],diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
19160da83c2eSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19170da83c2eSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bsizes[i]);CHKERRQ(ierr);
19180da83c2eSBarry Smith     }
19190da83c2eSBarry Smith     ncnt   += bsizes[i];
19200da83c2eSBarry Smith     diag += bsizes[i]*bsizes[i];
19210da83c2eSBarry Smith   }
19220da83c2eSBarry Smith   if (bsizemax > 7) {
19230da83c2eSBarry Smith     ierr = PetscFree2(v_work,v_pivots);CHKERRQ(ierr);
19240da83c2eSBarry Smith   }
19250da83c2eSBarry Smith   ierr = PetscFree(indx);CHKERRQ(ierr);
19260da83c2eSBarry Smith   PetscFunctionReturn(0);
19270da83c2eSBarry Smith }
19280da83c2eSBarry Smith 
1929422a814eSBarry Smith /*
1930422a814eSBarry Smith    Negative shift indicates do not generate an error if there is a zero diagonal, just invert it anyways
1931422a814eSBarry Smith */
19327087cfbeSBarry Smith PetscErrorCode  MatInvertDiagonal_SeqAIJ(Mat A,PetscScalar omega,PetscScalar fshift)
193371f1c65dSBarry Smith {
193471f1c65dSBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
193571f1c65dSBarry Smith   PetscErrorCode  ierr;
1936d0f46423SBarry Smith   PetscInt        i,*diag,m = A->rmap->n;
19372e5835c6SStefano Zampini   const MatScalar *v;
193854f21887SBarry Smith   PetscScalar     *idiag,*mdiag;
193971f1c65dSBarry Smith 
194071f1c65dSBarry Smith   PetscFunctionBegin;
194171f1c65dSBarry Smith   if (a->idiagvalid) PetscFunctionReturn(0);
194271f1c65dSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
194371f1c65dSBarry Smith   diag = a->diag;
194471f1c65dSBarry Smith   if (!a->idiag) {
1945dcca6d9dSJed Brown     ierr = PetscMalloc3(m,&a->idiag,m,&a->mdiag,m,&a->ssor_work);CHKERRQ(ierr);
19463bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,3*m*sizeof(PetscScalar));CHKERRQ(ierr);
194771f1c65dSBarry Smith   }
19482e5835c6SStefano Zampini 
194971f1c65dSBarry Smith   mdiag = a->mdiag;
195071f1c65dSBarry Smith   idiag = a->idiag;
19512e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
1952422a814eSBarry Smith   if (omega == 1.0 && PetscRealPart(fshift) <= 0.0) {
195371f1c65dSBarry Smith     for (i=0; i<m; i++) {
195471f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
1955899639b0SHong Zhang       if (!PetscAbsScalar(mdiag[i])) { /* zero diagonal */
1956899639b0SHong Zhang         if (PetscRealPart(fshift)) {
1957899639b0SHong Zhang           ierr = PetscInfo1(A,"Zero diagonal on row %D\n",i);CHKERRQ(ierr);
19587b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
19597b6c816cSBarry Smith           A->factorerror_zeropivot_value = 0.0;
19607b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
1961a6fa060aSHong Zhang         } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Zero diagonal on row %D",i);
1962899639b0SHong Zhang       }
196371f1c65dSBarry Smith       idiag[i] = 1.0/v[diag[i]];
196471f1c65dSBarry Smith     }
196571f1c65dSBarry Smith     ierr = PetscLogFlops(m);CHKERRQ(ierr);
196671f1c65dSBarry Smith   } else {
196771f1c65dSBarry Smith     for (i=0; i<m; i++) {
196871f1c65dSBarry Smith       mdiag[i] = v[diag[i]];
196971f1c65dSBarry Smith       idiag[i] = omega/(fshift + v[diag[i]]);
197071f1c65dSBarry Smith     }
1971dc0b31edSSatish Balay     ierr = PetscLogFlops(2.0*m);CHKERRQ(ierr);
197271f1c65dSBarry Smith   }
197371f1c65dSBarry Smith   a->idiagvalid = PETSC_TRUE;
19742e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
197571f1c65dSBarry Smith   PetscFunctionReturn(0);
197671f1c65dSBarry Smith }
197771f1c65dSBarry Smith 
1978c6db04a5SJed Brown #include <../src/mat/impls/aij/seq/ftn-kernels/frelax.h>
197941f059aeSBarry Smith PetscErrorCode MatSOR_SeqAIJ(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx)
198017ab2063SBarry Smith {
1981416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
1982e6d1f457SBarry Smith   PetscScalar       *x,d,sum,*t,scale;
19832e5835c6SStefano Zampini   const MatScalar   *v,*idiag=NULL,*mdiag,*aa;
198454f21887SBarry Smith   const PetscScalar *b, *bs,*xb, *ts;
1985dfbe8321SBarry Smith   PetscErrorCode    ierr;
19863d3eaba7SBarry Smith   PetscInt          n,m = A->rmap->n,i;
198797f1f81fSBarry Smith   const PetscInt    *idx,*diag;
198817ab2063SBarry Smith 
19893a40ed3dSBarry Smith   PetscFunctionBegin;
1990b215bc84SStefano Zampini   if (a->inode.use && a->inode.checked && omega == 1.0 && fshift == 0.0) {
1991b215bc84SStefano Zampini     ierr = MatSOR_SeqAIJ_Inode(A,bb,omega,flag,fshift,its,lits,xx);CHKERRQ(ierr);
1992b215bc84SStefano Zampini     PetscFunctionReturn(0);
1993b215bc84SStefano Zampini   }
1994b965ef7fSBarry Smith   its = its*lits;
199591723122SBarry Smith 
199671f1c65dSBarry Smith   if (fshift != a->fshift || omega != a->omega) a->idiagvalid = PETSC_FALSE; /* must recompute idiag[] */
199771f1c65dSBarry Smith   if (!a->idiagvalid) {ierr = MatInvertDiagonal_SeqAIJ(A,omega,fshift);CHKERRQ(ierr);}
199871f1c65dSBarry Smith   a->fshift = fshift;
199971f1c65dSBarry Smith   a->omega  = omega;
2000ed480e8bSBarry Smith 
200171f1c65dSBarry Smith   diag  = a->diag;
200271f1c65dSBarry Smith   t     = a->ssor_work;
2003ed480e8bSBarry Smith   idiag = a->idiag;
200471f1c65dSBarry Smith   mdiag = a->mdiag;
2005ed480e8bSBarry Smith 
20062e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
20071ebc52fbSHong Zhang   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
20083649974fSBarry Smith   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
2009ed480e8bSBarry Smith   /* We count flops by assuming the upper triangular and lower triangular parts have the same number of nonzeros */
201017ab2063SBarry Smith   if (flag == SOR_APPLY_UPPER) {
201117ab2063SBarry Smith     /* apply (U + D/omega) to the vector */
2012ed480e8bSBarry Smith     bs = b;
201317ab2063SBarry Smith     for (i=0; i<m; i++) {
201471f1c65dSBarry Smith       d   = fshift + mdiag[i];
2015416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2016ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20172e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
201817ab2063SBarry Smith       sum = b[i]*d/omega;
2019003131ecSBarry Smith       PetscSparseDensePlusDot(sum,bs,v,idx,n);
202017ab2063SBarry Smith       x[i] = sum;
202117ab2063SBarry Smith     }
20221ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20233649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20242e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2025efee365bSSatish Balay     ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20263a40ed3dSBarry Smith     PetscFunctionReturn(0);
202717ab2063SBarry Smith   }
2028c783ea89SBarry Smith 
20292205254eSKarl Rupp   if (flag == SOR_APPLY_LOWER) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SOR_APPLY_LOWER is not implemented");
20302205254eSKarl Rupp   else if (flag & SOR_EISENSTAT) {
20314c500f23SPierre Jolivet     /* Let  A = L + U + D; where L is lower triangular,
2032887ee2caSBarry Smith     U is upper triangular, E = D/omega; This routine applies
203317ab2063SBarry Smith 
203417ab2063SBarry Smith             (L + E)^{-1} A (U + E)^{-1}
203517ab2063SBarry Smith 
2036887ee2caSBarry Smith     to a vector efficiently using Eisenstat's trick.
203717ab2063SBarry Smith     */
203817ab2063SBarry Smith     scale = (2.0/omega) - 1.0;
203917ab2063SBarry Smith 
204017ab2063SBarry Smith     /*  x = (E + U)^{-1} b */
204117ab2063SBarry Smith     for (i=m-1; i>=0; i--) {
2042416022c9SBarry Smith       n   = a->i[i+1] - diag[i] - 1;
2043ed480e8bSBarry Smith       idx = a->j + diag[i] + 1;
20442e5835c6SStefano Zampini       v   = aa + diag[i] + 1;
204517ab2063SBarry Smith       sum = b[i];
2046e6d1f457SBarry Smith       PetscSparseDenseMinusDot(sum,x,v,idx,n);
2047ed480e8bSBarry Smith       x[i] = sum*idiag[i];
204817ab2063SBarry Smith     }
204917ab2063SBarry Smith 
205017ab2063SBarry Smith     /*  t = b - (2*E - D)x */
20512e5835c6SStefano Zampini     v = aa;
20522205254eSKarl Rupp     for (i=0; i<m; i++) t[i] = b[i] - scale*(v[*diag++])*x[i];
205317ab2063SBarry Smith 
205417ab2063SBarry Smith     /*  t = (E + L)^{-1}t */
2055ed480e8bSBarry Smith     ts   = t;
2056416022c9SBarry Smith     diag = a->diag;
205717ab2063SBarry Smith     for (i=0; i<m; i++) {
2058416022c9SBarry Smith       n   = diag[i] - a->i[i];
2059ed480e8bSBarry Smith       idx = a->j + a->i[i];
20602e5835c6SStefano Zampini       v   = aa + a->i[i];
206117ab2063SBarry Smith       sum = t[i];
2062003131ecSBarry Smith       PetscSparseDenseMinusDot(sum,ts,v,idx,n);
2063ed480e8bSBarry Smith       t[i] = sum*idiag[i];
2064733d66baSBarry Smith       /*  x = x + t */
2065733d66baSBarry Smith       x[i] += t[i];
206617ab2063SBarry Smith     }
206717ab2063SBarry Smith 
2068dc0b31edSSatish Balay     ierr = PetscLogFlops(6.0*m-1 + 2.0*a->nz);CHKERRQ(ierr);
20691ebc52fbSHong Zhang     ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
20703649974fSBarry Smith     ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
20713a40ed3dSBarry Smith     PetscFunctionReturn(0);
207217ab2063SBarry Smith   }
207317ab2063SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
207417ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
207517ab2063SBarry Smith       for (i=0; i<m; i++) {
2076416022c9SBarry Smith         n   = diag[i] - a->i[i];
2077ed480e8bSBarry Smith         idx = a->j + a->i[i];
20782e5835c6SStefano Zampini         v   = aa + a->i[i];
207917ab2063SBarry Smith         sum = b[i];
2080e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20815c99c7daSBarry Smith         t[i] = sum;
2082ed480e8bSBarry Smith         x[i] = sum*idiag[i];
208317ab2063SBarry Smith       }
20845c99c7daSBarry Smith       xb   = t;
2085efee365bSSatish Balay       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
20863a40ed3dSBarry Smith     } else xb = b;
208717ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
208817ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2089416022c9SBarry Smith         n   = a->i[i+1] - diag[i] - 1;
2090ed480e8bSBarry Smith         idx = a->j + diag[i] + 1;
20912e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
209217ab2063SBarry Smith         sum = xb[i];
2093e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
20945c99c7daSBarry Smith         if (xb == b) {
2095ed480e8bSBarry Smith           x[i] = sum*idiag[i];
20965c99c7daSBarry Smith         } else {
2097b19a5dc2SMark Adams           x[i] = (1-omega)*x[i] + sum*idiag[i];  /* omega in idiag */
209817ab2063SBarry Smith         }
20995c99c7daSBarry Smith       }
2100b19a5dc2SMark Adams       ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
210117ab2063SBarry Smith     }
210217ab2063SBarry Smith     its--;
210317ab2063SBarry Smith   }
210417ab2063SBarry Smith   while (its--) {
210517ab2063SBarry Smith     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
210617ab2063SBarry Smith       for (i=0; i<m; i++) {
2107b19a5dc2SMark Adams         /* lower */
2108b19a5dc2SMark Adams         n   = diag[i] - a->i[i];
2109ed480e8bSBarry Smith         idx = a->j + a->i[i];
21102e5835c6SStefano Zampini         v   = aa + a->i[i];
211117ab2063SBarry Smith         sum = b[i];
2112e6d1f457SBarry Smith         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2113b19a5dc2SMark Adams         t[i] = sum;             /* save application of the lower-triangular part */
2114b19a5dc2SMark Adams         /* upper */
2115b19a5dc2SMark Adams         n   = a->i[i+1] - diag[i] - 1;
2116b19a5dc2SMark Adams         idx = a->j + diag[i] + 1;
21172e5835c6SStefano Zampini         v   = aa + diag[i] + 1;
2118b19a5dc2SMark Adams         PetscSparseDenseMinusDot(sum,x,v,idx,n);
2119b19a5dc2SMark Adams         x[i] = (1. - omega)*x[i] + sum*idiag[i]; /* omega in idiag */
212017ab2063SBarry Smith       }
2121b19a5dc2SMark Adams       xb   = t;
21229f863219SBarry Smith       ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2123b19a5dc2SMark Adams     } else xb = b;
212417ab2063SBarry Smith     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
212517ab2063SBarry Smith       for (i=m-1; i>=0; i--) {
2126b19a5dc2SMark Adams         sum = xb[i];
2127b19a5dc2SMark Adams         if (xb == b) {
2128b19a5dc2SMark Adams           /* whole matrix (no checkpointing available) */
2129416022c9SBarry Smith           n   = a->i[i+1] - a->i[i];
2130ed480e8bSBarry Smith           idx = a->j + a->i[i];
21312e5835c6SStefano Zampini           v   = aa + a->i[i];
2132e6d1f457SBarry Smith           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2133ed480e8bSBarry Smith           x[i] = (1. - omega)*x[i] + (sum + mdiag[i]*x[i])*idiag[i];
2134b19a5dc2SMark Adams         } else { /* lower-triangular part has been saved, so only apply upper-triangular */
2135b19a5dc2SMark Adams           n   = a->i[i+1] - diag[i] - 1;
2136b19a5dc2SMark Adams           idx = a->j + diag[i] + 1;
21372e5835c6SStefano Zampini           v   = aa + diag[i] + 1;
2138b19a5dc2SMark Adams           PetscSparseDenseMinusDot(sum,x,v,idx,n);
2139b19a5dc2SMark Adams           x[i] = (1. - omega)*x[i] + sum*idiag[i];  /* omega in idiag */
214017ab2063SBarry Smith         }
2141b19a5dc2SMark Adams       }
2142b19a5dc2SMark Adams       if (xb == b) {
21439f863219SBarry Smith         ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
2144b19a5dc2SMark Adams       } else {
2145b19a5dc2SMark Adams         ierr = PetscLogFlops(a->nz);CHKERRQ(ierr); /* assumes 1/2 in upper */
2146b19a5dc2SMark Adams       }
214717ab2063SBarry Smith     }
214817ab2063SBarry Smith   }
21492e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
21501ebc52fbSHong Zhang   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
21513649974fSBarry Smith   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
2152365a8a9eSBarry Smith   PetscFunctionReturn(0);
215317ab2063SBarry Smith }
215417ab2063SBarry Smith 
2155dfbe8321SBarry Smith PetscErrorCode MatGetInfo_SeqAIJ(Mat A,MatInfoType flag,MatInfo *info)
215617ab2063SBarry Smith {
2157416022c9SBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
21584e220ebcSLois Curfman McInnes 
21593a40ed3dSBarry Smith   PetscFunctionBegin;
21604e220ebcSLois Curfman McInnes   info->block_size   = 1.0;
21613966268fSBarry Smith   info->nz_allocated = a->maxnz;
21623966268fSBarry Smith   info->nz_used      = a->nz;
21633966268fSBarry Smith   info->nz_unneeded  = (a->maxnz - a->nz);
21643966268fSBarry Smith   info->assemblies   = A->num_ass;
21653966268fSBarry Smith   info->mallocs      = A->info.mallocs;
21667adad957SLisandro Dalcin   info->memory       = ((PetscObject)A)->mem;
2167d5f3da31SBarry Smith   if (A->factortype) {
21684e220ebcSLois Curfman McInnes     info->fill_ratio_given  = A->info.fill_ratio_given;
21694e220ebcSLois Curfman McInnes     info->fill_ratio_needed = A->info.fill_ratio_needed;
21704e220ebcSLois Curfman McInnes     info->factor_mallocs    = A->info.factor_mallocs;
21714e220ebcSLois Curfman McInnes   } else {
21724e220ebcSLois Curfman McInnes     info->fill_ratio_given  = 0;
21734e220ebcSLois Curfman McInnes     info->fill_ratio_needed = 0;
21744e220ebcSLois Curfman McInnes     info->factor_mallocs    = 0;
21754e220ebcSLois Curfman McInnes   }
21763a40ed3dSBarry Smith   PetscFunctionReturn(0);
217717ab2063SBarry Smith }
217817ab2063SBarry Smith 
21792b40b63fSBarry Smith PetscErrorCode MatZeroRows_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
218017ab2063SBarry Smith {
2181416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2182c7da8527SEric Chamberland   PetscInt          i,m = A->rmap->n - 1;
21836849ba73SBarry Smith   PetscErrorCode    ierr;
218497b48c8fSBarry Smith   const PetscScalar *xx;
21852e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
2186c7da8527SEric Chamberland   PetscInt          d = 0;
218717ab2063SBarry Smith 
21883a40ed3dSBarry Smith   PetscFunctionBegin;
218997b48c8fSBarry Smith   if (x && b) {
219097b48c8fSBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
219197b48c8fSBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
219297b48c8fSBarry Smith     for (i=0; i<N; i++) {
219397b48c8fSBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2194447d62f5SStefano Zampini       if (rows[i] >= A->cmap->n) continue;
219597b48c8fSBarry Smith       bb[rows[i]] = diag*xx[rows[i]];
219697b48c8fSBarry Smith     }
219797b48c8fSBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
219897b48c8fSBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
219997b48c8fSBarry Smith   }
220097b48c8fSBarry Smith 
22012e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
2202a9817697SBarry Smith   if (a->keepnonzeropattern) {
2203f1e2ffcdSBarry Smith     for (i=0; i<N; i++) {
2204e32f2f54SBarry Smith       if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22052e5835c6SStefano Zampini       ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
2206f1e2ffcdSBarry Smith     }
2207f4df32b1SMatthew Knepley     if (diag != 0.0) {
2208c7da8527SEric Chamberland       for (i=0; i<N; i++) {
2209c7da8527SEric Chamberland         d = rows[i];
2210447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
2211c7da8527SEric Chamberland         if (a->diag[d] >= a->i[d+1]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in the zeroed row %D",d);
2212c7da8527SEric Chamberland       }
2213f1e2ffcdSBarry Smith       for (i=0; i<N; i++) {
2214447d62f5SStefano Zampini         if (rows[i] >= A->cmap->n) continue;
22152e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
2216f1e2ffcdSBarry Smith       }
2217f1e2ffcdSBarry Smith     }
2218f1e2ffcdSBarry Smith   } else {
2219f4df32b1SMatthew Knepley     if (diag != 0.0) {
222017ab2063SBarry Smith       for (i=0; i<N; i++) {
2221e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22227ae801bdSBarry Smith         if (a->ilen[rows[i]] > 0) {
2223447d62f5SStefano Zampini           if (rows[i] >= A->cmap->n) {
2224447d62f5SStefano Zampini             a->ilen[rows[i]] = 0;
2225447d62f5SStefano Zampini           } else {
2226416022c9SBarry Smith             a->ilen[rows[i]]    = 1;
22272e5835c6SStefano Zampini             aa[a->i[rows[i]]]   = diag;
2228bfeeae90SHong Zhang             a->j[a->i[rows[i]]] = rows[i];
2229447d62f5SStefano Zampini           }
2230447d62f5SStefano Zampini         } else if (rows[i] < A->cmap->n) { /* in case row was completely empty */
2231f4df32b1SMatthew Knepley           ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
223217ab2063SBarry Smith         }
223317ab2063SBarry Smith       }
22343a40ed3dSBarry Smith     } else {
223517ab2063SBarry Smith       for (i=0; i<N; i++) {
2236e32f2f54SBarry Smith         if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
2237416022c9SBarry Smith         a->ilen[rows[i]] = 0;
223817ab2063SBarry Smith       }
223917ab2063SBarry Smith     }
2240e56f5c9eSBarry Smith     A->nonzerostate++;
2241f1e2ffcdSBarry Smith   }
22422e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
22438c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2244c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2245e2cf4d64SStefano Zampini #endif
22464099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
22473a40ed3dSBarry Smith   PetscFunctionReturn(0);
224817ab2063SBarry Smith }
224917ab2063SBarry Smith 
22506e169961SBarry Smith PetscErrorCode MatZeroRowsColumns_SeqAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
22516e169961SBarry Smith {
22526e169961SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
22536e169961SBarry Smith   PetscInt          i,j,m = A->rmap->n - 1,d = 0;
22546e169961SBarry Smith   PetscErrorCode    ierr;
22552b40b63fSBarry Smith   PetscBool         missing,*zeroed,vecs = PETSC_FALSE;
22566e169961SBarry Smith   const PetscScalar *xx;
22572e5835c6SStefano Zampini   PetscScalar       *bb,*aa;
22586e169961SBarry Smith 
22596e169961SBarry Smith   PetscFunctionBegin;
22602e5835c6SStefano Zampini   if (!N) PetscFunctionReturn(0);
22612e5835c6SStefano Zampini   ierr = MatSeqAIJGetArray(A,&aa);CHKERRQ(ierr);
22626e169961SBarry Smith   if (x && b) {
22636e169961SBarry Smith     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
22646e169961SBarry Smith     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
22652b40b63fSBarry Smith     vecs = PETSC_TRUE;
22666e169961SBarry Smith   }
22671795a4d1SJed Brown   ierr = PetscCalloc1(A->rmap->n,&zeroed);CHKERRQ(ierr);
22686e169961SBarry Smith   for (i=0; i<N; i++) {
22696e169961SBarry Smith     if (rows[i] < 0 || rows[i] > m) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"row %D out of range", rows[i]);
22702e5835c6SStefano Zampini     ierr = PetscArrayzero(&aa[a->i[rows[i]]],a->ilen[rows[i]]);CHKERRQ(ierr);
22712205254eSKarl Rupp 
22726e169961SBarry Smith     zeroed[rows[i]] = PETSC_TRUE;
22736e169961SBarry Smith   }
22746e169961SBarry Smith   for (i=0; i<A->rmap->n; i++) {
22756e169961SBarry Smith     if (!zeroed[i]) {
22766e169961SBarry Smith       for (j=a->i[i]; j<a->i[i+1]; j++) {
22774cf107fdSStefano Zampini         if (a->j[j] < A->rmap->n && zeroed[a->j[j]]) {
22782e5835c6SStefano Zampini           if (vecs) bb[i] -= aa[j]*xx[a->j[j]];
22792e5835c6SStefano Zampini           aa[j] = 0.0;
22806e169961SBarry Smith         }
22816e169961SBarry Smith       }
22824cf107fdSStefano Zampini     } else if (vecs && i < A->cmap->N) bb[i] = diag*xx[i];
22836e169961SBarry Smith   }
22846e169961SBarry Smith   if (x && b) {
22856e169961SBarry Smith     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
22866e169961SBarry Smith     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
22876e169961SBarry Smith   }
22886e169961SBarry Smith   ierr = PetscFree(zeroed);CHKERRQ(ierr);
22896e169961SBarry Smith   if (diag != 0.0) {
22906e169961SBarry Smith     ierr = MatMissingDiagonal_SeqAIJ(A,&missing,&d);CHKERRQ(ierr);
22911d5a398dSstefano_zampini     if (missing) {
22921d5a398dSstefano_zampini       for (i=0; i<N; i++) {
22934cf107fdSStefano Zampini         if (rows[i] >= A->cmap->N) continue;
22944cf107fdSStefano Zampini         if (a->nonew && rows[i] >= d) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix is missing diagonal entry in row %D (%D)",d,rows[i]);
22951d5a398dSstefano_zampini         ierr = MatSetValues_SeqAIJ(A,1,&rows[i],1,&rows[i],&diag,INSERT_VALUES);CHKERRQ(ierr);
22961d5a398dSstefano_zampini       }
22971d5a398dSstefano_zampini     } else {
22986e169961SBarry Smith       for (i=0; i<N; i++) {
22992e5835c6SStefano Zampini         aa[a->diag[rows[i]]] = diag;
23006e169961SBarry Smith       }
23016e169961SBarry Smith     }
23021d5a398dSstefano_zampini   }
23032e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArray(A,&aa);CHKERRQ(ierr);
23048c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2305c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2306e2cf4d64SStefano Zampini #endif
23074099cc6bSBarry Smith   ierr = (*A->ops->assemblyend)(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
23086e169961SBarry Smith   PetscFunctionReturn(0);
23096e169961SBarry Smith }
23106e169961SBarry Smith 
2311a77337e4SBarry Smith PetscErrorCode MatGetRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
231217ab2063SBarry Smith {
2313416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
23142e5835c6SStefano Zampini   const PetscScalar *aa = a->a;
231597f1f81fSBarry Smith   PetscInt          *itmp;
23162e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23172e5835c6SStefano Zampini   PetscErrorCode    ierr;
23182e5835c6SStefano Zampini   PetscBool         rest = PETSC_FALSE;
23192e5835c6SStefano Zampini #endif
232017ab2063SBarry Smith 
23213a40ed3dSBarry Smith   PetscFunctionBegin;
23222e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23232e5835c6SStefano Zampini   if (v && A->offloadmask == PETSC_OFFLOAD_GPU) {
23242e5835c6SStefano Zampini     /* triggers copy to CPU */
23252e5835c6SStefano Zampini     rest = PETSC_TRUE;
23262e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
23272e5835c6SStefano Zampini   } else aa = a->a;
23282e5835c6SStefano Zampini #endif
2329416022c9SBarry Smith   *nz = a->i[row+1] - a->i[row];
23302e5835c6SStefano Zampini   if (v) *v = (PetscScalar*)(aa + a->i[row]);
233117ab2063SBarry Smith   if (idx) {
2332bfeeae90SHong Zhang     itmp = a->j + a->i[row];
233326fbe8dcSKarl Rupp     if (*nz) *idx = itmp;
2334f4259b30SLisandro Dalcin     else *idx = NULL;
233517ab2063SBarry Smith   }
23362e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
23372e5835c6SStefano Zampini   if (rest) {
23382e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
23392e5835c6SStefano Zampini   }
23402e5835c6SStefano Zampini #endif
23413a40ed3dSBarry Smith   PetscFunctionReturn(0);
234217ab2063SBarry Smith }
234317ab2063SBarry Smith 
2344a77337e4SBarry Smith PetscErrorCode MatRestoreRow_SeqAIJ(Mat A,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v)
234517ab2063SBarry Smith {
23463a40ed3dSBarry Smith   PetscFunctionBegin;
2347cb4a9cd9SHong Zhang   if (nz)  *nz = 0;
23482e5835c6SStefano Zampini   if (idx) *idx = NULL;
23492e5835c6SStefano Zampini   if (v)   *v = NULL;
23503a40ed3dSBarry Smith   PetscFunctionReturn(0);
235117ab2063SBarry Smith }
235217ab2063SBarry Smith 
2353dfbe8321SBarry Smith PetscErrorCode MatNorm_SeqAIJ(Mat A,NormType type,PetscReal *nrm)
235417ab2063SBarry Smith {
2355416022c9SBarry Smith   Mat_SeqAIJ      *a  = (Mat_SeqAIJ*)A->data;
23562e5835c6SStefano Zampini   const MatScalar *v;
235736db0b34SBarry Smith   PetscReal       sum = 0.0;
23586849ba73SBarry Smith   PetscErrorCode  ierr;
235997f1f81fSBarry Smith   PetscInt        i,j;
236017ab2063SBarry Smith 
23613a40ed3dSBarry Smith   PetscFunctionBegin;
23622e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&v);CHKERRQ(ierr);
236317ab2063SBarry Smith   if (type == NORM_FROBENIUS) {
2364570b7f6dSBarry Smith #if defined(PETSC_USE_REAL___FP16)
2365570b7f6dSBarry Smith     PetscBLASInt one = 1,nz = a->nz;
236673cf7048SBarry Smith     PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&nz,v,&one));
2367570b7f6dSBarry Smith #else
2368416022c9SBarry Smith     for (i=0; i<a->nz; i++) {
236936db0b34SBarry Smith       sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
237017ab2063SBarry Smith     }
23718f1a2a5eSBarry Smith     *nrm = PetscSqrtReal(sum);
2372570b7f6dSBarry Smith #endif
2373ca0c957dSBarry Smith     ierr = PetscLogFlops(2.0*a->nz);CHKERRQ(ierr);
23743a40ed3dSBarry Smith   } else if (type == NORM_1) {
237536db0b34SBarry Smith     PetscReal *tmp;
237697f1f81fSBarry Smith     PetscInt  *jj = a->j;
23771795a4d1SJed Brown     ierr = PetscCalloc1(A->cmap->n+1,&tmp);CHKERRQ(ierr);
2378064f8208SBarry Smith     *nrm = 0.0;
2379416022c9SBarry Smith     for (j=0; j<a->nz; j++) {
2380bfeeae90SHong Zhang       tmp[*jj++] += PetscAbsScalar(*v);  v++;
238117ab2063SBarry Smith     }
2382d0f46423SBarry Smith     for (j=0; j<A->cmap->n; j++) {
2383064f8208SBarry Smith       if (tmp[j] > *nrm) *nrm = tmp[j];
238417ab2063SBarry Smith     }
2385606d414cSSatish Balay     ierr = PetscFree(tmp);CHKERRQ(ierr);
238651f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
23873a40ed3dSBarry Smith   } else if (type == NORM_INFINITY) {
2388064f8208SBarry Smith     *nrm = 0.0;
2389d0f46423SBarry Smith     for (j=0; j<A->rmap->n; j++) {
23902e5835c6SStefano Zampini       const PetscScalar *v2 = v + a->i[j];
239117ab2063SBarry Smith       sum = 0.0;
2392416022c9SBarry Smith       for (i=0; i<a->i[j+1]-a->i[j]; i++) {
23932e5835c6SStefano Zampini         sum += PetscAbsScalar(*v2); v2++;
239417ab2063SBarry Smith       }
2395064f8208SBarry Smith       if (sum > *nrm) *nrm = sum;
239617ab2063SBarry Smith     }
239751f70360SJed Brown     ierr = PetscLogFlops(PetscMax(a->nz-1,0));CHKERRQ(ierr);
2398f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for two norm");
23992e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&v);CHKERRQ(ierr);
24003a40ed3dSBarry Smith   PetscFunctionReturn(0);
240117ab2063SBarry Smith }
240217ab2063SBarry Smith 
24034e938277SHong Zhang /* Merged from MatGetSymbolicTranspose_SeqAIJ() - replace MatGetSymbolicTranspose_SeqAIJ()? */
24044e938277SHong Zhang PetscErrorCode MatTransposeSymbolic_SeqAIJ(Mat A,Mat *B)
24054e938277SHong Zhang {
24064e938277SHong Zhang   PetscErrorCode ierr;
24074e938277SHong Zhang   PetscInt       i,j,anzj;
24084e938277SHong Zhang   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data,*b;
24094e938277SHong Zhang   PetscInt       an=A->cmap->N,am=A->rmap->N;
24104e938277SHong Zhang   PetscInt       *ati,*atj,*atfill,*ai=a->i,*aj=a->j;
24114e938277SHong Zhang 
24124e938277SHong Zhang   PetscFunctionBegin;
24134e938277SHong Zhang   /* Allocate space for symbolic transpose info and work array */
2414854ce69bSBarry Smith   ierr = PetscCalloc1(an+1,&ati);CHKERRQ(ierr);
2415785e854fSJed Brown   ierr = PetscMalloc1(ai[am],&atj);CHKERRQ(ierr);
2416785e854fSJed Brown   ierr = PetscMalloc1(an,&atfill);CHKERRQ(ierr);
24174e938277SHong Zhang 
24184e938277SHong Zhang   /* Walk through aj and count ## of non-zeros in each row of A^T. */
24194e938277SHong Zhang   /* Note: offset by 1 for fast conversion into csr format. */
242026fbe8dcSKarl Rupp   for (i=0;i<ai[am];i++) ati[aj[i]+1] += 1;
24214e938277SHong Zhang   /* Form ati for csr format of A^T. */
242226fbe8dcSKarl Rupp   for (i=0;i<an;i++) ati[i+1] += ati[i];
24234e938277SHong Zhang 
24244e938277SHong Zhang   /* Copy ati into atfill so we have locations of the next free space in atj */
2425580bdb30SBarry Smith   ierr = PetscArraycpy(atfill,ati,an);CHKERRQ(ierr);
24264e938277SHong Zhang 
24274e938277SHong Zhang   /* Walk through A row-wise and mark nonzero entries of A^T. */
24284e938277SHong Zhang   for (i=0;i<am;i++) {
24294e938277SHong Zhang     anzj = ai[i+1] - ai[i];
24304e938277SHong Zhang     for (j=0;j<anzj;j++) {
24314e938277SHong Zhang       atj[atfill[*aj]] = i;
24324e938277SHong Zhang       atfill[*aj++]   += 1;
24334e938277SHong Zhang     }
24344e938277SHong Zhang   }
24354e938277SHong Zhang 
24364e938277SHong Zhang   /* Clean up temporary space and complete requests. */
24374e938277SHong Zhang   ierr = PetscFree(atfill);CHKERRQ(ierr);
2438ce94432eSBarry Smith   ierr = MatCreateSeqAIJWithArrays(PetscObjectComm((PetscObject)A),an,am,ati,atj,NULL,B);CHKERRQ(ierr);
243933d57670SJed Brown   ierr = MatSetBlockSizes(*B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
2440b5bb3eecSMark Adams   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
2441a2f3521dSMark F. Adams 
24424e938277SHong Zhang   b          = (Mat_SeqAIJ*)((*B)->data);
24434e938277SHong Zhang   b->free_a  = PETSC_FALSE;
24444e938277SHong Zhang   b->free_ij = PETSC_TRUE;
24454e938277SHong Zhang   b->nonew   = 0;
24464e938277SHong Zhang   PetscFunctionReturn(0);
24474e938277SHong Zhang }
24484e938277SHong Zhang 
24497087cfbeSBarry Smith PetscErrorCode  MatIsTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
2450cd0d46ebSvictorle {
24513d3eaba7SBarry Smith   Mat_SeqAIJ      *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
245254f21887SBarry Smith   PetscInt        *adx,*bdx,*aii,*bii,*aptr,*bptr;
24532e5835c6SStefano Zampini   const MatScalar *va,*vb;
24546849ba73SBarry Smith   PetscErrorCode  ierr;
245597f1f81fSBarry Smith   PetscInt        ma,na,mb,nb, i;
2456cd0d46ebSvictorle 
2457cd0d46ebSvictorle   PetscFunctionBegin;
2458cd0d46ebSvictorle   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
2459cd0d46ebSvictorle   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
24605485867bSBarry Smith   if (ma!=nb || na!=mb) {
24615485867bSBarry Smith     *f = PETSC_FALSE;
24625485867bSBarry Smith     PetscFunctionReturn(0);
24635485867bSBarry Smith   }
24642e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&va);CHKERRQ(ierr);
24652e5835c6SStefano Zampini   ierr = MatSeqAIJGetArrayRead(B,&vb);CHKERRQ(ierr);
2466cd0d46ebSvictorle   aii  = aij->i; bii = bij->i;
2467cd0d46ebSvictorle   adx  = aij->j; bdx = bij->j;
2468785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2469785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
2470cd0d46ebSvictorle   for (i=0; i<ma; i++) aptr[i] = aii[i];
2471cd0d46ebSvictorle   for (i=0; i<mb; i++) bptr[i] = bii[i];
2472cd0d46ebSvictorle 
2473cd0d46ebSvictorle   *f = PETSC_TRUE;
2474cd0d46ebSvictorle   for (i=0; i<ma; i++) {
2475cd0d46ebSvictorle     while (aptr[i]<aii[i+1]) {
247697f1f81fSBarry Smith       PetscInt    idc,idr;
24775485867bSBarry Smith       PetscScalar vc,vr;
2478cd0d46ebSvictorle       /* column/row index/value */
24795485867bSBarry Smith       idc = adx[aptr[i]];
24805485867bSBarry Smith       idr = bdx[bptr[idc]];
24815485867bSBarry Smith       vc  = va[aptr[i]];
24825485867bSBarry Smith       vr  = vb[bptr[idc]];
24835485867bSBarry Smith       if (i!=idr || PetscAbsScalar(vc-vr) > tol) {
24845485867bSBarry Smith         *f = PETSC_FALSE;
24855485867bSBarry Smith         goto done;
2486cd0d46ebSvictorle       } else {
24875485867bSBarry Smith         aptr[i]++;
24885485867bSBarry Smith         if (B || i!=idc) bptr[idc]++;
2489cd0d46ebSvictorle       }
2490cd0d46ebSvictorle     }
2491cd0d46ebSvictorle   }
2492cd0d46ebSvictorle done:
2493cd0d46ebSvictorle   ierr = PetscFree(aptr);CHKERRQ(ierr);
24943aeef889SHong Zhang   ierr = PetscFree(bptr);CHKERRQ(ierr);
24952e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&va);CHKERRQ(ierr);
24962e5835c6SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(B,&vb);CHKERRQ(ierr);
2497cd0d46ebSvictorle   PetscFunctionReturn(0);
2498cd0d46ebSvictorle }
2499cd0d46ebSvictorle 
25007087cfbeSBarry Smith PetscErrorCode  MatIsHermitianTranspose_SeqAIJ(Mat A,Mat B,PetscReal tol,PetscBool  *f)
25011cbb95d3SBarry Smith {
25023d3eaba7SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*) A->data,*bij = (Mat_SeqAIJ*) B->data;
250354f21887SBarry Smith   PetscInt       *adx,*bdx,*aii,*bii,*aptr,*bptr;
250454f21887SBarry Smith   MatScalar      *va,*vb;
25051cbb95d3SBarry Smith   PetscErrorCode ierr;
25061cbb95d3SBarry Smith   PetscInt       ma,na,mb,nb, i;
25071cbb95d3SBarry Smith 
25081cbb95d3SBarry Smith   PetscFunctionBegin;
25091cbb95d3SBarry Smith   ierr = MatGetSize(A,&ma,&na);CHKERRQ(ierr);
25101cbb95d3SBarry Smith   ierr = MatGetSize(B,&mb,&nb);CHKERRQ(ierr);
25111cbb95d3SBarry Smith   if (ma!=nb || na!=mb) {
25121cbb95d3SBarry Smith     *f = PETSC_FALSE;
25131cbb95d3SBarry Smith     PetscFunctionReturn(0);
25141cbb95d3SBarry Smith   }
25151cbb95d3SBarry Smith   aii  = aij->i; bii = bij->i;
25161cbb95d3SBarry Smith   adx  = aij->j; bdx = bij->j;
25171cbb95d3SBarry Smith   va   = aij->a; vb = bij->a;
2518785e854fSJed Brown   ierr = PetscMalloc1(ma,&aptr);CHKERRQ(ierr);
2519785e854fSJed Brown   ierr = PetscMalloc1(mb,&bptr);CHKERRQ(ierr);
25201cbb95d3SBarry Smith   for (i=0; i<ma; i++) aptr[i] = aii[i];
25211cbb95d3SBarry Smith   for (i=0; i<mb; i++) bptr[i] = bii[i];
25221cbb95d3SBarry Smith 
25231cbb95d3SBarry Smith   *f = PETSC_TRUE;
25241cbb95d3SBarry Smith   for (i=0; i<ma; i++) {
25251cbb95d3SBarry Smith     while (aptr[i]<aii[i+1]) {
25261cbb95d3SBarry Smith       PetscInt    idc,idr;
25271cbb95d3SBarry Smith       PetscScalar vc,vr;
25281cbb95d3SBarry Smith       /* column/row index/value */
25291cbb95d3SBarry Smith       idc = adx[aptr[i]];
25301cbb95d3SBarry Smith       idr = bdx[bptr[idc]];
25311cbb95d3SBarry Smith       vc  = va[aptr[i]];
25321cbb95d3SBarry Smith       vr  = vb[bptr[idc]];
25331cbb95d3SBarry Smith       if (i!=idr || PetscAbsScalar(vc-PetscConj(vr)) > tol) {
25341cbb95d3SBarry Smith         *f = PETSC_FALSE;
25351cbb95d3SBarry Smith         goto done;
25361cbb95d3SBarry Smith       } else {
25371cbb95d3SBarry Smith         aptr[i]++;
25381cbb95d3SBarry Smith         if (B || i!=idc) bptr[idc]++;
25391cbb95d3SBarry Smith       }
25401cbb95d3SBarry Smith     }
25411cbb95d3SBarry Smith   }
25421cbb95d3SBarry Smith done:
25431cbb95d3SBarry Smith   ierr = PetscFree(aptr);CHKERRQ(ierr);
25441cbb95d3SBarry Smith   ierr = PetscFree(bptr);CHKERRQ(ierr);
25451cbb95d3SBarry Smith   PetscFunctionReturn(0);
25461cbb95d3SBarry Smith }
25471cbb95d3SBarry Smith 
2548ace3abfcSBarry Smith PetscErrorCode MatIsSymmetric_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25499e29f15eSvictorle {
2550dfbe8321SBarry Smith   PetscErrorCode ierr;
25516e111a19SKarl Rupp 
25529e29f15eSvictorle   PetscFunctionBegin;
25535485867bSBarry Smith   ierr = MatIsTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25549e29f15eSvictorle   PetscFunctionReturn(0);
25559e29f15eSvictorle }
25569e29f15eSvictorle 
2557ace3abfcSBarry Smith PetscErrorCode MatIsHermitian_SeqAIJ(Mat A,PetscReal tol,PetscBool  *f)
25581cbb95d3SBarry Smith {
25591cbb95d3SBarry Smith   PetscErrorCode ierr;
25606e111a19SKarl Rupp 
25611cbb95d3SBarry Smith   PetscFunctionBegin;
25621cbb95d3SBarry Smith   ierr = MatIsHermitianTranspose_SeqAIJ(A,A,tol,f);CHKERRQ(ierr);
25631cbb95d3SBarry Smith   PetscFunctionReturn(0);
25641cbb95d3SBarry Smith }
25651cbb95d3SBarry Smith 
2566dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_SeqAIJ(Mat A,Vec ll,Vec rr)
256717ab2063SBarry Smith {
2568416022c9SBarry Smith   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
2569fff8e43fSBarry Smith   const PetscScalar *l,*r;
2570fff8e43fSBarry Smith   PetscScalar       x;
257154f21887SBarry Smith   MatScalar         *v;
2572dfbe8321SBarry Smith   PetscErrorCode    ierr;
2573fff8e43fSBarry Smith   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,M,nz = a->nz;
2574fff8e43fSBarry Smith   const PetscInt    *jj;
257517ab2063SBarry Smith 
25763a40ed3dSBarry Smith   PetscFunctionBegin;
257717ab2063SBarry Smith   if (ll) {
25783ea7c6a1SSatish Balay     /* The local size is used so that VecMPI can be passed to this routine
25793ea7c6a1SSatish Balay        by MatDiagonalScale_MPIAIJ */
2580e1311b90SBarry Smith     ierr = VecGetLocalSize(ll,&m);CHKERRQ(ierr);
2581e32f2f54SBarry Smith     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vector wrong length");
2582fff8e43fSBarry Smith     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
25832e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
258417ab2063SBarry Smith     for (i=0; i<m; i++) {
258517ab2063SBarry Smith       x = l[i];
2586416022c9SBarry Smith       M = a->i[i+1] - a->i[i];
25872205254eSKarl Rupp       for (j=0; j<M; j++) (*v++) *= x;
258817ab2063SBarry Smith     }
2589fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
2590efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
25912e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
259217ab2063SBarry Smith   }
259317ab2063SBarry Smith   if (rr) {
2594e1311b90SBarry Smith     ierr = VecGetLocalSize(rr,&n);CHKERRQ(ierr);
2595e32f2f54SBarry Smith     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vector wrong length");
2596fff8e43fSBarry Smith     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
25972e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(A,&v);CHKERRQ(ierr);
25982e5835c6SStefano Zampini     jj = a->j;
25992205254eSKarl Rupp     for (i=0; i<nz; i++) (*v++) *= r[*jj++];
26002e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(A,&v);CHKERRQ(ierr);
2601fff8e43fSBarry Smith     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
2602efee365bSSatish Balay     ierr = PetscLogFlops(nz);CHKERRQ(ierr);
260317ab2063SBarry Smith   }
2604acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(A);CHKERRQ(ierr);
26058c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2606c70f7ee4SJunchao Zhang   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
2607e2cf4d64SStefano Zampini #endif
26083a40ed3dSBarry Smith   PetscFunctionReturn(0);
260917ab2063SBarry Smith }
261017ab2063SBarry Smith 
26117dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrix_SeqAIJ(Mat A,IS isrow,IS iscol,PetscInt csize,MatReuse scall,Mat *B)
261217ab2063SBarry Smith {
2613db02288aSLois Curfman McInnes   Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data,*c;
26146849ba73SBarry Smith   PetscErrorCode    ierr;
2615d0f46423SBarry Smith   PetscInt          *smap,i,k,kstart,kend,oldcols = A->cmap->n,*lens;
261697f1f81fSBarry Smith   PetscInt          row,mat_i,*mat_j,tcol,first,step,*mat_ilen,sum,lensi;
26175d0c19d7SBarry Smith   const PetscInt    *irow,*icol;
26182e5835c6SStefano Zampini   const PetscScalar *aa;
26195d0c19d7SBarry Smith   PetscInt          nrows,ncols;
262097f1f81fSBarry Smith   PetscInt          *starts,*j_new,*i_new,*aj = a->j,*ai = a->i,ii,*ailen = a->ilen;
262154f21887SBarry Smith   MatScalar         *a_new,*mat_a;
2622416022c9SBarry Smith   Mat               C;
2623cdc6f3adSToby Isaac   PetscBool         stride;
262417ab2063SBarry Smith 
26253a40ed3dSBarry Smith   PetscFunctionBegin;
262617ab2063SBarry Smith   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2627b9b97703SBarry Smith   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2628b9b97703SBarry Smith   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
262917ab2063SBarry Smith 
2630251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&stride);CHKERRQ(ierr);
2631ff718158SBarry Smith   if (stride) {
2632ff718158SBarry Smith     ierr = ISStrideGetInfo(iscol,&first,&step);CHKERRQ(ierr);
2633ff718158SBarry Smith   } else {
2634ff718158SBarry Smith     first = 0;
2635ff718158SBarry Smith     step  = 0;
2636ff718158SBarry Smith   }
2637fee21e36SBarry Smith   if (stride && step == 1) {
263802834360SBarry Smith     /* special case of contiguous rows */
2639dcca6d9dSJed Brown     ierr = PetscMalloc2(nrows,&lens,nrows,&starts);CHKERRQ(ierr);
264002834360SBarry Smith     /* loop over new rows determining lens and starting points */
264102834360SBarry Smith     for (i=0; i<nrows; i++) {
2642bfeeae90SHong Zhang       kstart = ai[irow[i]];
2643a2744918SBarry Smith       kend   = kstart + ailen[irow[i]];
2644a91a9bebSLisandro Dalcin       starts[i] = kstart;
264502834360SBarry Smith       for (k=kstart; k<kend; k++) {
2646bfeeae90SHong Zhang         if (aj[k] >= first) {
264702834360SBarry Smith           starts[i] = k;
264802834360SBarry Smith           break;
264902834360SBarry Smith         }
265002834360SBarry Smith       }
2651a2744918SBarry Smith       sum = 0;
265202834360SBarry Smith       while (k < kend) {
2653bfeeae90SHong Zhang         if (aj[k++] >= first+ncols) break;
2654a2744918SBarry Smith         sum++;
265502834360SBarry Smith       }
2656a2744918SBarry Smith       lens[i] = sum;
265702834360SBarry Smith     }
265802834360SBarry Smith     /* create submatrix */
2659cddf8d76SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
266097f1f81fSBarry Smith       PetscInt n_cols,n_rows;
266108480c60SBarry Smith       ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2662e32f2f54SBarry Smith       if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
2663d8ced48eSBarry Smith       ierr = MatZeroEntries(*B);CHKERRQ(ierr);
266408480c60SBarry Smith       C    = *B;
26653a40ed3dSBarry Smith     } else {
26663bef6203SJed Brown       PetscInt rbs,cbs;
2667ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2668f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
26693bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
26703bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
26713bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
26727adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2673ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
267408480c60SBarry Smith     }
2675db02288aSLois Curfman McInnes     c = (Mat_SeqAIJ*)C->data;
2676db02288aSLois Curfman McInnes 
267702834360SBarry Smith     /* loop over rows inserting into submatrix */
2678db02288aSLois Curfman McInnes     a_new = c->a;
2679db02288aSLois Curfman McInnes     j_new = c->j;
2680db02288aSLois Curfman McInnes     i_new = c->i;
26812e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
268202834360SBarry Smith     for (i=0; i<nrows; i++) {
2683a2744918SBarry Smith       ii    = starts[i];
2684a2744918SBarry Smith       lensi = lens[i];
2685a2744918SBarry Smith       for (k=0; k<lensi; k++) {
2686a2744918SBarry Smith         *j_new++ = aj[ii+k] - first;
268702834360SBarry Smith       }
26882e5835c6SStefano Zampini       ierr       = PetscArraycpy(a_new,aa + starts[i],lensi);CHKERRQ(ierr);
2689a2744918SBarry Smith       a_new     += lensi;
2690a2744918SBarry Smith       i_new[i+1] = i_new[i] + lensi;
2691a2744918SBarry Smith       c->ilen[i] = lensi;
269202834360SBarry Smith     }
26932e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
26940e83c824SBarry Smith     ierr = PetscFree2(lens,starts);CHKERRQ(ierr);
26953a40ed3dSBarry Smith   } else {
269602834360SBarry Smith     ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
26971795a4d1SJed Brown     ierr = PetscCalloc1(oldcols,&smap);CHKERRQ(ierr);
2698854ce69bSBarry Smith     ierr = PetscMalloc1(1+nrows,&lens);CHKERRQ(ierr);
26994dcab191SBarry Smith     for (i=0; i<ncols; i++) {
2700d9ef940eSSatish Balay       if (PetscUnlikelyDebug(icol[i] >= oldcols)) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Requesting column beyond largest column icol[%D] %D >= A->cmap->n %D",i,icol[i],oldcols);
27014dcab191SBarry Smith       smap[icol[i]] = i+1;
27024dcab191SBarry Smith     }
27034dcab191SBarry Smith 
270402834360SBarry Smith     /* determine lens of each row */
270502834360SBarry Smith     for (i=0; i<nrows; i++) {
2706bfeeae90SHong Zhang       kstart  = ai[irow[i]];
270702834360SBarry Smith       kend    = kstart + a->ilen[irow[i]];
270802834360SBarry Smith       lens[i] = 0;
270902834360SBarry Smith       for (k=kstart; k<kend; k++) {
2710bfeeae90SHong Zhang         if (smap[aj[k]]) {
271102834360SBarry Smith           lens[i]++;
271202834360SBarry Smith         }
271302834360SBarry Smith       }
271402834360SBarry Smith     }
271517ab2063SBarry Smith     /* Create and fill new matrix */
2716a2744918SBarry Smith     if (scall == MAT_REUSE_MATRIX) {
2717ace3abfcSBarry Smith       PetscBool equal;
27180f5bd95cSBarry Smith 
271999141d43SSatish Balay       c = (Mat_SeqAIJ*)((*B)->data);
2720e32f2f54SBarry Smith       if ((*B)->rmap->n  != nrows || (*B)->cmap->n != ncols) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong size");
2721580bdb30SBarry Smith       ierr = PetscArraycmp(c->ilen,lens,(*B)->rmap->n,&equal);CHKERRQ(ierr);
2722f23aa3ddSBarry Smith       if (!equal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. wrong no of nonzeros");
2723580bdb30SBarry Smith       ierr = PetscArrayzero(c->ilen,(*B)->rmap->n);CHKERRQ(ierr);
272408480c60SBarry Smith       C    = *B;
27253a40ed3dSBarry Smith     } else {
27263bef6203SJed Brown       PetscInt rbs,cbs;
2727ce94432eSBarry Smith       ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
2728f69a0ea3SMatthew Knepley       ierr = MatSetSizes(C,nrows,ncols,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr);
27293bef6203SJed Brown       ierr = ISGetBlockSize(isrow,&rbs);CHKERRQ(ierr);
27303bef6203SJed Brown       ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr);
27313bef6203SJed Brown       ierr = MatSetBlockSizes(C,rbs,cbs);CHKERRQ(ierr);
27327adad957SLisandro Dalcin       ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr);
2733ab93d7beSBarry Smith       ierr = MatSeqAIJSetPreallocation_SeqAIJ(C,0,lens);CHKERRQ(ierr);
273408480c60SBarry Smith     }
27352e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
273699141d43SSatish Balay     c = (Mat_SeqAIJ*)(C->data);
273717ab2063SBarry Smith     for (i=0; i<nrows; i++) {
273899141d43SSatish Balay       row      = irow[i];
2739bfeeae90SHong Zhang       kstart   = ai[row];
274099141d43SSatish Balay       kend     = kstart + a->ilen[row];
2741bfeeae90SHong Zhang       mat_i    = c->i[i];
274299141d43SSatish Balay       mat_j    = c->j + mat_i;
274399141d43SSatish Balay       mat_a    = c->a + mat_i;
274499141d43SSatish Balay       mat_ilen = c->ilen + i;
274517ab2063SBarry Smith       for (k=kstart; k<kend; k++) {
2746bfeeae90SHong Zhang         if ((tcol=smap[a->j[k]])) {
2747ed480e8bSBarry Smith           *mat_j++ = tcol - 1;
27482e5835c6SStefano Zampini           *mat_a++ = aa[k];
274999141d43SSatish Balay           (*mat_ilen)++;
275099141d43SSatish Balay 
275117ab2063SBarry Smith         }
275217ab2063SBarry Smith       }
275317ab2063SBarry Smith     }
27542e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
275502834360SBarry Smith     /* Free work space */
275602834360SBarry Smith     ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2757606d414cSSatish Balay     ierr = PetscFree(smap);CHKERRQ(ierr);
2758606d414cSSatish Balay     ierr = PetscFree(lens);CHKERRQ(ierr);
2759cdc6f3adSToby Isaac     /* sort */
2760cdc6f3adSToby Isaac     for (i = 0; i < nrows; i++) {
2761cdc6f3adSToby Isaac       PetscInt ilen;
2762cdc6f3adSToby Isaac 
2763cdc6f3adSToby Isaac       mat_i = c->i[i];
2764cdc6f3adSToby Isaac       mat_j = c->j + mat_i;
2765cdc6f3adSToby Isaac       mat_a = c->a + mat_i;
2766cdc6f3adSToby Isaac       ilen  = c->ilen[i];
2767390e1bf2SBarry Smith       ierr  = PetscSortIntWithScalarArray(ilen,mat_j,mat_a);CHKERRQ(ierr);
2768cdc6f3adSToby Isaac     }
276902834360SBarry Smith   }
27708c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
2771b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(C,A->boundtocpu);CHKERRQ(ierr);
2772305c6ccfSStefano Zampini #endif
27736d4a8577SBarry Smith   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
27746d4a8577SBarry Smith   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
277517ab2063SBarry Smith 
277617ab2063SBarry Smith   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2777416022c9SBarry Smith   *B   = C;
27783a40ed3dSBarry Smith   PetscFunctionReturn(0);
277917ab2063SBarry Smith }
278017ab2063SBarry Smith 
2781fc08c53fSHong Zhang PetscErrorCode  MatGetMultiProcBlock_SeqAIJ(Mat mat,MPI_Comm subComm,MatReuse scall,Mat *subMat)
278282d44351SHong Zhang {
278382d44351SHong Zhang   PetscErrorCode ierr;
278482d44351SHong Zhang   Mat            B;
278582d44351SHong Zhang 
278682d44351SHong Zhang   PetscFunctionBegin;
2787c2d650bdSHong Zhang   if (scall == MAT_INITIAL_MATRIX) {
278882d44351SHong Zhang     ierr    = MatCreate(subComm,&B);CHKERRQ(ierr);
278982d44351SHong Zhang     ierr    = MatSetSizes(B,mat->rmap->n,mat->cmap->n,mat->rmap->n,mat->cmap->n);CHKERRQ(ierr);
279033d57670SJed Brown     ierr    = MatSetBlockSizesFromMats(B,mat,mat);CHKERRQ(ierr);
279182d44351SHong Zhang     ierr    = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
279282d44351SHong Zhang     ierr    = MatDuplicateNoCreate_SeqAIJ(B,mat,MAT_COPY_VALUES,PETSC_TRUE);CHKERRQ(ierr);
279382d44351SHong Zhang     *subMat = B;
2794c2d650bdSHong Zhang   } else {
2795c2d650bdSHong Zhang     ierr = MatCopy_SeqAIJ(mat,*subMat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2796c2d650bdSHong Zhang   }
279782d44351SHong Zhang   PetscFunctionReturn(0);
279882d44351SHong Zhang }
279982d44351SHong Zhang 
28009a625307SHong Zhang PetscErrorCode MatILUFactor_SeqAIJ(Mat inA,IS row,IS col,const MatFactorInfo *info)
2801a871dcd8SBarry Smith {
280263b91edcSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2803dfbe8321SBarry Smith   PetscErrorCode ierr;
280463b91edcSBarry Smith   Mat            outA;
2805ace3abfcSBarry Smith   PetscBool      row_identity,col_identity;
280663b91edcSBarry Smith 
28073a40ed3dSBarry Smith   PetscFunctionBegin;
2808e32f2f54SBarry Smith   if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels=0 supported for in-place ilu");
28091df811f5SHong Zhang 
2810b8a78c4aSBarry Smith   ierr = ISIdentity(row,&row_identity);CHKERRQ(ierr);
2811b8a78c4aSBarry Smith   ierr = ISIdentity(col,&col_identity);CHKERRQ(ierr);
2812a871dcd8SBarry Smith 
281363b91edcSBarry Smith   outA             = inA;
2814d5f3da31SBarry Smith   outA->factortype = MAT_FACTOR_LU;
2815f6224b95SHong Zhang   ierr = PetscFree(inA->solvertype);CHKERRQ(ierr);
2816f6224b95SHong Zhang   ierr = PetscStrallocpy(MATSOLVERPETSC,&inA->solvertype);CHKERRQ(ierr);
28172205254eSKarl Rupp 
2818c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)row);CHKERRQ(ierr);
28196bf464f9SBarry Smith   ierr = ISDestroy(&a->row);CHKERRQ(ierr);
28202205254eSKarl Rupp 
2821c3122656SLisandro Dalcin   a->row = row;
28222205254eSKarl Rupp 
2823c38d4ed2SBarry Smith   ierr = PetscObjectReference((PetscObject)col);CHKERRQ(ierr);
28246bf464f9SBarry Smith   ierr = ISDestroy(&a->col);CHKERRQ(ierr);
28252205254eSKarl Rupp 
2826c3122656SLisandro Dalcin   a->col = col;
282763b91edcSBarry Smith 
282836db0b34SBarry Smith   /* Create the inverse permutation so that it can be used in MatLUFactorNumeric() */
28296bf464f9SBarry Smith   ierr = ISDestroy(&a->icol);CHKERRQ(ierr);
28304c49b128SBarry Smith   ierr = ISInvertPermutation(col,PETSC_DECIDE,&a->icol);CHKERRQ(ierr);
28313bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)inA,(PetscObject)a->icol);CHKERRQ(ierr);
2832f0ec6fceSSatish Balay 
283394a9d846SBarry Smith   if (!a->solve_work) { /* this matrix may have been factored before */
2834854ce69bSBarry Smith     ierr = PetscMalloc1(inA->rmap->n+1,&a->solve_work);CHKERRQ(ierr);
28353bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)inA, (inA->rmap->n+1)*sizeof(PetscScalar));CHKERRQ(ierr);
283694a9d846SBarry Smith   }
283763b91edcSBarry Smith 
2838f1e2ffcdSBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(inA);CHKERRQ(ierr);
2839137fb511SHong Zhang   if (row_identity && col_identity) {
2840ad04f41aSHong Zhang     ierr = MatLUFactorNumeric_SeqAIJ_inplace(outA,inA,info);CHKERRQ(ierr);
2841137fb511SHong Zhang   } else {
2842719d5645SBarry Smith     ierr = MatLUFactorNumeric_SeqAIJ_InplaceWithPerm(outA,inA,info);CHKERRQ(ierr);
2843137fb511SHong Zhang   }
28443a40ed3dSBarry Smith   PetscFunctionReturn(0);
2845a871dcd8SBarry Smith }
2846a871dcd8SBarry Smith 
2847f4df32b1SMatthew Knepley PetscErrorCode MatScale_SeqAIJ(Mat inA,PetscScalar alpha)
2848f0b747eeSBarry Smith {
2849f0b747eeSBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)inA->data;
2850dfa0f9e5SStefano Zampini   PetscScalar    *v;
2851efee365bSSatish Balay   PetscErrorCode ierr;
2852c5df96a5SBarry Smith   PetscBLASInt   one = 1,bnz;
28533a40ed3dSBarry Smith 
28543a40ed3dSBarry Smith   PetscFunctionBegin;
2855dfa0f9e5SStefano Zampini   ierr = MatSeqAIJGetArray(inA,&v);CHKERRQ(ierr);
2856c5df96a5SBarry Smith   ierr = PetscBLASIntCast(a->nz,&bnz);CHKERRQ(ierr);
2857dfa0f9e5SStefano Zampini   PetscStackCallBLAS("BLASscal",BLASscal_(&bnz,&alpha,v,&one));
2858efee365bSSatish Balay   ierr = PetscLogFlops(a->nz);CHKERRQ(ierr);
2859dfa0f9e5SStefano Zampini   ierr = MatSeqAIJRestoreArray(inA,&v);CHKERRQ(ierr);
2860acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal(inA);CHKERRQ(ierr);
28613a40ed3dSBarry Smith   PetscFunctionReturn(0);
2862f0b747eeSBarry Smith }
2863f0b747eeSBarry Smith 
2864f68bb481SHong Zhang PetscErrorCode MatDestroySubMatrix_Private(Mat_SubSppt *submatj)
286516b64355SHong Zhang {
286616b64355SHong Zhang   PetscErrorCode ierr;
286716b64355SHong Zhang   PetscInt       i;
286816b64355SHong Zhang 
286916b64355SHong Zhang   PetscFunctionBegin;
287016b64355SHong Zhang   if (!submatj->id) { /* delete data that are linked only to submats[id=0] */
287116b64355SHong Zhang     ierr = PetscFree4(submatj->sbuf1,submatj->ptr,submatj->tmp,submatj->ctr);CHKERRQ(ierr);
287216b64355SHong Zhang 
287316b64355SHong Zhang     for (i=0; i<submatj->nrqr; ++i) {
287416b64355SHong Zhang       ierr = PetscFree(submatj->sbuf2[i]);CHKERRQ(ierr);
287516b64355SHong Zhang     }
287616b64355SHong Zhang     ierr = PetscFree3(submatj->sbuf2,submatj->req_size,submatj->req_source1);CHKERRQ(ierr);
287716b64355SHong Zhang 
287816b64355SHong Zhang     if (submatj->rbuf1) {
287916b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1[0]);CHKERRQ(ierr);
288016b64355SHong Zhang       ierr = PetscFree(submatj->rbuf1);CHKERRQ(ierr);
288116b64355SHong Zhang     }
288216b64355SHong Zhang 
288316b64355SHong Zhang     for (i=0; i<submatj->nrqs; ++i) {
288416b64355SHong Zhang       ierr = PetscFree(submatj->rbuf3[i]);CHKERRQ(ierr);
288516b64355SHong Zhang     }
288616b64355SHong Zhang     ierr = PetscFree3(submatj->req_source2,submatj->rbuf2,submatj->rbuf3);CHKERRQ(ierr);
288716b64355SHong Zhang     ierr = PetscFree(submatj->pa);CHKERRQ(ierr);
288816b64355SHong Zhang   }
288916b64355SHong Zhang 
289016b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
289116b64355SHong Zhang   ierr = PetscTableDestroy((PetscTable*)&submatj->rmap);CHKERRQ(ierr);
289216b64355SHong Zhang   if (submatj->cmap_loc) {ierr = PetscFree(submatj->cmap_loc);CHKERRQ(ierr);}
289316b64355SHong Zhang   ierr = PetscFree(submatj->rmap_loc);CHKERRQ(ierr);
289416b64355SHong Zhang #else
289516b64355SHong Zhang   ierr = PetscFree(submatj->rmap);CHKERRQ(ierr);
289616b64355SHong Zhang #endif
289716b64355SHong Zhang 
289816b64355SHong Zhang   if (!submatj->allcolumns) {
289916b64355SHong Zhang #if defined(PETSC_USE_CTABLE)
290016b64355SHong Zhang     ierr = PetscTableDestroy((PetscTable*)&submatj->cmap);CHKERRQ(ierr);
290116b64355SHong Zhang #else
290216b64355SHong Zhang     ierr = PetscFree(submatj->cmap);CHKERRQ(ierr);
290316b64355SHong Zhang #endif
290416b64355SHong Zhang   }
290516b64355SHong Zhang   ierr = PetscFree(submatj->row2proc);CHKERRQ(ierr);
290616b64355SHong Zhang 
290716b64355SHong Zhang   ierr = PetscFree(submatj);CHKERRQ(ierr);
290816b64355SHong Zhang   PetscFunctionReturn(0);
290916b64355SHong Zhang }
291016b64355SHong Zhang 
29110fb991dcSHong Zhang PetscErrorCode MatDestroySubMatrix_SeqAIJ(Mat C)
291216b64355SHong Zhang {
291316b64355SHong Zhang   PetscErrorCode ierr;
291416b64355SHong Zhang   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data;
29155c39f6d9SHong Zhang   Mat_SubSppt    *submatj = c->submatis1;
291616b64355SHong Zhang 
291716b64355SHong Zhang   PetscFunctionBegin;
291834136279SStefano Zampini   ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2919f68bb481SHong Zhang   ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
292016b64355SHong Zhang   PetscFunctionReturn(0);
292116b64355SHong Zhang }
292216b64355SHong Zhang 
29232d033e1fSHong Zhang PetscErrorCode MatDestroySubMatrices_SeqAIJ(PetscInt n,Mat *mat[])
29242d033e1fSHong Zhang {
29252d033e1fSHong Zhang   PetscErrorCode ierr;
29262d033e1fSHong Zhang   PetscInt       i;
29270fb991dcSHong Zhang   Mat            C;
29280fb991dcSHong Zhang   Mat_SeqAIJ     *c;
29290fb991dcSHong Zhang   Mat_SubSppt    *submatj;
29302d033e1fSHong Zhang 
29312d033e1fSHong Zhang   PetscFunctionBegin;
29322d033e1fSHong Zhang   for (i=0; i<n; i++) {
29330fb991dcSHong Zhang     C       = (*mat)[i];
29340fb991dcSHong Zhang     c       = (Mat_SeqAIJ*)C->data;
29350fb991dcSHong Zhang     submatj = c->submatis1;
29362d033e1fSHong Zhang     if (submatj) {
2937682e4c99SStefano Zampini       if (--((PetscObject)C)->refct <= 0) {
293834136279SStefano Zampini         ierr = (*submatj->destroy)(C);CHKERRQ(ierr);
2939f68bb481SHong Zhang         ierr = MatDestroySubMatrix_Private(submatj);CHKERRQ(ierr);
294034136279SStefano Zampini         ierr = PetscFree(C->defaultvectype);CHKERRQ(ierr);
29412d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->rmap);CHKERRQ(ierr);
29422d033e1fSHong Zhang         ierr = PetscLayoutDestroy(&C->cmap);CHKERRQ(ierr);
29432d033e1fSHong Zhang         ierr = PetscHeaderDestroy(&C);CHKERRQ(ierr);
2944682e4c99SStefano Zampini       }
29452d033e1fSHong Zhang     } else {
29462d033e1fSHong Zhang       ierr = MatDestroy(&C);CHKERRQ(ierr);
29472d033e1fSHong Zhang     }
29482d033e1fSHong Zhang   }
294986e85357SHong Zhang 
295063a75b2aSHong Zhang   /* Destroy Dummy submatrices created for reuse */
295163a75b2aSHong Zhang   ierr = MatDestroySubMatrices_Dummy(n,mat);CHKERRQ(ierr);
295263a75b2aSHong Zhang 
29532d033e1fSHong Zhang   ierr = PetscFree(*mat);CHKERRQ(ierr);
29542d033e1fSHong Zhang   PetscFunctionReturn(0);
29552d033e1fSHong Zhang }
29562d033e1fSHong Zhang 
29577dae84e0SHong Zhang PetscErrorCode MatCreateSubMatrices_SeqAIJ(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2958cddf8d76SBarry Smith {
2959dfbe8321SBarry Smith   PetscErrorCode ierr;
296097f1f81fSBarry Smith   PetscInt       i;
2961cddf8d76SBarry Smith 
29623a40ed3dSBarry Smith   PetscFunctionBegin;
2963cddf8d76SBarry Smith   if (scall == MAT_INITIAL_MATRIX) {
2964df750dc8SHong Zhang     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
2965cddf8d76SBarry Smith   }
2966cddf8d76SBarry Smith 
2967cddf8d76SBarry Smith   for (i=0; i<n; i++) {
29687dae84e0SHong Zhang     ierr = MatCreateSubMatrix_SeqAIJ(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
2969cddf8d76SBarry Smith   }
29703a40ed3dSBarry Smith   PetscFunctionReturn(0);
2971cddf8d76SBarry Smith }
2972cddf8d76SBarry Smith 
297397f1f81fSBarry Smith PetscErrorCode MatIncreaseOverlap_SeqAIJ(Mat A,PetscInt is_max,IS is[],PetscInt ov)
29744dcbc457SBarry Smith {
2975e4d965acSSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
29766849ba73SBarry Smith   PetscErrorCode ierr;
29775d0c19d7SBarry Smith   PetscInt       row,i,j,k,l,m,n,*nidx,isz,val;
29785d0c19d7SBarry Smith   const PetscInt *idx;
297997f1f81fSBarry Smith   PetscInt       start,end,*ai,*aj;
2980f1af5d2fSBarry Smith   PetscBT        table;
2981bbd702dbSSatish Balay 
29823a40ed3dSBarry Smith   PetscFunctionBegin;
2983d0f46423SBarry Smith   m  = A->rmap->n;
2984e4d965acSSatish Balay   ai = a->i;
2985bfeeae90SHong Zhang   aj = a->j;
29868a047759SSatish Balay 
2987e32f2f54SBarry Smith   if (ov < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"illegal negative overlap value used");
298806763907SSatish Balay 
2989854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&nidx);CHKERRQ(ierr);
299053b8de81SBarry Smith   ierr = PetscBTCreate(m,&table);CHKERRQ(ierr);
299106763907SSatish Balay 
2992e4d965acSSatish Balay   for (i=0; i<is_max; i++) {
2993b97fc60eSLois Curfman McInnes     /* Initialize the two local arrays */
2994e4d965acSSatish Balay     isz  = 0;
29956831982aSBarry Smith     ierr = PetscBTMemzero(m,table);CHKERRQ(ierr);
2996e4d965acSSatish Balay 
2997e4d965acSSatish Balay     /* Extract the indices, assume there can be duplicate entries */
29984dcbc457SBarry Smith     ierr = ISGetIndices(is[i],&idx);CHKERRQ(ierr);
2999b9b97703SBarry Smith     ierr = ISGetLocalSize(is[i],&n);CHKERRQ(ierr);
3000e4d965acSSatish Balay 
3001dd097bc3SLois Curfman McInnes     /* Enter these into the temp arrays. I.e., mark table[row], enter row into new index */
3002e4d965acSSatish Balay     for (j=0; j<n; ++j) {
30032205254eSKarl Rupp       if (!PetscBTLookupSet(table,idx[j])) nidx[isz++] = idx[j];
30044dcbc457SBarry Smith     }
300506763907SSatish Balay     ierr = ISRestoreIndices(is[i],&idx);CHKERRQ(ierr);
30066bf464f9SBarry Smith     ierr = ISDestroy(&is[i]);CHKERRQ(ierr);
3007e4d965acSSatish Balay 
300804a348a9SBarry Smith     k = 0;
300904a348a9SBarry Smith     for (j=0; j<ov; j++) { /* for each overlap */
301004a348a9SBarry Smith       n = isz;
301106763907SSatish Balay       for (; k<n; k++) { /* do only those rows in nidx[k], which are not done yet */
3012e4d965acSSatish Balay         row   = nidx[k];
3013e4d965acSSatish Balay         start = ai[row];
3014e4d965acSSatish Balay         end   = ai[row+1];
301504a348a9SBarry Smith         for (l = start; l<end; l++) {
3016efb16452SHong Zhang           val = aj[l];
30172205254eSKarl Rupp           if (!PetscBTLookupSet(table,val)) nidx[isz++] = val;
3018e4d965acSSatish Balay         }
3019e4d965acSSatish Balay       }
3020e4d965acSSatish Balay     }
302170b3c8c7SBarry Smith     ierr = ISCreateGeneral(PETSC_COMM_SELF,isz,nidx,PETSC_COPY_VALUES,(is+i));CHKERRQ(ierr);
3022e4d965acSSatish Balay   }
302394bacf5dSBarry Smith   ierr = PetscBTDestroy(&table);CHKERRQ(ierr);
3024606d414cSSatish Balay   ierr = PetscFree(nidx);CHKERRQ(ierr);
30253a40ed3dSBarry Smith   PetscFunctionReturn(0);
30264dcbc457SBarry Smith }
302717ab2063SBarry Smith 
30280513a670SBarry Smith /* -------------------------------------------------------------- */
3029dfbe8321SBarry Smith PetscErrorCode MatPermute_SeqAIJ(Mat A,IS rowp,IS colp,Mat *B)
30300513a670SBarry Smith {
30310513a670SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
30326849ba73SBarry Smith   PetscErrorCode ierr;
30333b98c0a2SBarry Smith   PetscInt       i,nz = 0,m = A->rmap->n,n = A->cmap->n;
30345d0c19d7SBarry Smith   const PetscInt *row,*col;
30355d0c19d7SBarry Smith   PetscInt       *cnew,j,*lens;
303656cd22aeSBarry Smith   IS             icolp,irowp;
30370298fd71SBarry Smith   PetscInt       *cwork = NULL;
30380298fd71SBarry Smith   PetscScalar    *vwork = NULL;
30390513a670SBarry Smith 
30403a40ed3dSBarry Smith   PetscFunctionBegin;
30414c49b128SBarry Smith   ierr = ISInvertPermutation(rowp,PETSC_DECIDE,&irowp);CHKERRQ(ierr);
304256cd22aeSBarry Smith   ierr = ISGetIndices(irowp,&row);CHKERRQ(ierr);
30434c49b128SBarry Smith   ierr = ISInvertPermutation(colp,PETSC_DECIDE,&icolp);CHKERRQ(ierr);
304456cd22aeSBarry Smith   ierr = ISGetIndices(icolp,&col);CHKERRQ(ierr);
30450513a670SBarry Smith 
30460513a670SBarry Smith   /* determine lengths of permuted rows */
3047854ce69bSBarry Smith   ierr = PetscMalloc1(m+1,&lens);CHKERRQ(ierr);
30482205254eSKarl Rupp   for (i=0; i<m; i++) lens[row[i]] = a->i[i+1] - a->i[i];
3049ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
3050f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*B,m,n,m,n);CHKERRQ(ierr);
305133d57670SJed Brown   ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
30527adad957SLisandro Dalcin   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
3053ab93d7beSBarry Smith   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*B,0,lens);CHKERRQ(ierr);
3054606d414cSSatish Balay   ierr = PetscFree(lens);CHKERRQ(ierr);
30550513a670SBarry Smith 
3056785e854fSJed Brown   ierr = PetscMalloc1(n,&cnew);CHKERRQ(ierr);
30570513a670SBarry Smith   for (i=0; i<m; i++) {
305832ec9ce4SBarry Smith     ierr = MatGetRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30592205254eSKarl Rupp     for (j=0; j<nz; j++) cnew[j] = col[cwork[j]];
3060cdc0ba36SBarry Smith     ierr = MatSetValues_SeqAIJ(*B,1,&row[i],nz,cnew,vwork,INSERT_VALUES);CHKERRQ(ierr);
306132ec9ce4SBarry Smith     ierr = MatRestoreRow_SeqAIJ(A,i,&nz,&cwork,&vwork);CHKERRQ(ierr);
30620513a670SBarry Smith   }
3063606d414cSSatish Balay   ierr = PetscFree(cnew);CHKERRQ(ierr);
30642205254eSKarl Rupp 
30653c7d62e4SBarry Smith   (*B)->assembled = PETSC_FALSE;
30662205254eSKarl Rupp 
30678c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
3068b470e4b4SRichard Tran Mills   ierr = MatBindToCPU(*B,A->boundtocpu);CHKERRQ(ierr);
30699fe5e383SStefano Zampini #endif
30700513a670SBarry Smith   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
30710513a670SBarry Smith   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
307256cd22aeSBarry Smith   ierr = ISRestoreIndices(irowp,&row);CHKERRQ(ierr);
307356cd22aeSBarry Smith   ierr = ISRestoreIndices(icolp,&col);CHKERRQ(ierr);
30746bf464f9SBarry Smith   ierr = ISDestroy(&irowp);CHKERRQ(ierr);
30756bf464f9SBarry Smith   ierr = ISDestroy(&icolp);CHKERRQ(ierr);
30766768869dSprj-   if (rowp == colp) {
3077dc29a518SPierre Jolivet     ierr = MatPropagateSymmetryOptions(A,*B);CHKERRQ(ierr);
30786768869dSprj-   }
30793a40ed3dSBarry Smith   PetscFunctionReturn(0);
30800513a670SBarry Smith }
30810513a670SBarry Smith 
3082dfbe8321SBarry Smith PetscErrorCode MatCopy_SeqAIJ(Mat A,Mat B,MatStructure str)
3083cb5b572fSBarry Smith {
3084dfbe8321SBarry Smith   PetscErrorCode ierr;
3085cb5b572fSBarry Smith 
3086cb5b572fSBarry Smith   PetscFunctionBegin;
308733f4a19fSKris Buschelman   /* If the two matrices have the same copy implementation, use fast copy. */
308833f4a19fSKris Buschelman   if (str == SAME_NONZERO_PATTERN && (A->ops->copy == B->ops->copy)) {
3089be6bf707SBarry Smith     Mat_SeqAIJ        *a = (Mat_SeqAIJ*)A->data;
3090be6bf707SBarry Smith     Mat_SeqAIJ        *b = (Mat_SeqAIJ*)B->data;
30912e5835c6SStefano Zampini     const PetscScalar *aa;
3092be6bf707SBarry Smith 
30932e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
30944d805d7cSStefano Zampini     if (a->i[A->rmap->n] != b->i[B->rmap->n]) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of nonzeros in two matrices are different %D != %D",a->i[A->rmap->n],b->i[B->rmap->n]);
30952e5835c6SStefano Zampini     ierr = PetscArraycpy(b->a,aa,a->i[A->rmap->n]);CHKERRQ(ierr);
3096cdc753b6SBarry Smith     ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
30972e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(A,&aa);CHKERRQ(ierr);
3098cb5b572fSBarry Smith   } else {
3099cb5b572fSBarry Smith     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
3100cb5b572fSBarry Smith   }
3101cb5b572fSBarry Smith   PetscFunctionReturn(0);
3102cb5b572fSBarry Smith }
3103cb5b572fSBarry Smith 
31044994cf47SJed Brown PetscErrorCode MatSetUp_SeqAIJ(Mat A)
3105273d9f13SBarry Smith {
3106dfbe8321SBarry Smith   PetscErrorCode ierr;
3107273d9f13SBarry Smith 
3108273d9f13SBarry Smith   PetscFunctionBegin;
3109f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(A,PETSC_DEFAULT,NULL);CHKERRQ(ierr);
3110273d9f13SBarry Smith   PetscFunctionReturn(0);
3111273d9f13SBarry Smith }
3112273d9f13SBarry Smith 
3113f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJGetArray_SeqAIJ(Mat A,PetscScalar *array[])
31146c0721eeSBarry Smith {
31156c0721eeSBarry Smith   Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data;
31166e111a19SKarl Rupp 
31176c0721eeSBarry Smith   PetscFunctionBegin;
31186c0721eeSBarry Smith   *array = a->a;
31196c0721eeSBarry Smith   PetscFunctionReturn(0);
31206c0721eeSBarry Smith }
31216c0721eeSBarry Smith 
3122f38c1e66SStefano Zampini PETSC_INTERN PetscErrorCode MatSeqAIJRestoreArray_SeqAIJ(Mat A,PetscScalar *array[])
31236c0721eeSBarry Smith {
31246c0721eeSBarry Smith   PetscFunctionBegin;
3125f38c1e66SStefano Zampini   *array = NULL;
31266c0721eeSBarry Smith   PetscFunctionReturn(0);
31276c0721eeSBarry Smith }
3128273d9f13SBarry Smith 
31298229c054SShri Abhyankar /*
31308229c054SShri Abhyankar    Computes the number of nonzeros per row needed for preallocation when X and Y
31318229c054SShri Abhyankar    have different nonzero structure.
31328229c054SShri Abhyankar */
3133b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *yi,const PetscInt *yj,PetscInt *nnz)
3134ec7775f6SShri Abhyankar {
3135b264fe52SHong Zhang   PetscInt       i,j,k,nzx,nzy;
3136ec7775f6SShri Abhyankar 
3137ec7775f6SShri Abhyankar   PetscFunctionBegin;
3138ec7775f6SShri Abhyankar   /* Set the number of nonzeros in the new matrix */
3139ec7775f6SShri Abhyankar   for (i=0; i<m; i++) {
3140b264fe52SHong Zhang     const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i];
3141b264fe52SHong Zhang     nzx = xi[i+1] - xi[i];
3142b264fe52SHong Zhang     nzy = yi[i+1] - yi[i];
31438af7cee1SJed Brown     nnz[i] = 0;
31448af7cee1SJed Brown     for (j=0,k=0; j<nzx; j++) {                   /* Point in X */
3145b264fe52SHong Zhang       for (; k<nzy && yjj[k]<xjj[j]; k++) nnz[i]++; /* Catch up to X */
3146b264fe52SHong Zhang       if (k<nzy && yjj[k]==xjj[j]) k++;             /* Skip duplicate */
31478af7cee1SJed Brown       nnz[i]++;
31488af7cee1SJed Brown     }
31498af7cee1SJed Brown     for (; k<nzy; k++) nnz[i]++;
3150ec7775f6SShri Abhyankar   }
3151ec7775f6SShri Abhyankar   PetscFunctionReturn(0);
3152ec7775f6SShri Abhyankar }
3153ec7775f6SShri Abhyankar 
3154b264fe52SHong Zhang PetscErrorCode MatAXPYGetPreallocation_SeqAIJ(Mat Y,Mat X,PetscInt *nnz)
3155b264fe52SHong Zhang {
3156b264fe52SHong Zhang   PetscInt       m = Y->rmap->N;
3157b264fe52SHong Zhang   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data;
3158b264fe52SHong Zhang   Mat_SeqAIJ     *y = (Mat_SeqAIJ*)Y->data;
3159b264fe52SHong Zhang   PetscErrorCode ierr;
3160b264fe52SHong Zhang 
3161b264fe52SHong Zhang   PetscFunctionBegin;
3162b264fe52SHong Zhang   /* Set the number of nonzeros in the new matrix */
3163b264fe52SHong Zhang   ierr = MatAXPYGetPreallocation_SeqX_private(m,x->i,x->j,y->i,y->j,nnz);CHKERRQ(ierr);
3164b264fe52SHong Zhang   PetscFunctionReturn(0);
3165b264fe52SHong Zhang }
3166b264fe52SHong Zhang 
3167f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_SeqAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str)
3168ac90fabeSBarry Smith {
3169dfbe8321SBarry Smith   PetscErrorCode ierr;
3170ac90fabeSBarry Smith   Mat_SeqAIJ     *x = (Mat_SeqAIJ*)X->data,*y = (Mat_SeqAIJ*)Y->data;
3171ac90fabeSBarry Smith 
3172ac90fabeSBarry Smith   PetscFunctionBegin;
317341f5e1b1SStefano Zampini   if (str == UNKNOWN_NONZERO_PATTERN && x->nz == y->nz) {
317481fa06acSBarry Smith     PetscBool e;
317581fa06acSBarry Smith     ierr = PetscArraycmp(x->i,y->i,Y->rmap->n+1,&e);CHKERRQ(ierr);
317681fa06acSBarry Smith     if (e) {
317781fa06acSBarry Smith       ierr = PetscArraycmp(x->j,y->j,y->nz,&e);CHKERRQ(ierr);
317881fa06acSBarry Smith       if (e) {
317981fa06acSBarry Smith         str = SAME_NONZERO_PATTERN;
318081fa06acSBarry Smith       }
318181fa06acSBarry Smith     }
318281fa06acSBarry Smith   }
3183ac90fabeSBarry Smith   if (str == SAME_NONZERO_PATTERN) {
31842e5835c6SStefano Zampini     const PetscScalar *xa;
31852e5835c6SStefano Zampini     PetscScalar       *ya,alpha = a;
318681fa06acSBarry Smith     PetscBLASInt      one = 1,bnz;
318781fa06acSBarry Smith 
318881fa06acSBarry Smith     ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr);
31892e5835c6SStefano Zampini     ierr = MatSeqAIJGetArray(Y,&ya);CHKERRQ(ierr);
31902e5835c6SStefano Zampini     ierr = MatSeqAIJGetArrayRead(X,&xa);CHKERRQ(ierr);
31912e5835c6SStefano Zampini     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,xa,&one,ya,&one));
31922e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArrayRead(X,&xa);CHKERRQ(ierr);
31932e5835c6SStefano Zampini     ierr = MatSeqAIJRestoreArray(Y,&ya);CHKERRQ(ierr);
319441f5e1b1SStefano Zampini     ierr = PetscLogFlops(2.0*bnz);CHKERRQ(ierr);
3195acf2f550SJed Brown     ierr = MatSeqAIJInvalidateDiagonal(Y);CHKERRQ(ierr);
3196a3fa217bSJose E. Roman     ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
3197ab784542SHong Zhang   } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */
3198ab784542SHong Zhang     ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr);
3199ac90fabeSBarry Smith   } else {
32008229c054SShri Abhyankar     Mat      B;
32018229c054SShri Abhyankar     PetscInt *nnz;
3202785e854fSJed Brown     ierr = PetscMalloc1(Y->rmap->N,&nnz);CHKERRQ(ierr);
3203ce94432eSBarry Smith     ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr);
3204bc5a2726SShri Abhyankar     ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr);
320581fa06acSBarry Smith     ierr = MatSetLayouts(B,Y->rmap,Y->cmap);CHKERRQ(ierr);
32062e5835c6SStefano Zampini     ierr = MatSetType(B,((PetscObject)Y)->type_name);CHKERRQ(ierr);
32078229c054SShri Abhyankar     ierr = MatAXPYGetPreallocation_SeqAIJ(Y,X,nnz);CHKERRQ(ierr);
3208ecd8bba6SJed Brown     ierr = MatSeqAIJSetPreallocation(B,0,nnz);CHKERRQ(ierr);
3209ec7775f6SShri Abhyankar     ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr);
321028be2f97SBarry Smith     ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr);
32118229c054SShri Abhyankar     ierr = PetscFree(nnz);CHKERRQ(ierr);
3212ac90fabeSBarry Smith   }
3213ac90fabeSBarry Smith   PetscFunctionReturn(0);
3214ac90fabeSBarry Smith }
3215ac90fabeSBarry Smith 
32162726fb6dSPierre Jolivet PETSC_INTERN PetscErrorCode MatConjugate_SeqAIJ(Mat mat)
3217354c94deSBarry Smith {
3218354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX)
3219354c94deSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
3220354c94deSBarry Smith   PetscInt       i,nz;
3221354c94deSBarry Smith   PetscScalar    *a;
3222ce496241SStefano Zampini   PetscErrorCode ierr;
3223354c94deSBarry Smith 
3224354c94deSBarry Smith   PetscFunctionBegin;
3225354c94deSBarry Smith   nz = aij->nz;
3226ce496241SStefano Zampini   ierr = MatSeqAIJGetArray(mat,&a);CHKERRQ(ierr);
32272205254eSKarl Rupp   for (i=0; i<nz; i++) a[i] = PetscConj(a[i]);
3228ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArray(mat,&a);CHKERRQ(ierr);
3229354c94deSBarry Smith #else
3230354c94deSBarry Smith   PetscFunctionBegin;
3231354c94deSBarry Smith #endif
3232354c94deSBarry Smith   PetscFunctionReturn(0);
3233354c94deSBarry Smith }
3234354c94deSBarry Smith 
3235985db425SBarry Smith PetscErrorCode MatGetRowMaxAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3236e34fafa9SBarry Smith {
3237e34fafa9SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3238e34fafa9SBarry Smith   PetscErrorCode  ierr;
3239d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3240e34fafa9SBarry Smith   PetscReal       atmp;
3241985db425SBarry Smith   PetscScalar     *x;
3242ce496241SStefano Zampini   const MatScalar *aa,*av;
3243e34fafa9SBarry Smith 
3244e34fafa9SBarry Smith   PetscFunctionBegin;
3245e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3246ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3247ce496241SStefano Zampini   aa = av;
3248e34fafa9SBarry Smith   ai = a->i;
3249e34fafa9SBarry Smith   aj = a->j;
3250e34fafa9SBarry Smith 
3251985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3252475b8b61SHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3253e34fafa9SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3254e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3255e34fafa9SBarry Smith   for (i=0; i<m; i++) {
3256e34fafa9SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3257e34fafa9SBarry Smith     for (j=0; j<ncols; j++) {
3258985db425SBarry Smith       atmp = PetscAbsScalar(*aa);
3259985db425SBarry Smith       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = *aj;}
3260985db425SBarry Smith       aa++; aj++;
3261985db425SBarry Smith     }
3262985db425SBarry Smith   }
3263475b8b61SHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3264ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3265985db425SBarry Smith   PetscFunctionReturn(0);
3266985db425SBarry Smith }
3267985db425SBarry Smith 
3268985db425SBarry Smith PetscErrorCode MatGetRowMax_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3269985db425SBarry Smith {
3270985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3271985db425SBarry Smith   PetscErrorCode  ierr;
3272d0f46423SBarry Smith   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3273985db425SBarry Smith   PetscScalar     *x;
3274ce496241SStefano Zampini   const MatScalar *aa,*av;
3275985db425SBarry Smith 
3276985db425SBarry Smith   PetscFunctionBegin;
3277e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3278ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3279ce496241SStefano Zampini   aa = av;
3280985db425SBarry Smith   ai = a->i;
3281985db425SBarry Smith   aj = a->j;
3282985db425SBarry Smith 
3283985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3284fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3285985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3286e32f2f54SBarry Smith   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3287985db425SBarry Smith   for (i=0; i<m; i++) {
3288985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3289d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3290985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3291985db425SBarry Smith     } else {  /* row is sparse so already KNOW maximum is 0.0 or higher */
3292985db425SBarry Smith       x[i] = 0.0;
3293985db425SBarry Smith       if (idx) {
3294985db425SBarry Smith         for (j=0; j<ncols; j++) { /* find first implicit 0.0 in the row */
3295985db425SBarry Smith           if (aj[j] > j) {
3296985db425SBarry Smith             idx[i] = j;
3297985db425SBarry Smith             break;
3298985db425SBarry Smith           }
3299985db425SBarry Smith         }
33001a254869SHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
33011a254869SHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3302985db425SBarry Smith       }
3303985db425SBarry Smith     }
3304985db425SBarry Smith     for (j=0; j<ncols; j++) {
3305985db425SBarry Smith       if (PetscRealPart(x[i]) < PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3306985db425SBarry Smith       aa++; aj++;
3307985db425SBarry Smith     }
3308985db425SBarry Smith   }
3309fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3310ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3311985db425SBarry Smith   PetscFunctionReturn(0);
3312985db425SBarry Smith }
3313985db425SBarry Smith 
3314c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3315c87e5d42SMatthew Knepley {
3316c87e5d42SMatthew Knepley   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3317c87e5d42SMatthew Knepley   PetscErrorCode  ierr;
3318c87e5d42SMatthew Knepley   PetscInt        i,j,m = A->rmap->n,*ai,*aj,ncols,n;
3319ce496241SStefano Zampini   PetscScalar     *x;
3320ce496241SStefano Zampini   const MatScalar *aa,*av;
3321c87e5d42SMatthew Knepley 
3322c87e5d42SMatthew Knepley   PetscFunctionBegin;
3323ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3324ce496241SStefano Zampini   aa = av;
3325c87e5d42SMatthew Knepley   ai = a->i;
3326c87e5d42SMatthew Knepley   aj = a->j;
3327c87e5d42SMatthew Knepley 
3328c87e5d42SMatthew Knepley   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3329f07e67edSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3330c87e5d42SMatthew Knepley   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3331f07e67edSHong Zhang   if (n != m) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector, %D vs. %D rows", m, n);
3332c87e5d42SMatthew Knepley   for (i=0; i<m; i++) {
3333c87e5d42SMatthew Knepley     ncols = ai[1] - ai[0]; ai++;
3334f07e67edSHong Zhang     if (ncols == A->cmap->n) { /* row is dense */
3335f07e67edSHong Zhang       x[i] = *aa; if (idx) idx[i] = 0;
3336f07e67edSHong Zhang     } else {  /* row is sparse so already KNOW minimum is 0.0 or higher */
3337f07e67edSHong Zhang       x[i] = 0.0;
3338f07e67edSHong Zhang       if (idx) {   /* find first implicit 0.0 in the row */
3339289a08f5SMatthew Knepley         for (j=0; j<ncols; j++) {
3340f07e67edSHong Zhang           if (aj[j] > j) {
3341f07e67edSHong Zhang             idx[i] = j;
33422205254eSKarl Rupp             break;
33432205254eSKarl Rupp           }
3344289a08f5SMatthew Knepley         }
3345f07e67edSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3346f07e67edSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3347f07e67edSHong Zhang       }
3348289a08f5SMatthew Knepley     }
3349c87e5d42SMatthew Knepley     for (j=0; j<ncols; j++) {
3350f07e67edSHong Zhang       if (PetscAbsScalar(x[i]) > PetscAbsScalar(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3351c87e5d42SMatthew Knepley       aa++; aj++;
3352c87e5d42SMatthew Knepley     }
3353c87e5d42SMatthew Knepley   }
3354f07e67edSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3355ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3356c87e5d42SMatthew Knepley   PetscFunctionReturn(0);
3357c87e5d42SMatthew Knepley }
3358c87e5d42SMatthew Knepley 
3359985db425SBarry Smith PetscErrorCode MatGetRowMin_SeqAIJ(Mat A,Vec v,PetscInt idx[])
3360985db425SBarry Smith {
3361985db425SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
3362985db425SBarry Smith   PetscErrorCode  ierr;
3363d9ca1df4SBarry Smith   PetscInt        i,j,m = A->rmap->n,ncols,n;
3364d9ca1df4SBarry Smith   const PetscInt  *ai,*aj;
3365985db425SBarry Smith   PetscScalar     *x;
3366ce496241SStefano Zampini   const MatScalar *aa,*av;
3367985db425SBarry Smith 
3368985db425SBarry Smith   PetscFunctionBegin;
3369e32f2f54SBarry Smith   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
3370ce496241SStefano Zampini   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
3371ce496241SStefano Zampini   aa = av;
3372985db425SBarry Smith   ai = a->i;
3373985db425SBarry Smith   aj = a->j;
3374985db425SBarry Smith 
3375985db425SBarry Smith   ierr = VecSet(v,0.0);CHKERRQ(ierr);
3376fa213d2fSHong Zhang   ierr = VecGetArrayWrite(v,&x);CHKERRQ(ierr);
3377985db425SBarry Smith   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
3378f07e67edSHong Zhang   if (n != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
3379985db425SBarry Smith   for (i=0; i<m; i++) {
3380985db425SBarry Smith     ncols = ai[1] - ai[0]; ai++;
3381d0f46423SBarry Smith     if (ncols == A->cmap->n) { /* row is dense */
3382985db425SBarry Smith       x[i] = *aa; if (idx) idx[i] = 0;
3383985db425SBarry Smith     } else {  /* row is sparse so already KNOW minimum is 0.0 or lower */
3384985db425SBarry Smith       x[i] = 0.0;
3385985db425SBarry Smith       if (idx) {   /* find first implicit 0.0 in the row */
3386985db425SBarry Smith         for (j=0; j<ncols; j++) {
3387985db425SBarry Smith           if (aj[j] > j) {
3388985db425SBarry Smith             idx[i] = j;
3389985db425SBarry Smith             break;
3390985db425SBarry Smith           }
3391985db425SBarry Smith         }
3392fa213d2fSHong Zhang         /* in case first implicit 0.0 in the row occurs at ncols-th column */
3393fa213d2fSHong Zhang         if (j==ncols && j < A->cmap->n) idx[i] = j;
3394985db425SBarry Smith       }
3395985db425SBarry Smith     }
3396985db425SBarry Smith     for (j=0; j<ncols; j++) {
3397985db425SBarry Smith       if (PetscRealPart(x[i]) > PetscRealPart(*aa)) {x[i] = *aa; if (idx) idx[i] = *aj;}
3398985db425SBarry Smith       aa++; aj++;
3399e34fafa9SBarry Smith     }
3400e34fafa9SBarry Smith   }
3401fa213d2fSHong Zhang   ierr = VecRestoreArrayWrite(v,&x);CHKERRQ(ierr);
3402ce496241SStefano Zampini   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
3403e34fafa9SBarry Smith   PetscFunctionReturn(0);
3404e34fafa9SBarry Smith }
3405bbead8a2SBarry Smith 
3406713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_SeqAIJ(Mat A,const PetscScalar **values)
3407bbead8a2SBarry Smith {
3408bbead8a2SBarry Smith   Mat_SeqAIJ      *a = (Mat_SeqAIJ*) A->data;
3409bbead8a2SBarry Smith   PetscErrorCode  ierr;
341033d57670SJed Brown   PetscInt        i,bs = PetscAbs(A->rmap->bs),mbs = A->rmap->n/bs,ipvt[5],bs2 = bs*bs,*v_pivots,ij[7],*IJ,j;
3411bbead8a2SBarry Smith   MatScalar       *diag,work[25],*v_work;
34120da83c2eSBarry Smith   const PetscReal shift = 0.0;
34131a9391e3SHong Zhang   PetscBool       allowzeropivot,zeropivotdetected=PETSC_FALSE;
3414bbead8a2SBarry Smith 
3415bbead8a2SBarry Smith   PetscFunctionBegin;
3416a455e926SHong Zhang   allowzeropivot = PetscNot(A->erroriffailure);
34174a0d0026SBarry Smith   if (a->ibdiagvalid) {
34184a0d0026SBarry Smith     if (values) *values = a->ibdiag;
34194a0d0026SBarry Smith     PetscFunctionReturn(0);
34204a0d0026SBarry Smith   }
3421bbead8a2SBarry Smith   ierr = MatMarkDiagonal_SeqAIJ(A);CHKERRQ(ierr);
3422bbead8a2SBarry Smith   if (!a->ibdiag) {
3423785e854fSJed Brown     ierr = PetscMalloc1(bs2*mbs,&a->ibdiag);CHKERRQ(ierr);
34243bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)A,bs2*mbs*sizeof(PetscScalar));CHKERRQ(ierr);
3425bbead8a2SBarry Smith   }
3426bbead8a2SBarry Smith   diag = a->ibdiag;
3427bbead8a2SBarry Smith   if (values) *values = a->ibdiag;
3428bbead8a2SBarry Smith   /* factor and invert each block */
3429bbead8a2SBarry Smith   switch (bs) {
3430bbead8a2SBarry Smith   case 1:
3431bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3432bbead8a2SBarry Smith       ierr = MatGetValues(A,1,&i,1,&i,diag+i);CHKERRQ(ierr);
3433ec1892c8SHong Zhang       if (PetscAbsScalar(diag[i] + shift) < PETSC_MACHINE_EPSILON) {
3434ec1892c8SHong Zhang         if (allowzeropivot) {
34357b6c816cSBarry Smith           A->factorerrortype             = MAT_FACTOR_NUMERIC_ZEROPIVOT;
34367b6c816cSBarry Smith           A->factorerror_zeropivot_value = PetscAbsScalar(diag[i]);
34377b6c816cSBarry Smith           A->factorerror_zeropivot_row   = i;
34387b6c816cSBarry Smith           ierr = PetscInfo3(A,"Zero pivot, row %D pivot %g tolerance %g\n",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);CHKERRQ(ierr);
34397b6c816cSBarry Smith         } else SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Zero pivot, row %D pivot %g tolerance %g",i,(double)PetscAbsScalar(diag[i]),(double)PETSC_MACHINE_EPSILON);
3440ec1892c8SHong Zhang       }
3441bbead8a2SBarry Smith       diag[i] = (PetscScalar)1.0 / (diag[i] + shift);
3442bbead8a2SBarry Smith     }
3443bbead8a2SBarry Smith     break;
3444bbead8a2SBarry Smith   case 2:
3445bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3446bbead8a2SBarry Smith       ij[0] = 2*i; ij[1] = 2*i + 1;
3447bbead8a2SBarry Smith       ierr  = MatGetValues(A,2,ij,2,ij,diag);CHKERRQ(ierr);
3448a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_2(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34497b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
345096b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_2(diag);CHKERRQ(ierr);
3451bbead8a2SBarry Smith       diag += 4;
3452bbead8a2SBarry Smith     }
3453bbead8a2SBarry Smith     break;
3454bbead8a2SBarry Smith   case 3:
3455bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3456bbead8a2SBarry Smith       ij[0] = 3*i; ij[1] = 3*i + 1; ij[2] = 3*i + 2;
3457bbead8a2SBarry Smith       ierr  = MatGetValues(A,3,ij,3,ij,diag);CHKERRQ(ierr);
3458a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_3(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34597b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
346096b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_3(diag);CHKERRQ(ierr);
3461bbead8a2SBarry Smith       diag += 9;
3462bbead8a2SBarry Smith     }
3463bbead8a2SBarry Smith     break;
3464bbead8a2SBarry Smith   case 4:
3465bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3466bbead8a2SBarry Smith       ij[0] = 4*i; ij[1] = 4*i + 1; ij[2] = 4*i + 2; ij[3] = 4*i + 3;
3467bbead8a2SBarry Smith       ierr  = MatGetValues(A,4,ij,4,ij,diag);CHKERRQ(ierr);
3468a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_4(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34697b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
347096b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_4(diag);CHKERRQ(ierr);
3471bbead8a2SBarry Smith       diag += 16;
3472bbead8a2SBarry Smith     }
3473bbead8a2SBarry Smith     break;
3474bbead8a2SBarry Smith   case 5:
3475bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3476bbead8a2SBarry 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;
3477bbead8a2SBarry Smith       ierr  = MatGetValues(A,5,ij,5,ij,diag);CHKERRQ(ierr);
3478a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_5(diag,ipvt,work,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34797b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
348096b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_5(diag);CHKERRQ(ierr);
3481bbead8a2SBarry Smith       diag += 25;
3482bbead8a2SBarry Smith     }
3483bbead8a2SBarry Smith     break;
3484bbead8a2SBarry Smith   case 6:
3485bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3486bbead8a2SBarry 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;
3487bbead8a2SBarry Smith       ierr  = MatGetValues(A,6,ij,6,ij,diag);CHKERRQ(ierr);
3488a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_6(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34897b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
349096b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_6(diag);CHKERRQ(ierr);
3491bbead8a2SBarry Smith       diag += 36;
3492bbead8a2SBarry Smith     }
3493bbead8a2SBarry Smith     break;
3494bbead8a2SBarry Smith   case 7:
3495bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3496bbead8a2SBarry 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;
3497bbead8a2SBarry Smith       ierr  = MatGetValues(A,7,ij,7,ij,diag);CHKERRQ(ierr);
3498a455e926SHong Zhang       ierr  = PetscKernel_A_gets_inverse_A_7(diag,shift,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
34997b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
350096b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_7(diag);CHKERRQ(ierr);
3501bbead8a2SBarry Smith       diag += 49;
3502bbead8a2SBarry Smith     }
3503bbead8a2SBarry Smith     break;
3504bbead8a2SBarry Smith   default:
3505dcca6d9dSJed Brown     ierr = PetscMalloc3(bs,&v_work,bs,&v_pivots,bs,&IJ);CHKERRQ(ierr);
3506bbead8a2SBarry Smith     for (i=0; i<mbs; i++) {
3507bbead8a2SBarry Smith       for (j=0; j<bs; j++) {
3508bbead8a2SBarry Smith         IJ[j] = bs*i + j;
3509bbead8a2SBarry Smith       }
3510bbead8a2SBarry Smith       ierr  = MatGetValues(A,bs,IJ,bs,IJ,diag);CHKERRQ(ierr);
35115f8bbccaSHong Zhang       ierr  = PetscKernel_A_gets_inverse_A(bs,diag,v_pivots,v_work,allowzeropivot,&zeropivotdetected);CHKERRQ(ierr);
35127b6c816cSBarry Smith       if (zeropivotdetected) A->factorerrortype = MAT_FACTOR_NUMERIC_ZEROPIVOT;
351396b95a6bSBarry Smith       ierr  = PetscKernel_A_gets_transpose_A_N(diag,bs);CHKERRQ(ierr);
3514bbead8a2SBarry Smith       diag += bs2;
3515bbead8a2SBarry Smith     }
3516bbead8a2SBarry Smith     ierr = PetscFree3(v_work,v_pivots,IJ);CHKERRQ(ierr);
3517bbead8a2SBarry Smith   }
3518bbead8a2SBarry Smith   a->ibdiagvalid = PETSC_TRUE;
3519bbead8a2SBarry Smith   PetscFunctionReturn(0);
3520bbead8a2SBarry Smith }
3521bbead8a2SBarry Smith 
352273a71a0fSBarry Smith static PetscErrorCode  MatSetRandom_SeqAIJ(Mat x,PetscRandom rctx)
352373a71a0fSBarry Smith {
352473a71a0fSBarry Smith   PetscErrorCode ierr;
352573a71a0fSBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
352673a71a0fSBarry Smith   PetscScalar    a;
352773a71a0fSBarry Smith   PetscInt       m,n,i,j,col;
352873a71a0fSBarry Smith 
352973a71a0fSBarry Smith   PetscFunctionBegin;
353073a71a0fSBarry Smith   if (!x->assembled) {
353173a71a0fSBarry Smith     ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
353273a71a0fSBarry Smith     for (i=0; i<m; i++) {
353373a71a0fSBarry Smith       for (j=0; j<aij->imax[i]; j++) {
353473a71a0fSBarry Smith         ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
353573a71a0fSBarry Smith         col  = (PetscInt)(n*PetscRealPart(a));
353673a71a0fSBarry Smith         ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
353773a71a0fSBarry Smith       }
353873a71a0fSBarry Smith     }
3539e2ce353bSJunchao Zhang   } else {
3540e2ce353bSJunchao Zhang     for (i=0; i<aij->nz; i++) {ierr = PetscRandomGetValue(rctx,aij->a+i);CHKERRQ(ierr);}
3541e2ce353bSJunchao Zhang   }
3542ce496241SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
3543ce496241SStefano Zampini   if (x->offloadmask != PETSC_OFFLOAD_UNALLOCATED) x->offloadmask = PETSC_OFFLOAD_CPU;
3544ce496241SStefano Zampini #endif
354573a71a0fSBarry Smith   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
354673a71a0fSBarry Smith   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
354773a71a0fSBarry Smith   PetscFunctionReturn(0);
354873a71a0fSBarry Smith }
354973a71a0fSBarry Smith 
3550679944adSJunchao Zhang /* Like MatSetRandom_SeqAIJ, but do not set values on columns in range of [low, high) */
3551679944adSJunchao Zhang PetscErrorCode  MatSetRandomSkipColumnRange_SeqAIJ_Private(Mat x,PetscInt low,PetscInt high,PetscRandom rctx)
3552679944adSJunchao Zhang {
3553679944adSJunchao Zhang   PetscErrorCode ierr;
3554679944adSJunchao Zhang   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)x->data;
3555679944adSJunchao Zhang   PetscScalar    a;
3556679944adSJunchao Zhang   PetscInt       m,n,i,j,col,nskip;
3557679944adSJunchao Zhang 
3558679944adSJunchao Zhang   PetscFunctionBegin;
3559679944adSJunchao Zhang   nskip = high - low;
3560679944adSJunchao Zhang   ierr  = MatGetSize(x,&m,&n);CHKERRQ(ierr);
3561679944adSJunchao Zhang   n    -= nskip; /* shrink number of columns where nonzeros can be set */
3562679944adSJunchao Zhang   for (i=0; i<m; i++) {
3563679944adSJunchao Zhang     for (j=0; j<aij->imax[i]; j++) {
3564679944adSJunchao Zhang       ierr = PetscRandomGetValue(rctx,&a);CHKERRQ(ierr);
3565679944adSJunchao Zhang       col  = (PetscInt)(n*PetscRealPart(a));
3566679944adSJunchao Zhang       if (col >= low) col += nskip; /* shift col rightward to skip the hole */
3567679944adSJunchao Zhang       ierr = MatSetValues(x,1,&i,1,&col,&a,ADD_VALUES);CHKERRQ(ierr);
3568679944adSJunchao Zhang     }
3569e2ce353bSJunchao Zhang   }
3570679944adSJunchao Zhang   ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3571679944adSJunchao Zhang   ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3572679944adSJunchao Zhang   PetscFunctionReturn(0);
3573679944adSJunchao Zhang }
3574679944adSJunchao Zhang 
3575682d7d0cSBarry Smith /* -------------------------------------------------------------------*/
35760a6ffc59SBarry Smith static struct _MatOps MatOps_Values = { MatSetValues_SeqAIJ,
3577cb5b572fSBarry Smith                                         MatGetRow_SeqAIJ,
3578cb5b572fSBarry Smith                                         MatRestoreRow_SeqAIJ,
3579cb5b572fSBarry Smith                                         MatMult_SeqAIJ,
358097304618SKris Buschelman                                 /*  4*/ MatMultAdd_SeqAIJ,
35817c922b88SBarry Smith                                         MatMultTranspose_SeqAIJ,
35827c922b88SBarry Smith                                         MatMultTransposeAdd_SeqAIJ,
3583f4259b30SLisandro Dalcin                                         NULL,
3584f4259b30SLisandro Dalcin                                         NULL,
3585f4259b30SLisandro Dalcin                                         NULL,
3586f4259b30SLisandro Dalcin                                 /* 10*/ NULL,
3587cb5b572fSBarry Smith                                         MatLUFactor_SeqAIJ,
3588f4259b30SLisandro Dalcin                                         NULL,
358941f059aeSBarry Smith                                         MatSOR_SeqAIJ,
359091e9d3e2SHong Zhang                                         MatTranspose_SeqAIJ,
359197304618SKris Buschelman                                 /*1 5*/ MatGetInfo_SeqAIJ,
3592cb5b572fSBarry Smith                                         MatEqual_SeqAIJ,
3593cb5b572fSBarry Smith                                         MatGetDiagonal_SeqAIJ,
3594cb5b572fSBarry Smith                                         MatDiagonalScale_SeqAIJ,
3595cb5b572fSBarry Smith                                         MatNorm_SeqAIJ,
3596f4259b30SLisandro Dalcin                                 /* 20*/ NULL,
3597cb5b572fSBarry Smith                                         MatAssemblyEnd_SeqAIJ,
3598cb5b572fSBarry Smith                                         MatSetOption_SeqAIJ,
3599cb5b572fSBarry Smith                                         MatZeroEntries_SeqAIJ,
3600d519adbfSMatthew Knepley                                 /* 24*/ MatZeroRows_SeqAIJ,
3601f4259b30SLisandro Dalcin                                         NULL,
3602f4259b30SLisandro Dalcin                                         NULL,
3603f4259b30SLisandro Dalcin                                         NULL,
3604f4259b30SLisandro Dalcin                                         NULL,
36054994cf47SJed Brown                                 /* 29*/ MatSetUp_SeqAIJ,
3606f4259b30SLisandro Dalcin                                         NULL,
3607f4259b30SLisandro Dalcin                                         NULL,
3608f4259b30SLisandro Dalcin                                         NULL,
3609f4259b30SLisandro Dalcin                                         NULL,
3610d519adbfSMatthew Knepley                                 /* 34*/ MatDuplicate_SeqAIJ,
3611f4259b30SLisandro Dalcin                                         NULL,
3612f4259b30SLisandro Dalcin                                         NULL,
3613cb5b572fSBarry Smith                                         MatILUFactor_SeqAIJ,
3614f4259b30SLisandro Dalcin                                         NULL,
3615d519adbfSMatthew Knepley                                 /* 39*/ MatAXPY_SeqAIJ,
36167dae84e0SHong Zhang                                         MatCreateSubMatrices_SeqAIJ,
3617cb5b572fSBarry Smith                                         MatIncreaseOverlap_SeqAIJ,
3618cb5b572fSBarry Smith                                         MatGetValues_SeqAIJ,
3619cb5b572fSBarry Smith                                         MatCopy_SeqAIJ,
3620d519adbfSMatthew Knepley                                 /* 44*/ MatGetRowMax_SeqAIJ,
3621cb5b572fSBarry Smith                                         MatScale_SeqAIJ,
36227d68702bSBarry Smith                                         MatShift_SeqAIJ,
362379299369SBarry Smith                                         MatDiagonalSet_SeqAIJ,
36246e169961SBarry Smith                                         MatZeroRowsColumns_SeqAIJ,
362573a71a0fSBarry Smith                                 /* 49*/ MatSetRandom_SeqAIJ,
36263b2fbd54SBarry Smith                                         MatGetRowIJ_SeqAIJ,
36273b2fbd54SBarry Smith                                         MatRestoreRowIJ_SeqAIJ,
36283b2fbd54SBarry Smith                                         MatGetColumnIJ_SeqAIJ,
3629a93ec695SBarry Smith                                         MatRestoreColumnIJ_SeqAIJ,
363093dfae19SHong Zhang                                 /* 54*/ MatFDColoringCreate_SeqXAIJ,
3631f4259b30SLisandro Dalcin                                         NULL,
3632f4259b30SLisandro Dalcin                                         NULL,
3633cda55fadSBarry Smith                                         MatPermute_SeqAIJ,
3634f4259b30SLisandro Dalcin                                         NULL,
3635f4259b30SLisandro Dalcin                                 /* 59*/ NULL,
3636b9b97703SBarry Smith                                         MatDestroy_SeqAIJ,
3637b9b97703SBarry Smith                                         MatView_SeqAIJ,
3638f4259b30SLisandro Dalcin                                         NULL,
3639f4259b30SLisandro Dalcin                                         NULL,
3640f4259b30SLisandro Dalcin                                 /* 64*/ NULL,
3641321b30b9SSatish Balay                                         MatMatMatMultNumeric_SeqAIJ_SeqAIJ_SeqAIJ,
3642f4259b30SLisandro Dalcin                                         NULL,
3643f4259b30SLisandro Dalcin                                         NULL,
3644f4259b30SLisandro Dalcin                                         NULL,
3645d519adbfSMatthew Knepley                                 /* 69*/ MatGetRowMaxAbs_SeqAIJ,
3646c87e5d42SMatthew Knepley                                         MatGetRowMinAbs_SeqAIJ,
3647f4259b30SLisandro Dalcin                                         NULL,
3648f4259b30SLisandro Dalcin                                         NULL,
3649f4259b30SLisandro Dalcin                                         NULL,
3650f4259b30SLisandro Dalcin                                 /* 74*/ NULL,
36513acb8795SBarry Smith                                         MatFDColoringApply_AIJ,
3652f4259b30SLisandro Dalcin                                         NULL,
3653f4259b30SLisandro Dalcin                                         NULL,
3654f4259b30SLisandro Dalcin                                         NULL,
36556ce1633cSBarry Smith                                 /* 79*/ MatFindZeroDiagonals_SeqAIJ,
3656f4259b30SLisandro Dalcin                                         NULL,
3657f4259b30SLisandro Dalcin                                         NULL,
3658f4259b30SLisandro Dalcin                                         NULL,
3659bc011b1eSHong Zhang                                         MatLoad_SeqAIJ,
3660d519adbfSMatthew Knepley                                 /* 84*/ MatIsSymmetric_SeqAIJ,
36611cbb95d3SBarry Smith                                         MatIsHermitian_SeqAIJ,
3662f4259b30SLisandro Dalcin                                         NULL,
3663f4259b30SLisandro Dalcin                                         NULL,
3664f4259b30SLisandro Dalcin                                         NULL,
3665f4259b30SLisandro Dalcin                                 /* 89*/ NULL,
3666f4259b30SLisandro Dalcin                                         NULL,
366726be0446SHong Zhang                                         MatMatMultNumeric_SeqAIJ_SeqAIJ,
3668f4259b30SLisandro Dalcin                                         NULL,
3669f4259b30SLisandro Dalcin                                         NULL,
36708fa4b5a6SHong Zhang                                 /* 94*/ MatPtAPNumeric_SeqAIJ_SeqAIJ_SparseAxpy,
3671f4259b30SLisandro Dalcin                                         NULL,
3672f4259b30SLisandro Dalcin                                         NULL,
36736fc122caSHong Zhang                                         MatMatTransposeMultNumeric_SeqAIJ_SeqAIJ,
3674f4259b30SLisandro Dalcin                                         NULL,
36754222ddf1SHong Zhang                                 /* 99*/ MatProductSetFromOptions_SeqAIJ,
3676f4259b30SLisandro Dalcin                                         NULL,
3677f4259b30SLisandro Dalcin                                         NULL,
367887d4246cSBarry Smith                                         MatConjugate_SeqAIJ,
3679f4259b30SLisandro Dalcin                                         NULL,
3680d519adbfSMatthew Knepley                                 /*104*/ MatSetValuesRow_SeqAIJ,
368199cafbc1SBarry Smith                                         MatRealPart_SeqAIJ,
3682f5edf698SHong Zhang                                         MatImaginaryPart_SeqAIJ,
3683f4259b30SLisandro Dalcin                                         NULL,
3684f4259b30SLisandro Dalcin                                         NULL,
3685cbd44569SHong Zhang                                 /*109*/ MatMatSolve_SeqAIJ,
3686f4259b30SLisandro Dalcin                                         NULL,
36872af78befSBarry Smith                                         MatGetRowMin_SeqAIJ,
3688f4259b30SLisandro Dalcin                                         NULL,
3689599ef60dSHong Zhang                                         MatMissingDiagonal_SeqAIJ,
3690f4259b30SLisandro Dalcin                                 /*114*/ NULL,
3691f4259b30SLisandro Dalcin                                         NULL,
3692f4259b30SLisandro Dalcin                                         NULL,
3693f4259b30SLisandro Dalcin                                         NULL,
3694f4259b30SLisandro Dalcin                                         NULL,
3695f4259b30SLisandro Dalcin                                 /*119*/ NULL,
3696f4259b30SLisandro Dalcin                                         NULL,
3697f4259b30SLisandro Dalcin                                         NULL,
3698f4259b30SLisandro Dalcin                                         NULL,
3699b3a44c85SBarry Smith                                         MatGetMultiProcBlock_SeqAIJ,
37000716a85fSBarry Smith                                 /*124*/ MatFindNonzeroRows_SeqAIJ,
3701*a873a8cdSSam Reynolds                                         MatGetColumnReductions_SeqAIJ,
370237868618SMatthew G Knepley                                         MatInvertBlockDiagonal_SeqAIJ,
37030da83c2eSBarry Smith                                         MatInvertVariableBlockDiagonal_SeqAIJ,
3704f4259b30SLisandro Dalcin                                         NULL,
3705f4259b30SLisandro Dalcin                                 /*129*/ NULL,
3706f4259b30SLisandro Dalcin                                         NULL,
3707f4259b30SLisandro Dalcin                                         NULL,
370875648e8dSHong Zhang                                         MatTransposeMatMultNumeric_SeqAIJ_SeqAIJ,
3709b9af6bddSHong Zhang                                         MatTransposeColoringCreate_SeqAIJ,
3710b9af6bddSHong Zhang                                 /*134*/ MatTransColoringApplySpToDen_SeqAIJ,
37112b8ad9a3SHong Zhang                                         MatTransColoringApplyDenToSp_SeqAIJ,
3712f4259b30SLisandro Dalcin                                         NULL,
3713f4259b30SLisandro Dalcin                                         NULL,
37143964eb88SJed Brown                                         MatRARtNumeric_SeqAIJ_SeqAIJ,
3715f4259b30SLisandro Dalcin                                  /*139*/NULL,
3716f4259b30SLisandro Dalcin                                         NULL,
3717f4259b30SLisandro Dalcin                                         NULL,
37183a062f41SBarry Smith                                         MatFDColoringSetUp_SeqXAIJ,
37199c8f2541SHong Zhang                                         MatFindOffBlockDiagonalEntries_SeqAIJ,
37204222ddf1SHong Zhang                                         MatCreateMPIMatConcatenateSeqMat_SeqAIJ,
37214222ddf1SHong Zhang                                  /*145*/MatDestroySubMatrices_SeqAIJ,
3722f4259b30SLisandro Dalcin                                         NULL,
3723f4259b30SLisandro Dalcin                                         NULL
37249e29f15eSvictorle };
372517ab2063SBarry Smith 
37267087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices_SeqAIJ(Mat mat,PetscInt *indices)
3727bef8e0ddSBarry Smith {
3728bef8e0ddSBarry Smith   Mat_SeqAIJ *aij = (Mat_SeqAIJ*)mat->data;
372997f1f81fSBarry Smith   PetscInt   i,nz,n;
3730bef8e0ddSBarry Smith 
3731bef8e0ddSBarry Smith   PetscFunctionBegin;
3732bef8e0ddSBarry Smith   nz = aij->maxnz;
3733d0f46423SBarry Smith   n  = mat->rmap->n;
3734bef8e0ddSBarry Smith   for (i=0; i<nz; i++) {
3735bef8e0ddSBarry Smith     aij->j[i] = indices[i];
3736bef8e0ddSBarry Smith   }
3737bef8e0ddSBarry Smith   aij->nz = nz;
3738bef8e0ddSBarry Smith   for (i=0; i<n; i++) {
3739bef8e0ddSBarry Smith     aij->ilen[i] = aij->imax[i];
3740bef8e0ddSBarry Smith   }
3741bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3742bef8e0ddSBarry Smith }
3743bef8e0ddSBarry Smith 
3744a3bb6f32SFande Kong /*
3745ddea5d60SJunchao Zhang  * Given a sparse matrix with global column indices, compact it by using a local column space.
3746ddea5d60SJunchao Zhang  * The result matrix helps saving memory in other algorithms, such as MatPtAPSymbolic_MPIAIJ_MPIAIJ_scalable()
3747ddea5d60SJunchao Zhang  */
3748a3bb6f32SFande Kong PetscErrorCode  MatSeqAIJCompactOutExtraColumns_SeqAIJ(Mat mat, ISLocalToGlobalMapping *mapping)
3749a3bb6f32SFande Kong {
3750a3bb6f32SFande Kong   Mat_SeqAIJ         *aij = (Mat_SeqAIJ*)mat->data;
3751a3bb6f32SFande Kong   PetscTable         gid1_lid1;
3752a3bb6f32SFande Kong   PetscTablePosition tpos;
375325b670f0SStefano Zampini   PetscInt           gid,lid,i,ec,nz = aij->nz;
375425b670f0SStefano Zampini   PetscInt           *garray,*jj = aij->j;
3755a3bb6f32SFande Kong   PetscErrorCode     ierr;
3756a3bb6f32SFande Kong 
3757a3bb6f32SFande Kong   PetscFunctionBegin;
3758a3bb6f32SFande Kong   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3759a3bb6f32SFande Kong   PetscValidPointer(mapping,2);
3760a3bb6f32SFande Kong   /* use a table */
3761a3bb6f32SFande Kong   ierr = PetscTableCreate(mat->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr);
3762a3bb6f32SFande Kong   ec = 0;
376325b670f0SStefano Zampini   for (i=0; i<nz; i++) {
376425b670f0SStefano Zampini     PetscInt data,gid1 = jj[i] + 1;
3765a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
3766a3bb6f32SFande Kong     if (!data) {
3767a3bb6f32SFande Kong       /* one based table */
3768a3bb6f32SFande Kong       ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr);
3769a3bb6f32SFande Kong     }
3770a3bb6f32SFande Kong   }
3771a3bb6f32SFande Kong   /* form array of columns we need */
3772b3c64f9dSJunchao Zhang   ierr = PetscMalloc1(ec,&garray);CHKERRQ(ierr);
3773a3bb6f32SFande Kong   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
3774a3bb6f32SFande Kong   while (tpos) {
3775a3bb6f32SFande Kong     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
3776a3bb6f32SFande Kong     gid--;
3777a3bb6f32SFande Kong     lid--;
3778a3bb6f32SFande Kong     garray[lid] = gid;
3779a3bb6f32SFande Kong   }
3780a3bb6f32SFande Kong   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */
3781a3bb6f32SFande Kong   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
3782a3bb6f32SFande Kong   for (i=0; i<ec; i++) {
3783a3bb6f32SFande Kong     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr);
3784a3bb6f32SFande Kong   }
3785a3bb6f32SFande Kong   /* compact out the extra columns in B */
378625b670f0SStefano Zampini   for (i=0; i<nz; i++) {
378725b670f0SStefano Zampini     PetscInt gid1 = jj[i] + 1;
3788a3bb6f32SFande Kong     ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
3789a3bb6f32SFande Kong     lid--;
379025b670f0SStefano Zampini     jj[i] = lid;
3791a3bb6f32SFande Kong   }
3792ca5434daSLawrence Mitchell   ierr = PetscLayoutDestroy(&mat->cmap);CHKERRQ(ierr);
3793a3bb6f32SFande Kong   ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr);
379425b670f0SStefano Zampini   ierr = PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)mat),ec,ec,1,&mat->cmap);CHKERRQ(ierr);
3795a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingCreate(PETSC_COMM_SELF,mat->cmap->bs,mat->cmap->n,garray,PETSC_OWN_POINTER,mapping);CHKERRQ(ierr);
3796a3bb6f32SFande Kong   ierr = ISLocalToGlobalMappingSetType(*mapping,ISLOCALTOGLOBALMAPPINGHASH);CHKERRQ(ierr);
3797a3bb6f32SFande Kong   PetscFunctionReturn(0);
3798a3bb6f32SFande Kong }
3799a3bb6f32SFande Kong 
3800bef8e0ddSBarry Smith /*@
3801bef8e0ddSBarry Smith     MatSeqAIJSetColumnIndices - Set the column indices for all the rows
3802bef8e0ddSBarry Smith        in the matrix.
3803bef8e0ddSBarry Smith 
3804bef8e0ddSBarry Smith   Input Parameters:
3805bef8e0ddSBarry Smith +  mat - the SeqAIJ matrix
3806bef8e0ddSBarry Smith -  indices - the column indices
3807bef8e0ddSBarry Smith 
380815091d37SBarry Smith   Level: advanced
380915091d37SBarry Smith 
3810bef8e0ddSBarry Smith   Notes:
3811bef8e0ddSBarry Smith     This can be called if you have precomputed the nonzero structure of the
3812bef8e0ddSBarry Smith   matrix and want to provide it to the matrix object to improve the performance
3813bef8e0ddSBarry Smith   of the MatSetValues() operation.
3814bef8e0ddSBarry Smith 
3815bef8e0ddSBarry Smith     You MUST have set the correct numbers of nonzeros per row in the call to
3816d1be2dadSMatthew Knepley   MatCreateSeqAIJ(), and the columns indices MUST be sorted.
3817bef8e0ddSBarry Smith 
3818bef8e0ddSBarry Smith     MUST be called before any calls to MatSetValues();
3819bef8e0ddSBarry Smith 
3820b9617806SBarry Smith     The indices should start with zero, not one.
3821b9617806SBarry Smith 
3822bef8e0ddSBarry Smith @*/
38237087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetColumnIndices(Mat mat,PetscInt *indices)
3824bef8e0ddSBarry Smith {
38254ac538c5SBarry Smith   PetscErrorCode ierr;
3826bef8e0ddSBarry Smith 
3827bef8e0ddSBarry Smith   PetscFunctionBegin;
38280700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
38294482741eSBarry Smith   PetscValidPointer(indices,2);
38304ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatSeqAIJSetColumnIndices_C",(Mat,PetscInt*),(mat,indices));CHKERRQ(ierr);
3831bef8e0ddSBarry Smith   PetscFunctionReturn(0);
3832bef8e0ddSBarry Smith }
3833bef8e0ddSBarry Smith 
3834be6bf707SBarry Smith /* ----------------------------------------------------------------------------------------*/
3835be6bf707SBarry Smith 
38367087cfbeSBarry Smith PetscErrorCode  MatStoreValues_SeqAIJ(Mat mat)
3837be6bf707SBarry Smith {
3838be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
38396849ba73SBarry Smith   PetscErrorCode ierr;
3840d0f46423SBarry Smith   size_t         nz = aij->i[mat->rmap->n];
3841be6bf707SBarry Smith 
3842be6bf707SBarry Smith   PetscFunctionBegin;
3843169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3844be6bf707SBarry Smith 
3845be6bf707SBarry Smith   /* allocate space for values if not already there */
3846be6bf707SBarry Smith   if (!aij->saved_values) {
3847854ce69bSBarry Smith     ierr = PetscMalloc1(nz+1,&aij->saved_values);CHKERRQ(ierr);
38483bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)mat,(nz+1)*sizeof(PetscScalar));CHKERRQ(ierr);
3849be6bf707SBarry Smith   }
3850be6bf707SBarry Smith 
3851be6bf707SBarry Smith   /* copy values over */
3852580bdb30SBarry Smith   ierr = PetscArraycpy(aij->saved_values,aij->a,nz);CHKERRQ(ierr);
3853be6bf707SBarry Smith   PetscFunctionReturn(0);
3854be6bf707SBarry Smith }
3855be6bf707SBarry Smith 
3856be6bf707SBarry Smith /*@
3857be6bf707SBarry Smith     MatStoreValues - Stashes a copy of the matrix values; this allows, for
3858be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3859be6bf707SBarry Smith        nonlinear portion.
3860be6bf707SBarry Smith 
3861be6bf707SBarry Smith    Collect on Mat
3862be6bf707SBarry Smith 
3863be6bf707SBarry Smith   Input Parameters:
38640e609b76SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3865be6bf707SBarry Smith 
386615091d37SBarry Smith   Level: advanced
386715091d37SBarry Smith 
3868be6bf707SBarry Smith   Common Usage, with SNESSolve():
3869be6bf707SBarry Smith $    Create Jacobian matrix
3870be6bf707SBarry Smith $    Set linear terms into matrix
3871be6bf707SBarry Smith $    Apply boundary conditions to matrix, at this time matrix must have
3872be6bf707SBarry Smith $      final nonzero structure (i.e. setting the nonlinear terms and applying
3873be6bf707SBarry Smith $      boundary conditions again will not change the nonzero structure
3874512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3875be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3876be6bf707SBarry Smith $    Call SNESSetJacobian() with matrix
3877be6bf707SBarry Smith $    In your Jacobian routine
3878be6bf707SBarry Smith $      ierr = MatRetrieveValues(mat);
3879be6bf707SBarry Smith $      Set nonlinear terms in matrix
3880be6bf707SBarry Smith 
3881be6bf707SBarry Smith   Common Usage without SNESSolve(), i.e. when you handle nonlinear solve yourself:
3882be6bf707SBarry Smith $    // build linear portion of Jacobian
3883512a5fc5SBarry Smith $    ierr = MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);
3884be6bf707SBarry Smith $    ierr = MatStoreValues(mat);
3885be6bf707SBarry Smith $    loop over nonlinear iterations
3886be6bf707SBarry Smith $       ierr = MatRetrieveValues(mat);
3887be6bf707SBarry Smith $       // call MatSetValues(mat,...) to set nonliner portion of Jacobian
3888be6bf707SBarry Smith $       // call MatAssemblyBegin/End() on matrix
3889be6bf707SBarry Smith $       Solve linear system with Jacobian
3890be6bf707SBarry Smith $    endloop
3891be6bf707SBarry Smith 
3892be6bf707SBarry Smith   Notes:
3893be6bf707SBarry Smith     Matrix must already be assemblied before calling this routine
3894512a5fc5SBarry Smith     Must set the matrix option MatSetOption(mat,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE); before
3895be6bf707SBarry Smith     calling this routine.
3896be6bf707SBarry Smith 
38970c468ba9SBarry Smith     When this is called multiple times it overwrites the previous set of stored values
38980c468ba9SBarry Smith     and does not allocated additional space.
38990c468ba9SBarry Smith 
3900be6bf707SBarry Smith .seealso: MatRetrieveValues()
3901be6bf707SBarry Smith 
3902be6bf707SBarry Smith @*/
39037087cfbeSBarry Smith PetscErrorCode  MatStoreValues(Mat mat)
3904be6bf707SBarry Smith {
39054ac538c5SBarry Smith   PetscErrorCode ierr;
3906be6bf707SBarry Smith 
3907be6bf707SBarry Smith   PetscFunctionBegin;
39080700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3909e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3910e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39114ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatStoreValues_C",(Mat),(mat));CHKERRQ(ierr);
3912be6bf707SBarry Smith   PetscFunctionReturn(0);
3913be6bf707SBarry Smith }
3914be6bf707SBarry Smith 
39157087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues_SeqAIJ(Mat mat)
3916be6bf707SBarry Smith {
3917be6bf707SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)mat->data;
39186849ba73SBarry Smith   PetscErrorCode ierr;
3919d0f46423SBarry Smith   PetscInt       nz = aij->i[mat->rmap->n];
3920be6bf707SBarry Smith 
3921be6bf707SBarry Smith   PetscFunctionBegin;
3922169f6850SBarry Smith   if (!aij->nonew) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatSetOption(A,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);first");
3923f23aa3ddSBarry Smith   if (!aij->saved_values) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Must call MatStoreValues(A);first");
3924be6bf707SBarry Smith   /* copy values over */
3925580bdb30SBarry Smith   ierr = PetscArraycpy(aij->a,aij->saved_values,nz);CHKERRQ(ierr);
3926be6bf707SBarry Smith   PetscFunctionReturn(0);
3927be6bf707SBarry Smith }
3928be6bf707SBarry Smith 
3929be6bf707SBarry Smith /*@
3930be6bf707SBarry Smith     MatRetrieveValues - Retrieves the copy of the matrix values; this allows, for
3931be6bf707SBarry Smith        example, reuse of the linear part of a Jacobian, while recomputing the
3932be6bf707SBarry Smith        nonlinear portion.
3933be6bf707SBarry Smith 
3934be6bf707SBarry Smith    Collect on Mat
3935be6bf707SBarry Smith 
3936be6bf707SBarry Smith   Input Parameters:
3937386f7cf9SBarry Smith .  mat - the matrix (currently only AIJ matrices support this option)
3938be6bf707SBarry Smith 
393915091d37SBarry Smith   Level: advanced
394015091d37SBarry Smith 
3941be6bf707SBarry Smith .seealso: MatStoreValues()
3942be6bf707SBarry Smith 
3943be6bf707SBarry Smith @*/
39447087cfbeSBarry Smith PetscErrorCode  MatRetrieveValues(Mat mat)
3945be6bf707SBarry Smith {
39464ac538c5SBarry Smith   PetscErrorCode ierr;
3947be6bf707SBarry Smith 
3948be6bf707SBarry Smith   PetscFunctionBegin;
39490700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3950e32f2f54SBarry Smith   if (!mat->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
3951e32f2f54SBarry Smith   if (mat->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
39524ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatRetrieveValues_C",(Mat),(mat));CHKERRQ(ierr);
3953be6bf707SBarry Smith   PetscFunctionReturn(0);
3954be6bf707SBarry Smith }
3955be6bf707SBarry Smith 
3956be6bf707SBarry Smith /* --------------------------------------------------------------------------------*/
395717ab2063SBarry Smith /*@C
3958682d7d0cSBarry Smith    MatCreateSeqAIJ - Creates a sparse matrix in AIJ (compressed row) format
39590d15e28bSLois Curfman McInnes    (the default parallel PETSc format).  For good matrix assembly performance
39606e62573dSLois Curfman McInnes    the user should preallocate the matrix storage by setting the parameter nz
396151c19458SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
39622bd5e0b2SLois Curfman McInnes    during matrix assembly can be increased by more than a factor of 50.
396317ab2063SBarry Smith 
3964d083f849SBarry Smith    Collective
3965db81eaa0SLois Curfman McInnes 
396617ab2063SBarry Smith    Input Parameters:
3967db81eaa0SLois Curfman McInnes +  comm - MPI communicator, set to PETSC_COMM_SELF
396817ab2063SBarry Smith .  m - number of rows
396917ab2063SBarry Smith .  n - number of columns
397017ab2063SBarry Smith .  nz - number of nonzeros per row (same for all rows)
397151c19458SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
39720298fd71SBarry Smith          (possibly different for each row) or NULL
397317ab2063SBarry Smith 
397417ab2063SBarry Smith    Output Parameter:
3975416022c9SBarry Smith .  A - the matrix
397617ab2063SBarry Smith 
3977175b88e8SBarry Smith    It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(),
3978f6f02116SRichard Tran Mills    MatXXXXSetPreallocation() paradigm instead of this routine directly.
3979175b88e8SBarry Smith    [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation]
3980175b88e8SBarry Smith 
3981b259b22eSLois Curfman McInnes    Notes:
398249a6f317SBarry Smith    If nnz is given then nz is ignored
398349a6f317SBarry Smith 
398417ab2063SBarry Smith    The AIJ format (also called the Yale sparse matrix format or
398517ab2063SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
39860002213bSLois Curfman McInnes    storage.  That is, the stored row and column indices can begin at
398744cd7ae7SLois Curfman McInnes    either one (as in Fortran) or zero.  See the users' manual for details.
398817ab2063SBarry Smith 
398917ab2063SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
39900298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
39913d323bbdSBarry Smith    allocation.  For large problems you MUST preallocate memory or you
39926da5968aSLois Curfman McInnes    will get TERRIBLE performance, see the users' manual chapter on matrices.
399317ab2063SBarry Smith 
3994682d7d0cSBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
39954fca80b9SLois Curfman McInnes    improve numerical efficiency of matrix-vector products and solves. We
3996682d7d0cSBarry Smith    search for consecutive rows with the same nonzero structure, thereby
39976c7ebb05SLois Curfman McInnes    reusing matrix information to achieve increased efficiency.
39986c7ebb05SLois Curfman McInnes 
39996c7ebb05SLois Curfman McInnes    Options Database Keys:
4000698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
40019db58ca8SBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
400217ab2063SBarry Smith 
4003027ccd11SLois Curfman McInnes    Level: intermediate
4004027ccd11SLois Curfman McInnes 
400569b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays()
400636db0b34SBarry Smith 
400717ab2063SBarry Smith @*/
40087087cfbeSBarry Smith PetscErrorCode  MatCreateSeqAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt nz,const PetscInt nnz[],Mat *A)
400917ab2063SBarry Smith {
4010dfbe8321SBarry Smith   PetscErrorCode ierr;
40116945ee14SBarry Smith 
40123a40ed3dSBarry Smith   PetscFunctionBegin;
4013f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,A);CHKERRQ(ierr);
4014117016b1SBarry Smith   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
4015c4752a88SBarry Smith   ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr);
4016d28bb7d2SJed Brown   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*A,nz,nnz);CHKERRQ(ierr);
4017273d9f13SBarry Smith   PetscFunctionReturn(0);
4018273d9f13SBarry Smith }
4019273d9f13SBarry Smith 
4020273d9f13SBarry Smith /*@C
4021273d9f13SBarry Smith    MatSeqAIJSetPreallocation - For good matrix assembly performance
4022273d9f13SBarry Smith    the user should preallocate the matrix storage by setting the parameter nz
4023273d9f13SBarry Smith    (or the array nnz).  By setting these parameters accurately, performance
4024273d9f13SBarry Smith    during matrix assembly can be increased by more than a factor of 50.
4025273d9f13SBarry Smith 
4026d083f849SBarry Smith    Collective
4027273d9f13SBarry Smith 
4028273d9f13SBarry Smith    Input Parameters:
40291c4f3114SJed Brown +  B - The matrix
4030273d9f13SBarry Smith .  nz - number of nonzeros per row (same for all rows)
4031273d9f13SBarry Smith -  nnz - array containing the number of nonzeros in the various rows
40320298fd71SBarry Smith          (possibly different for each row) or NULL
4033273d9f13SBarry Smith 
4034273d9f13SBarry Smith    Notes:
403549a6f317SBarry Smith      If nnz is given then nz is ignored
403649a6f317SBarry Smith 
4037273d9f13SBarry Smith     The AIJ format (also called the Yale sparse matrix format or
4038273d9f13SBarry Smith    compressed row storage), is fully compatible with standard Fortran 77
4039273d9f13SBarry Smith    storage.  That is, the stored row and column indices can begin at
4040273d9f13SBarry Smith    either one (as in Fortran) or zero.  See the users' manual for details.
4041273d9f13SBarry Smith 
4042273d9f13SBarry Smith    Specify the preallocated storage with either nz or nnz (not both).
40430298fd71SBarry Smith    Set nz=PETSC_DEFAULT and nnz=NULL for PETSc to control dynamic memory
4044273d9f13SBarry Smith    allocation.  For large problems you MUST preallocate memory or you
4045273d9f13SBarry Smith    will get TERRIBLE performance, see the users' manual chapter on matrices.
4046273d9f13SBarry Smith 
4047aa95bbe8SBarry Smith    You can call MatGetInfo() to get information on how effective the preallocation was;
4048aa95bbe8SBarry Smith    for example the fields mallocs,nz_allocated,nz_used,nz_unneeded;
4049aa95bbe8SBarry Smith    You can also run with the option -info and look for messages with the string
4050aa95bbe8SBarry Smith    malloc in them to see if additional memory allocation was needed.
4051aa95bbe8SBarry Smith 
4052a96a251dSBarry Smith    Developers: Use nz of MAT_SKIP_ALLOCATION to not allocate any space for the matrix
4053a96a251dSBarry Smith    entries or columns indices
4054a96a251dSBarry Smith 
4055273d9f13SBarry Smith    By default, this format uses inodes (identical nodes) when possible, to
4056273d9f13SBarry Smith    improve numerical efficiency of matrix-vector products and solves. We
4057273d9f13SBarry Smith    search for consecutive rows with the same nonzero structure, thereby
4058273d9f13SBarry Smith    reusing matrix information to achieve increased efficiency.
4059273d9f13SBarry Smith 
4060273d9f13SBarry Smith    Options Database Keys:
4061698d4c6aSKris Buschelman +  -mat_no_inode  - Do not use inodes
406247b2e64bSBarry Smith -  -mat_inode_limit <limit> - Sets inode limit (max limit=5)
4063273d9f13SBarry Smith 
4064273d9f13SBarry Smith    Level: intermediate
4065273d9f13SBarry Smith 
406619b08ed1SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatSetValues(), MatSeqAIJSetColumnIndices(), MatCreateSeqAIJWithArrays(), MatGetInfo(),
406719b08ed1SBarry Smith           MatSeqAIJSetTotalPreallocation()
4068273d9f13SBarry Smith 
4069273d9f13SBarry Smith @*/
40707087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation(Mat B,PetscInt nz,const PetscInt nnz[])
4071273d9f13SBarry Smith {
40724ac538c5SBarry Smith   PetscErrorCode ierr;
4073a23d5eceSKris Buschelman 
4074a23d5eceSKris Buschelman   PetscFunctionBegin;
40756ba663aaSJed Brown   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
40766ba663aaSJed Brown   PetscValidType(B,1);
40774ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[]),(B,nz,nnz));CHKERRQ(ierr);
4078a23d5eceSKris Buschelman   PetscFunctionReturn(0);
4079a23d5eceSKris Buschelman }
4080a23d5eceSKris Buschelman 
40817087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocation_SeqAIJ(Mat B,PetscInt nz,const PetscInt *nnz)
4082a23d5eceSKris Buschelman {
4083273d9f13SBarry Smith   Mat_SeqAIJ     *b;
40842576faa2SJed Brown   PetscBool      skipallocation = PETSC_FALSE,realalloc = PETSC_FALSE;
40856849ba73SBarry Smith   PetscErrorCode ierr;
408697f1f81fSBarry Smith   PetscInt       i;
4087273d9f13SBarry Smith 
4088273d9f13SBarry Smith   PetscFunctionBegin;
40892576faa2SJed Brown   if (nz >= 0 || nnz) realalloc = PETSC_TRUE;
4090a96a251dSBarry Smith   if (nz == MAT_SKIP_ALLOCATION) {
4091c461c341SBarry Smith     skipallocation = PETSC_TRUE;
4092c461c341SBarry Smith     nz             = 0;
4093c461c341SBarry Smith   }
409426283091SBarry Smith   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
409526283091SBarry Smith   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4096899cda47SBarry Smith 
4097435da068SBarry Smith   if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 5;
409860e0710aSBarry Smith   if (nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nz cannot be less than 0: value %D",nz);
4099cf9c20a2SJed Brown   if (PetscUnlikelyDebug(nnz)) {
4100d0f46423SBarry Smith     for (i=0; i<B->rmap->n; i++) {
410160e0710aSBarry Smith       if (nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be less than 0: local row %D value %D",i,nnz[i]);
410260e0710aSBarry Smith       if (nnz[i] > B->cmap->n) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"nnz cannot be greater than row length: local row %D value %d rowlength %D",i,nnz[i],B->cmap->n);
4103b73539f3SBarry Smith     }
4104b73539f3SBarry Smith   }
4105b73539f3SBarry Smith 
4106273d9f13SBarry Smith   B->preallocated = PETSC_TRUE;
41072205254eSKarl Rupp 
4108273d9f13SBarry Smith   b = (Mat_SeqAIJ*)B->data;
4109273d9f13SBarry Smith 
4110ab93d7beSBarry Smith   if (!skipallocation) {
41112ee49352SLisandro Dalcin     if (!b->imax) {
4112071fcb05SBarry Smith       ierr = PetscMalloc1(B->rmap->n,&b->imax);CHKERRQ(ierr);
4113071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4114071fcb05SBarry Smith     }
4115071fcb05SBarry Smith     if (!b->ilen) {
4116071fcb05SBarry Smith       /* b->ilen will count nonzeros in each row so far. */
4117071fcb05SBarry Smith       ierr = PetscCalloc1(B->rmap->n,&b->ilen);CHKERRQ(ierr);
4118071fcb05SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4119071fcb05SBarry Smith     } else {
4120071fcb05SBarry Smith       ierr = PetscMemzero(b->ilen,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
41212ee49352SLisandro Dalcin     }
4122846b4da1SFande Kong     if (!b->ipre) {
4123846b4da1SFande Kong       ierr = PetscMalloc1(B->rmap->n,&b->ipre);CHKERRQ(ierr);
4124846b4da1SFande Kong       ierr = PetscLogObjectMemory((PetscObject)B,B->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
4125846b4da1SFande Kong     }
4126273d9f13SBarry Smith     if (!nnz) {
4127435da068SBarry Smith       if (nz == PETSC_DEFAULT || nz == PETSC_DECIDE) nz = 10;
4128c62bd62aSJed Brown       else if (nz < 0) nz = 1;
41295d2a9ed1SStefano Zampini       nz = PetscMin(nz,B->cmap->n);
4130d0f46423SBarry Smith       for (i=0; i<B->rmap->n; i++) b->imax[i] = nz;
4131d0f46423SBarry Smith       nz = nz*B->rmap->n;
4132273d9f13SBarry Smith     } else {
4133c73702f5SBarry Smith       PetscInt64 nz64 = 0;
4134c73702f5SBarry Smith       for (i=0; i<B->rmap->n; i++) {b->imax[i] = nnz[i]; nz64 += nnz[i];}
4135c73702f5SBarry Smith       ierr = PetscIntCast(nz64,&nz);CHKERRQ(ierr);
4136273d9f13SBarry Smith     }
4137ab93d7beSBarry Smith 
4138273d9f13SBarry Smith     /* allocate the matrix space */
413953dd7562SDmitry Karpeev     /* FIXME: should B's old memory be unlogged? */
41402ee49352SLisandro Dalcin     ierr = MatSeqXAIJFreeAIJ(B,&b->a,&b->j,&b->i);CHKERRQ(ierr);
4141396832f4SHong Zhang     if (B->structure_only) {
41425848002fSHong Zhang       ierr = PetscMalloc1(nz,&b->j);CHKERRQ(ierr);
41435848002fSHong Zhang       ierr = PetscMalloc1(B->rmap->n+1,&b->i);CHKERRQ(ierr);
4144396832f4SHong Zhang       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*sizeof(PetscInt));CHKERRQ(ierr);
4145396832f4SHong Zhang     } else {
4146dcca6d9dSJed Brown       ierr = PetscMalloc3(nz,&b->a,nz,&b->j,B->rmap->n+1,&b->i);CHKERRQ(ierr);
41473bb1ff40SBarry Smith       ierr = PetscLogObjectMemory((PetscObject)B,(B->rmap->n+1)*sizeof(PetscInt)+nz*(sizeof(PetscScalar)+sizeof(PetscInt)));CHKERRQ(ierr);
4148396832f4SHong Zhang     }
4149bfeeae90SHong Zhang     b->i[0] = 0;
4150d0f46423SBarry Smith     for (i=1; i<B->rmap->n+1; i++) {
41515da197adSKris Buschelman       b->i[i] = b->i[i-1] + b->imax[i-1];
41525da197adSKris Buschelman     }
4153396832f4SHong Zhang     if (B->structure_only) {
4154396832f4SHong Zhang       b->singlemalloc = PETSC_FALSE;
4155396832f4SHong Zhang       b->free_a       = PETSC_FALSE;
4156396832f4SHong Zhang     } else {
4157273d9f13SBarry Smith       b->singlemalloc = PETSC_TRUE;
4158e6b907acSBarry Smith       b->free_a       = PETSC_TRUE;
4159396832f4SHong Zhang     }
4160e6b907acSBarry Smith     b->free_ij      = PETSC_TRUE;
4161c461c341SBarry Smith   } else {
4162e6b907acSBarry Smith     b->free_a  = PETSC_FALSE;
4163e6b907acSBarry Smith     b->free_ij = PETSC_FALSE;
4164c461c341SBarry Smith   }
4165273d9f13SBarry Smith 
4166846b4da1SFande Kong   if (b->ipre && nnz != b->ipre  && b->imax) {
4167846b4da1SFande Kong     /* reserve user-requested sparsity */
4168580bdb30SBarry Smith     ierr = PetscArraycpy(b->ipre,b->imax,B->rmap->n);CHKERRQ(ierr);
4169846b4da1SFande Kong   }
4170846b4da1SFande Kong 
4171273d9f13SBarry Smith   b->nz               = 0;
4172273d9f13SBarry Smith   b->maxnz            = nz;
4173273d9f13SBarry Smith   B->info.nz_unneeded = (double)b->maxnz;
41742205254eSKarl Rupp   if (realalloc) {
41752205254eSKarl Rupp     ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
41762205254eSKarl Rupp   }
4177cb7b82ddSBarry Smith   B->was_assembled = PETSC_FALSE;
4178cb7b82ddSBarry Smith   B->assembled     = PETSC_FALSE;
4179273d9f13SBarry Smith   PetscFunctionReturn(0);
4180273d9f13SBarry Smith }
4181273d9f13SBarry Smith 
4182846b4da1SFande Kong PetscErrorCode MatResetPreallocation_SeqAIJ(Mat A)
4183846b4da1SFande Kong {
4184846b4da1SFande Kong   Mat_SeqAIJ     *a;
4185a5bbaf83SFande Kong   PetscInt       i;
4186846b4da1SFande Kong   PetscErrorCode ierr;
4187846b4da1SFande Kong 
4188846b4da1SFande Kong   PetscFunctionBegin;
4189846b4da1SFande Kong   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
419014d0e64fSAlex Lindsay 
419114d0e64fSAlex Lindsay   /* Check local size. If zero, then return */
419214d0e64fSAlex Lindsay   if (!A->rmap->n) PetscFunctionReturn(0);
419314d0e64fSAlex Lindsay 
4194846b4da1SFande Kong   a = (Mat_SeqAIJ*)A->data;
41952c814fdeSFande Kong   /* if no saved info, we error out */
4196fb4dc15dSAlex Lindsay   if (!a->ipre) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"No saved preallocation info \n");
41972c814fdeSFande Kong 
4198fb4dc15dSAlex Lindsay   if (!a->i || !a->j || !a->a || !a->imax || !a->ilen) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"Memory info is incomplete, and can not reset preallocation \n");
41992c814fdeSFande Kong 
4200580bdb30SBarry Smith   ierr = PetscArraycpy(a->imax,a->ipre,A->rmap->n);CHKERRQ(ierr);
4201580bdb30SBarry Smith   ierr = PetscArrayzero(a->ilen,A->rmap->n);CHKERRQ(ierr);
4202846b4da1SFande Kong   a->i[0] = 0;
4203846b4da1SFande Kong   for (i=1; i<A->rmap->n+1; i++) {
4204846b4da1SFande Kong     a->i[i] = a->i[i-1] + a->imax[i-1];
4205846b4da1SFande Kong   }
4206846b4da1SFande Kong   A->preallocated     = PETSC_TRUE;
4207846b4da1SFande Kong   a->nz               = 0;
4208846b4da1SFande Kong   a->maxnz            = a->i[A->rmap->n];
4209846b4da1SFande Kong   A->info.nz_unneeded = (double)a->maxnz;
4210846b4da1SFande Kong   A->was_assembled    = PETSC_FALSE;
4211846b4da1SFande Kong   A->assembled        = PETSC_FALSE;
4212846b4da1SFande Kong   PetscFunctionReturn(0);
4213846b4da1SFande Kong }
4214846b4da1SFande Kong 
421558d36128SBarry Smith /*@
4216a1661176SMatthew Knepley    MatSeqAIJSetPreallocationCSR - Allocates memory for a sparse sequential matrix in AIJ format.
4217a1661176SMatthew Knepley 
4218a1661176SMatthew Knepley    Input Parameters:
4219a1661176SMatthew Knepley +  B - the matrix
4220a1661176SMatthew Knepley .  i - the indices into j for the start of each row (starts with zero)
4221a1661176SMatthew Knepley .  j - the column indices for each row (starts with zero) these must be sorted for each row
4222a1661176SMatthew Knepley -  v - optional values in the matrix
4223a1661176SMatthew Knepley 
4224a1661176SMatthew Knepley    Level: developer
4225a1661176SMatthew Knepley 
42266a9b8d82SBarry Smith    Notes:
422758d36128SBarry Smith       The i,j,v values are COPIED with this routine; to avoid the copy use MatCreateSeqAIJWithArrays()
422858d36128SBarry Smith 
42296a9b8d82SBarry Smith       This routine may be called multiple times with different nonzero patterns (or the same nonzero pattern). The nonzero
42306a9b8d82SBarry Smith       structure will be the union of all the previous nonzero structures.
42316a9b8d82SBarry Smith 
42326a9b8d82SBarry Smith     Developer Notes:
42336a9b8d82SBarry 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
42346a9b8d82SBarry Smith       then just copies the v values directly with PetscMemcpy().
42356a9b8d82SBarry Smith 
42366a9b8d82SBarry Smith       This routine could also take a PetscCopyMode argument to allow sharing the values instead of always copying them.
42376a9b8d82SBarry Smith 
42386a9b8d82SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatSeqAIJSetPreallocation(), MatCreateSeqAIJ(), MATSEQAIJ, MatResetPreallocation()
4239a1661176SMatthew Knepley @*/
4240a1661176SMatthew Knepley PetscErrorCode MatSeqAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[],const PetscScalar v[])
4241a1661176SMatthew Knepley {
4242a1661176SMatthew Knepley   PetscErrorCode ierr;
4243a1661176SMatthew Knepley 
4244a1661176SMatthew Knepley   PetscFunctionBegin;
42450700a824SBarry Smith   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
42466ba663aaSJed Brown   PetscValidType(B,1);
42474ac538c5SBarry Smith   ierr = PetscTryMethod(B,"MatSeqAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr);
4248a1661176SMatthew Knepley   PetscFunctionReturn(0);
4249a1661176SMatthew Knepley }
4250a1661176SMatthew Knepley 
42517087cfbeSBarry Smith PetscErrorCode  MatSeqAIJSetPreallocationCSR_SeqAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[])
4252a1661176SMatthew Knepley {
4253a1661176SMatthew Knepley   PetscInt       i;
4254a1661176SMatthew Knepley   PetscInt       m,n;
4255a1661176SMatthew Knepley   PetscInt       nz;
42566a9b8d82SBarry Smith   PetscInt       *nnz;
4257a1661176SMatthew Knepley   PetscErrorCode ierr;
4258a1661176SMatthew Knepley 
4259a1661176SMatthew Knepley   PetscFunctionBegin;
426065e19b50SBarry Smith   if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Ii[0] must be 0 it is %D", Ii[0]);
4261779a8d59SSatish Balay 
4262779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
4263779a8d59SSatish Balay   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
4264779a8d59SSatish Balay 
4265779a8d59SSatish Balay   ierr = MatGetSize(B, &m, &n);CHKERRQ(ierr);
4266854ce69bSBarry Smith   ierr = PetscMalloc1(m+1, &nnz);CHKERRQ(ierr);
4267a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4268b7940d39SSatish Balay     nz     = Ii[i+1]- Ii[i];
426965e19b50SBarry Smith     if (nz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Local row %D has a negative number of columns %D", i, nnz);
4270a1661176SMatthew Knepley     nnz[i] = nz;
4271a1661176SMatthew Knepley   }
4272a1661176SMatthew Knepley   ierr = MatSeqAIJSetPreallocation(B, 0, nnz);CHKERRQ(ierr);
4273a1661176SMatthew Knepley   ierr = PetscFree(nnz);CHKERRQ(ierr);
4274a1661176SMatthew Knepley 
4275a1661176SMatthew Knepley   for (i = 0; i < m; i++) {
4276071fcb05SBarry Smith     ierr = MatSetValues_SeqAIJ(B, 1, &i, Ii[i+1] - Ii[i], J+Ii[i], v ? v + Ii[i] : NULL, INSERT_VALUES);CHKERRQ(ierr);
4277a1661176SMatthew Knepley   }
4278a1661176SMatthew Knepley 
4279a1661176SMatthew Knepley   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4280a1661176SMatthew Knepley   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4281a1661176SMatthew Knepley 
42827827cd58SJed Brown   ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
4283a1661176SMatthew Knepley   PetscFunctionReturn(0);
4284a1661176SMatthew Knepley }
4285a1661176SMatthew Knepley 
4286ad7e164aSPierre Jolivet /*@
4287ad7e164aSPierre Jolivet    MatSeqAIJKron - Computes C, the Kronecker product of A and B.
4288ad7e164aSPierre Jolivet 
4289ad7e164aSPierre Jolivet    Input Parameters:
4290ad7e164aSPierre Jolivet +  A - left-hand side matrix
4291ad7e164aSPierre Jolivet .  B - right-hand side matrix
4292ad7e164aSPierre Jolivet -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
4293ad7e164aSPierre Jolivet 
4294ad7e164aSPierre Jolivet    Output Parameter:
4295ad7e164aSPierre Jolivet .  C - Kronecker product of A and B
4296ad7e164aSPierre Jolivet 
4297ad7e164aSPierre Jolivet    Level: intermediate
4298ad7e164aSPierre Jolivet 
4299ad7e164aSPierre Jolivet    Notes:
4300ad7e164aSPierre 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().
4301ad7e164aSPierre Jolivet 
4302ad7e164aSPierre Jolivet .seealso: MatCreateSeqAIJ(), MATSEQAIJ, MATKAIJ, MatReuse
4303ad7e164aSPierre Jolivet @*/
4304ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron(Mat A,Mat B,MatReuse reuse,Mat *C)
4305ad7e164aSPierre Jolivet {
4306ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4307ad7e164aSPierre Jolivet 
4308ad7e164aSPierre Jolivet   PetscFunctionBegin;
4309ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
4310ad7e164aSPierre Jolivet   PetscValidType(A,1);
4311ad7e164aSPierre Jolivet   PetscValidHeaderSpecific(B,MAT_CLASSID,2);
4312ad7e164aSPierre Jolivet   PetscValidType(B,2);
4313ad7e164aSPierre Jolivet   PetscValidPointer(C,4);
4314ad7e164aSPierre Jolivet   if (reuse == MAT_REUSE_MATRIX) {
4315ad7e164aSPierre Jolivet     PetscValidHeaderSpecific(*C,MAT_CLASSID,4);
4316ad7e164aSPierre Jolivet     PetscValidType(*C,4);
4317ad7e164aSPierre Jolivet   }
4318ad7e164aSPierre Jolivet   ierr = PetscTryMethod(A,"MatSeqAIJKron_C",(Mat,Mat,MatReuse,Mat*),(A,B,reuse,C));CHKERRQ(ierr);
4319ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4320ad7e164aSPierre Jolivet }
4321ad7e164aSPierre Jolivet 
4322ad7e164aSPierre Jolivet PetscErrorCode MatSeqAIJKron_SeqAIJ(Mat A,Mat B,MatReuse reuse,Mat *C)
4323ad7e164aSPierre Jolivet {
4324ad7e164aSPierre Jolivet   Mat            newmat;
4325ad7e164aSPierre Jolivet   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
4326ad7e164aSPierre Jolivet   Mat_SeqAIJ     *b = (Mat_SeqAIJ*)B->data;
4327ad7e164aSPierre Jolivet   PetscScalar    *v;
4328ad7e164aSPierre 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;
4329ad7e164aSPierre Jolivet   PetscBool      flg;
4330ad7e164aSPierre Jolivet   PetscErrorCode ierr;
4331ad7e164aSPierre Jolivet 
4332ad7e164aSPierre Jolivet   PetscFunctionBegin;
4333ad7e164aSPierre Jolivet   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4334ad7e164aSPierre Jolivet   if (!A->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4335ad7e164aSPierre Jolivet   if (B->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
4336ad7e164aSPierre Jolivet   if (!B->assembled) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix");
4337ad7e164aSPierre Jolivet   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQAIJ,&flg);CHKERRQ(ierr);
4338ad7e164aSPierre Jolivet   if (!flg) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatType %s",((PetscObject)B)->type_name);
4339ad7e164aSPierre Jolivet   if (reuse != MAT_INITIAL_MATRIX && reuse != MAT_REUSE_MATRIX) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatReuse %d",(int)reuse);
4340ad7e164aSPierre Jolivet   if (reuse == MAT_INITIAL_MATRIX) {
4341ad7e164aSPierre Jolivet     ierr = PetscMalloc2(am*bm+1,&i,a->i[am]*b->i[bm],&j);CHKERRQ(ierr);
4342ad7e164aSPierre Jolivet     ierr = MatCreate(PETSC_COMM_SELF,&newmat);CHKERRQ(ierr);
4343ad7e164aSPierre Jolivet     ierr = MatSetSizes(newmat,am*bm,an*bn,am*bm,an*bn);CHKERRQ(ierr);
4344ad7e164aSPierre Jolivet     ierr = MatSetType(newmat,MATAIJ);CHKERRQ(ierr);
4345ad7e164aSPierre Jolivet     i[0] = 0;
4346ad7e164aSPierre Jolivet     for (m = 0; m < am; ++m) {
4347ad7e164aSPierre Jolivet       for (p = 0; p < bm; ++p) {
4348ad7e164aSPierre Jolivet         i[m*bm + p + 1] = i[m*bm + p] + (a->i[m+1] - a->i[m]) * (b->i[p+1] - b->i[p]);
4349ad7e164aSPierre Jolivet         for (n = a->i[m]; n < a->i[m+1]; ++n) {
4350ad7e164aSPierre Jolivet           for (q = b->i[p]; q < b->i[p+1]; ++q) {
4351ad7e164aSPierre Jolivet             j[nnz++] = a->j[n]*bn + b->j[q];
4352ad7e164aSPierre Jolivet           }
4353ad7e164aSPierre Jolivet         }
4354ad7e164aSPierre Jolivet       }
4355ad7e164aSPierre Jolivet     }
4356ad7e164aSPierre Jolivet     ierr = MatSeqAIJSetPreallocationCSR(newmat,i,j,NULL);CHKERRQ(ierr);
4357ad7e164aSPierre Jolivet     *C = newmat;
4358ad7e164aSPierre Jolivet     ierr = PetscFree2(i,j);CHKERRQ(ierr);
4359ad7e164aSPierre Jolivet     nnz = 0;
4360ad7e164aSPierre Jolivet   }
4361ad7e164aSPierre Jolivet   ierr = MatSeqAIJGetArray(*C,&v);CHKERRQ(ierr);
4362ad7e164aSPierre Jolivet   for (m = 0; m < am; ++m) {
4363ad7e164aSPierre Jolivet     for (p = 0; p < bm; ++p) {
4364ad7e164aSPierre Jolivet       for (n = a->i[m]; n < a->i[m+1]; ++n) {
4365ad7e164aSPierre Jolivet         for (q = b->i[p]; q < b->i[p+1]; ++q) {
4366ad7e164aSPierre Jolivet           v[nnz++] = a->a[n] * b->a[q];
4367ad7e164aSPierre Jolivet         }
4368ad7e164aSPierre Jolivet       }
4369ad7e164aSPierre Jolivet     }
4370ad7e164aSPierre Jolivet   }
4371ad7e164aSPierre Jolivet   ierr = MatSeqAIJRestoreArray(*C,&v);CHKERRQ(ierr);
4372ad7e164aSPierre Jolivet   PetscFunctionReturn(0);
4373ad7e164aSPierre Jolivet }
4374ad7e164aSPierre Jolivet 
4375c6db04a5SJed Brown #include <../src/mat/impls/dense/seq/dense.h>
4376af0996ceSBarry Smith #include <petsc/private/kernels/petscaxpy.h>
4377170fe5c8SBarry Smith 
4378170fe5c8SBarry Smith /*
4379170fe5c8SBarry Smith     Computes (B'*A')' since computing B*A directly is untenable
4380170fe5c8SBarry Smith 
4381170fe5c8SBarry Smith                n                       p                          p
43822da392ccSBarry Smith         [             ]       [             ]         [                 ]
43832da392ccSBarry Smith       m [      A      ]  *  n [       B     ]   =   m [         C       ]
43842da392ccSBarry Smith         [             ]       [             ]         [                 ]
4385170fe5c8SBarry Smith 
4386170fe5c8SBarry Smith */
4387170fe5c8SBarry Smith PetscErrorCode MatMatMultNumeric_SeqDense_SeqAIJ(Mat A,Mat B,Mat C)
4388170fe5c8SBarry Smith {
4389170fe5c8SBarry Smith   PetscErrorCode    ierr;
4390170fe5c8SBarry Smith   Mat_SeqDense      *sub_a = (Mat_SeqDense*)A->data;
4391170fe5c8SBarry Smith   Mat_SeqAIJ        *sub_b = (Mat_SeqAIJ*)B->data;
4392170fe5c8SBarry Smith   Mat_SeqDense      *sub_c = (Mat_SeqDense*)C->data;
439386214ceeSStefano Zampini   PetscInt          i,j,n,m,q,p;
4394170fe5c8SBarry Smith   const PetscInt    *ii,*idx;
4395170fe5c8SBarry Smith   const PetscScalar *b,*a,*a_q;
4396170fe5c8SBarry Smith   PetscScalar       *c,*c_q;
439786214ceeSStefano Zampini   PetscInt          clda = sub_c->lda;
439886214ceeSStefano Zampini   PetscInt          alda = sub_a->lda;
4399170fe5c8SBarry Smith 
4400170fe5c8SBarry Smith   PetscFunctionBegin;
4401d0f46423SBarry Smith   m    = A->rmap->n;
4402d0f46423SBarry Smith   n    = A->cmap->n;
4403d0f46423SBarry Smith   p    = B->cmap->n;
4404170fe5c8SBarry Smith   a    = sub_a->v;
4405170fe5c8SBarry Smith   b    = sub_b->a;
4406170fe5c8SBarry Smith   c    = sub_c->v;
440786214ceeSStefano Zampini   if (clda == m) {
4408580bdb30SBarry Smith     ierr = PetscArrayzero(c,m*p);CHKERRQ(ierr);
440986214ceeSStefano Zampini   } else {
441086214ceeSStefano Zampini     for (j=0;j<p;j++)
441186214ceeSStefano Zampini       for (i=0;i<m;i++)
441286214ceeSStefano Zampini         c[j*clda + i] = 0.0;
441386214ceeSStefano Zampini   }
4414170fe5c8SBarry Smith   ii  = sub_b->i;
4415170fe5c8SBarry Smith   idx = sub_b->j;
4416170fe5c8SBarry Smith   for (i=0; i<n; i++) {
4417170fe5c8SBarry Smith     q = ii[i+1] - ii[i];
4418170fe5c8SBarry Smith     while (q-->0) {
441986214ceeSStefano Zampini       c_q = c + clda*(*idx);
442086214ceeSStefano Zampini       a_q = a + alda*i;
4421854c7f52SBarry Smith       PetscKernelAXPY(c_q,*b,a_q,m);
4422170fe5c8SBarry Smith       idx++;
4423170fe5c8SBarry Smith       b++;
4424170fe5c8SBarry Smith     }
4425170fe5c8SBarry Smith   }
4426170fe5c8SBarry Smith   PetscFunctionReturn(0);
4427170fe5c8SBarry Smith }
4428170fe5c8SBarry Smith 
44294222ddf1SHong Zhang PetscErrorCode MatMatMultSymbolic_SeqDense_SeqAIJ(Mat A,Mat B,PetscReal fill,Mat C)
4430170fe5c8SBarry Smith {
4431170fe5c8SBarry Smith   PetscErrorCode ierr;
4432d0f46423SBarry Smith   PetscInt       m=A->rmap->n,n=B->cmap->n;
443386214ceeSStefano Zampini   PetscBool      cisdense;
4434170fe5c8SBarry Smith 
4435170fe5c8SBarry Smith   PetscFunctionBegin;
443660e0710aSBarry Smith   if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %D != B->rmap->n %D\n",A->cmap->n,B->rmap->n);
44374222ddf1SHong Zhang   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
44384222ddf1SHong Zhang   ierr = MatSetBlockSizesFromMats(C,A,B);CHKERRQ(ierr);
443986214ceeSStefano Zampini   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
444086214ceeSStefano Zampini   if (!cisdense) {
444186214ceeSStefano Zampini     ierr = MatSetType(C,MATDENSE);CHKERRQ(ierr);
444286214ceeSStefano Zampini   }
444386214ceeSStefano Zampini   ierr = MatSetUp(C);CHKERRQ(ierr);
4444d73949e8SHong Zhang 
44454222ddf1SHong Zhang   C->ops->matmultnumeric = MatMatMultNumeric_SeqDense_SeqAIJ;
4446170fe5c8SBarry Smith   PetscFunctionReturn(0);
4447170fe5c8SBarry Smith }
4448170fe5c8SBarry Smith 
4449170fe5c8SBarry Smith /* ----------------------------------------------------------------*/
44500bad9183SKris Buschelman /*MC
4451fafad747SKris Buschelman    MATSEQAIJ - MATSEQAIJ = "seqaij" - A matrix type to be used for sequential sparse matrices,
44520bad9183SKris Buschelman    based on compressed sparse row format.
44530bad9183SKris Buschelman 
44540bad9183SKris Buschelman    Options Database Keys:
44550bad9183SKris Buschelman . -mat_type seqaij - sets the matrix type to "seqaij" during a call to MatSetFromOptions()
44560bad9183SKris Buschelman 
44570bad9183SKris Buschelman    Level: beginner
44580bad9183SKris Buschelman 
44590cd7f59aSBarry Smith    Notes:
44600cd7f59aSBarry Smith     MatSetValues() may be called for this matrix type with a NULL argument for the numerical values,
44610cd7f59aSBarry Smith     in this case the values associated with the rows and columns one passes in are set to zero
44620cd7f59aSBarry Smith     in the matrix
44630cd7f59aSBarry Smith 
44640cd7f59aSBarry Smith     MatSetOptions(,MAT_STRUCTURE_ONLY,PETSC_TRUE) may be called for this matrix type. In this no
44650cd7f59aSBarry Smith     space is allocated for the nonzero entries and any entries passed with MatSetValues() are ignored
44660cd7f59aSBarry Smith 
44670cd7f59aSBarry Smith   Developer Notes:
44680cd7f59aSBarry Smith     It would be nice if all matrix formats supported passing NULL in for the numerical values
44690cd7f59aSBarry Smith 
4470f587520bSBarry Smith .seealso: MatCreateSeqAIJ(), MatSetFromOptions(), MatSetType(), MatCreate(), MatType
44710bad9183SKris Buschelman M*/
44720bad9183SKris Buschelman 
4473ccd284c7SBarry Smith /*MC
4474ccd284c7SBarry Smith    MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices.
4475ccd284c7SBarry Smith 
4476ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJ when constructed with a single process communicator,
4477ccd284c7SBarry Smith    and MATMPIAIJ otherwise.  As a result, for single process communicators,
44780cd7f59aSBarry Smith   MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported
4479ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4480ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4481ccd284c7SBarry Smith 
4482ccd284c7SBarry Smith    Options Database Keys:
4483ccd284c7SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions()
4484ccd284c7SBarry Smith 
448595452b02SPatrick Sanan   Developer Notes:
4486ca9cdca7SRichard Tran Mills     Subclasses include MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when
4487ccd284c7SBarry Smith    enough exist.
4488ccd284c7SBarry Smith 
4489ccd284c7SBarry Smith   Level: beginner
4490ccd284c7SBarry Smith 
4491ccd284c7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ
4492ccd284c7SBarry Smith M*/
4493ccd284c7SBarry Smith 
4494ccd284c7SBarry Smith /*MC
4495ccd284c7SBarry Smith    MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices.
4496ccd284c7SBarry Smith 
4497ccd284c7SBarry Smith    This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator,
4498ccd284c7SBarry Smith    and MATMPIAIJCRL otherwise.  As a result, for single process communicators,
4499ccd284c7SBarry Smith    MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported
4500ccd284c7SBarry Smith   for communicators controlling multiple processes.  It is recommended that you call both of
4501ccd284c7SBarry Smith   the above preallocation routines for simplicity.
4502ccd284c7SBarry Smith 
4503ccd284c7SBarry Smith    Options Database Keys:
4504ccd284c7SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions()
4505ccd284c7SBarry Smith 
4506ccd284c7SBarry Smith   Level: beginner
4507ccd284c7SBarry Smith 
4508ccd284c7SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL
4509ccd284c7SBarry Smith M*/
4510ccd284c7SBarry Smith 
45117906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCRL(Mat,MatType,MatReuse,Mat*);
45127906f579SHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
45137906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_Elemental(Mat,MatType,MatReuse,Mat*);
45147906f579SHong Zhang #endif
4515d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4516d24d4204SJose E. Roman PETSC_INTERN PetscErrorCode MatConvert_AIJ_ScaLAPACK(Mat,MatType,MatReuse,Mat*);
4517d24d4204SJose E. Roman #endif
45187906f579SHong Zhang #if defined(PETSC_HAVE_HYPRE)
45197906f579SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat A,MatType,MatReuse,Mat*);
45207906f579SHong Zhang #endif
45217906f579SHong Zhang 
4522d4002b98SHong Zhang PETSC_EXTERN PetscErrorCode MatConvert_SeqAIJ_SeqSELL(Mat,MatType,MatReuse,Mat*);
4523c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*);
45244222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat);
45257906f579SHong Zhang 
45268c778c55SBarry Smith /*@C
45278f1ea47aSStefano Zampini    MatSeqAIJGetArray - gives read/write access to the array where the data for a MATSEQAIJ matrix is stored
45288c778c55SBarry Smith 
45298c778c55SBarry Smith    Not Collective
45308c778c55SBarry Smith 
45318c778c55SBarry Smith    Input Parameter:
4532579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
45338c778c55SBarry Smith 
45348c778c55SBarry Smith    Output Parameter:
45358c778c55SBarry Smith .   array - pointer to the data
45368c778c55SBarry Smith 
45378c778c55SBarry Smith    Level: intermediate
45388c778c55SBarry Smith 
4539774cf152SJed Brown .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
45408c778c55SBarry Smith @*/
45418c778c55SBarry Smith PetscErrorCode  MatSeqAIJGetArray(Mat A,PetscScalar **array)
45428c778c55SBarry Smith {
45438c778c55SBarry Smith   PetscErrorCode ierr;
45448c778c55SBarry Smith 
45458c778c55SBarry Smith   PetscFunctionBegin;
45468c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
45472e5835c6SStefano Zampini #if defined(PETSC_HAVE_DEVICE)
45482e5835c6SStefano Zampini   if (A->offloadmask != PETSC_OFFLOAD_UNALLOCATED) A->offloadmask = PETSC_OFFLOAD_CPU;
45492e5835c6SStefano Zampini #endif
45508c778c55SBarry Smith   PetscFunctionReturn(0);
45518c778c55SBarry Smith }
45528c778c55SBarry Smith 
455321e72a00SBarry Smith /*@C
45548f1ea47aSStefano Zampini    MatSeqAIJGetArrayRead - gives read-only access to the array where the data for a MATSEQAIJ matrix is stored
45558f1ea47aSStefano Zampini 
45568f1ea47aSStefano Zampini    Not Collective
45578f1ea47aSStefano Zampini 
45588f1ea47aSStefano Zampini    Input Parameter:
45598f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45608f1ea47aSStefano Zampini 
45618f1ea47aSStefano Zampini    Output Parameter:
45628f1ea47aSStefano Zampini .   array - pointer to the data
45638f1ea47aSStefano Zampini 
45648f1ea47aSStefano Zampini    Level: intermediate
45658f1ea47aSStefano Zampini 
45668f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayRead()
45678f1ea47aSStefano Zampini @*/
45688f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJGetArrayRead(Mat A,const PetscScalar **array)
45698f1ea47aSStefano Zampini {
45708c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4571c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
45728f1ea47aSStefano Zampini #endif
45738f1ea47aSStefano Zampini   PetscErrorCode ierr;
45748f1ea47aSStefano Zampini 
45758f1ea47aSStefano Zampini   PetscFunctionBegin;
45768c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4577c70f7ee4SJunchao Zhang   oval = A->offloadmask;
45788f1ea47aSStefano Zampini #endif
45798f1ea47aSStefano Zampini   ierr = MatSeqAIJGetArray(A,(PetscScalar**)array);CHKERRQ(ierr);
45808c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4581c70f7ee4SJunchao Zhang   if (oval == PETSC_OFFLOAD_GPU || oval == PETSC_OFFLOAD_BOTH) A->offloadmask = PETSC_OFFLOAD_BOTH;
45828f1ea47aSStefano Zampini #endif
45838f1ea47aSStefano Zampini   PetscFunctionReturn(0);
45848f1ea47aSStefano Zampini }
45858f1ea47aSStefano Zampini 
45868f1ea47aSStefano Zampini /*@C
45878f1ea47aSStefano Zampini    MatSeqAIJRestoreArrayRead - restore the read-only access array obtained from MatSeqAIJGetArrayRead
45888f1ea47aSStefano Zampini 
45898f1ea47aSStefano Zampini    Not Collective
45908f1ea47aSStefano Zampini 
45918f1ea47aSStefano Zampini    Input Parameter:
45928f1ea47aSStefano Zampini .  mat - a MATSEQAIJ matrix
45938f1ea47aSStefano Zampini 
45948f1ea47aSStefano Zampini    Output Parameter:
45958f1ea47aSStefano Zampini .   array - pointer to the data
45968f1ea47aSStefano Zampini 
45978f1ea47aSStefano Zampini    Level: intermediate
45988f1ea47aSStefano Zampini 
45998f1ea47aSStefano Zampini .seealso: MatSeqAIJGetArray(), MatSeqAIJGetArrayRead()
46008f1ea47aSStefano Zampini @*/
46018f1ea47aSStefano Zampini PetscErrorCode  MatSeqAIJRestoreArrayRead(Mat A,const PetscScalar **array)
46028f1ea47aSStefano Zampini {
46038c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4604c70f7ee4SJunchao Zhang   PetscOffloadMask oval;
46058f1ea47aSStefano Zampini #endif
46068f1ea47aSStefano Zampini   PetscErrorCode ierr;
46078f1ea47aSStefano Zampini 
46088f1ea47aSStefano Zampini   PetscFunctionBegin;
46098c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4610c70f7ee4SJunchao Zhang   oval = A->offloadmask;
46118f1ea47aSStefano Zampini #endif
46128f1ea47aSStefano Zampini   ierr = MatSeqAIJRestoreArray(A,(PetscScalar**)array);CHKERRQ(ierr);
46138c3ff71bSJunchao Zhang #if defined(PETSC_HAVE_DEVICE)
4614c70f7ee4SJunchao Zhang   A->offloadmask = oval;
46158f1ea47aSStefano Zampini #endif
46168f1ea47aSStefano Zampini   PetscFunctionReturn(0);
46178f1ea47aSStefano Zampini }
46188f1ea47aSStefano Zampini 
46198f1ea47aSStefano Zampini /*@C
462021e72a00SBarry Smith    MatSeqAIJGetMaxRowNonzeros - returns the maximum number of nonzeros in any row
462121e72a00SBarry Smith 
462221e72a00SBarry Smith    Not Collective
462321e72a00SBarry Smith 
462421e72a00SBarry Smith    Input Parameter:
4625579dbff0SBarry Smith .  mat - a MATSEQAIJ matrix
462621e72a00SBarry Smith 
462721e72a00SBarry Smith    Output Parameter:
462821e72a00SBarry Smith .   nz - the maximum number of nonzeros in any row
462921e72a00SBarry Smith 
463021e72a00SBarry Smith    Level: intermediate
463121e72a00SBarry Smith 
463221e72a00SBarry Smith .seealso: MatSeqAIJRestoreArray(), MatSeqAIJGetArrayF90()
463321e72a00SBarry Smith @*/
463421e72a00SBarry Smith PetscErrorCode  MatSeqAIJGetMaxRowNonzeros(Mat A,PetscInt *nz)
463521e72a00SBarry Smith {
463621e72a00SBarry Smith   Mat_SeqAIJ     *aij = (Mat_SeqAIJ*)A->data;
463721e72a00SBarry Smith 
463821e72a00SBarry Smith   PetscFunctionBegin;
463921e72a00SBarry Smith   *nz = aij->rmax;
464021e72a00SBarry Smith   PetscFunctionReturn(0);
464121e72a00SBarry Smith }
464221e72a00SBarry Smith 
46438c778c55SBarry Smith /*@C
4644579dbff0SBarry Smith    MatSeqAIJRestoreArray - returns access to the array where the data for a MATSEQAIJ matrix is stored obtained by MatSeqAIJGetArray()
46458c778c55SBarry Smith 
46468c778c55SBarry Smith    Not Collective
46478c778c55SBarry Smith 
46488c778c55SBarry Smith    Input Parameters:
4649a2b725a8SWilliam Gropp +  mat - a MATSEQAIJ matrix
4650a2b725a8SWilliam Gropp -  array - pointer to the data
46518c778c55SBarry Smith 
46528c778c55SBarry Smith    Level: intermediate
46538c778c55SBarry Smith 
4654774cf152SJed Brown .seealso: MatSeqAIJGetArray(), MatSeqAIJRestoreArrayF90()
46558c778c55SBarry Smith @*/
46568c778c55SBarry Smith PetscErrorCode  MatSeqAIJRestoreArray(Mat A,PetscScalar **array)
46578c778c55SBarry Smith {
46588c778c55SBarry Smith   PetscErrorCode ierr;
46598c778c55SBarry Smith 
46608c778c55SBarry Smith   PetscFunctionBegin;
46618c778c55SBarry Smith   ierr = PetscUseMethod(A,"MatSeqAIJRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
46628c778c55SBarry Smith   PetscFunctionReturn(0);
46638c778c55SBarry Smith }
46648c778c55SBarry Smith 
466534b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
46660ce8acdeSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJCUSPARSE(Mat);
466702fe1965SBarry Smith #endif
46683d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
46693d0639e7SStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqAIJKokkos(Mat);
46703d0639e7SStefano Zampini #endif
467102fe1965SBarry Smith 
46728cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_SeqAIJ(Mat B)
4673273d9f13SBarry Smith {
4674273d9f13SBarry Smith   Mat_SeqAIJ     *b;
4675dfbe8321SBarry Smith   PetscErrorCode ierr;
467638baddfdSBarry Smith   PetscMPIInt    size;
4677273d9f13SBarry Smith 
4678273d9f13SBarry Smith   PetscFunctionBegin;
4679ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
4680e32f2f54SBarry Smith   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Comm must be of size 1");
4681273d9f13SBarry Smith 
4682b00a9115SJed Brown   ierr = PetscNewLog(B,&b);CHKERRQ(ierr);
46832205254eSKarl Rupp 
4684b0a32e0cSBarry Smith   B->data = (void*)b;
46852205254eSKarl Rupp 
4686549d3d68SSatish Balay   ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
4687071fcb05SBarry Smith   if (B->sortedfull) B->ops->setvalues = MatSetValues_SeqAIJ_SortedFull;
46882205254eSKarl Rupp 
4689f4259b30SLisandro Dalcin   b->row                = NULL;
4690f4259b30SLisandro Dalcin   b->col                = NULL;
4691f4259b30SLisandro Dalcin   b->icol               = NULL;
4692b810aeb4SBarry Smith   b->reallocs           = 0;
469336db0b34SBarry Smith   b->ignorezeroentries  = PETSC_FALSE;
4694f1e2ffcdSBarry Smith   b->roworiented        = PETSC_TRUE;
4695416022c9SBarry Smith   b->nonew              = 0;
4696f4259b30SLisandro Dalcin   b->diag               = NULL;
4697f4259b30SLisandro Dalcin   b->solve_work         = NULL;
4698f4259b30SLisandro Dalcin   B->spptr              = NULL;
4699f4259b30SLisandro Dalcin   b->saved_values       = NULL;
4700f4259b30SLisandro Dalcin   b->idiag              = NULL;
4701f4259b30SLisandro Dalcin   b->mdiag              = NULL;
4702f4259b30SLisandro Dalcin   b->ssor_work          = NULL;
470371f1c65dSBarry Smith   b->omega              = 1.0;
470471f1c65dSBarry Smith   b->fshift             = 0.0;
470571f1c65dSBarry Smith   b->idiagvalid         = PETSC_FALSE;
4706bbead8a2SBarry Smith   b->ibdiagvalid        = PETSC_FALSE;
4707a9817697SBarry Smith   b->keepnonzeropattern = PETSC_FALSE;
470817ab2063SBarry Smith 
470935d8aa7fSBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
4710bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJGetArray_C",MatSeqAIJGetArray_SeqAIJ);CHKERRQ(ierr);
4711bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJRestoreArray_C",MatSeqAIJRestoreArray_SeqAIJ);CHKERRQ(ierr);
47128c778c55SBarry Smith 
4713b3866ffcSBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
4714bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEnginePut_C",MatlabEnginePut_SeqAIJ);CHKERRQ(ierr);
4715bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"PetscMatlabEngineGet_C",MatlabEngineGet_SeqAIJ);CHKERRQ(ierr);
4716b3866ffcSBarry Smith #endif
471717f1a0eaSHong Zhang 
4718bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetColumnIndices_C",MatSeqAIJSetColumnIndices_SeqAIJ);CHKERRQ(ierr);
4719bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_SeqAIJ);CHKERRQ(ierr);
4720bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_SeqAIJ);CHKERRQ(ierr);
4721bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsbaij_C",MatConvert_SeqAIJ_SeqSBAIJ);CHKERRQ(ierr);
4722bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqbaij_C",MatConvert_SeqAIJ_SeqBAIJ);CHKERRQ(ierr);
4723bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijperm_C",MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
47244dfdc2d9SRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijsell_C",MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
47259779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
47264a2a386eSRichard Tran Mills   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijmkl_C",MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
4727191b95cbSRichard Tran Mills #endif
472834b5b067SBarry Smith #if defined(PETSC_HAVE_CUDA)
472902fe1965SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcusparse_C",MatConvert_SeqAIJ_SeqAIJCUSPARSE);CHKERRQ(ierr);
47304222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaijcusparse_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4731fcdce8c4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaijcusparse_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
473202fe1965SBarry Smith #endif
47333d0639e7SStefano Zampini #if defined(PETSC_HAVE_KOKKOS_KERNELS)
47343d0639e7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijkokkos_C",MatConvert_SeqAIJ_SeqAIJKokkos);CHKERRQ(ierr);
47353d0639e7SStefano Zampini #endif
4736bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqaijcrl_C",MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
4737af8000cdSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL)
4738af8000cdSHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_elemental_C",MatConvert_SeqAIJ_Elemental);CHKERRQ(ierr);
4739af8000cdSHong Zhang #endif
4740d24d4204SJose E. Roman #if defined(PETSC_HAVE_SCALAPACK)
4741d24d4204SJose E. Roman   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_scalapack_C",MatConvert_AIJ_ScaLAPACK);CHKERRQ(ierr);
4742d24d4204SJose E. Roman #endif
474363c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE)
474463c07aadSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr);
47454222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_transpose_seqaij_seqaij_C",MatProductSetFromOptions_Transpose_AIJ_AIJ);CHKERRQ(ierr);
474663c07aadSStefano Zampini #endif
4747b49cda9fSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqdense_C",MatConvert_SeqAIJ_SeqDense);CHKERRQ(ierr);
4748d4002b98SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_seqsell_C",MatConvert_SeqAIJ_SeqSELL);CHKERRQ(ierr);
4749c9225affSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr);
4750bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4751bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsHermitianTranspose_C",MatIsTranspose_SeqAIJ);CHKERRQ(ierr);
4752bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocation_C",MatSeqAIJSetPreallocation_SeqAIJ);CHKERRQ(ierr);
4753846b4da1SFande Kong   ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_SeqAIJ);CHKERRQ(ierr);
4754bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJSetPreallocationCSR_C",MatSeqAIJSetPreallocationCSR_SeqAIJ);CHKERRQ(ierr);
4755bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)B,"MatReorderForNonzeroDiagonal_C",MatReorderForNonzeroDiagonal_SeqAIJ);CHKERRQ(ierr);
47564222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_is_seqaij_C",MatProductSetFromOptions_IS_XAIJ);CHKERRQ(ierr);
47574222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqaij_C",MatProductSetFromOptions_SeqDense_SeqAIJ);CHKERRQ(ierr);
47584222ddf1SHong Zhang   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqaij_C",MatProductSetFromOptions_SeqAIJ);CHKERRQ(ierr);
4759ad7e164aSPierre Jolivet   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqAIJKron_C",MatSeqAIJKron_SeqAIJ);CHKERRQ(ierr);
47604108e4d5SBarry Smith   ierr = MatCreate_SeqAIJ_Inode(B);CHKERRQ(ierr);
476117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQAIJ);CHKERRQ(ierr);
47624099cc6bSBarry Smith   ierr = MatSeqAIJSetTypeFromOptions(B);CHKERRQ(ierr);  /* this allows changing the matrix subtype to say MATSEQAIJPERM */
47633a40ed3dSBarry Smith   PetscFunctionReturn(0);
476417ab2063SBarry Smith }
476517ab2063SBarry Smith 
4766b24902e0SBarry Smith /*
4767b24902e0SBarry Smith     Given a matrix generated with MatGetFactor() duplicates all the information in A into B
4768b24902e0SBarry Smith */
4769ace3abfcSBarry Smith PetscErrorCode MatDuplicateNoCreate_SeqAIJ(Mat C,Mat A,MatDuplicateOption cpvalues,PetscBool mallocmatspace)
477017ab2063SBarry Smith {
47712a350339SBarry Smith   Mat_SeqAIJ     *c = (Mat_SeqAIJ*)C->data,*a = (Mat_SeqAIJ*)A->data;
47726849ba73SBarry Smith   PetscErrorCode ierr;
4773071fcb05SBarry Smith   PetscInt       m = A->rmap->n,i;
477417ab2063SBarry Smith 
47753a40ed3dSBarry Smith   PetscFunctionBegin;
4776ca133879SJose E. Roman   if (!A->assembled && cpvalues!=MAT_DO_NOT_COPY_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot duplicate unassembled matrix");
4777273d9f13SBarry Smith 
4778d5f3da31SBarry Smith   C->factortype = A->factortype;
4779f4259b30SLisandro Dalcin   c->row        = NULL;
4780f4259b30SLisandro Dalcin   c->col        = NULL;
4781f4259b30SLisandro Dalcin   c->icol       = NULL;
47826ad4291fSHong Zhang   c->reallocs   = 0;
478317ab2063SBarry Smith 
47846ad4291fSHong Zhang   C->assembled = PETSC_TRUE;
478517ab2063SBarry Smith 
4786aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->rmap,&C->rmap);CHKERRQ(ierr);
4787aa5ea44dSBarry Smith   ierr = PetscLayoutReference(A->cmap,&C->cmap);CHKERRQ(ierr);
4788eec197d1SBarry Smith 
4789071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->imax);CHKERRQ(ierr);
4790071fcb05SBarry Smith   ierr = PetscMemcpy(c->imax,a->imax,m*sizeof(PetscInt));CHKERRQ(ierr);
4791071fcb05SBarry Smith   ierr = PetscMalloc1(m,&c->ilen);CHKERRQ(ierr);
4792071fcb05SBarry Smith   ierr = PetscMemcpy(c->ilen,a->ilen,m*sizeof(PetscInt));CHKERRQ(ierr);
47933bb1ff40SBarry Smith   ierr = PetscLogObjectMemory((PetscObject)C, 2*m*sizeof(PetscInt));CHKERRQ(ierr);
479417ab2063SBarry Smith 
479517ab2063SBarry Smith   /* allocate the matrix space */
4796f77e22a1SHong Zhang   if (mallocmatspace) {
4797dcca6d9dSJed Brown     ierr = PetscMalloc3(a->i[m],&c->a,a->i[m],&c->j,m+1,&c->i);CHKERRQ(ierr);
47983bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C, a->i[m]*(sizeof(PetscScalar)+sizeof(PetscInt))+(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
47992205254eSKarl Rupp 
4800f1e2ffcdSBarry Smith     c->singlemalloc = PETSC_TRUE;
48012205254eSKarl Rupp 
4802580bdb30SBarry Smith     ierr = PetscArraycpy(c->i,a->i,m+1);CHKERRQ(ierr);
480317ab2063SBarry Smith     if (m > 0) {
4804580bdb30SBarry Smith       ierr = PetscArraycpy(c->j,a->j,a->i[m]);CHKERRQ(ierr);
4805be6bf707SBarry Smith       if (cpvalues == MAT_COPY_VALUES) {
48062e5835c6SStefano Zampini         const PetscScalar *aa;
48072e5835c6SStefano Zampini 
48082e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
48092e5835c6SStefano Zampini         ierr = PetscArraycpy(c->a,aa,a->i[m]);CHKERRQ(ierr);
48102e5835c6SStefano Zampini         ierr = MatSeqAIJGetArrayRead(A,&aa);CHKERRQ(ierr);
4811be6bf707SBarry Smith       } else {
4812580bdb30SBarry Smith         ierr = PetscArrayzero(c->a,a->i[m]);CHKERRQ(ierr);
481317ab2063SBarry Smith       }
481408480c60SBarry Smith     }
4815f77e22a1SHong Zhang   }
481617ab2063SBarry Smith 
48176ad4291fSHong Zhang   c->ignorezeroentries = a->ignorezeroentries;
4818416022c9SBarry Smith   c->roworiented       = a->roworiented;
4819416022c9SBarry Smith   c->nonew             = a->nonew;
4820416022c9SBarry Smith   if (a->diag) {
4821854ce69bSBarry Smith     ierr = PetscMalloc1(m+1,&c->diag);CHKERRQ(ierr);
4822071fcb05SBarry Smith     ierr = PetscMemcpy(c->diag,a->diag,m*sizeof(PetscInt));CHKERRQ(ierr);
48233bb1ff40SBarry Smith     ierr = PetscLogObjectMemory((PetscObject)C,(m+1)*sizeof(PetscInt));CHKERRQ(ierr);
4824071fcb05SBarry Smith   } else c->diag = NULL;
48252205254eSKarl Rupp 
4826f4259b30SLisandro Dalcin   c->solve_work         = NULL;
4827f4259b30SLisandro Dalcin   c->saved_values       = NULL;
4828f4259b30SLisandro Dalcin   c->idiag              = NULL;
4829f4259b30SLisandro Dalcin   c->ssor_work          = NULL;
4830a9817697SBarry Smith   c->keepnonzeropattern = a->keepnonzeropattern;
4831e6b907acSBarry Smith   c->free_a             = PETSC_TRUE;
4832e6b907acSBarry Smith   c->free_ij            = PETSC_TRUE;
48336ad4291fSHong Zhang 
4834893ad86cSHong Zhang   c->rmax         = a->rmax;
4835416022c9SBarry Smith   c->nz           = a->nz;
48368ed568f8SMatthew G Knepley   c->maxnz        = a->nz;       /* Since we allocate exactly the right amount */
4837273d9f13SBarry Smith   C->preallocated = PETSC_TRUE;
4838754ec7b1SSatish Balay 
48396ad4291fSHong Zhang   c->compressedrow.use   = a->compressedrow.use;
48406ad4291fSHong Zhang   c->compressedrow.nrows = a->compressedrow.nrows;
4841cd6b891eSBarry Smith   if (a->compressedrow.use) {
48426ad4291fSHong Zhang     i    = a->compressedrow.nrows;
4843dcca6d9dSJed Brown     ierr = PetscMalloc2(i+1,&c->compressedrow.i,i,&c->compressedrow.rindex);CHKERRQ(ierr);
4844580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.i,a->compressedrow.i,i+1);CHKERRQ(ierr);
4845580bdb30SBarry Smith     ierr = PetscArraycpy(c->compressedrow.rindex,a->compressedrow.rindex,i);CHKERRQ(ierr);
484627ea64f8SHong Zhang   } else {
484727ea64f8SHong Zhang     c->compressedrow.use    = PETSC_FALSE;
48480298fd71SBarry Smith     c->compressedrow.i      = NULL;
48490298fd71SBarry Smith     c->compressedrow.rindex = NULL;
48506ad4291fSHong Zhang   }
4851ea632784SBarry Smith   c->nonzerorowcnt = a->nonzerorowcnt;
4852e56f5c9eSBarry Smith   C->nonzerostate  = A->nonzerostate;
48534846f1f5SKris Buschelman 
48542205254eSKarl Rupp   ierr = MatDuplicate_SeqAIJ_Inode(A,cpvalues,&C);CHKERRQ(ierr);
4855140e18c1SBarry Smith   ierr = PetscFunctionListDuplicate(((PetscObject)A)->qlist,&((PetscObject)C)->qlist);CHKERRQ(ierr);
48563a40ed3dSBarry Smith   PetscFunctionReturn(0);
485717ab2063SBarry Smith }
485817ab2063SBarry Smith 
4859b24902e0SBarry Smith PetscErrorCode MatDuplicate_SeqAIJ(Mat A,MatDuplicateOption cpvalues,Mat *B)
4860b24902e0SBarry Smith {
4861b24902e0SBarry Smith   PetscErrorCode ierr;
4862b24902e0SBarry Smith 
4863b24902e0SBarry Smith   PetscFunctionBegin;
4864ce94432eSBarry Smith   ierr = MatCreate(PetscObjectComm((PetscObject)A),B);CHKERRQ(ierr);
48654b6263acSBarry Smith   ierr = MatSetSizes(*B,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
4866cfd3f464SBarry Smith   if (!(A->rmap->n % A->rmap->bs) && !(A->cmap->n % A->cmap->bs)) {
486733d57670SJed Brown     ierr = MatSetBlockSizesFromMats(*B,A,A);CHKERRQ(ierr);
4868cfd3f464SBarry Smith   }
4869a54f2f98SBarry Smith   ierr = MatSetType(*B,((PetscObject)A)->type_name);CHKERRQ(ierr);
4870f77e22a1SHong Zhang   ierr = MatDuplicateNoCreate_SeqAIJ(*B,A,cpvalues,PETSC_TRUE);CHKERRQ(ierr);
4871b24902e0SBarry Smith   PetscFunctionReturn(0);
4872b24902e0SBarry Smith }
4873b24902e0SBarry Smith 
4874112444f4SShri Abhyankar PetscErrorCode MatLoad_SeqAIJ(Mat newMat, PetscViewer viewer)
4875fbdbba38SShri Abhyankar {
487652f91c60SVaclav Hapla   PetscBool      isbinary, ishdf5;
487752f91c60SVaclav Hapla   PetscErrorCode ierr;
487852f91c60SVaclav Hapla 
487952f91c60SVaclav Hapla   PetscFunctionBegin;
488052f91c60SVaclav Hapla   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
488152f91c60SVaclav Hapla   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
4882c27b3999SVaclav Hapla   /* force binary viewer to load .info file if it has not yet done so */
4883c27b3999SVaclav Hapla   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
488452f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
488552f91c60SVaclav Hapla   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
488652f91c60SVaclav Hapla   if (isbinary) {
488752f91c60SVaclav Hapla     ierr = MatLoad_SeqAIJ_Binary(newMat,viewer);CHKERRQ(ierr);
488852f91c60SVaclav Hapla   } else if (ishdf5) {
488952f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5)
489052f91c60SVaclav Hapla     ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr);
489152f91c60SVaclav Hapla #else
489252f91c60SVaclav Hapla     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
489352f91c60SVaclav Hapla #endif
489452f91c60SVaclav Hapla   } else {
489552f91c60SVaclav Hapla     SETERRQ2(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name);
489652f91c60SVaclav Hapla   }
489752f91c60SVaclav Hapla   PetscFunctionReturn(0);
489852f91c60SVaclav Hapla }
489952f91c60SVaclav Hapla 
49003ea6fe3dSLisandro Dalcin PetscErrorCode MatLoad_SeqAIJ_Binary(Mat mat, PetscViewer viewer)
490152f91c60SVaclav Hapla {
49023ea6fe3dSLisandro Dalcin   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)mat->data;
4903fbdbba38SShri Abhyankar   PetscErrorCode ierr;
49043ea6fe3dSLisandro Dalcin   PetscInt       header[4],*rowlens,M,N,nz,sum,rows,cols,i;
4905fbdbba38SShri Abhyankar 
4906fbdbba38SShri Abhyankar   PetscFunctionBegin;
49073ea6fe3dSLisandro Dalcin   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
4908bbead8a2SBarry Smith 
49093ea6fe3dSLisandro Dalcin   /* read in matrix header */
49103ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
49113ea6fe3dSLisandro Dalcin   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
4912fbdbba38SShri Abhyankar   M = header[1]; N = header[2]; nz = header[3];
49133ea6fe3dSLisandro Dalcin   if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
49143ea6fe3dSLisandro Dalcin   if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
4915bbead8a2SBarry Smith   if (nz < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk, cannot load as SeqAIJ");
4916fbdbba38SShri Abhyankar 
49173ea6fe3dSLisandro Dalcin   /* set block sizes from the viewer's .info file */
49183ea6fe3dSLisandro Dalcin   ierr = MatLoad_Binary_BlockSizes(mat,viewer);CHKERRQ(ierr);
49193ea6fe3dSLisandro Dalcin   /* set local and global sizes if not set already */
49203ea6fe3dSLisandro Dalcin   if (mat->rmap->n < 0) mat->rmap->n = M;
49213ea6fe3dSLisandro Dalcin   if (mat->cmap->n < 0) mat->cmap->n = N;
49223ea6fe3dSLisandro Dalcin   if (mat->rmap->N < 0) mat->rmap->N = M;
49233ea6fe3dSLisandro Dalcin   if (mat->cmap->N < 0) mat->cmap->N = N;
49243ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->rmap);CHKERRQ(ierr);
49253ea6fe3dSLisandro Dalcin   ierr = PetscLayoutSetUp(mat->cmap);CHKERRQ(ierr);
49263ea6fe3dSLisandro Dalcin 
49273ea6fe3dSLisandro Dalcin   /* check if the matrix sizes are correct */
49283ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
49293ea6fe3dSLisandro Dalcin   if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%D, %D) than the input matrix (%D, %D)",M,N,rows,cols);
49303ea6fe3dSLisandro Dalcin 
4931fbdbba38SShri Abhyankar   /* read in row lengths */
49323ea6fe3dSLisandro Dalcin   ierr = PetscMalloc1(M,&rowlens);CHKERRQ(ierr);
49333ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,rowlens,M,NULL,PETSC_INT);CHKERRQ(ierr);
49343ea6fe3dSLisandro Dalcin   /* check if sum(rowlens) is same as nz */
49353ea6fe3dSLisandro Dalcin   sum = 0; for (i=0; i<M; i++) sum += rowlens[i];
49363ea6fe3dSLisandro Dalcin   if (sum != nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent matrix data in file: nonzeros = %D, sum-row-lengths = %D\n",nz,sum);
49373ea6fe3dSLisandro Dalcin   /* preallocate and check sizes */
49383ea6fe3dSLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(mat,0,rowlens);CHKERRQ(ierr);
49393ea6fe3dSLisandro Dalcin   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
494060e0710aSBarry Smith   if (M != rows || N != cols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%D, %D) than the input matrix (%D, %D)",M,N,rows,cols);
49413ea6fe3dSLisandro Dalcin   /* store row lengths */
49423ea6fe3dSLisandro Dalcin   ierr = PetscArraycpy(a->ilen,rowlens,M);CHKERRQ(ierr);
49433ea6fe3dSLisandro Dalcin   ierr = PetscFree(rowlens);CHKERRQ(ierr);
4944fbdbba38SShri Abhyankar 
49453ea6fe3dSLisandro Dalcin   /* fill in "i" row pointers */
49463ea6fe3dSLisandro Dalcin   a->i[0] = 0; for (i=0; i<M; i++) a->i[i+1] = a->i[i] + a->ilen[i];
49473ea6fe3dSLisandro Dalcin   /* read in "j" column indices */
49483ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->j,nz,NULL,PETSC_INT);CHKERRQ(ierr);
49493ea6fe3dSLisandro Dalcin   /* read in "a" nonzero values */
49503ea6fe3dSLisandro Dalcin   ierr = PetscViewerBinaryRead(viewer,a->a,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr);
4951fbdbba38SShri Abhyankar 
49523ea6fe3dSLisandro Dalcin   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
49533ea6fe3dSLisandro Dalcin   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
4954fbdbba38SShri Abhyankar   PetscFunctionReturn(0);
4955fbdbba38SShri Abhyankar }
4956fbdbba38SShri Abhyankar 
4957ace3abfcSBarry Smith PetscErrorCode MatEqual_SeqAIJ(Mat A,Mat B,PetscBool * flg)
49587264ac53SSatish Balay {
49597264ac53SSatish Balay   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data,*b = (Mat_SeqAIJ*)B->data;
4960dfbe8321SBarry Smith   PetscErrorCode ierr;
4961eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4962eeffb40dSHong Zhang   PetscInt k;
4963eeffb40dSHong Zhang #endif
49647264ac53SSatish Balay 
49653a40ed3dSBarry Smith   PetscFunctionBegin;
4966bfeeae90SHong Zhang   /* If the  matrix dimensions are not equal,or no of nonzeros */
4967d0f46423SBarry Smith   if ((A->rmap->n != B->rmap->n) || (A->cmap->n != B->cmap->n) ||(a->nz != b->nz)) {
4968ca44d042SBarry Smith     *flg = PETSC_FALSE;
4969ca44d042SBarry Smith     PetscFunctionReturn(0);
4970bcd2baecSBarry Smith   }
49717264ac53SSatish Balay 
49727264ac53SSatish Balay   /* if the a->i are the same */
4973580bdb30SBarry Smith   ierr = PetscArraycmp(a->i,b->i,A->rmap->n+1,flg);CHKERRQ(ierr);
4974abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
49757264ac53SSatish Balay 
49767264ac53SSatish Balay   /* if a->j are the same */
4977580bdb30SBarry Smith   ierr = PetscArraycmp(a->j,b->j,a->nz,flg);CHKERRQ(ierr);
4978abc0a331SBarry Smith   if (!*flg) PetscFunctionReturn(0);
4979bcd2baecSBarry Smith 
4980bcd2baecSBarry Smith   /* if a->a are the same */
4981eeffb40dSHong Zhang #if defined(PETSC_USE_COMPLEX)
4982eeffb40dSHong Zhang   for (k=0; k<a->nz; k++) {
4983eeffb40dSHong Zhang     if (PetscRealPart(a->a[k]) != PetscRealPart(b->a[k]) || PetscImaginaryPart(a->a[k]) != PetscImaginaryPart(b->a[k])) {
4984eeffb40dSHong Zhang       *flg = PETSC_FALSE;
49853a40ed3dSBarry Smith       PetscFunctionReturn(0);
4986eeffb40dSHong Zhang     }
4987eeffb40dSHong Zhang   }
4988eeffb40dSHong Zhang #else
4989580bdb30SBarry Smith   ierr = PetscArraycmp(a->a,b->a,a->nz,flg);CHKERRQ(ierr);
4990eeffb40dSHong Zhang #endif
4991eeffb40dSHong Zhang   PetscFunctionReturn(0);
49927264ac53SSatish Balay }
499336db0b34SBarry Smith 
499405869f15SSatish Balay /*@
499536db0b34SBarry Smith      MatCreateSeqAIJWithArrays - Creates an sequential AIJ matrix using matrix elements (in CSR format)
499636db0b34SBarry Smith               provided by the user.
499736db0b34SBarry Smith 
4998d083f849SBarry Smith       Collective
499936db0b34SBarry Smith 
500036db0b34SBarry Smith    Input Parameters:
500136db0b34SBarry Smith +   comm - must be an MPI communicator of size 1
500236db0b34SBarry Smith .   m - number of rows
500336db0b34SBarry Smith .   n - number of columns
5004483a2f95SBarry Smith .   i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix
500536db0b34SBarry Smith .   j - column indices
500636db0b34SBarry Smith -   a - matrix values
500736db0b34SBarry Smith 
500836db0b34SBarry Smith    Output Parameter:
500936db0b34SBarry Smith .   mat - the matrix
501036db0b34SBarry Smith 
501136db0b34SBarry Smith    Level: intermediate
501236db0b34SBarry Smith 
501336db0b34SBarry Smith    Notes:
50140551d7c0SBarry Smith        The i, j, and a arrays are not copied by this routine, the user must free these arrays
5015292fb18eSBarry Smith     once the matrix is destroyed and not before
501636db0b34SBarry Smith 
501736db0b34SBarry Smith        You cannot set new nonzero locations into this matrix, that will generate an error.
501836db0b34SBarry Smith 
5019bfeeae90SHong Zhang        The i and j indices are 0 based
502036db0b34SBarry Smith 
5021a4552177SSatish Balay        The format which is used for the sparse matrix input, is equivalent to a
5022a4552177SSatish Balay     row-major ordering.. i.e for the following matrix, the input data expected is
50238eef79e4SBarry Smith     as shown
5024a4552177SSatish Balay 
50258eef79e4SBarry Smith $        1 0 0
50268eef79e4SBarry Smith $        2 0 3
50278eef79e4SBarry Smith $        4 5 6
50288eef79e4SBarry Smith $
50298eef79e4SBarry Smith $        i =  {0,1,3,6}  [size = nrow+1  = 3+1]
50308eef79e4SBarry Smith $        j =  {0,0,2,0,1,2}  [size = 6]; values must be sorted for each row
50318eef79e4SBarry Smith $        v =  {1,2,3,4,5,6}  [size = 6]
5032a4552177SSatish Balay 
503369b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateMPIAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
503436db0b34SBarry Smith 
503536db0b34SBarry Smith @*/
5036c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat)
503736db0b34SBarry Smith {
5038dfbe8321SBarry Smith   PetscErrorCode ierr;
5039cbcfb4deSHong Zhang   PetscInt       ii;
504036db0b34SBarry Smith   Mat_SeqAIJ     *aij;
5041cbcfb4deSHong Zhang   PetscInt jj;
504236db0b34SBarry Smith 
504336db0b34SBarry Smith   PetscFunctionBegin;
504441096f02SStefano Zampini   if (m > 0 && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0");
5045f69a0ea3SMatthew Knepley   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
5046f69a0ea3SMatthew Knepley   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
5047a2f3521dSMark F. Adams   /* ierr = MatSetBlockSizes(*mat,,);CHKERRQ(ierr); */
5048ab93d7beSBarry Smith   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
5049f4259b30SLisandro Dalcin   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,MAT_SKIP_ALLOCATION,NULL);CHKERRQ(ierr);
5050ab93d7beSBarry Smith   aij  = (Mat_SeqAIJ*)(*mat)->data;
5051071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->imax);CHKERRQ(ierr);
5052071fcb05SBarry Smith   ierr = PetscMalloc1(m,&aij->ilen);CHKERRQ(ierr);
5053ab93d7beSBarry Smith 
505436db0b34SBarry Smith   aij->i            = i;
505536db0b34SBarry Smith   aij->j            = j;
505636db0b34SBarry Smith   aij->a            = a;
505736db0b34SBarry Smith   aij->singlemalloc = PETSC_FALSE;
505836db0b34SBarry Smith   aij->nonew        = -1;             /*this indicates that inserting a new value in the matrix that generates a new nonzero is an error*/
5059e6b907acSBarry Smith   aij->free_a       = PETSC_FALSE;
5060e6b907acSBarry Smith   aij->free_ij      = PETSC_FALSE;
506136db0b34SBarry Smith 
506236db0b34SBarry Smith   for (ii=0; ii<m; ii++) {
506336db0b34SBarry Smith     aij->ilen[ii] = aij->imax[ii] = i[ii+1] - i[ii];
506476bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
506560e0710aSBarry Smith       if (i[ii+1] - i[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row length in i (row indices) row = %D length = %D",ii,i[ii+1] - i[ii]);
50669985e31cSBarry Smith       for (jj=i[ii]+1; jj<i[ii+1]; jj++) {
5067a061629eSStefano Zampini         if (j[jj] < j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is not sorted",jj-i[ii],j[jj],ii);
5068a061629eSStefano Zampini         if (j[jj] == j[jj-1]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column entry number %D (actual column %D) in row %D is identical to previous entry",jj-i[ii],j[jj],ii);
50699985e31cSBarry Smith       }
507036db0b34SBarry Smith     }
507176bd3646SJed Brown   }
507276bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
507336db0b34SBarry Smith     for (ii=0; ii<aij->i[m]; ii++) {
507460e0710aSBarry Smith       if (j[ii] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column index at location = %D index = %D",ii,j[ii]);
507560e0710aSBarry Smith       if (j[ii] > n - 1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column index to large at location = %D index = %D",ii,j[ii]);
507636db0b34SBarry Smith     }
507776bd3646SJed Brown   }
507836db0b34SBarry Smith 
5079b65db4caSBarry Smith   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5080b65db4caSBarry Smith   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
508136db0b34SBarry Smith   PetscFunctionReturn(0);
508236db0b34SBarry Smith }
508380ef6e79SMatthew G Knepley /*@C
5084d021a1c5SVictor Minden      MatCreateSeqAIJFromTriple - Creates an sequential AIJ matrix using matrix elements (in COO format)
50858a0b0e6bSVictor Minden               provided by the user.
50868a0b0e6bSVictor Minden 
5087d083f849SBarry Smith       Collective
50888a0b0e6bSVictor Minden 
50898a0b0e6bSVictor Minden    Input Parameters:
50908a0b0e6bSVictor Minden +   comm - must be an MPI communicator of size 1
50918a0b0e6bSVictor Minden .   m   - number of rows
50928a0b0e6bSVictor Minden .   n   - number of columns
50938a0b0e6bSVictor Minden .   i   - row indices
50948a0b0e6bSVictor Minden .   j   - column indices
50951230e6d1SVictor Minden .   a   - matrix values
50961230e6d1SVictor Minden .   nz  - number of nonzeros
50971230e6d1SVictor Minden -   idx - 0 or 1 based
50988a0b0e6bSVictor Minden 
50998a0b0e6bSVictor Minden    Output Parameter:
51008a0b0e6bSVictor Minden .   mat - the matrix
51018a0b0e6bSVictor Minden 
51028a0b0e6bSVictor Minden    Level: intermediate
51038a0b0e6bSVictor Minden 
51048a0b0e6bSVictor Minden    Notes:
51058a0b0e6bSVictor Minden        The i and j indices are 0 based
51068a0b0e6bSVictor Minden 
51078a0b0e6bSVictor Minden        The format which is used for the sparse matrix input, is equivalent to a
51088a0b0e6bSVictor Minden     row-major ordering.. i.e for the following matrix, the input data expected is
51098a0b0e6bSVictor Minden     as shown:
51108a0b0e6bSVictor Minden 
51118a0b0e6bSVictor Minden         1 0 0
51128a0b0e6bSVictor Minden         2 0 3
51138a0b0e6bSVictor Minden         4 5 6
51148a0b0e6bSVictor Minden 
51158a0b0e6bSVictor Minden         i =  {0,1,1,2,2,2}
51168a0b0e6bSVictor Minden         j =  {0,0,2,0,1,2}
51178a0b0e6bSVictor Minden         v =  {1,2,3,4,5,6}
51188a0b0e6bSVictor Minden 
511969b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateAIJ(), MatCreateSeqAIJ(), MatCreateSeqAIJWithArrays(), MatMPIAIJSetPreallocationCSR()
51208a0b0e6bSVictor Minden 
51218a0b0e6bSVictor Minden @*/
5122c3c607ccSBarry Smith PetscErrorCode  MatCreateSeqAIJFromTriple(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt i[],PetscInt j[],PetscScalar a[],Mat *mat,PetscInt nz,PetscBool idx)
51238a0b0e6bSVictor Minden {
51248a0b0e6bSVictor Minden   PetscErrorCode ierr;
5125d021a1c5SVictor Minden   PetscInt       ii, *nnz, one = 1,row,col;
51268a0b0e6bSVictor Minden 
51278a0b0e6bSVictor Minden   PetscFunctionBegin;
51281795a4d1SJed Brown   ierr = PetscCalloc1(m,&nnz);CHKERRQ(ierr);
51291230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
5130c8d679ebSHong Zhang     nnz[i[ii] - !!idx] += 1;
51311230e6d1SVictor Minden   }
51328a0b0e6bSVictor Minden   ierr = MatCreate(comm,mat);CHKERRQ(ierr);
51338a0b0e6bSVictor Minden   ierr = MatSetSizes(*mat,m,n,m,n);CHKERRQ(ierr);
51348a0b0e6bSVictor Minden   ierr = MatSetType(*mat,MATSEQAIJ);CHKERRQ(ierr);
51351230e6d1SVictor Minden   ierr = MatSeqAIJSetPreallocation_SeqAIJ(*mat,0,nnz);CHKERRQ(ierr);
51361230e6d1SVictor Minden   for (ii = 0; ii < nz; ii++) {
51371230e6d1SVictor Minden     if (idx) {
51381230e6d1SVictor Minden       row = i[ii] - 1;
51391230e6d1SVictor Minden       col = j[ii] - 1;
51401230e6d1SVictor Minden     } else {
51411230e6d1SVictor Minden       row = i[ii];
51421230e6d1SVictor Minden       col = j[ii];
51438a0b0e6bSVictor Minden     }
51441230e6d1SVictor Minden     ierr = MatSetValues(*mat,one,&row,one,&col,&a[ii],ADD_VALUES);CHKERRQ(ierr);
51458a0b0e6bSVictor Minden   }
51468a0b0e6bSVictor Minden   ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
51478a0b0e6bSVictor Minden   ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5148d021a1c5SVictor Minden   ierr = PetscFree(nnz);CHKERRQ(ierr);
51498a0b0e6bSVictor Minden   PetscFunctionReturn(0);
51508a0b0e6bSVictor Minden }
515136db0b34SBarry Smith 
5152acf2f550SJed Brown PetscErrorCode MatSeqAIJInvalidateDiagonal(Mat A)
5153acf2f550SJed Brown {
5154acf2f550SJed Brown   Mat_SeqAIJ     *a=(Mat_SeqAIJ*)A->data;
5155acf2f550SJed Brown   PetscErrorCode ierr;
5156acf2f550SJed Brown 
5157acf2f550SJed Brown   PetscFunctionBegin;
5158acf2f550SJed Brown   a->idiagvalid  = PETSC_FALSE;
5159acf2f550SJed Brown   a->ibdiagvalid = PETSC_FALSE;
51602205254eSKarl Rupp 
5161acf2f550SJed Brown   ierr = MatSeqAIJInvalidateDiagonal_Inode(A);CHKERRQ(ierr);
5162acf2f550SJed Brown   PetscFunctionReturn(0);
5163acf2f550SJed Brown }
5164acf2f550SJed Brown 
51659c8f2541SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
51669c8f2541SHong Zhang {
51679c8f2541SHong Zhang   PetscErrorCode ierr;
51688761c3d6SHong Zhang   PetscMPIInt    size;
51699c8f2541SHong Zhang 
51709c8f2541SHong Zhang   PetscFunctionBegin;
5171ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
51727bbdc51dSHong Zhang   if (size == 1) {
51737bbdc51dSHong Zhang     if (scall == MAT_INITIAL_MATRIX) {
51747bbdc51dSHong Zhang       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
51757bbdc51dSHong Zhang     } else {
51768761c3d6SHong Zhang       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
51777bbdc51dSHong Zhang     }
51788761c3d6SHong Zhang   } else {
51799c8f2541SHong Zhang     ierr = MatCreateMPIMatConcatenateSeqMat_MPIAIJ(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
51808761c3d6SHong Zhang   }
51819c8f2541SHong Zhang   PetscFunctionReturn(0);
51829c8f2541SHong Zhang }
51839c8f2541SHong Zhang 
518481824310SBarry Smith /*
518553dd7562SDmitry Karpeev  Permute A into C's *local* index space using rowemb,colemb.
518653dd7562SDmitry Karpeev  The embedding are supposed to be injections and the above implies that the range of rowemb is a subset
518753dd7562SDmitry Karpeev  of [0,m), colemb is in [0,n).
518853dd7562SDmitry Karpeev  If pattern == DIFFERENT_NONZERO_PATTERN, C is preallocated according to A.
518953dd7562SDmitry Karpeev  */
519053dd7562SDmitry Karpeev PetscErrorCode MatSetSeqMat_SeqAIJ(Mat C,IS rowemb,IS colemb,MatStructure pattern,Mat B)
519153dd7562SDmitry Karpeev {
519253dd7562SDmitry Karpeev   /* If making this function public, change the error returned in this function away from _PLIB. */
519353dd7562SDmitry Karpeev   PetscErrorCode ierr;
519453dd7562SDmitry Karpeev   Mat_SeqAIJ     *Baij;
519553dd7562SDmitry Karpeev   PetscBool      seqaij;
519653dd7562SDmitry Karpeev   PetscInt       m,n,*nz,i,j,count;
519753dd7562SDmitry Karpeev   PetscScalar    v;
519853dd7562SDmitry Karpeev   const PetscInt *rowindices,*colindices;
519953dd7562SDmitry Karpeev 
520053dd7562SDmitry Karpeev   PetscFunctionBegin;
520153dd7562SDmitry Karpeev   if (!B) PetscFunctionReturn(0);
520253dd7562SDmitry Karpeev   /* Check to make sure the target matrix (and embeddings) are compatible with C and each other. */
52034099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)B,MATSEQAIJ,&seqaij);CHKERRQ(ierr);
520453dd7562SDmitry Karpeev   if (!seqaij) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is of wrong type");
520553dd7562SDmitry Karpeev   if (rowemb) {
520653dd7562SDmitry Karpeev     ierr = ISGetLocalSize(rowemb,&m);CHKERRQ(ierr);
520753dd7562SDmitry Karpeev     if (m != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Row IS of size %D is incompatible with matrix row size %D",m,B->rmap->n);
520853dd7562SDmitry Karpeev   } else {
52096c4ed002SBarry Smith     if (C->rmap->n != B->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is row-incompatible with the target matrix");
521053dd7562SDmitry Karpeev   }
521153dd7562SDmitry Karpeev   if (colemb) {
521253dd7562SDmitry Karpeev     ierr = ISGetLocalSize(colemb,&n);CHKERRQ(ierr);
521353dd7562SDmitry Karpeev     if (n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Diag col IS of size %D is incompatible with input matrix col size %D",n,B->cmap->n);
521453dd7562SDmitry Karpeev   } else {
521553dd7562SDmitry Karpeev     if (C->cmap->n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Input matrix is col-incompatible with the target matrix");
521653dd7562SDmitry Karpeev   }
521753dd7562SDmitry Karpeev 
521853dd7562SDmitry Karpeev   Baij = (Mat_SeqAIJ*)(B->data);
521953dd7562SDmitry Karpeev   if (pattern == DIFFERENT_NONZERO_PATTERN) {
522053dd7562SDmitry Karpeev     ierr = PetscMalloc1(B->rmap->n,&nz);CHKERRQ(ierr);
522153dd7562SDmitry Karpeev     for (i=0; i<B->rmap->n; i++) {
522253dd7562SDmitry Karpeev       nz[i] = Baij->i[i+1] - Baij->i[i];
522353dd7562SDmitry Karpeev     }
522453dd7562SDmitry Karpeev     ierr = MatSeqAIJSetPreallocation(C,0,nz);CHKERRQ(ierr);
522553dd7562SDmitry Karpeev     ierr = PetscFree(nz);CHKERRQ(ierr);
522653dd7562SDmitry Karpeev   }
522753dd7562SDmitry Karpeev   if (pattern == SUBSET_NONZERO_PATTERN) {
522853dd7562SDmitry Karpeev     ierr = MatZeroEntries(C);CHKERRQ(ierr);
522953dd7562SDmitry Karpeev   }
523053dd7562SDmitry Karpeev   count = 0;
523153dd7562SDmitry Karpeev   rowindices = NULL;
523253dd7562SDmitry Karpeev   colindices = NULL;
523353dd7562SDmitry Karpeev   if (rowemb) {
523453dd7562SDmitry Karpeev     ierr = ISGetIndices(rowemb,&rowindices);CHKERRQ(ierr);
523553dd7562SDmitry Karpeev   }
523653dd7562SDmitry Karpeev   if (colemb) {
523753dd7562SDmitry Karpeev     ierr = ISGetIndices(colemb,&colindices);CHKERRQ(ierr);
523853dd7562SDmitry Karpeev   }
523953dd7562SDmitry Karpeev   for (i=0; i<B->rmap->n; i++) {
524053dd7562SDmitry Karpeev     PetscInt row;
524153dd7562SDmitry Karpeev     row = i;
524253dd7562SDmitry Karpeev     if (rowindices) row = rowindices[i];
524353dd7562SDmitry Karpeev     for (j=Baij->i[i]; j<Baij->i[i+1]; j++) {
524453dd7562SDmitry Karpeev       PetscInt col;
524553dd7562SDmitry Karpeev       col  = Baij->j[count];
524653dd7562SDmitry Karpeev       if (colindices) col = colindices[col];
524753dd7562SDmitry Karpeev       v    = Baij->a[count];
524853dd7562SDmitry Karpeev       ierr = MatSetValues(C,1,&row,1,&col,&v,INSERT_VALUES);CHKERRQ(ierr);
524953dd7562SDmitry Karpeev       ++count;
525053dd7562SDmitry Karpeev     }
525153dd7562SDmitry Karpeev   }
525253dd7562SDmitry Karpeev   /* FIXME: set C's nonzerostate correctly. */
525353dd7562SDmitry Karpeev   /* Assembly for C is necessary. */
525453dd7562SDmitry Karpeev   C->preallocated = PETSC_TRUE;
525553dd7562SDmitry Karpeev   C->assembled     = PETSC_TRUE;
525653dd7562SDmitry Karpeev   C->was_assembled = PETSC_FALSE;
525753dd7562SDmitry Karpeev   PetscFunctionReturn(0);
525853dd7562SDmitry Karpeev }
525953dd7562SDmitry Karpeev 
52604099cc6bSBarry Smith PetscFunctionList MatSeqAIJList = NULL;
52614099cc6bSBarry Smith 
52624099cc6bSBarry Smith /*@C
52634099cc6bSBarry Smith    MatSeqAIJSetType - Converts a MATSEQAIJ matrix to a subtype
52644099cc6bSBarry Smith 
52654099cc6bSBarry Smith    Collective on Mat
52664099cc6bSBarry Smith 
52674099cc6bSBarry Smith    Input Parameters:
52684099cc6bSBarry Smith +  mat      - the matrix object
52694099cc6bSBarry Smith -  matype   - matrix type
52704099cc6bSBarry Smith 
52714099cc6bSBarry Smith    Options Database Key:
52724099cc6bSBarry Smith .  -mat_seqai_type  <method> - for example seqaijcrl
52734099cc6bSBarry Smith 
52744099cc6bSBarry Smith   Level: intermediate
52754099cc6bSBarry Smith 
52764099cc6bSBarry Smith .seealso: PCSetType(), VecSetType(), MatCreate(), MatType, Mat
52774099cc6bSBarry Smith @*/
52784099cc6bSBarry Smith PetscErrorCode  MatSeqAIJSetType(Mat mat, MatType matype)
52794099cc6bSBarry Smith {
5280fd9d3c67SJed Brown   PetscErrorCode ierr,(*r)(Mat,MatType,MatReuse,Mat*);
52814099cc6bSBarry Smith   PetscBool      sametype;
52824099cc6bSBarry Smith 
52834099cc6bSBarry Smith   PetscFunctionBegin;
52844099cc6bSBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
52854099cc6bSBarry Smith   ierr = PetscObjectTypeCompare((PetscObject)mat,matype,&sametype);CHKERRQ(ierr);
52864099cc6bSBarry Smith   if (sametype) PetscFunctionReturn(0);
52874099cc6bSBarry Smith 
52884099cc6bSBarry Smith   ierr =  PetscFunctionListFind(MatSeqAIJList,matype,&r);CHKERRQ(ierr);
52894099cc6bSBarry Smith   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown Mat type given: %s",matype);
52904099cc6bSBarry Smith   ierr = (*r)(mat,matype,MAT_INPLACE_MATRIX,&mat);CHKERRQ(ierr);
52914099cc6bSBarry Smith   PetscFunctionReturn(0);
52924099cc6bSBarry Smith }
52934099cc6bSBarry Smith 
52944099cc6bSBarry Smith /*@C
52954099cc6bSBarry Smith   MatSeqAIJRegister -  - Adds a new sub-matrix type for sequential AIJ matrices
52964099cc6bSBarry Smith 
52974099cc6bSBarry Smith    Not Collective
52984099cc6bSBarry Smith 
52994099cc6bSBarry Smith    Input Parameters:
53004099cc6bSBarry Smith +  name - name of a new user-defined matrix type, for example MATSEQAIJCRL
53014099cc6bSBarry Smith -  function - routine to convert to subtype
53024099cc6bSBarry Smith 
53034099cc6bSBarry Smith    Notes:
53044099cc6bSBarry Smith    MatSeqAIJRegister() may be called multiple times to add several user-defined solvers.
53054099cc6bSBarry Smith 
53064099cc6bSBarry Smith    Then, your matrix can be chosen with the procedural interface at runtime via the option
53074099cc6bSBarry Smith $     -mat_seqaij_type my_mat
53084099cc6bSBarry Smith 
53094099cc6bSBarry Smith    Level: advanced
53104099cc6bSBarry Smith 
53114099cc6bSBarry Smith .seealso: MatSeqAIJRegisterAll()
53124099cc6bSBarry Smith 
53134099cc6bSBarry Smith   Level: advanced
53144099cc6bSBarry Smith @*/
5315388d47a6SSatish Balay PetscErrorCode  MatSeqAIJRegister(const char sname[],PetscErrorCode (*function)(Mat,MatType,MatReuse,Mat *))
53164099cc6bSBarry Smith {
53174099cc6bSBarry Smith   PetscErrorCode ierr;
53184099cc6bSBarry Smith 
53194099cc6bSBarry Smith   PetscFunctionBegin;
53209cc31a68SJed Brown   ierr = MatInitializePackage();CHKERRQ(ierr);
53214099cc6bSBarry Smith   ierr = PetscFunctionListAdd(&MatSeqAIJList,sname,function);CHKERRQ(ierr);
53224099cc6bSBarry Smith   PetscFunctionReturn(0);
53234099cc6bSBarry Smith }
53244099cc6bSBarry Smith 
53254099cc6bSBarry Smith PetscBool MatSeqAIJRegisterAllCalled = PETSC_FALSE;
53264099cc6bSBarry Smith 
53274099cc6bSBarry Smith /*@C
53284099cc6bSBarry Smith   MatSeqAIJRegisterAll - Registers all of the matrix subtypes of SeqAIJ
53294099cc6bSBarry Smith 
53304099cc6bSBarry Smith   Not Collective
53314099cc6bSBarry Smith 
53324099cc6bSBarry Smith   Level: advanced
53334099cc6bSBarry Smith 
5334f719121fSJed Brown   Developers Note: CUSPARSE does not yet support the MatConvert_SeqAIJ..() paradigm and thus cannot be registered here
53354099cc6bSBarry Smith 
53364099cc6bSBarry Smith .seealso:  MatRegisterAll(), MatSeqAIJRegister()
53374099cc6bSBarry Smith @*/
53384099cc6bSBarry Smith PetscErrorCode  MatSeqAIJRegisterAll(void)
53394099cc6bSBarry Smith {
53404099cc6bSBarry Smith   PetscErrorCode ierr;
53414099cc6bSBarry Smith 
53424099cc6bSBarry Smith   PetscFunctionBegin;
53434099cc6bSBarry Smith   if (MatSeqAIJRegisterAllCalled) PetscFunctionReturn(0);
53444099cc6bSBarry Smith   MatSeqAIJRegisterAllCalled = PETSC_TRUE;
53454099cc6bSBarry Smith 
53464099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJCRL,      MatConvert_SeqAIJ_SeqAIJCRL);CHKERRQ(ierr);
53474099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATSEQAIJPERM,     MatConvert_SeqAIJ_SeqAIJPERM);CHKERRQ(ierr);
53484dfdc2d9SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJSELL,     MatConvert_SeqAIJ_SeqAIJSELL);CHKERRQ(ierr);
53499779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE)
53506b62b571SRichard Tran Mills   ierr = MatSeqAIJRegister(MATSEQAIJMKL,      MatConvert_SeqAIJ_SeqAIJMKL);CHKERRQ(ierr);
5351485f9817SRichard Tran Mills #endif
53524099cc6bSBarry Smith #if defined(PETSC_HAVE_VIENNACL) && defined(PETSC_HAVE_VIENNACL_NO_CUDA)
53534099cc6bSBarry Smith   ierr = MatSeqAIJRegister(MATMPIAIJVIENNACL, MatConvert_SeqAIJ_SeqAIJViennaCL);CHKERRQ(ierr);
53544099cc6bSBarry Smith #endif
53554099cc6bSBarry Smith   PetscFunctionReturn(0);
53564099cc6bSBarry Smith }
535753dd7562SDmitry Karpeev 
535853dd7562SDmitry Karpeev /*
535981824310SBarry Smith     Special version for direct calls from Fortran
536081824310SBarry Smith */
5361af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
536281824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS)
536381824310SBarry Smith #define matsetvaluesseqaij_ MATSETVALUESSEQAIJ
536481824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
536581824310SBarry Smith #define matsetvaluesseqaij_ matsetvaluesseqaij
536681824310SBarry Smith #endif
536781824310SBarry Smith 
536881824310SBarry Smith /* Change these macros so can be used in void function */
536981824310SBarry Smith #undef CHKERRQ
5370ce94432eSBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PetscObjectComm((PetscObject)A),ierr)
537181824310SBarry Smith #undef SETERRQ2
5372e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr)
53734994cf47SJed Brown #undef SETERRQ3
53744994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr)
537581824310SBarry Smith 
537619caf8f3SSatish Balay PETSC_EXTERN void matsetvaluesseqaij_(Mat *AA,PetscInt *mm,const PetscInt im[],PetscInt *nn,const PetscInt in[],const PetscScalar v[],InsertMode *isis, PetscErrorCode *_ierr)
537781824310SBarry Smith {
537881824310SBarry Smith   Mat            A  = *AA;
537981824310SBarry Smith   PetscInt       m  = *mm, n = *nn;
538081824310SBarry Smith   InsertMode     is = *isis;
538181824310SBarry Smith   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
538281824310SBarry Smith   PetscInt       *rp,k,low,high,t,ii,row,nrow,i,col,l,rmax,N;
538381824310SBarry Smith   PetscInt       *imax,*ai,*ailen;
538481824310SBarry Smith   PetscErrorCode ierr;
538581824310SBarry Smith   PetscInt       *aj,nonew = a->nonew,lastcol = -1;
538654f21887SBarry Smith   MatScalar      *ap,value,*aa;
5387ace3abfcSBarry Smith   PetscBool      ignorezeroentries = a->ignorezeroentries;
5388ace3abfcSBarry Smith   PetscBool      roworiented       = a->roworiented;
538981824310SBarry Smith 
539081824310SBarry Smith   PetscFunctionBegin;
53914994cf47SJed Brown   MatCheckPreallocated(A,1);
539281824310SBarry Smith   imax  = a->imax;
539381824310SBarry Smith   ai    = a->i;
539481824310SBarry Smith   ailen = a->ilen;
539581824310SBarry Smith   aj    = a->j;
539681824310SBarry Smith   aa    = a->a;
539781824310SBarry Smith 
539881824310SBarry Smith   for (k=0; k<m; k++) { /* loop over added rows */
539981824310SBarry Smith     row = im[k];
540081824310SBarry Smith     if (row < 0) continue;
5401cf9c20a2SJed Brown     if (PetscUnlikelyDebug(row >= A->rmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Row too large");
540281824310SBarry Smith     rp   = aj + ai[row]; ap = aa + ai[row];
540381824310SBarry Smith     rmax = imax[row]; nrow = ailen[row];
540481824310SBarry Smith     low  = 0;
540581824310SBarry Smith     high = nrow;
540681824310SBarry Smith     for (l=0; l<n; l++) { /* loop over added columns */
540781824310SBarry Smith       if (in[l] < 0) continue;
5408cf9c20a2SJed Brown       if (PetscUnlikelyDebug(in[l] >= A->cmap->n)) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Column too large");
540981824310SBarry Smith       col = in[l];
54102205254eSKarl Rupp       if (roworiented) value = v[l + k*n];
54112205254eSKarl Rupp       else value = v[k + l*m];
54122205254eSKarl Rupp 
541381824310SBarry Smith       if (value == 0.0 && ignorezeroentries && (is == ADD_VALUES)) continue;
541481824310SBarry Smith 
54152205254eSKarl Rupp       if (col <= lastcol) low = 0;
54162205254eSKarl Rupp       else high = nrow;
541781824310SBarry Smith       lastcol = col;
541881824310SBarry Smith       while (high-low > 5) {
541981824310SBarry Smith         t = (low+high)/2;
542081824310SBarry Smith         if (rp[t] > col) high = t;
542181824310SBarry Smith         else             low  = t;
542281824310SBarry Smith       }
542381824310SBarry Smith       for (i=low; i<high; i++) {
542481824310SBarry Smith         if (rp[i] > col) break;
542581824310SBarry Smith         if (rp[i] == col) {
542681824310SBarry Smith           if (is == ADD_VALUES) ap[i] += value;
542781824310SBarry Smith           else                  ap[i] = value;
542881824310SBarry Smith           goto noinsert;
542981824310SBarry Smith         }
543081824310SBarry Smith       }
543181824310SBarry Smith       if (value == 0.0 && ignorezeroentries) goto noinsert;
543281824310SBarry Smith       if (nonew == 1) goto noinsert;
5433ce94432eSBarry Smith       if (nonew == -1) SETERRABORT(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero in the matrix");
5434fef13f97SBarry Smith       MatSeqXAIJReallocateAIJ(A,A->rmap->n,1,nrow,row,col,rmax,aa,ai,aj,rp,ap,imax,nonew,MatScalar);
543581824310SBarry Smith       N = nrow++ - 1; a->nz++; high++;
543681824310SBarry Smith       /* shift up all the later entries in this row */
543781824310SBarry Smith       for (ii=N; ii>=i; ii--) {
543881824310SBarry Smith         rp[ii+1] = rp[ii];
543981824310SBarry Smith         ap[ii+1] = ap[ii];
544081824310SBarry Smith       }
544181824310SBarry Smith       rp[i] = col;
544281824310SBarry Smith       ap[i] = value;
5443e56f5c9eSBarry Smith       A->nonzerostate++;
544481824310SBarry Smith noinsert:;
544581824310SBarry Smith       low = i + 1;
544681824310SBarry Smith     }
544781824310SBarry Smith     ailen[row] = nrow;
544881824310SBarry Smith   }
544981824310SBarry Smith   PetscFunctionReturnVoid();
545081824310SBarry Smith }
5451