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