xref: /petsc/src/mat/impls/dense/seq/dense.c (revision dd169d643cbf4b5f50ca99c97eb8f9235c6ca078)
1 
2 /*
3      Defines the basic matrix operations for sequential dense.
4 */
5 
6 #include <../src/mat/impls/dense/seq/dense.h> /*I "petscmat.h" I*/
7 #include <petscblaslapack.h>
8 
9 #include <../src/mat/impls/aij/seq/aij.h>
10 
11 static PetscErrorCode MatSeqDenseSymmetrize_Private(Mat A, PetscBool hermitian)
12 {
13   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
14   PetscInt      j, k, n = A->rmap->n;
15 
16   PetscFunctionBegin;
17   if (A->rmap->n != A->cmap->n) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Cannot symmetrize a rectangular matrix");
18   if (!hermitian) {
19     for (k=0;k<n;k++) {
20       for (j=k;j<n;j++) {
21         mat->v[j*mat->lda + k] = mat->v[k*mat->lda + j];
22       }
23     }
24   } else {
25     for (k=0;k<n;k++) {
26       for (j=k;j<n;j++) {
27         mat->v[j*mat->lda + k] = PetscConj(mat->v[k*mat->lda + j]);
28       }
29     }
30   }
31   PetscFunctionReturn(0);
32 }
33 
34 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat A)
35 {
36 #if defined(PETSC_MISSING_LAPACK_POTRF)
37   PetscFunctionBegin;
38   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable.");
39 #else
40   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
41   PetscErrorCode ierr;
42   PetscBLASInt   info,n;
43 
44   PetscFunctionBegin;
45   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
46   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
47   if (A->factortype == MAT_FACTOR_LU) {
48     if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present");
49     if (!mat->fwork) {
50       mat->lfwork = n;
51       ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr);
52       ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr);
53     }
54     PetscStackCallBLAS("LAPACKgetri",LAPACKgetri_(&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
55     ierr = PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);CHKERRQ(ierr); /* TODO CHECK FLOPS */
56   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
57     if (A->spd) {
58       PetscStackCallBLAS("LAPACKpotri",LAPACKpotri_("L",&n,mat->v,&mat->lda,&info));
59       ierr = MatSeqDenseSymmetrize_Private(A,PETSC_TRUE);CHKERRQ(ierr);
60 #if defined (PETSC_USE_COMPLEX)
61     } else if (A->hermitian) {
62       if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present");
63       if (!mat->fwork) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Fwork not present");
64       PetscStackCallBLAS("LAPACKhetri",LAPACKhetri_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&info));
65       ierr = MatSeqDenseSymmetrize_Private(A,PETSC_TRUE);CHKERRQ(ierr);
66 #endif
67     } else { /* symmetric case */
68       if (!mat->pivots) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Pivots not present");
69       if (!mat->fwork) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Fwork not present");
70       PetscStackCallBLAS("LAPACKsytri",LAPACKsytri_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&info));
71       ierr = MatSeqDenseSymmetrize_Private(A,PETSC_FALSE);CHKERRQ(ierr);
72     }
73     if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_CH_ZRPVT,"Bad Inversion: zero pivot in row %D",(PetscInt)info-1);
74     ierr = PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);CHKERRQ(ierr); /* TODO CHECK FLOPS */
75   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
76 #endif
77 
78   A->ops->solve             = NULL;
79   A->ops->matsolve          = NULL;
80   A->ops->solvetranspose    = NULL;
81   A->ops->matsolvetranspose = NULL;
82   A->ops->solveadd          = NULL;
83   A->ops->solvetransposeadd = NULL;
84   A->factortype             = MAT_FACTOR_NONE;
85   ierr                      = PetscFree(A->solvertype);CHKERRQ(ierr);
86   PetscFunctionReturn(0);
87 }
88 
89 PetscErrorCode MatZeroRowsColumns_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
90 {
91   PetscErrorCode    ierr;
92   Mat_SeqDense      *l = (Mat_SeqDense*)A->data;
93   PetscInt          m  = l->lda, n = A->cmap->n,r = A->rmap->n, i,j;
94   PetscScalar       *slot,*bb;
95   const PetscScalar *xx;
96 
97   PetscFunctionBegin;
98 #if defined(PETSC_USE_DEBUG)
99   for (i=0; i<N; i++) {
100     if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed");
101     if (rows[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested to be zeroed greater than or equal number of rows %D",rows[i],A->rmap->n);
102     if (rows[i] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Col %D requested to be zeroed greater than or equal number of cols %D",rows[i],A->cmap->n);
103   }
104 #endif
105 
106   /* fix right hand side if needed */
107   if (x && b) {
108     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
109     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
110     for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]];
111     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
112     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
113   }
114 
115   for (i=0; i<N; i++) {
116     slot = l->v + rows[i]*m;
117     ierr = PetscMemzero(slot,r*sizeof(PetscScalar));CHKERRQ(ierr);
118   }
119   for (i=0; i<N; i++) {
120     slot = l->v + rows[i];
121     for (j=0; j<n; j++) { *slot = 0.0; slot += m;}
122   }
123   if (diag != 0.0) {
124     if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices");
125     for (i=0; i<N; i++) {
126       slot  = l->v + (m+1)*rows[i];
127       *slot = diag;
128     }
129   }
130   PetscFunctionReturn(0);
131 }
132 
133 PetscErrorCode MatPtAPNumeric_SeqDense_SeqDense(Mat A,Mat P,Mat C)
134 {
135   Mat_SeqDense   *c = (Mat_SeqDense*)(C->data);
136   PetscErrorCode ierr;
137 
138   PetscFunctionBegin;
139   ierr = MatMatMultNumeric_SeqDense_SeqDense(A,P,c->ptapwork);CHKERRQ(ierr);
140   ierr = MatTransposeMatMultNumeric_SeqDense_SeqDense(P,c->ptapwork,C);CHKERRQ(ierr);
141   PetscFunctionReturn(0);
142 }
143 
144 PetscErrorCode MatPtAPSymbolic_SeqDense_SeqDense(Mat A,Mat P,PetscReal fill,Mat *C)
145 {
146   Mat_SeqDense   *c;
147   PetscErrorCode ierr;
148 
149   PetscFunctionBegin;
150   ierr = MatCreateSeqDense(PetscObjectComm((PetscObject)A),P->cmap->N,P->cmap->N,NULL,C);CHKERRQ(ierr);
151   c = (Mat_SeqDense*)((*C)->data);
152   ierr = MatCreateSeqDense(PetscObjectComm((PetscObject)A),A->rmap->N,P->cmap->N,NULL,&c->ptapwork);CHKERRQ(ierr);
153   PetscFunctionReturn(0);
154 }
155 
156 PETSC_INTERN PetscErrorCode MatPtAP_SeqDense_SeqDense(Mat A,Mat P,MatReuse reuse,PetscReal fill,Mat *C)
157 {
158   PetscErrorCode ierr;
159 
160   PetscFunctionBegin;
161   if (reuse == MAT_INITIAL_MATRIX) {
162     ierr = MatPtAPSymbolic_SeqDense_SeqDense(A,P,fill,C);CHKERRQ(ierr);
163   }
164   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
165   ierr = (*(*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
166   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
167   PetscFunctionReturn(0);
168 }
169 
170 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
171 {
172   Mat            B = NULL;
173   Mat_SeqAIJ     *a = (Mat_SeqAIJ*)A->data;
174   Mat_SeqDense   *b;
175   PetscErrorCode ierr;
176   PetscInt       *ai=a->i,*aj=a->j,m=A->rmap->N,n=A->cmap->N,i;
177   MatScalar      *av=a->a;
178   PetscBool      isseqdense;
179 
180   PetscFunctionBegin;
181   if (reuse == MAT_REUSE_MATRIX) {
182     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
183     if (!isseqdense) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
184   }
185   if (reuse != MAT_REUSE_MATRIX) {
186     ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
187     ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr);
188     ierr = MatSetType(B,MATSEQDENSE);CHKERRQ(ierr);
189     ierr = MatSeqDenseSetPreallocation(B,NULL);CHKERRQ(ierr);
190     b    = (Mat_SeqDense*)(B->data);
191   } else {
192     b    = (Mat_SeqDense*)((*newmat)->data);
193     ierr = PetscMemzero(b->v,m*n*sizeof(PetscScalar));CHKERRQ(ierr);
194   }
195   for (i=0; i<m; i++) {
196     PetscInt j;
197     for (j=0;j<ai[1]-ai[0];j++) {
198       b->v[*aj*m+i] = *av;
199       aj++;
200       av++;
201     }
202     ai++;
203   }
204 
205   if (reuse == MAT_INPLACE_MATRIX) {
206     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
207     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
208     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
209   } else {
210     if (B) *newmat = B;
211     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
212     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
213   }
214   PetscFunctionReturn(0);
215 }
216 
217 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
218 {
219   Mat            B;
220   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
221   PetscErrorCode ierr;
222   PetscInt       i, j;
223   PetscInt       *rows, *nnz;
224   MatScalar      *aa = a->v, *vals;
225 
226   PetscFunctionBegin;
227   ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
228   ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
229   ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
230   ierr = PetscCalloc3(A->rmap->n,&rows,A->rmap->n,&nnz,A->rmap->n,&vals);CHKERRQ(ierr);
231   for (j=0; j<A->cmap->n; j++) {
232     for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || i == j) ++nnz[i];
233     aa += a->lda;
234   }
235   ierr = MatSeqAIJSetPreallocation(B,PETSC_DETERMINE,nnz);CHKERRQ(ierr);
236   aa = a->v;
237   for (j=0; j<A->cmap->n; j++) {
238     PetscInt numRows = 0;
239     for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || i == j) {rows[numRows] = i; vals[numRows++] = aa[i];}
240     ierr = MatSetValues(B,numRows,rows,1,&j,vals,INSERT_VALUES);CHKERRQ(ierr);
241     aa  += a->lda;
242   }
243   ierr = PetscFree3(rows,nnz,vals);CHKERRQ(ierr);
244   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
245   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
246 
247   if (reuse == MAT_INPLACE_MATRIX) {
248     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
249   } else {
250     *newmat = B;
251   }
252   PetscFunctionReturn(0);
253 }
254 
255 static PetscErrorCode MatAXPY_SeqDense(Mat Y,PetscScalar alpha,Mat X,MatStructure str)
256 {
257   Mat_SeqDense   *x     = (Mat_SeqDense*)X->data,*y = (Mat_SeqDense*)Y->data;
258   PetscScalar    oalpha = alpha;
259   PetscInt       j;
260   PetscBLASInt   N,m,ldax,lday,one = 1;
261   PetscErrorCode ierr;
262 
263   PetscFunctionBegin;
264   ierr = PetscBLASIntCast(X->rmap->n*X->cmap->n,&N);CHKERRQ(ierr);
265   ierr = PetscBLASIntCast(X->rmap->n,&m);CHKERRQ(ierr);
266   ierr = PetscBLASIntCast(x->lda,&ldax);CHKERRQ(ierr);
267   ierr = PetscBLASIntCast(y->lda,&lday);CHKERRQ(ierr);
268   if (ldax>m || lday>m) {
269     for (j=0; j<X->cmap->n; j++) {
270       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&m,&oalpha,x->v+j*ldax,&one,y->v+j*lday,&one));
271     }
272   } else {
273     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&N,&oalpha,x->v,&one,y->v,&one));
274   }
275   ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr);
276   ierr = PetscLogFlops(PetscMax(2*N-1,0));CHKERRQ(ierr);
277   PetscFunctionReturn(0);
278 }
279 
280 static PetscErrorCode MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info)
281 {
282   PetscInt N = A->rmap->n*A->cmap->n;
283 
284   PetscFunctionBegin;
285   info->block_size        = 1.0;
286   info->nz_allocated      = (double)N;
287   info->nz_used           = (double)N;
288   info->nz_unneeded       = (double)0;
289   info->assemblies        = (double)A->num_ass;
290   info->mallocs           = 0;
291   info->memory            = ((PetscObject)A)->mem;
292   info->fill_ratio_given  = 0;
293   info->fill_ratio_needed = 0;
294   info->factor_mallocs    = 0;
295   PetscFunctionReturn(0);
296 }
297 
298 static PetscErrorCode MatScale_SeqDense(Mat A,PetscScalar alpha)
299 {
300   Mat_SeqDense   *a     = (Mat_SeqDense*)A->data;
301   PetscScalar    oalpha = alpha;
302   PetscErrorCode ierr;
303   PetscBLASInt   one = 1,j,nz,lda;
304 
305   PetscFunctionBegin;
306   ierr = PetscBLASIntCast(a->lda,&lda);CHKERRQ(ierr);
307   if (lda>A->rmap->n) {
308     ierr = PetscBLASIntCast(A->rmap->n,&nz);CHKERRQ(ierr);
309     for (j=0; j<A->cmap->n; j++) {
310       PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&oalpha,a->v+j*lda,&one));
311     }
312   } else {
313     ierr = PetscBLASIntCast(A->rmap->n*A->cmap->n,&nz);CHKERRQ(ierr);
314     PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&oalpha,a->v,&one));
315   }
316   ierr = PetscLogFlops(nz);CHKERRQ(ierr);
317   PetscFunctionReturn(0);
318 }
319 
320 static PetscErrorCode MatIsHermitian_SeqDense(Mat A,PetscReal rtol,PetscBool  *fl)
321 {
322   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
323   PetscInt     i,j,m = A->rmap->n,N;
324   PetscScalar  *v = a->v;
325 
326   PetscFunctionBegin;
327   *fl = PETSC_FALSE;
328   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(0);
329   N = a->lda;
330 
331   for (i=0; i<m; i++) {
332     for (j=i+1; j<m; j++) {
333       if (PetscAbsScalar(v[i+j*N] - PetscConj(v[j+i*N])) > rtol) PetscFunctionReturn(0);
334     }
335   }
336   *fl = PETSC_TRUE;
337   PetscFunctionReturn(0);
338 }
339 
340 static PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi,Mat A,MatDuplicateOption cpvalues)
341 {
342   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data,*l;
343   PetscErrorCode ierr;
344   PetscInt       lda = (PetscInt)mat->lda,j,m;
345 
346   PetscFunctionBegin;
347   ierr = PetscLayoutReference(A->rmap,&newi->rmap);CHKERRQ(ierr);
348   ierr = PetscLayoutReference(A->cmap,&newi->cmap);CHKERRQ(ierr);
349   ierr = MatSeqDenseSetPreallocation(newi,NULL);CHKERRQ(ierr);
350   if (cpvalues == MAT_COPY_VALUES) {
351     l = (Mat_SeqDense*)newi->data;
352     if (lda>A->rmap->n) {
353       m = A->rmap->n;
354       for (j=0; j<A->cmap->n; j++) {
355         ierr = PetscMemcpy(l->v+j*m,mat->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr);
356       }
357     } else {
358       ierr = PetscMemcpy(l->v,mat->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));CHKERRQ(ierr);
359     }
360   }
361   newi->assembled = PETSC_TRUE;
362   PetscFunctionReturn(0);
363 }
364 
365 static PetscErrorCode MatDuplicate_SeqDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
366 {
367   PetscErrorCode ierr;
368 
369   PetscFunctionBegin;
370   ierr = MatCreate(PetscObjectComm((PetscObject)A),newmat);CHKERRQ(ierr);
371   ierr = MatSetSizes(*newmat,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
372   ierr = MatSetType(*newmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
373   ierr = MatDuplicateNoCreate_SeqDense(*newmat,A,cpvalues);CHKERRQ(ierr);
374   PetscFunctionReturn(0);
375 }
376 
377 
378 static PetscErrorCode MatLUFactor_SeqDense(Mat,IS,IS,const MatFactorInfo*);
379 
380 static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy)
381 {
382   MatFactorInfo  info;
383   PetscErrorCode ierr;
384 
385   PetscFunctionBegin;
386   ierr = MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);CHKERRQ(ierr);
387   ierr = MatLUFactor_SeqDense(fact,0,0,&info);CHKERRQ(ierr);
388   PetscFunctionReturn(0);
389 }
390 
391 static PetscErrorCode MatSolve_SeqDense(Mat A,Vec xx,Vec yy)
392 {
393   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
394   PetscErrorCode    ierr;
395   const PetscScalar *x;
396   PetscScalar       *y;
397   PetscBLASInt      one = 1,info,m;
398 
399   PetscFunctionBegin;
400   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
401   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
402   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
403   ierr = PetscMemcpy(y,x,A->rmap->n*sizeof(PetscScalar));CHKERRQ(ierr);
404   if (A->factortype == MAT_FACTOR_LU) {
405 #if defined(PETSC_MISSING_LAPACK_GETRS)
406     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
407 #else
408     PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
409     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve");
410 #endif
411   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
412 #if defined(PETSC_MISSING_LAPACK_POTRS)
413     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
414 #else
415     if (A->spd) {
416       PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info));
417       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve");
418 #if defined (PETSC_USE_COMPLEX)
419     } else if (A->hermitian) {
420       PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
421       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"HETRS Bad solve");
422 #endif
423     } else { /* symmetric case */
424       PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
425       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve");
426     }
427 #endif
428   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
429   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
430   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
431   ierr = PetscLogFlops(2.0*A->cmap->n*A->cmap->n - A->cmap->n);CHKERRQ(ierr);
432   PetscFunctionReturn(0);
433 }
434 
435 static PetscErrorCode MatMatSolve_SeqDense(Mat A,Mat B,Mat X)
436 {
437   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
438   PetscErrorCode ierr;
439   PetscScalar    *b,*x;
440   PetscInt       n;
441   PetscBLASInt   nrhs,info,m;
442   PetscBool      flg;
443 
444   PetscFunctionBegin;
445   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
446   ierr = PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr);
447   if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix B must be MATDENSE matrix");
448   ierr = PetscObjectTypeCompareAny((PetscObject)X,&flg,MATSEQDENSE,MATMPIDENSE,NULL);CHKERRQ(ierr);
449   if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Matrix X must be MATDENSE matrix");
450 
451   ierr = MatGetSize(B,NULL,&n);CHKERRQ(ierr);
452   ierr = PetscBLASIntCast(n,&nrhs);CHKERRQ(ierr);
453   ierr = MatDenseGetArray(B,&b);CHKERRQ(ierr);
454   ierr = MatDenseGetArray(X,&x);CHKERRQ(ierr);
455 
456   ierr = PetscMemcpy(x,b,m*nrhs*sizeof(PetscScalar));CHKERRQ(ierr);
457 
458   if (A->factortype == MAT_FACTOR_LU) {
459 #if defined(PETSC_MISSING_LAPACK_GETRS)
460     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
461 #else
462     PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("N",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
463     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve");
464 #endif
465   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
466 #if defined(PETSC_MISSING_LAPACK_POTRS)
467     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
468 #else
469     if (A->spd) {
470       PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&nrhs,mat->v,&mat->lda,x,&m,&info));
471       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve");
472 #if defined (PETSC_USE_COMPLEX)
473     } else if (A->hermitian) {
474       PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
475       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"HETRS Bad solve");
476 #endif
477     } else { /* symmetric case */
478       PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
479       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve");
480     }
481 #endif
482   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
483 
484   ierr = MatDenseRestoreArray(B,&b);CHKERRQ(ierr);
485   ierr = MatDenseRestoreArray(X,&x);CHKERRQ(ierr);
486   ierr = PetscLogFlops(nrhs*(2.0*m*m - m));CHKERRQ(ierr);
487   PetscFunctionReturn(0);
488 }
489 
490 static PetscErrorCode MatSolveTranspose_SeqDense(Mat A,Vec xx,Vec yy)
491 {
492   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
493   PetscErrorCode    ierr;
494   const PetscScalar *x;
495   PetscScalar       *y;
496   PetscBLASInt      one = 1,info,m;
497 
498   PetscFunctionBegin;
499   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
500   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
501   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
502   ierr = PetscMemcpy(y,x,A->rmap->n*sizeof(PetscScalar));CHKERRQ(ierr);
503   if (A->factortype == MAT_FACTOR_LU) {
504 #if defined(PETSC_MISSING_LAPACK_GETRS)
505     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
506 #else
507     PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
508     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS - Bad solve");
509 #endif
510   } else if (A->factortype == MAT_FACTOR_CHOLESKY) {
511 #if defined(PETSC_MISSING_LAPACK_POTRS)
512     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
513 #else
514     if (A->spd) {
515       PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info));
516       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve");
517 #if defined (PETSC_USE_COMPLEX)
518     } else if (A->hermitian) {
519       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatSolveTranspose with Cholesky/Hermitian not available");
520 #endif
521     } else { /* symmetric case */
522       PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info));
523       if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve");
524     }
525 #endif
526   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
527   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
528   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
529   ierr = PetscLogFlops(2.0*A->cmap->n*A->cmap->n - A->cmap->n);CHKERRQ(ierr);
530   PetscFunctionReturn(0);
531 }
532 
533 static PetscErrorCode MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
534 {
535   PetscErrorCode    ierr;
536   const PetscScalar *x;
537   PetscScalar       *y,sone = 1.0;
538   Vec               tmp = 0;
539 
540   PetscFunctionBegin;
541   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
542   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
543   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
544   if (yy == zz) {
545     ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr);
546     ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)tmp);CHKERRQ(ierr);
547     ierr = VecCopy(yy,tmp);CHKERRQ(ierr);
548   }
549   ierr = MatSolve_SeqDense(A,xx,yy);CHKERRQ(ierr);
550   if (tmp) {
551     ierr = VecAXPY(yy,sone,tmp);CHKERRQ(ierr);
552     ierr = VecDestroy(&tmp);CHKERRQ(ierr);
553   } else {
554     ierr = VecAXPY(yy,sone,zz);CHKERRQ(ierr);
555   }
556   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
557   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
558   ierr = PetscLogFlops(A->cmap->n);CHKERRQ(ierr);
559   PetscFunctionReturn(0);
560 }
561 
562 static PetscErrorCode MatSolveTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
563 {
564   PetscErrorCode    ierr;
565   const PetscScalar *x;
566   PetscScalar       *y,sone = 1.0;
567   Vec               tmp = NULL;
568 
569   PetscFunctionBegin;
570   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
571   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
572   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
573   if (yy == zz) {
574     ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr);
575     ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)tmp);CHKERRQ(ierr);
576     ierr = VecCopy(yy,tmp);CHKERRQ(ierr);
577   }
578   ierr = MatSolveTranspose_SeqDense(A,xx,yy);CHKERRQ(ierr);
579   if (tmp) {
580     ierr = VecAXPY(yy,sone,tmp);CHKERRQ(ierr);
581     ierr = VecDestroy(&tmp);CHKERRQ(ierr);
582   } else {
583     ierr = VecAXPY(yy,sone,zz);CHKERRQ(ierr);
584   }
585   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
586   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
587   ierr = PetscLogFlops(A->cmap->n);CHKERRQ(ierr);
588   PetscFunctionReturn(0);
589 }
590 
591 /* ---------------------------------------------------------------*/
592 /* COMMENT: I have chosen to hide row permutation in the pivots,
593    rather than put it in the Mat->row slot.*/
594 static PetscErrorCode MatLUFactor_SeqDense(Mat A,IS row,IS col,const MatFactorInfo *minfo)
595 {
596 #if defined(PETSC_MISSING_LAPACK_GETRF)
597   PetscFunctionBegin;
598   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GETRF - Lapack routine is unavailable.");
599 #else
600   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
601   PetscErrorCode ierr;
602   PetscBLASInt   n,m,info;
603 
604   PetscFunctionBegin;
605   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
606   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
607   if (!mat->pivots) {
608     ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr);
609     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr);
610   }
611   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
612   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
613   PetscStackCallBLAS("LAPACKgetrf",LAPACKgetrf_(&m,&n,mat->v,&mat->lda,mat->pivots,&info));
614   ierr = PetscFPTrapPop();CHKERRQ(ierr);
615 
616   if (info<0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to LU factorization");
617   if (info>0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
618 
619   A->ops->solve             = MatSolve_SeqDense;
620   A->ops->matsolve          = MatMatSolve_SeqDense;
621   A->ops->solvetranspose    = MatSolveTranspose_SeqDense;
622   A->ops->solveadd          = MatSolveAdd_SeqDense;
623   A->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense;
624   A->factortype             = MAT_FACTOR_LU;
625 
626   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
627   ierr = PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);CHKERRQ(ierr);
628 
629   ierr = PetscLogFlops((2.0*A->cmap->n*A->cmap->n*A->cmap->n)/3);CHKERRQ(ierr);
630 #endif
631   PetscFunctionReturn(0);
632 }
633 
634 /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
635 static PetscErrorCode MatCholeskyFactor_SeqDense(Mat A,IS perm,const MatFactorInfo *factinfo)
636 {
637 #if defined(PETSC_MISSING_LAPACK_POTRF)
638   PetscFunctionBegin;
639   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable.");
640 #else
641   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
642   PetscErrorCode ierr;
643   PetscBLASInt   info,n;
644 
645   PetscFunctionBegin;
646   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
647   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
648   if (A->spd) {
649     PetscStackCallBLAS("LAPACKpotrf",LAPACKpotrf_("L",&n,mat->v,&mat->lda,&info));
650 #if defined (PETSC_USE_COMPLEX)
651   } else if (A->hermitian) {
652     if (!mat->pivots) {
653       ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr);
654       ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr);
655     }
656     if (!mat->fwork) {
657       PetscScalar dummy;
658 
659       mat->lfwork = -1;
660       PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info));
661       mat->lfwork = (PetscInt)PetscRealPart(dummy);
662       ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr);
663       ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr);
664     }
665     PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
666 #endif
667   } else { /* symmetric case */
668     if (!mat->pivots) {
669       ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr);
670       ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr);
671     }
672     if (!mat->fwork) {
673       PetscScalar dummy;
674 
675       mat->lfwork = -1;
676       PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info));
677       mat->lfwork = (PetscInt)PetscRealPart(dummy);
678       ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr);
679       ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr);
680     }
681     PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
682   }
683   if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_CH_ZRPVT,"Bad factorization: zero pivot in row %D",(PetscInt)info-1);
684 
685   A->ops->solve             = MatSolve_SeqDense;
686   A->ops->matsolve          = MatMatSolve_SeqDense;
687   A->ops->solvetranspose    = MatSolveTranspose_SeqDense;
688   A->ops->solveadd          = MatSolveAdd_SeqDense;
689   A->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense;
690   A->factortype             = MAT_FACTOR_CHOLESKY;
691 
692   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
693   ierr = PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);CHKERRQ(ierr);
694 
695   ierr = PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);CHKERRQ(ierr);
696 #endif
697   PetscFunctionReturn(0);
698 }
699 
700 
701 PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy)
702 {
703   PetscErrorCode ierr;
704   MatFactorInfo  info;
705 
706   PetscFunctionBegin;
707   info.fill = 1.0;
708 
709   ierr = MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);CHKERRQ(ierr);
710   ierr = MatCholeskyFactor_SeqDense(fact,0,&info);CHKERRQ(ierr);
711   PetscFunctionReturn(0);
712 }
713 
714 static PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,const MatFactorInfo *info)
715 {
716   PetscFunctionBegin;
717   fact->assembled                  = PETSC_TRUE;
718   fact->preallocated               = PETSC_TRUE;
719   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
720   fact->ops->solve                 = MatSolve_SeqDense;
721   fact->ops->matsolve              = MatMatSolve_SeqDense;
722   fact->ops->solvetranspose        = MatSolveTranspose_SeqDense;
723   fact->ops->solveadd              = MatSolveAdd_SeqDense;
724   fact->ops->solvetransposeadd     = MatSolveTransposeAdd_SeqDense;
725   PetscFunctionReturn(0);
726 }
727 
728 static PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,IS col,const MatFactorInfo *info)
729 {
730   PetscFunctionBegin;
731   fact->preallocated           = PETSC_TRUE;
732   fact->assembled              = PETSC_TRUE;
733   fact->ops->lufactornumeric   = MatLUFactorNumeric_SeqDense;
734   fact->ops->solve             = MatSolve_SeqDense;
735   fact->ops->matsolve          = MatMatSolve_SeqDense;
736   fact->ops->solvetranspose    = MatSolveTranspose_SeqDense;
737   fact->ops->solveadd          = MatSolveAdd_SeqDense;
738   fact->ops->solvetransposeadd = MatSolveTransposeAdd_SeqDense;
739   PetscFunctionReturn(0);
740 }
741 
742 PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A,MatFactorType ftype,Mat *fact)
743 {
744   PetscErrorCode ierr;
745 
746   PetscFunctionBegin;
747   ierr = MatCreate(PetscObjectComm((PetscObject)A),fact);CHKERRQ(ierr);
748   ierr = MatSetSizes(*fact,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
749   ierr = MatSetType(*fact,((PetscObject)A)->type_name);CHKERRQ(ierr);
750   if (ftype == MAT_FACTOR_LU) {
751     (*fact)->ops->lufactorsymbolic = MatLUFactorSymbolic_SeqDense;
752   } else {
753     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
754   }
755   (*fact)->factortype = ftype;
756 
757   ierr = PetscFree((*fact)->solvertype);CHKERRQ(ierr);
758   ierr = PetscStrallocpy(MATSOLVERPETSC,&(*fact)->solvertype);CHKERRQ(ierr);
759   PetscFunctionReturn(0);
760 }
761 
762 /* ------------------------------------------------------------------*/
763 static PetscErrorCode MatSOR_SeqDense(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec xx)
764 {
765   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
766   PetscScalar       *x,*v = mat->v,zero = 0.0,xt;
767   const PetscScalar *b;
768   PetscErrorCode    ierr;
769   PetscInt          m = A->rmap->n,i;
770   PetscBLASInt      o = 1,bm;
771 
772   PetscFunctionBegin;
773   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
774   ierr = PetscBLASIntCast(m,&bm);CHKERRQ(ierr);
775   if (flag & SOR_ZERO_INITIAL_GUESS) {
776     /* this is a hack fix, should have another version without the second BLASdot */
777     ierr = VecSet(xx,zero);CHKERRQ(ierr);
778   }
779   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
780   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
781   its  = its*lits;
782   if (its <= 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
783   while (its--) {
784     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
785       for (i=0; i<m; i++) {
786         PetscStackCallBLAS("BLASdot",xt   = b[i] - BLASdot_(&bm,v+i,&bm,x,&o));
787         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
788       }
789     }
790     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
791       for (i=m-1; i>=0; i--) {
792         PetscStackCallBLAS("BLASdot",xt   = b[i] - BLASdot_(&bm,v+i,&bm,x,&o));
793         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
794       }
795     }
796   }
797   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
798   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
799   PetscFunctionReturn(0);
800 }
801 
802 /* -----------------------------------------------------------------*/
803 PETSC_INTERN PetscErrorCode MatMultTranspose_SeqDense(Mat A,Vec xx,Vec yy)
804 {
805   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
806   const PetscScalar *v   = mat->v,*x;
807   PetscScalar       *y;
808   PetscErrorCode    ierr;
809   PetscBLASInt      m, n,_One=1;
810   PetscScalar       _DOne=1.0,_DZero=0.0;
811 
812   PetscFunctionBegin;
813   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
814   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
815   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
816   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
817   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
818   PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&mat->lda,x,&_One,&_DZero,y,&_One));
819   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
820   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
821   ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->cmap->n);CHKERRQ(ierr);
822   PetscFunctionReturn(0);
823 }
824 
825 PETSC_INTERN PetscErrorCode MatMult_SeqDense(Mat A,Vec xx,Vec yy)
826 {
827   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
828   PetscScalar       *y,_DOne=1.0,_DZero=0.0;
829   PetscErrorCode    ierr;
830   PetscBLASInt      m, n, _One=1;
831   const PetscScalar *v = mat->v,*x;
832 
833   PetscFunctionBegin;
834   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
835   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
836   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
837   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
838   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
839   PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DZero,y,&_One));
840   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
841   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
842   ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->rmap->n);CHKERRQ(ierr);
843   PetscFunctionReturn(0);
844 }
845 
846 PETSC_INTERN PetscErrorCode MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
847 {
848   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
849   const PetscScalar *v = mat->v,*x;
850   PetscScalar       *y,_DOne=1.0;
851   PetscErrorCode    ierr;
852   PetscBLASInt      m, n, _One=1;
853 
854   PetscFunctionBegin;
855   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
856   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
857   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
858   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
859   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
860   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
861   PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One));
862   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
863   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
864   ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n);CHKERRQ(ierr);
865   PetscFunctionReturn(0);
866 }
867 
868 static PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
869 {
870   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
871   const PetscScalar *v = mat->v,*x;
872   PetscScalar       *y;
873   PetscErrorCode    ierr;
874   PetscBLASInt      m, n, _One=1;
875   PetscScalar       _DOne=1.0;
876 
877   PetscFunctionBegin;
878   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
879   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
880   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
881   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
882   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
883   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
884   PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One));
885   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
886   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
887   ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n);CHKERRQ(ierr);
888   PetscFunctionReturn(0);
889 }
890 
891 /* -----------------------------------------------------------------*/
892 static PetscErrorCode MatGetRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
893 {
894   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
895   PetscScalar    *v;
896   PetscErrorCode ierr;
897   PetscInt       i;
898 
899   PetscFunctionBegin;
900   *ncols = A->cmap->n;
901   if (cols) {
902     ierr = PetscMalloc1(A->cmap->n+1,cols);CHKERRQ(ierr);
903     for (i=0; i<A->cmap->n; i++) (*cols)[i] = i;
904   }
905   if (vals) {
906     ierr = PetscMalloc1(A->cmap->n+1,vals);CHKERRQ(ierr);
907     v    = mat->v + row;
908     for (i=0; i<A->cmap->n; i++) {(*vals)[i] = *v; v += mat->lda;}
909   }
910   PetscFunctionReturn(0);
911 }
912 
913 static PetscErrorCode MatRestoreRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
914 {
915   PetscErrorCode ierr;
916 
917   PetscFunctionBegin;
918   if (cols) {ierr = PetscFree(*cols);CHKERRQ(ierr);}
919   if (vals) {ierr = PetscFree(*vals);CHKERRQ(ierr); }
920   PetscFunctionReturn(0);
921 }
922 /* ----------------------------------------------------------------*/
923 static PetscErrorCode MatSetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],const PetscScalar v[],InsertMode addv)
924 {
925   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
926   PetscInt     i,j,idx=0;
927 
928   PetscFunctionBegin;
929   if (!mat->roworiented) {
930     if (addv == INSERT_VALUES) {
931       for (j=0; j<n; j++) {
932         if (indexn[j] < 0) {idx += m; continue;}
933 #if defined(PETSC_USE_DEBUG)
934         if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
935 #endif
936         for (i=0; i<m; i++) {
937           if (indexm[i] < 0) {idx++; continue;}
938 #if defined(PETSC_USE_DEBUG)
939           if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
940 #endif
941           mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
942         }
943       }
944     } else {
945       for (j=0; j<n; j++) {
946         if (indexn[j] < 0) {idx += m; continue;}
947 #if defined(PETSC_USE_DEBUG)
948         if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
949 #endif
950         for (i=0; i<m; i++) {
951           if (indexm[i] < 0) {idx++; continue;}
952 #if defined(PETSC_USE_DEBUG)
953           if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
954 #endif
955           mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
956         }
957       }
958     }
959   } else {
960     if (addv == INSERT_VALUES) {
961       for (i=0; i<m; i++) {
962         if (indexm[i] < 0) { idx += n; continue;}
963 #if defined(PETSC_USE_DEBUG)
964         if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
965 #endif
966         for (j=0; j<n; j++) {
967           if (indexn[j] < 0) { idx++; continue;}
968 #if defined(PETSC_USE_DEBUG)
969           if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
970 #endif
971           mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
972         }
973       }
974     } else {
975       for (i=0; i<m; i++) {
976         if (indexm[i] < 0) { idx += n; continue;}
977 #if defined(PETSC_USE_DEBUG)
978         if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap->n-1);
979 #endif
980         for (j=0; j<n; j++) {
981           if (indexn[j] < 0) { idx++; continue;}
982 #if defined(PETSC_USE_DEBUG)
983           if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap->n-1);
984 #endif
985           mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
986         }
987       }
988     }
989   }
990   PetscFunctionReturn(0);
991 }
992 
993 static PetscErrorCode MatGetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],PetscScalar v[])
994 {
995   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
996   PetscInt     i,j;
997 
998   PetscFunctionBegin;
999   /* row-oriented output */
1000   for (i=0; i<m; i++) {
1001     if (indexm[i] < 0) {v += n;continue;}
1002     if (indexm[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested larger than number rows %D",indexm[i],A->rmap->n);
1003     for (j=0; j<n; j++) {
1004       if (indexn[j] < 0) {v++; continue;}
1005       if (indexn[j] >= A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column %D requested larger than number columns %D",indexn[j],A->cmap->n);
1006       *v++ = mat->v[indexn[j]*mat->lda + indexm[i]];
1007     }
1008   }
1009   PetscFunctionReturn(0);
1010 }
1011 
1012 /* -----------------------------------------------------------------*/
1013 
1014 static PetscErrorCode MatLoad_SeqDense(Mat newmat,PetscViewer viewer)
1015 {
1016   Mat_SeqDense   *a;
1017   PetscErrorCode ierr;
1018   PetscInt       *scols,i,j,nz,header[4];
1019   int            fd;
1020   PetscMPIInt    size;
1021   PetscInt       *rowlengths = 0,M,N,*cols,grows,gcols;
1022   PetscScalar    *vals,*svals,*v,*w;
1023   MPI_Comm       comm;
1024 
1025   PetscFunctionBegin;
1026   /* force binary viewer to load .info file if it has not yet done so */
1027   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1028   ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr);
1029   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1030   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"view must have one processor");
1031   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
1032   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
1033   if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Not matrix object");
1034   M = header[1]; N = header[2]; nz = header[3];
1035 
1036   /* set global size if not set already*/
1037   if (newmat->rmap->n < 0 && newmat->rmap->N < 0 && newmat->cmap->n < 0 && newmat->cmap->N < 0) {
1038     ierr = MatSetSizes(newmat,M,N,M,N);CHKERRQ(ierr);
1039   } else {
1040     /* if sizes and type are already set, check if the vector global sizes are correct */
1041     ierr = MatGetSize(newmat,&grows,&gcols);CHKERRQ(ierr);
1042     if (M != grows ||  N != gcols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different length (%d, %d) than the input matrix (%d, %d)",M,N,grows,gcols);
1043   }
1044   a = (Mat_SeqDense*)newmat->data;
1045   if (!a->user_alloc) {
1046     ierr = MatSeqDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr);
1047   }
1048 
1049   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */
1050     a = (Mat_SeqDense*)newmat->data;
1051     v = a->v;
1052     /* Allocate some temp space to read in the values and then flip them
1053        from row major to column major */
1054     ierr = PetscMalloc1(M*N > 0 ? M*N : 1,&w);CHKERRQ(ierr);
1055     /* read in nonzero values */
1056     ierr = PetscBinaryRead(fd,w,M*N,PETSC_SCALAR);CHKERRQ(ierr);
1057     /* now flip the values and store them in the matrix*/
1058     for (j=0; j<N; j++) {
1059       for (i=0; i<M; i++) {
1060         *v++ =w[i*N+j];
1061       }
1062     }
1063     ierr = PetscFree(w);CHKERRQ(ierr);
1064   } else {
1065     /* read row lengths */
1066     ierr = PetscMalloc1(M+1,&rowlengths);CHKERRQ(ierr);
1067     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
1068 
1069     a = (Mat_SeqDense*)newmat->data;
1070     v = a->v;
1071 
1072     /* read column indices and nonzeros */
1073     ierr = PetscMalloc1(nz+1,&scols);CHKERRQ(ierr);
1074     cols = scols;
1075     ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr);
1076     ierr = PetscMalloc1(nz+1,&svals);CHKERRQ(ierr);
1077     vals = svals;
1078     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
1079 
1080     /* insert into matrix */
1081     for (i=0; i<M; i++) {
1082       for (j=0; j<rowlengths[i]; j++) v[i+M*scols[j]] = svals[j];
1083       svals += rowlengths[i]; scols += rowlengths[i];
1084     }
1085     ierr = PetscFree(vals);CHKERRQ(ierr);
1086     ierr = PetscFree(cols);CHKERRQ(ierr);
1087     ierr = PetscFree(rowlengths);CHKERRQ(ierr);
1088   }
1089   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1090   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1091   PetscFunctionReturn(0);
1092 }
1093 
1094 static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer)
1095 {
1096   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
1097   PetscErrorCode    ierr;
1098   PetscInt          i,j;
1099   const char        *name;
1100   PetscScalar       *v;
1101   PetscViewerFormat format;
1102 #if defined(PETSC_USE_COMPLEX)
1103   PetscBool         allreal = PETSC_TRUE;
1104 #endif
1105 
1106   PetscFunctionBegin;
1107   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1108   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1109     PetscFunctionReturn(0);  /* do nothing for now */
1110   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
1111     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1112     for (i=0; i<A->rmap->n; i++) {
1113       v    = a->v + i;
1114       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
1115       for (j=0; j<A->cmap->n; j++) {
1116 #if defined(PETSC_USE_COMPLEX)
1117         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
1118           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i) ",j,(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));CHKERRQ(ierr);
1119         } else if (PetscRealPart(*v)) {
1120           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)PetscRealPart(*v));CHKERRQ(ierr);
1121         }
1122 #else
1123         if (*v) {
1124           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)*v);CHKERRQ(ierr);
1125         }
1126 #endif
1127         v += a->lda;
1128       }
1129       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
1130     }
1131     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1132   } else {
1133     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1134 #if defined(PETSC_USE_COMPLEX)
1135     /* determine if matrix has all real values */
1136     v = a->v;
1137     for (i=0; i<A->rmap->n*A->cmap->n; i++) {
1138       if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break;}
1139     }
1140 #endif
1141     if (format == PETSC_VIEWER_ASCII_MATLAB) {
1142       ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
1143       ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->rmap->n,A->cmap->n);CHKERRQ(ierr);
1144       ierr = PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
1145       ierr = PetscViewerASCIIPrintf(viewer,"%s = [\n",name);CHKERRQ(ierr);
1146     }
1147 
1148     for (i=0; i<A->rmap->n; i++) {
1149       v = a->v + i;
1150       for (j=0; j<A->cmap->n; j++) {
1151 #if defined(PETSC_USE_COMPLEX)
1152         if (allreal) {
1153           ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)PetscRealPart(*v));CHKERRQ(ierr);
1154         } else {
1155           ierr = PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ei ",(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));CHKERRQ(ierr);
1156         }
1157 #else
1158         ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)*v);CHKERRQ(ierr);
1159 #endif
1160         v += a->lda;
1161       }
1162       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
1163     }
1164     if (format == PETSC_VIEWER_ASCII_MATLAB) {
1165       ierr = PetscViewerASCIIPrintf(viewer,"];\n");CHKERRQ(ierr);
1166     }
1167     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1168   }
1169   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1170   PetscFunctionReturn(0);
1171 }
1172 
1173 static PetscErrorCode MatView_SeqDense_Binary(Mat A,PetscViewer viewer)
1174 {
1175   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
1176   PetscErrorCode    ierr;
1177   int               fd;
1178   PetscInt          ict,j,n = A->cmap->n,m = A->rmap->n,i,*col_lens,nz = m*n;
1179   PetscScalar       *v,*anonz,*vals;
1180   PetscViewerFormat format;
1181 
1182   PetscFunctionBegin;
1183   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
1184 
1185   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1186   if (format == PETSC_VIEWER_NATIVE) {
1187     /* store the matrix as a dense matrix */
1188     ierr = PetscMalloc1(4,&col_lens);CHKERRQ(ierr);
1189 
1190     col_lens[0] = MAT_FILE_CLASSID;
1191     col_lens[1] = m;
1192     col_lens[2] = n;
1193     col_lens[3] = MATRIX_BINARY_FORMAT_DENSE;
1194 
1195     ierr = PetscBinaryWrite(fd,col_lens,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
1196     ierr = PetscFree(col_lens);CHKERRQ(ierr);
1197 
1198     /* write out matrix, by rows */
1199     ierr = PetscMalloc1(m*n+1,&vals);CHKERRQ(ierr);
1200     v    = a->v;
1201     for (j=0; j<n; j++) {
1202       for (i=0; i<m; i++) {
1203         vals[j + i*n] = *v++;
1204       }
1205     }
1206     ierr = PetscBinaryWrite(fd,vals,n*m,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
1207     ierr = PetscFree(vals);CHKERRQ(ierr);
1208   } else {
1209     ierr = PetscMalloc1(4+nz,&col_lens);CHKERRQ(ierr);
1210 
1211     col_lens[0] = MAT_FILE_CLASSID;
1212     col_lens[1] = m;
1213     col_lens[2] = n;
1214     col_lens[3] = nz;
1215 
1216     /* store lengths of each row and write (including header) to file */
1217     for (i=0; i<m; i++) col_lens[4+i] = n;
1218     ierr = PetscBinaryWrite(fd,col_lens,4+m,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
1219 
1220     /* Possibly should write in smaller increments, not whole matrix at once? */
1221     /* store column indices (zero start index) */
1222     ict = 0;
1223     for (i=0; i<m; i++) {
1224       for (j=0; j<n; j++) col_lens[ict++] = j;
1225     }
1226     ierr = PetscBinaryWrite(fd,col_lens,nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
1227     ierr = PetscFree(col_lens);CHKERRQ(ierr);
1228 
1229     /* store nonzero values */
1230     ierr = PetscMalloc1(nz+1,&anonz);CHKERRQ(ierr);
1231     ict  = 0;
1232     for (i=0; i<m; i++) {
1233       v = a->v + i;
1234       for (j=0; j<n; j++) {
1235         anonz[ict++] = *v; v += a->lda;
1236       }
1237     }
1238     ierr = PetscBinaryWrite(fd,anonz,nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
1239     ierr = PetscFree(anonz);CHKERRQ(ierr);
1240   }
1241   PetscFunctionReturn(0);
1242 }
1243 
1244 #include <petscdraw.h>
1245 static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa)
1246 {
1247   Mat               A  = (Mat) Aa;
1248   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
1249   PetscErrorCode    ierr;
1250   PetscInt          m  = A->rmap->n,n = A->cmap->n,i,j;
1251   int               color = PETSC_DRAW_WHITE;
1252   PetscScalar       *v = a->v;
1253   PetscViewer       viewer;
1254   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1255   PetscViewerFormat format;
1256 
1257   PetscFunctionBegin;
1258   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1259   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1260   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1261 
1262   /* Loop over matrix elements drawing boxes */
1263 
1264   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1265     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
1266     /* Blue for negative and Red for positive */
1267     for (j = 0; j < n; j++) {
1268       x_l = j; x_r = x_l + 1.0;
1269       for (i = 0; i < m; i++) {
1270         y_l = m - i - 1.0;
1271         y_r = y_l + 1.0;
1272         if (PetscRealPart(v[j*m+i]) >  0.) {
1273           color = PETSC_DRAW_RED;
1274         } else if (PetscRealPart(v[j*m+i]) <  0.) {
1275           color = PETSC_DRAW_BLUE;
1276         } else {
1277           continue;
1278         }
1279         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1280       }
1281     }
1282     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
1283   } else {
1284     /* use contour shading to indicate magnitude of values */
1285     /* first determine max of all nonzero values */
1286     PetscReal minv = 0.0, maxv = 0.0;
1287     PetscDraw popup;
1288 
1289     for (i=0; i < m*n; i++) {
1290       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1291     }
1292     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1293     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
1294     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1295 
1296     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
1297     for (j=0; j<n; j++) {
1298       x_l = j;
1299       x_r = x_l + 1.0;
1300       for (i=0; i<m; i++) {
1301         y_l = m - i - 1.0;
1302         y_r = y_l + 1.0;
1303         color = PetscDrawRealToColor(PetscAbsScalar(v[j*m+i]),minv,maxv);
1304         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1305       }
1306     }
1307     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
1308   }
1309   PetscFunctionReturn(0);
1310 }
1311 
1312 static PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer)
1313 {
1314   PetscDraw      draw;
1315   PetscBool      isnull;
1316   PetscReal      xr,yr,xl,yl,h,w;
1317   PetscErrorCode ierr;
1318 
1319   PetscFunctionBegin;
1320   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1321   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1322   if (isnull) PetscFunctionReturn(0);
1323 
1324   xr   = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
1325   xr  += w;          yr += h;        xl = -w;     yl = -h;
1326   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1327   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1328   ierr = PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);CHKERRQ(ierr);
1329   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1330   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1331   PetscFunctionReturn(0);
1332 }
1333 
1334 PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer)
1335 {
1336   PetscErrorCode ierr;
1337   PetscBool      iascii,isbinary,isdraw;
1338 
1339   PetscFunctionBegin;
1340   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1341   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1342   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1343 
1344   if (iascii) {
1345     ierr = MatView_SeqDense_ASCII(A,viewer);CHKERRQ(ierr);
1346   } else if (isbinary) {
1347     ierr = MatView_SeqDense_Binary(A,viewer);CHKERRQ(ierr);
1348   } else if (isdraw) {
1349     ierr = MatView_SeqDense_Draw(A,viewer);CHKERRQ(ierr);
1350   }
1351   PetscFunctionReturn(0);
1352 }
1353 
1354 static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A,const PetscScalar array[])
1355 {
1356   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1357 
1358   PetscFunctionBegin;
1359   a->unplacedarray       = a->v;
1360   a->unplaced_user_alloc = a->user_alloc;
1361   a->v                   = (PetscScalar*) array;
1362   PetscFunctionReturn(0);
1363 }
1364 
1365 static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1366 {
1367   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1368 
1369   PetscFunctionBegin;
1370   a->v             = a->unplacedarray;
1371   a->user_alloc    = a->unplaced_user_alloc;
1372   a->unplacedarray = NULL;
1373   PetscFunctionReturn(0);
1374 }
1375 
1376 static PetscErrorCode MatDestroy_SeqDense(Mat mat)
1377 {
1378   Mat_SeqDense   *l = (Mat_SeqDense*)mat->data;
1379   PetscErrorCode ierr;
1380 
1381   PetscFunctionBegin;
1382 #if defined(PETSC_USE_LOG)
1383   PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->rmap->n,mat->cmap->n);
1384 #endif
1385   ierr = PetscFree(l->pivots);CHKERRQ(ierr);
1386   ierr = PetscFree(l->fwork);CHKERRQ(ierr);
1387   ierr = MatDestroy(&l->ptapwork);CHKERRQ(ierr);
1388   if (!l->user_alloc) {ierr = PetscFree(l->v);CHKERRQ(ierr);}
1389   ierr = PetscFree(mat->data);CHKERRQ(ierr);
1390 
1391   ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr);
1392   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArray_C",NULL);CHKERRQ(ierr);
1393   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDensePlaceArray_C",NULL);CHKERRQ(ierr);
1394   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseResetArray_C",NULL);CHKERRQ(ierr);
1395   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArray_C",NULL);CHKERRQ(ierr);
1396   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
1397 #if defined(PETSC_HAVE_ELEMENTAL)
1398   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_elemental_C",NULL);CHKERRQ(ierr);
1399 #endif
1400   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatSeqDenseSetPreallocation_C",NULL);CHKERRQ(ierr);
1401   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMult_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1402   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultSymbolic_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1403   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMultNumeric_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1404   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatPtAP_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1405   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMult_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1406   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1407   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatTransposeMatMultNumeric_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1408   PetscFunctionReturn(0);
1409 }
1410 
1411 static PetscErrorCode MatTranspose_SeqDense(Mat A,MatReuse reuse,Mat *matout)
1412 {
1413   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1414   PetscErrorCode ierr;
1415   PetscInt       k,j,m,n,M;
1416   PetscScalar    *v,tmp;
1417 
1418   PetscFunctionBegin;
1419   v = mat->v; m = A->rmap->n; M = mat->lda; n = A->cmap->n;
1420   if (reuse == MAT_INPLACE_MATRIX) { /* in place transpose */
1421     if (m != n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Can not transpose non-square matrix in place");
1422     else {
1423       for (j=0; j<m; j++) {
1424         for (k=0; k<j; k++) {
1425           tmp        = v[j + k*M];
1426           v[j + k*M] = v[k + j*M];
1427           v[k + j*M] = tmp;
1428         }
1429       }
1430     }
1431   } else { /* out-of-place transpose */
1432     Mat          tmat;
1433     Mat_SeqDense *tmatd;
1434     PetscScalar  *v2;
1435     PetscInt     M2;
1436 
1437     if (reuse == MAT_INITIAL_MATRIX) {
1438       ierr = MatCreate(PetscObjectComm((PetscObject)A),&tmat);CHKERRQ(ierr);
1439       ierr = MatSetSizes(tmat,A->cmap->n,A->rmap->n,A->cmap->n,A->rmap->n);CHKERRQ(ierr);
1440       ierr = MatSetType(tmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
1441       ierr = MatSeqDenseSetPreallocation(tmat,NULL);CHKERRQ(ierr);
1442     } else {
1443       tmat = *matout;
1444     }
1445     tmatd = (Mat_SeqDense*)tmat->data;
1446     v = mat->v; v2 = tmatd->v; M2 = tmatd->lda;
1447     for (j=0; j<n; j++) {
1448       for (k=0; k<m; k++) v2[j + k*M2] = v[k + j*M];
1449     }
1450     ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1451     ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1452     *matout = tmat;
1453   }
1454   PetscFunctionReturn(0);
1455 }
1456 
1457 static PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscBool  *flg)
1458 {
1459   Mat_SeqDense *mat1 = (Mat_SeqDense*)A1->data;
1460   Mat_SeqDense *mat2 = (Mat_SeqDense*)A2->data;
1461   PetscInt     i,j;
1462   PetscScalar  *v1,*v2;
1463 
1464   PetscFunctionBegin;
1465   if (A1->rmap->n != A2->rmap->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1466   if (A1->cmap->n != A2->cmap->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1467   for (i=0; i<A1->rmap->n; i++) {
1468     v1 = mat1->v+i; v2 = mat2->v+i;
1469     for (j=0; j<A1->cmap->n; j++) {
1470       if (*v1 != *v2) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1471       v1 += mat1->lda; v2 += mat2->lda;
1472     }
1473   }
1474   *flg = PETSC_TRUE;
1475   PetscFunctionReturn(0);
1476 }
1477 
1478 static PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v)
1479 {
1480   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1481   PetscErrorCode ierr;
1482   PetscInt       i,n,len;
1483   PetscScalar    *x,zero = 0.0;
1484 
1485   PetscFunctionBegin;
1486   ierr = VecSet(v,zero);CHKERRQ(ierr);
1487   ierr = VecGetSize(v,&n);CHKERRQ(ierr);
1488   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1489   len  = PetscMin(A->rmap->n,A->cmap->n);
1490   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
1491   for (i=0; i<len; i++) {
1492     x[i] = mat->v[i*mat->lda + i];
1493   }
1494   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1495   PetscFunctionReturn(0);
1496 }
1497 
1498 static PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr)
1499 {
1500   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1501   const PetscScalar *l,*r;
1502   PetscScalar       x,*v;
1503   PetscErrorCode    ierr;
1504   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n;
1505 
1506   PetscFunctionBegin;
1507   if (ll) {
1508     ierr = VecGetSize(ll,&m);CHKERRQ(ierr);
1509     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
1510     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size");
1511     for (i=0; i<m; i++) {
1512       x = l[i];
1513       v = mat->v + i;
1514       for (j=0; j<n; j++) { (*v) *= x; v+= mat->lda;}
1515     }
1516     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
1517     ierr = PetscLogFlops(1.0*n*m);CHKERRQ(ierr);
1518   }
1519   if (rr) {
1520     ierr = VecGetSize(rr,&n);CHKERRQ(ierr);
1521     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
1522     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size");
1523     for (i=0; i<n; i++) {
1524       x = r[i];
1525       v = mat->v + i*mat->lda;
1526       for (j=0; j<m; j++) (*v++) *= x;
1527     }
1528     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
1529     ierr = PetscLogFlops(1.0*n*m);CHKERRQ(ierr);
1530   }
1531   PetscFunctionReturn(0);
1532 }
1533 
1534 static PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm)
1535 {
1536   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1537   PetscScalar    *v   = mat->v;
1538   PetscReal      sum  = 0.0;
1539   PetscInt       lda  =mat->lda,m=A->rmap->n,i,j;
1540   PetscErrorCode ierr;
1541 
1542   PetscFunctionBegin;
1543   if (type == NORM_FROBENIUS) {
1544     if (lda>m) {
1545       for (j=0; j<A->cmap->n; j++) {
1546         v = mat->v+j*lda;
1547         for (i=0; i<m; i++) {
1548           sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1549         }
1550       }
1551     } else {
1552 #if defined(PETSC_USE_REAL___FP16)
1553       PetscBLASInt one = 1,cnt = A->cmap->n*A->rmap->n;
1554       *nrm = BLASnrm2_(&cnt,v,&one);
1555     }
1556 #else
1557       for (i=0; i<A->cmap->n*A->rmap->n; i++) {
1558         sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1559       }
1560     }
1561     *nrm = PetscSqrtReal(sum);
1562 #endif
1563     ierr = PetscLogFlops(2.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr);
1564   } else if (type == NORM_1) {
1565     *nrm = 0.0;
1566     for (j=0; j<A->cmap->n; j++) {
1567       v   = mat->v + j*mat->lda;
1568       sum = 0.0;
1569       for (i=0; i<A->rmap->n; i++) {
1570         sum += PetscAbsScalar(*v);  v++;
1571       }
1572       if (sum > *nrm) *nrm = sum;
1573     }
1574     ierr = PetscLogFlops(1.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr);
1575   } else if (type == NORM_INFINITY) {
1576     *nrm = 0.0;
1577     for (j=0; j<A->rmap->n; j++) {
1578       v   = mat->v + j;
1579       sum = 0.0;
1580       for (i=0; i<A->cmap->n; i++) {
1581         sum += PetscAbsScalar(*v); v += mat->lda;
1582       }
1583       if (sum > *nrm) *nrm = sum;
1584     }
1585     ierr = PetscLogFlops(1.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr);
1586   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No two norm");
1587   PetscFunctionReturn(0);
1588 }
1589 
1590 static PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op,PetscBool flg)
1591 {
1592   Mat_SeqDense   *aij = (Mat_SeqDense*)A->data;
1593   PetscErrorCode ierr;
1594 
1595   PetscFunctionBegin;
1596   switch (op) {
1597   case MAT_ROW_ORIENTED:
1598     aij->roworiented = flg;
1599     break;
1600   case MAT_NEW_NONZERO_LOCATIONS:
1601   case MAT_NEW_NONZERO_LOCATION_ERR:
1602   case MAT_NEW_NONZERO_ALLOCATION_ERR:
1603   case MAT_NEW_DIAGONALS:
1604   case MAT_KEEP_NONZERO_PATTERN:
1605   case MAT_IGNORE_OFF_PROC_ENTRIES:
1606   case MAT_USE_HASH_TABLE:
1607   case MAT_IGNORE_ZERO_ENTRIES:
1608   case MAT_IGNORE_LOWER_TRIANGULAR:
1609     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1610     break;
1611   case MAT_SPD:
1612   case MAT_SYMMETRIC:
1613   case MAT_STRUCTURALLY_SYMMETRIC:
1614   case MAT_HERMITIAN:
1615   case MAT_SYMMETRY_ETERNAL:
1616     /* These options are handled directly by MatSetOption() */
1617     break;
1618   default:
1619     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
1620   }
1621   PetscFunctionReturn(0);
1622 }
1623 
1624 static PetscErrorCode MatZeroEntries_SeqDense(Mat A)
1625 {
1626   Mat_SeqDense   *l = (Mat_SeqDense*)A->data;
1627   PetscErrorCode ierr;
1628   PetscInt       lda=l->lda,m=A->rmap->n,j;
1629 
1630   PetscFunctionBegin;
1631   if (lda>m) {
1632     for (j=0; j<A->cmap->n; j++) {
1633       ierr = PetscMemzero(l->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr);
1634     }
1635   } else {
1636     ierr = PetscMemzero(l->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));CHKERRQ(ierr);
1637   }
1638   PetscFunctionReturn(0);
1639 }
1640 
1641 static PetscErrorCode MatZeroRows_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
1642 {
1643   PetscErrorCode    ierr;
1644   Mat_SeqDense      *l = (Mat_SeqDense*)A->data;
1645   PetscInt          m  = l->lda, n = A->cmap->n, i,j;
1646   PetscScalar       *slot,*bb;
1647   const PetscScalar *xx;
1648 
1649   PetscFunctionBegin;
1650 #if defined(PETSC_USE_DEBUG)
1651   for (i=0; i<N; i++) {
1652     if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed");
1653     if (rows[i] >= A->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested to be zeroed greater than or equal number of rows %D",rows[i],A->rmap->n);
1654   }
1655 #endif
1656 
1657   /* fix right hand side if needed */
1658   if (x && b) {
1659     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
1660     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
1661     for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]];
1662     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
1663     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
1664   }
1665 
1666   for (i=0; i<N; i++) {
1667     slot = l->v + rows[i];
1668     for (j=0; j<n; j++) { *slot = 0.0; slot += m;}
1669   }
1670   if (diag != 0.0) {
1671     if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices");
1672     for (i=0; i<N; i++) {
1673       slot  = l->v + (m+1)*rows[i];
1674       *slot = diag;
1675     }
1676   }
1677   PetscFunctionReturn(0);
1678 }
1679 
1680 static PetscErrorCode MatDenseGetArray_SeqDense(Mat A,PetscScalar *array[])
1681 {
1682   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1683 
1684   PetscFunctionBegin;
1685   if (mat->lda != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get array for Dense matrices with LDA different from number of rows");
1686   *array = mat->v;
1687   PetscFunctionReturn(0);
1688 }
1689 
1690 static PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A,PetscScalar *array[])
1691 {
1692   PetscFunctionBegin;
1693   *array = 0; /* user cannot accidently use the array later */
1694   PetscFunctionReturn(0);
1695 }
1696 
1697 /*@C
1698    MatDenseGetArray - gives access to the array where the data for a SeqDense matrix is stored
1699 
1700    Not Collective
1701 
1702    Input Parameter:
1703 .  mat - a MATSEQDENSE or MATMPIDENSE matrix
1704 
1705    Output Parameter:
1706 .   array - pointer to the data
1707 
1708    Level: intermediate
1709 
1710 .seealso: MatDenseRestoreArray()
1711 @*/
1712 PetscErrorCode  MatDenseGetArray(Mat A,PetscScalar **array)
1713 {
1714   PetscErrorCode ierr;
1715 
1716   PetscFunctionBegin;
1717   ierr = PetscUseMethod(A,"MatDenseGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
1718   PetscFunctionReturn(0);
1719 }
1720 
1721 /*@C
1722    MatDenseRestoreArray - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray()
1723 
1724    Not Collective
1725 
1726    Input Parameters:
1727 .  mat - a MATSEQDENSE or MATMPIDENSE matrix
1728 .  array - pointer to the data
1729 
1730    Level: intermediate
1731 
1732 .seealso: MatDenseGetArray()
1733 @*/
1734 PetscErrorCode  MatDenseRestoreArray(Mat A,PetscScalar **array)
1735 {
1736   PetscErrorCode ierr;
1737 
1738   PetscFunctionBegin;
1739   ierr = PetscUseMethod(A,"MatDenseRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
1740   PetscFunctionReturn(0);
1741 }
1742 
1743 static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B)
1744 {
1745   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1746   PetscErrorCode ierr;
1747   PetscInt       i,j,nrows,ncols;
1748   const PetscInt *irow,*icol;
1749   PetscScalar    *av,*bv,*v = mat->v;
1750   Mat            newmat;
1751 
1752   PetscFunctionBegin;
1753   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1754   ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1755   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1756   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1757 
1758   /* Check submatrixcall */
1759   if (scall == MAT_REUSE_MATRIX) {
1760     PetscInt n_cols,n_rows;
1761     ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1762     if (n_rows != nrows || n_cols != ncols) {
1763       /* resize the result matrix to match number of requested rows/columns */
1764       ierr = MatSetSizes(*B,nrows,ncols,nrows,ncols);CHKERRQ(ierr);
1765     }
1766     newmat = *B;
1767   } else {
1768     /* Create and fill new matrix */
1769     ierr = MatCreate(PetscObjectComm((PetscObject)A),&newmat);CHKERRQ(ierr);
1770     ierr = MatSetSizes(newmat,nrows,ncols,nrows,ncols);CHKERRQ(ierr);
1771     ierr = MatSetType(newmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
1772     ierr = MatSeqDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr);
1773   }
1774 
1775   /* Now extract the data pointers and do the copy,column at a time */
1776   bv = ((Mat_SeqDense*)newmat->data)->v;
1777 
1778   for (i=0; i<ncols; i++) {
1779     av = v + mat->lda*icol[i];
1780     for (j=0; j<nrows; j++) *bv++ = av[irow[j]];
1781   }
1782 
1783   /* Assemble the matrices so that the correct flags are set */
1784   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1785   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1786 
1787   /* Free work space */
1788   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1789   ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1790   *B   = newmat;
1791   PetscFunctionReturn(0);
1792 }
1793 
1794 static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1795 {
1796   PetscErrorCode ierr;
1797   PetscInt       i;
1798 
1799   PetscFunctionBegin;
1800   if (scall == MAT_INITIAL_MATRIX) {
1801     ierr = PetscCalloc1(n+1,B);CHKERRQ(ierr);
1802   }
1803 
1804   for (i=0; i<n; i++) {
1805     ierr = MatCreateSubMatrix_SeqDense(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1806   }
1807   PetscFunctionReturn(0);
1808 }
1809 
1810 static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat,MatAssemblyType mode)
1811 {
1812   PetscFunctionBegin;
1813   PetscFunctionReturn(0);
1814 }
1815 
1816 static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat,MatAssemblyType mode)
1817 {
1818   PetscFunctionBegin;
1819   PetscFunctionReturn(0);
1820 }
1821 
1822 static PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str)
1823 {
1824   Mat_SeqDense   *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense*)B->data;
1825   PetscErrorCode ierr;
1826   PetscInt       lda1=a->lda,lda2=b->lda, m=A->rmap->n,n=A->cmap->n, j;
1827 
1828   PetscFunctionBegin;
1829   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
1830   if (A->ops->copy != B->ops->copy) {
1831     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1832     PetscFunctionReturn(0);
1833   }
1834   if (m != B->rmap->n || n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"size(B) != size(A)");
1835   if (lda1>m || lda2>m) {
1836     for (j=0; j<n; j++) {
1837       ierr = PetscMemcpy(b->v+j*lda2,a->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr);
1838     }
1839   } else {
1840     ierr = PetscMemcpy(b->v,a->v,A->rmap->n*A->cmap->n*sizeof(PetscScalar));CHKERRQ(ierr);
1841   }
1842   PetscFunctionReturn(0);
1843 }
1844 
1845 static PetscErrorCode MatSetUp_SeqDense(Mat A)
1846 {
1847   PetscErrorCode ierr;
1848 
1849   PetscFunctionBegin;
1850   ierr =  MatSeqDenseSetPreallocation(A,0);CHKERRQ(ierr);
1851   PetscFunctionReturn(0);
1852 }
1853 
1854 static PetscErrorCode MatConjugate_SeqDense(Mat A)
1855 {
1856   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1857   PetscInt     i,nz = A->rmap->n*A->cmap->n;
1858   PetscScalar  *aa = a->v;
1859 
1860   PetscFunctionBegin;
1861   for (i=0; i<nz; i++) aa[i] = PetscConj(aa[i]);
1862   PetscFunctionReturn(0);
1863 }
1864 
1865 static PetscErrorCode MatRealPart_SeqDense(Mat A)
1866 {
1867   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1868   PetscInt     i,nz = A->rmap->n*A->cmap->n;
1869   PetscScalar  *aa = a->v;
1870 
1871   PetscFunctionBegin;
1872   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
1873   PetscFunctionReturn(0);
1874 }
1875 
1876 static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
1877 {
1878   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1879   PetscInt     i,nz = A->rmap->n*A->cmap->n;
1880   PetscScalar  *aa = a->v;
1881 
1882   PetscFunctionBegin;
1883   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
1884   PetscFunctionReturn(0);
1885 }
1886 
1887 /* ----------------------------------------------------------------*/
1888 PETSC_INTERN PetscErrorCode MatMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
1889 {
1890   PetscErrorCode ierr;
1891 
1892   PetscFunctionBegin;
1893   if (scall == MAT_INITIAL_MATRIX) {
1894     ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
1895     ierr = MatMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr);
1896     ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
1897   }
1898   ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
1899   ierr = MatMatMultNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr);
1900   ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr);
1901   PetscFunctionReturn(0);
1902 }
1903 
1904 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
1905 {
1906   PetscErrorCode ierr;
1907   PetscInt       m=A->rmap->n,n=B->cmap->n;
1908   Mat            Cmat;
1909 
1910   PetscFunctionBegin;
1911   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);
1912   ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr);
1913   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
1914   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
1915   ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr);
1916 
1917   *C = Cmat;
1918   PetscFunctionReturn(0);
1919 }
1920 
1921 PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
1922 {
1923   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1924   Mat_SeqDense   *b = (Mat_SeqDense*)B->data;
1925   Mat_SeqDense   *c = (Mat_SeqDense*)C->data;
1926   PetscBLASInt   m,n,k;
1927   PetscScalar    _DOne=1.0,_DZero=0.0;
1928   PetscErrorCode ierr;
1929   PetscBool      flg;
1930 
1931   PetscFunctionBegin;
1932   ierr = PetscObjectTypeCompare((PetscObject)B,MATSEQDENSE,&flg);CHKERRQ(ierr);
1933   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Second matrix must be dense");
1934 
1935   /* Handle case where where user provided the final C matrix rather than calling MatMatMult() with MAT_INITIAL_MATRIX*/
1936   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQAIJ,&flg);CHKERRQ(ierr);
1937   if (flg) {
1938     C->ops->matmultnumeric = MatMatMultNumeric_SeqAIJ_SeqDense;
1939     ierr = (*C->ops->matmultnumeric)(A,B,C);CHKERRQ(ierr);
1940     PetscFunctionReturn(0);
1941   }
1942 
1943   ierr = PetscObjectTypeCompare((PetscObject)A,MATSEQDENSE,&flg);CHKERRQ(ierr);
1944   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"First matrix must be dense");
1945   ierr = PetscBLASIntCast(C->rmap->n,&m);CHKERRQ(ierr);
1946   ierr = PetscBLASIntCast(C->cmap->n,&n);CHKERRQ(ierr);
1947   ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr);
1948   PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
1949   PetscFunctionReturn(0);
1950 }
1951 
1952 PetscErrorCode MatMatTransposeMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
1953 {
1954   PetscErrorCode ierr;
1955 
1956   PetscFunctionBegin;
1957   if (scall == MAT_INITIAL_MATRIX) {
1958     ierr = PetscLogEventBegin(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr);
1959     ierr = MatMatTransposeMultSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr);
1960     ierr = PetscLogEventEnd(MAT_MatTransposeMultSymbolic,A,B,0,0);CHKERRQ(ierr);
1961   }
1962   ierr = PetscLogEventBegin(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
1963   ierr = MatMatTransposeMultNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr);
1964   ierr = PetscLogEventEnd(MAT_MatTransposeMultNumeric,A,B,0,0);CHKERRQ(ierr);
1965   PetscFunctionReturn(0);
1966 }
1967 
1968 PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
1969 {
1970   PetscErrorCode ierr;
1971   PetscInt       m=A->rmap->n,n=B->rmap->n;
1972   Mat            Cmat;
1973 
1974   PetscFunctionBegin;
1975   if (A->cmap->n != B->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->cmap->n %d\n",A->cmap->n,B->cmap->n);
1976   ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr);
1977   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
1978   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
1979   ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr);
1980 
1981   Cmat->assembled = PETSC_TRUE;
1982 
1983   *C = Cmat;
1984   PetscFunctionReturn(0);
1985 }
1986 
1987 PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
1988 {
1989   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1990   Mat_SeqDense   *b = (Mat_SeqDense*)B->data;
1991   Mat_SeqDense   *c = (Mat_SeqDense*)C->data;
1992   PetscBLASInt   m,n,k;
1993   PetscScalar    _DOne=1.0,_DZero=0.0;
1994   PetscErrorCode ierr;
1995 
1996   PetscFunctionBegin;
1997   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
1998   ierr = PetscBLASIntCast(B->rmap->n,&n);CHKERRQ(ierr);
1999   ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr);
2000   PetscStackCallBLAS("BLASgemm",BLASgemm_("N","T",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2001   PetscFunctionReturn(0);
2002 }
2003 
2004 PetscErrorCode MatTransposeMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
2005 {
2006   PetscErrorCode ierr;
2007 
2008   PetscFunctionBegin;
2009   if (scall == MAT_INITIAL_MATRIX) {
2010     ierr = PetscLogEventBegin(MAT_TransposeMatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
2011     ierr = MatTransposeMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr);
2012     ierr = PetscLogEventEnd(MAT_TransposeMatMultSymbolic,A,B,0,0);CHKERRQ(ierr);
2013   }
2014   ierr = PetscLogEventBegin(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
2015   ierr = MatTransposeMatMultNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr);
2016   ierr = PetscLogEventEnd(MAT_TransposeMatMultNumeric,A,B,0,0);CHKERRQ(ierr);
2017   PetscFunctionReturn(0);
2018 }
2019 
2020 PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
2021 {
2022   PetscErrorCode ierr;
2023   PetscInt       m=A->cmap->n,n=B->cmap->n;
2024   Mat            Cmat;
2025 
2026   PetscFunctionBegin;
2027   if (A->rmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->rmap->n %d != B->rmap->n %d\n",A->rmap->n,B->rmap->n);
2028   ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr);
2029   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
2030   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
2031   ierr = MatSeqDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr);
2032 
2033   Cmat->assembled = PETSC_TRUE;
2034 
2035   *C = Cmat;
2036   PetscFunctionReturn(0);
2037 }
2038 
2039 PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2040 {
2041   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
2042   Mat_SeqDense   *b = (Mat_SeqDense*)B->data;
2043   Mat_SeqDense   *c = (Mat_SeqDense*)C->data;
2044   PetscBLASInt   m,n,k;
2045   PetscScalar    _DOne=1.0,_DZero=0.0;
2046   PetscErrorCode ierr;
2047 
2048   PetscFunctionBegin;
2049   ierr = PetscBLASIntCast(C->rmap->n,&m);CHKERRQ(ierr);
2050   ierr = PetscBLASIntCast(C->cmap->n,&n);CHKERRQ(ierr);
2051   ierr = PetscBLASIntCast(A->rmap->n,&k);CHKERRQ(ierr);
2052   PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda));
2053   PetscFunctionReturn(0);
2054 }
2055 
2056 static PetscErrorCode MatGetRowMax_SeqDense(Mat A,Vec v,PetscInt idx[])
2057 {
2058   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
2059   PetscErrorCode ierr;
2060   PetscInt       i,j,m = A->rmap->n,n = A->cmap->n,p;
2061   PetscScalar    *x;
2062   MatScalar      *aa = a->v;
2063 
2064   PetscFunctionBegin;
2065   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2066 
2067   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2068   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2069   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
2070   if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2071   for (i=0; i<m; i++) {
2072     x[i] = aa[i]; if (idx) idx[i] = 0;
2073     for (j=1; j<n; j++) {
2074       if (PetscRealPart(x[i]) < PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
2075     }
2076   }
2077   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2078   PetscFunctionReturn(0);
2079 }
2080 
2081 static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A,Vec v,PetscInt idx[])
2082 {
2083   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
2084   PetscErrorCode ierr;
2085   PetscInt       i,j,m = A->rmap->n,n = A->cmap->n,p;
2086   PetscScalar    *x;
2087   PetscReal      atmp;
2088   MatScalar      *aa = a->v;
2089 
2090   PetscFunctionBegin;
2091   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2092 
2093   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2094   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2095   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
2096   if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2097   for (i=0; i<m; i++) {
2098     x[i] = PetscAbsScalar(aa[i]);
2099     for (j=1; j<n; j++) {
2100       atmp = PetscAbsScalar(aa[i+m*j]);
2101       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = j;}
2102     }
2103   }
2104   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2105   PetscFunctionReturn(0);
2106 }
2107 
2108 static PetscErrorCode MatGetRowMin_SeqDense(Mat A,Vec v,PetscInt idx[])
2109 {
2110   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
2111   PetscErrorCode ierr;
2112   PetscInt       i,j,m = A->rmap->n,n = A->cmap->n,p;
2113   PetscScalar    *x;
2114   MatScalar      *aa = a->v;
2115 
2116   PetscFunctionBegin;
2117   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2118 
2119   ierr = VecSet(v,0.0);CHKERRQ(ierr);
2120   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2121   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
2122   if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2123   for (i=0; i<m; i++) {
2124     x[i] = aa[i]; if (idx) idx[i] = 0;
2125     for (j=1; j<n; j++) {
2126       if (PetscRealPart(x[i]) > PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
2127     }
2128   }
2129   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2130   PetscFunctionReturn(0);
2131 }
2132 
2133 static PetscErrorCode MatGetColumnVector_SeqDense(Mat A,Vec v,PetscInt col)
2134 {
2135   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
2136   PetscErrorCode ierr;
2137   PetscScalar    *x;
2138 
2139   PetscFunctionBegin;
2140   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2141 
2142   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2143   ierr = PetscMemcpy(x,a->v+col*a->lda,A->rmap->n*sizeof(PetscScalar));CHKERRQ(ierr);
2144   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2145   PetscFunctionReturn(0);
2146 }
2147 
2148 
2149 PetscErrorCode MatGetColumnNorms_SeqDense(Mat A,NormType type,PetscReal *norms)
2150 {
2151   PetscErrorCode ierr;
2152   PetscInt       i,j,m,n;
2153   PetscScalar    *a;
2154 
2155   PetscFunctionBegin;
2156   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
2157   ierr = PetscMemzero(norms,n*sizeof(PetscReal));CHKERRQ(ierr);
2158   ierr = MatDenseGetArray(A,&a);CHKERRQ(ierr);
2159   if (type == NORM_2) {
2160     for (i=0; i<n; i++) {
2161       for (j=0; j<m; j++) {
2162         norms[i] += PetscAbsScalar(a[j]*a[j]);
2163       }
2164       a += m;
2165     }
2166   } else if (type == NORM_1) {
2167     for (i=0; i<n; i++) {
2168       for (j=0; j<m; j++) {
2169         norms[i] += PetscAbsScalar(a[j]);
2170       }
2171       a += m;
2172     }
2173   } else if (type == NORM_INFINITY) {
2174     for (i=0; i<n; i++) {
2175       for (j=0; j<m; j++) {
2176         norms[i] = PetscMax(PetscAbsScalar(a[j]),norms[i]);
2177       }
2178       a += m;
2179     }
2180   } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Unknown NormType");
2181   ierr = MatDenseRestoreArray(A,&a);CHKERRQ(ierr);
2182   if (type == NORM_2) {
2183     for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]);
2184   }
2185   PetscFunctionReturn(0);
2186 }
2187 
2188 static PetscErrorCode  MatSetRandom_SeqDense(Mat x,PetscRandom rctx)
2189 {
2190   PetscErrorCode ierr;
2191   PetscScalar    *a;
2192   PetscInt       m,n,i;
2193 
2194   PetscFunctionBegin;
2195   ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
2196   ierr = MatDenseGetArray(x,&a);CHKERRQ(ierr);
2197   for (i=0; i<m*n; i++) {
2198     ierr = PetscRandomGetValue(rctx,a+i);CHKERRQ(ierr);
2199   }
2200   ierr = MatDenseRestoreArray(x,&a);CHKERRQ(ierr);
2201   PetscFunctionReturn(0);
2202 }
2203 
2204 static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A,PetscBool  *missing,PetscInt *d)
2205 {
2206   PetscFunctionBegin;
2207   *missing = PETSC_FALSE;
2208   PetscFunctionReturn(0);
2209 }
2210 
2211 
2212 /* -------------------------------------------------------------------*/
2213 static struct _MatOps MatOps_Values = { MatSetValues_SeqDense,
2214                                         MatGetRow_SeqDense,
2215                                         MatRestoreRow_SeqDense,
2216                                         MatMult_SeqDense,
2217                                 /*  4*/ MatMultAdd_SeqDense,
2218                                         MatMultTranspose_SeqDense,
2219                                         MatMultTransposeAdd_SeqDense,
2220                                         0,
2221                                         0,
2222                                         0,
2223                                 /* 10*/ 0,
2224                                         MatLUFactor_SeqDense,
2225                                         MatCholeskyFactor_SeqDense,
2226                                         MatSOR_SeqDense,
2227                                         MatTranspose_SeqDense,
2228                                 /* 15*/ MatGetInfo_SeqDense,
2229                                         MatEqual_SeqDense,
2230                                         MatGetDiagonal_SeqDense,
2231                                         MatDiagonalScale_SeqDense,
2232                                         MatNorm_SeqDense,
2233                                 /* 20*/ MatAssemblyBegin_SeqDense,
2234                                         MatAssemblyEnd_SeqDense,
2235                                         MatSetOption_SeqDense,
2236                                         MatZeroEntries_SeqDense,
2237                                 /* 24*/ MatZeroRows_SeqDense,
2238                                         0,
2239                                         0,
2240                                         0,
2241                                         0,
2242                                 /* 29*/ MatSetUp_SeqDense,
2243                                         0,
2244                                         0,
2245                                         0,
2246                                         0,
2247                                 /* 34*/ MatDuplicate_SeqDense,
2248                                         0,
2249                                         0,
2250                                         0,
2251                                         0,
2252                                 /* 39*/ MatAXPY_SeqDense,
2253                                         MatCreateSubMatrices_SeqDense,
2254                                         0,
2255                                         MatGetValues_SeqDense,
2256                                         MatCopy_SeqDense,
2257                                 /* 44*/ MatGetRowMax_SeqDense,
2258                                         MatScale_SeqDense,
2259                                         MatShift_Basic,
2260                                         0,
2261                                         MatZeroRowsColumns_SeqDense,
2262                                 /* 49*/ MatSetRandom_SeqDense,
2263                                         0,
2264                                         0,
2265                                         0,
2266                                         0,
2267                                 /* 54*/ 0,
2268                                         0,
2269                                         0,
2270                                         0,
2271                                         0,
2272                                 /* 59*/ 0,
2273                                         MatDestroy_SeqDense,
2274                                         MatView_SeqDense,
2275                                         0,
2276                                         0,
2277                                 /* 64*/ 0,
2278                                         0,
2279                                         0,
2280                                         0,
2281                                         0,
2282                                 /* 69*/ MatGetRowMaxAbs_SeqDense,
2283                                         0,
2284                                         0,
2285                                         0,
2286                                         0,
2287                                 /* 74*/ 0,
2288                                         0,
2289                                         0,
2290                                         0,
2291                                         0,
2292                                 /* 79*/ 0,
2293                                         0,
2294                                         0,
2295                                         0,
2296                                 /* 83*/ MatLoad_SeqDense,
2297                                         0,
2298                                         MatIsHermitian_SeqDense,
2299                                         0,
2300                                         0,
2301                                         0,
2302                                 /* 89*/ MatMatMult_SeqDense_SeqDense,
2303                                         MatMatMultSymbolic_SeqDense_SeqDense,
2304                                         MatMatMultNumeric_SeqDense_SeqDense,
2305                                         MatPtAP_SeqDense_SeqDense,
2306                                         MatPtAPSymbolic_SeqDense_SeqDense,
2307                                 /* 94*/ MatPtAPNumeric_SeqDense_SeqDense,
2308                                         MatMatTransposeMult_SeqDense_SeqDense,
2309                                         MatMatTransposeMultSymbolic_SeqDense_SeqDense,
2310                                         MatMatTransposeMultNumeric_SeqDense_SeqDense,
2311                                         0,
2312                                 /* 99*/ 0,
2313                                         0,
2314                                         0,
2315                                         MatConjugate_SeqDense,
2316                                         0,
2317                                 /*104*/ 0,
2318                                         MatRealPart_SeqDense,
2319                                         MatImaginaryPart_SeqDense,
2320                                         0,
2321                                         0,
2322                                 /*109*/ 0,
2323                                         0,
2324                                         MatGetRowMin_SeqDense,
2325                                         MatGetColumnVector_SeqDense,
2326                                         MatMissingDiagonal_SeqDense,
2327                                 /*114*/ 0,
2328                                         0,
2329                                         0,
2330                                         0,
2331                                         0,
2332                                 /*119*/ 0,
2333                                         0,
2334                                         0,
2335                                         0,
2336                                         0,
2337                                 /*124*/ 0,
2338                                         MatGetColumnNorms_SeqDense,
2339                                         0,
2340                                         0,
2341                                         0,
2342                                 /*129*/ 0,
2343                                         MatTransposeMatMult_SeqDense_SeqDense,
2344                                         MatTransposeMatMultSymbolic_SeqDense_SeqDense,
2345                                         MatTransposeMatMultNumeric_SeqDense_SeqDense,
2346                                         0,
2347                                 /*134*/ 0,
2348                                         0,
2349                                         0,
2350                                         0,
2351                                         0,
2352                                 /*139*/ 0,
2353                                         0,
2354                                         0
2355 };
2356 
2357 /*@C
2358    MatCreateSeqDense - Creates a sequential dense matrix that
2359    is stored in column major order (the usual Fortran 77 manner). Many
2360    of the matrix operations use the BLAS and LAPACK routines.
2361 
2362    Collective on MPI_Comm
2363 
2364    Input Parameters:
2365 +  comm - MPI communicator, set to PETSC_COMM_SELF
2366 .  m - number of rows
2367 .  n - number of columns
2368 -  data - optional location of matrix data in column major order.  Set data=NULL for PETSc
2369    to control all matrix memory allocation.
2370 
2371    Output Parameter:
2372 .  A - the matrix
2373 
2374    Notes:
2375    The data input variable is intended primarily for Fortran programmers
2376    who wish to allocate their own matrix memory space.  Most users should
2377    set data=NULL.
2378 
2379    Level: intermediate
2380 
2381 .keywords: dense, matrix, LAPACK, BLAS
2382 
2383 .seealso: MatCreate(), MatCreateDense(), MatSetValues()
2384 @*/
2385 PetscErrorCode  MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A)
2386 {
2387   PetscErrorCode ierr;
2388 
2389   PetscFunctionBegin;
2390   ierr = MatCreate(comm,A);CHKERRQ(ierr);
2391   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
2392   ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr);
2393   ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr);
2394   PetscFunctionReturn(0);
2395 }
2396 
2397 /*@C
2398    MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements
2399 
2400    Collective on MPI_Comm
2401 
2402    Input Parameters:
2403 +  B - the matrix
2404 -  data - the array (or NULL)
2405 
2406    Notes:
2407    The data input variable is intended primarily for Fortran programmers
2408    who wish to allocate their own matrix memory space.  Most users should
2409    need not call this routine.
2410 
2411    Level: intermediate
2412 
2413 .keywords: dense, matrix, LAPACK, BLAS
2414 
2415 .seealso: MatCreate(), MatCreateDense(), MatSetValues(), MatSeqDenseSetLDA()
2416 
2417 @*/
2418 PetscErrorCode  MatSeqDenseSetPreallocation(Mat B,PetscScalar data[])
2419 {
2420   PetscErrorCode ierr;
2421 
2422   PetscFunctionBegin;
2423   ierr = PetscTryMethod(B,"MatSeqDenseSetPreallocation_C",(Mat,PetscScalar[]),(B,data));CHKERRQ(ierr);
2424   PetscFunctionReturn(0);
2425 }
2426 
2427 PetscErrorCode  MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data)
2428 {
2429   Mat_SeqDense   *b;
2430   PetscErrorCode ierr;
2431 
2432   PetscFunctionBegin;
2433   B->preallocated = PETSC_TRUE;
2434 
2435   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
2436   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
2437 
2438   b       = (Mat_SeqDense*)B->data;
2439   b->Mmax = B->rmap->n;
2440   b->Nmax = B->cmap->n;
2441   if (b->lda <= 0 || b->changelda) b->lda = B->rmap->n;
2442 
2443   ierr = PetscIntMultError(b->lda,b->Nmax,NULL);CHKERRQ(ierr);
2444   if (!data) { /* petsc-allocated storage */
2445     if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); }
2446     ierr = PetscCalloc1((size_t)b->lda*b->Nmax,&b->v);CHKERRQ(ierr);
2447     ierr = PetscLogObjectMemory((PetscObject)B,b->lda*b->Nmax*sizeof(PetscScalar));CHKERRQ(ierr);
2448 
2449     b->user_alloc = PETSC_FALSE;
2450   } else { /* user-allocated storage */
2451     if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); }
2452     b->v          = data;
2453     b->user_alloc = PETSC_TRUE;
2454   }
2455   B->assembled = PETSC_TRUE;
2456   PetscFunctionReturn(0);
2457 }
2458 
2459 #if defined(PETSC_HAVE_ELEMENTAL)
2460 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
2461 {
2462   Mat            mat_elemental;
2463   PetscErrorCode ierr;
2464   PetscScalar    *array,*v_colwise;
2465   PetscInt       M=A->rmap->N,N=A->cmap->N,i,j,k,*rows,*cols;
2466 
2467   PetscFunctionBegin;
2468   ierr = PetscMalloc3(M*N,&v_colwise,M,&rows,N,&cols);CHKERRQ(ierr);
2469   ierr = MatDenseGetArray(A,&array);CHKERRQ(ierr);
2470   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
2471   k = 0;
2472   for (j=0; j<N; j++) {
2473     cols[j] = j;
2474     for (i=0; i<M; i++) {
2475       v_colwise[j*M+i] = array[k++];
2476     }
2477   }
2478   for (i=0; i<M; i++) {
2479     rows[i] = i;
2480   }
2481   ierr = MatDenseRestoreArray(A,&array);CHKERRQ(ierr);
2482 
2483   ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
2484   ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
2485   ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
2486   ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
2487 
2488   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
2489   ierr = MatSetValues(mat_elemental,M,rows,N,cols,v_colwise,ADD_VALUES);CHKERRQ(ierr);
2490   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2491   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2492   ierr = PetscFree3(v_colwise,rows,cols);CHKERRQ(ierr);
2493 
2494   if (reuse == MAT_INPLACE_MATRIX) {
2495     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
2496   } else {
2497     *newmat = mat_elemental;
2498   }
2499   PetscFunctionReturn(0);
2500 }
2501 #endif
2502 
2503 /*@C
2504   MatSeqDenseSetLDA - Declare the leading dimension of the user-provided array
2505 
2506   Input parameter:
2507 + A - the matrix
2508 - lda - the leading dimension
2509 
2510   Notes:
2511   This routine is to be used in conjunction with MatSeqDenseSetPreallocation();
2512   it asserts that the preallocation has a leading dimension (the LDA parameter
2513   of Blas and Lapack fame) larger than M, the first dimension of the matrix.
2514 
2515   Level: intermediate
2516 
2517 .keywords: dense, matrix, LAPACK, BLAS
2518 
2519 .seealso: MatCreate(), MatCreateSeqDense(), MatSeqDenseSetPreallocation(), MatSetMaximumSize()
2520 
2521 @*/
2522 PetscErrorCode  MatSeqDenseSetLDA(Mat B,PetscInt lda)
2523 {
2524   Mat_SeqDense *b = (Mat_SeqDense*)B->data;
2525 
2526   PetscFunctionBegin;
2527   if (lda < B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"LDA %D must be at least matrix dimension %D",lda,B->rmap->n);
2528   b->lda       = lda;
2529   b->changelda = PETSC_FALSE;
2530   b->Mmax      = PetscMax(b->Mmax,lda);
2531   PetscFunctionReturn(0);
2532 }
2533 
2534 /*MC
2535    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
2536 
2537    Options Database Keys:
2538 . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions()
2539 
2540   Level: beginner
2541 
2542 .seealso: MatCreateSeqDense()
2543 
2544 M*/
2545 
2546 PETSC_EXTERN PetscErrorCode MatCreate_SeqDense(Mat B)
2547 {
2548   Mat_SeqDense   *b;
2549   PetscErrorCode ierr;
2550   PetscMPIInt    size;
2551 
2552   PetscFunctionBegin;
2553   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr);
2554   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
2555 
2556   ierr    = PetscNewLog(B,&b);CHKERRQ(ierr);
2557   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
2558   B->data = (void*)b;
2559 
2560   b->roworiented = PETSC_TRUE;
2561 
2562   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArray_C",MatDenseGetArray_SeqDense);CHKERRQ(ierr);
2563   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDensePlaceArray_C",MatDensePlaceArray_SeqDense);CHKERRQ(ierr);
2564   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseResetArray_C",MatDenseResetArray_SeqDense);CHKERRQ(ierr);
2565   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArray_C",MatDenseRestoreArray_SeqDense);CHKERRQ(ierr);
2566   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_seqaij_C",MatConvert_SeqDense_SeqAIJ);CHKERRQ(ierr);
2567 #if defined(PETSC_HAVE_ELEMENTAL)
2568   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_elemental_C",MatConvert_SeqDense_Elemental);CHKERRQ(ierr);
2569 #endif
2570   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",MatSeqDenseSetPreallocation_SeqDense);CHKERRQ(ierr);
2571   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_seqaij_seqdense_C",MatMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr);
2572   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_seqaij_seqdense_C",MatMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr);
2573   ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_seqaij_seqdense_C",MatMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr);
2574   ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_seqaij_seqdense_C",MatPtAP_SeqDense_SeqDense);CHKERRQ(ierr);
2575   ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMult_seqaij_seqdense_C",MatTransposeMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr);
2576   ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultSymbolic_seqaij_seqdense_C",MatTransposeMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr);
2577   ierr = PetscObjectComposeFunction((PetscObject)B,"MatTransposeMatMultNumeric_seqaij_seqdense_C",MatTransposeMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr);
2578   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQDENSE);CHKERRQ(ierr);
2579   PetscFunctionReturn(0);
2580 }
2581