xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 4e2f9904488dd406fb68cd588e33edb05ad91616)
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 (PetscDefined(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   }
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 SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_SUP,"Must call MatPtAPSymbolic_SeqDense_SeqDense() first");
161   PetscFunctionReturn(0);
162 }
163 
164 PetscErrorCode MatPtAPSymbolic_SeqDense_SeqDense(Mat A,Mat P,PetscReal fill,Mat C)
165 {
166   Mat_SeqDense   *c;
167   PetscBool      cisdense;
168   PetscErrorCode ierr;
169 
170   PetscFunctionBegin;
171   ierr = MatSetSizes(C,P->cmap->n,P->cmap->n,P->cmap->N,P->cmap->N);CHKERRQ(ierr);
172   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
173   if (!cisdense) {
174     PetscBool flg;
175 
176     ierr = PetscObjectTypeCompare((PetscObject)P,((PetscObject)A)->type_name,&flg);CHKERRQ(ierr);
177     ierr = MatSetType(C,flg ? ((PetscObject)A)->type_name : MATDENSE);CHKERRQ(ierr);
178   }
179   ierr = MatSetUp(C);CHKERRQ(ierr);
180   c    = (Mat_SeqDense*)C->data;
181   ierr = MatCreate(PetscObjectComm((PetscObject)A),&c->ptapwork);CHKERRQ(ierr);
182   ierr = MatSetSizes(c->ptapwork,A->rmap->n,P->cmap->n,A->rmap->N,P->cmap->N);CHKERRQ(ierr);
183   ierr = MatSetType(c->ptapwork,((PetscObject)C)->type_name);CHKERRQ(ierr);
184   ierr = MatSetUp(c->ptapwork);CHKERRQ(ierr);
185   PetscFunctionReturn(0);
186 }
187 
188 PETSC_INTERN PetscErrorCode MatConvert_SeqAIJ_SeqDense(Mat A,MatType newtype,MatReuse reuse,Mat *newmat)
189 {
190   Mat             B = NULL;
191   Mat_SeqAIJ      *a = (Mat_SeqAIJ*)A->data;
192   Mat_SeqDense    *b;
193   PetscErrorCode  ierr;
194   PetscInt        *ai=a->i,*aj=a->j,m=A->rmap->N,n=A->cmap->N,i;
195   const MatScalar *av;
196   PetscBool       isseqdense;
197 
198   PetscFunctionBegin;
199   if (reuse == MAT_REUSE_MATRIX) {
200     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
201     if (!isseqdense) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name);
202   }
203   if (reuse != MAT_REUSE_MATRIX) {
204     ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
205     ierr = MatSetSizes(B,m,n,m,n);CHKERRQ(ierr);
206     ierr = MatSetType(B,MATSEQDENSE);CHKERRQ(ierr);
207     ierr = MatSeqDenseSetPreallocation(B,NULL);CHKERRQ(ierr);
208     b    = (Mat_SeqDense*)(B->data);
209   } else {
210     b    = (Mat_SeqDense*)((*newmat)->data);
211     ierr = PetscArrayzero(b->v,m*n);CHKERRQ(ierr);
212   }
213   ierr = MatSeqAIJGetArrayRead(A,&av);CHKERRQ(ierr);
214   for (i=0; i<m; i++) {
215     PetscInt j;
216     for (j=0;j<ai[1]-ai[0];j++) {
217       b->v[*aj*m+i] = *av;
218       aj++;
219       av++;
220     }
221     ai++;
222   }
223   ierr = MatSeqAIJRestoreArrayRead(A,&av);CHKERRQ(ierr);
224 
225   if (reuse == MAT_INPLACE_MATRIX) {
226     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
227     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
228     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
229   } else {
230     if (B) *newmat = B;
231     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
232     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
233   }
234   PetscFunctionReturn(0);
235 }
236 
237 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_SeqAIJ(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
238 {
239   Mat            B = NULL;
240   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
241   PetscErrorCode ierr;
242   PetscInt       i, j;
243   PetscInt       *rows, *nnz;
244   MatScalar      *aa = a->v, *vals;
245 
246   PetscFunctionBegin;
247   ierr = PetscCalloc3(A->rmap->n,&rows,A->rmap->n,&nnz,A->rmap->n,&vals);CHKERRQ(ierr);
248   if (reuse != MAT_REUSE_MATRIX) {
249     ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr);
250     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
251     ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr);
252     for (j=0; j<A->cmap->n; j++) {
253       for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) ++nnz[i];
254       aa += a->lda;
255     }
256     ierr = MatSeqAIJSetPreallocation(B,PETSC_DETERMINE,nnz);CHKERRQ(ierr);
257   } else B = *newmat;
258   aa = a->v;
259   for (j=0; j<A->cmap->n; j++) {
260     PetscInt numRows = 0;
261     for (i=0; i<A->rmap->n; i++) if (aa[i] != 0.0 || (i == j && A->cmap->n == A->rmap->n)) {rows[numRows] = i; vals[numRows++] = aa[i];}
262     ierr = MatSetValues(B,numRows,rows,1,&j,vals,INSERT_VALUES);CHKERRQ(ierr);
263     aa  += a->lda;
264   }
265   ierr = PetscFree3(rows,nnz,vals);CHKERRQ(ierr);
266   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
267   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
268 
269   if (reuse == MAT_INPLACE_MATRIX) {
270     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
271   } else if (reuse != MAT_REUSE_MATRIX) *newmat = B;
272   PetscFunctionReturn(0);
273 }
274 
275 PetscErrorCode MatAXPY_SeqDense(Mat Y,PetscScalar alpha,Mat X,MatStructure str)
276 {
277   Mat_SeqDense      *x = (Mat_SeqDense*)X->data,*y = (Mat_SeqDense*)Y->data;
278   const PetscScalar *xv;
279   PetscScalar       *yv;
280   PetscBLASInt      N,m,ldax = 0,lday = 0,one = 1;
281   PetscErrorCode    ierr;
282 
283   PetscFunctionBegin;
284   ierr = MatDenseGetArrayRead(X,&xv);CHKERRQ(ierr);
285   ierr = MatDenseGetArray(Y,&yv);CHKERRQ(ierr);
286   ierr = PetscBLASIntCast(X->rmap->n*X->cmap->n,&N);CHKERRQ(ierr);
287   ierr = PetscBLASIntCast(X->rmap->n,&m);CHKERRQ(ierr);
288   ierr = PetscBLASIntCast(x->lda,&ldax);CHKERRQ(ierr);
289   ierr = PetscBLASIntCast(y->lda,&lday);CHKERRQ(ierr);
290   if (ldax>m || lday>m) {
291     PetscInt j;
292 
293     for (j=0; j<X->cmap->n; j++) {
294       PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&m,&alpha,xv+j*ldax,&one,yv+j*lday,&one));
295     }
296   } else {
297     PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&N,&alpha,xv,&one,yv,&one));
298   }
299   ierr = MatDenseRestoreArrayRead(X,&xv);CHKERRQ(ierr);
300   ierr = MatDenseRestoreArray(Y,&yv);CHKERRQ(ierr);
301   ierr = PetscLogFlops(PetscMax(2.0*N-1,0));CHKERRQ(ierr);
302   PetscFunctionReturn(0);
303 }
304 
305 static PetscErrorCode MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info)
306 {
307   PetscLogDouble N = A->rmap->n*A->cmap->n;
308 
309   PetscFunctionBegin;
310   info->block_size        = 1.0;
311   info->nz_allocated      = N;
312   info->nz_used           = N;
313   info->nz_unneeded       = 0;
314   info->assemblies        = A->num_ass;
315   info->mallocs           = 0;
316   info->memory            = ((PetscObject)A)->mem;
317   info->fill_ratio_given  = 0;
318   info->fill_ratio_needed = 0;
319   info->factor_mallocs    = 0;
320   PetscFunctionReturn(0);
321 }
322 
323 PetscErrorCode MatScale_SeqDense(Mat A,PetscScalar alpha)
324 {
325   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
326   PetscScalar    *v;
327   PetscErrorCode ierr;
328   PetscBLASInt   one = 1,j,nz,lda = 0;
329 
330   PetscFunctionBegin;
331   ierr = MatDenseGetArray(A,&v);CHKERRQ(ierr);
332   ierr = PetscBLASIntCast(a->lda,&lda);CHKERRQ(ierr);
333   if (lda>A->rmap->n) {
334     ierr = PetscBLASIntCast(A->rmap->n,&nz);CHKERRQ(ierr);
335     for (j=0; j<A->cmap->n; j++) {
336       PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&alpha,v+j*lda,&one));
337     }
338   } else {
339     ierr = PetscBLASIntCast(A->rmap->n*A->cmap->n,&nz);CHKERRQ(ierr);
340     PetscStackCallBLAS("BLASscal",BLASscal_(&nz,&alpha,v,&one));
341   }
342   ierr = PetscLogFlops(nz);CHKERRQ(ierr);
343   ierr = MatDenseRestoreArray(A,&v);CHKERRQ(ierr);
344   PetscFunctionReturn(0);
345 }
346 
347 static PetscErrorCode MatIsHermitian_SeqDense(Mat A,PetscReal rtol,PetscBool  *fl)
348 {
349   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
350   PetscInt          i,j,m = A->rmap->n,N = a->lda;
351   const PetscScalar *v;
352   PetscErrorCode    ierr;
353 
354   PetscFunctionBegin;
355   *fl = PETSC_FALSE;
356   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(0);
357   ierr = MatDenseGetArrayRead(A,&v);CHKERRQ(ierr);
358   for (i=0; i<m; i++) {
359     for (j=i; j<m; j++) {
360       if (PetscAbsScalar(v[i+j*N] - PetscConj(v[j+i*N])) > rtol) {
361         goto restore;
362       }
363     }
364   }
365   *fl  = PETSC_TRUE;
366 restore:
367   ierr = MatDenseRestoreArrayRead(A,&v);CHKERRQ(ierr);
368   PetscFunctionReturn(0);
369 }
370 
371 static PetscErrorCode MatIsSymmetric_SeqDense(Mat A,PetscReal rtol,PetscBool  *fl)
372 {
373   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
374   PetscInt          i,j,m = A->rmap->n,N = a->lda;
375   const PetscScalar *v;
376   PetscErrorCode    ierr;
377 
378   PetscFunctionBegin;
379   *fl = PETSC_FALSE;
380   if (A->rmap->n != A->cmap->n) PetscFunctionReturn(0);
381   ierr = MatDenseGetArrayRead(A,&v);CHKERRQ(ierr);
382   for (i=0; i<m; i++) {
383     for (j=i; j<m; j++) {
384       if (PetscAbsScalar(v[i+j*N] - v[j+i*N]) > rtol) {
385         goto restore;
386       }
387     }
388   }
389   *fl  = PETSC_TRUE;
390 restore:
391   ierr = MatDenseRestoreArrayRead(A,&v);CHKERRQ(ierr);
392   PetscFunctionReturn(0);
393 }
394 
395 PetscErrorCode MatDuplicateNoCreate_SeqDense(Mat newi,Mat A,MatDuplicateOption cpvalues)
396 {
397   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
398   PetscErrorCode ierr;
399   PetscInt       lda = (PetscInt)mat->lda,j,m,nlda = lda;
400 
401   PetscFunctionBegin;
402   ierr = PetscLayoutReference(A->rmap,&newi->rmap);CHKERRQ(ierr);
403   ierr = PetscLayoutReference(A->cmap,&newi->cmap);CHKERRQ(ierr);
404   if (cpvalues == MAT_SHARE_NONZERO_PATTERN) { /* propagate LDA */
405     ierr = MatDenseSetLDA(newi,lda);CHKERRQ(ierr);
406   }
407   ierr = MatSeqDenseSetPreallocation(newi,NULL);CHKERRQ(ierr);
408   if (cpvalues == MAT_COPY_VALUES) {
409     const PetscScalar *av;
410     PetscScalar       *v;
411 
412     ierr = MatDenseGetArrayRead(A,&av);CHKERRQ(ierr);
413     ierr = MatDenseGetArray(newi,&v);CHKERRQ(ierr);
414     ierr = MatDenseGetLDA(newi,&nlda);CHKERRQ(ierr);
415     m    = A->rmap->n;
416     if (lda>m || nlda>m) {
417       for (j=0; j<A->cmap->n; j++) {
418         ierr = PetscArraycpy(v+j*nlda,av+j*lda,m);CHKERRQ(ierr);
419       }
420     } else {
421       ierr = PetscArraycpy(v,av,A->rmap->n*A->cmap->n);CHKERRQ(ierr);
422     }
423     ierr = MatDenseRestoreArray(newi,&v);CHKERRQ(ierr);
424     ierr = MatDenseRestoreArrayRead(A,&av);CHKERRQ(ierr);
425   }
426   PetscFunctionReturn(0);
427 }
428 
429 PetscErrorCode MatDuplicate_SeqDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
430 {
431   PetscErrorCode ierr;
432 
433   PetscFunctionBegin;
434   ierr = MatCreate(PetscObjectComm((PetscObject)A),newmat);CHKERRQ(ierr);
435   ierr = MatSetSizes(*newmat,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
436   ierr = MatSetType(*newmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
437   ierr = MatDuplicateNoCreate_SeqDense(*newmat,A,cpvalues);CHKERRQ(ierr);
438   PetscFunctionReturn(0);
439 }
440 
441 static PetscErrorCode MatSolve_SeqDense_Internal_LU(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
442 {
443   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
444   PetscBLASInt    info;
445   PetscErrorCode  ierr;
446 
447   PetscFunctionBegin;
448   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
449   PetscStackCallBLAS("LAPACKgetrs",LAPACKgetrs_(T ? "T" : "N",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
450   ierr = PetscFPTrapPop();CHKERRQ(ierr);
451   if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"GETRS - Bad solve");
452   ierr = PetscLogFlops(nrhs*(2.0*m*m - m));CHKERRQ(ierr);
453   PetscFunctionReturn(0);
454 }
455 
456 static PetscErrorCode MatConjugate_SeqDense(Mat);
457 
458 static PetscErrorCode MatSolve_SeqDense_Internal_Cholesky(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k, PetscBool T)
459 {
460   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
461   PetscBLASInt    info;
462   PetscErrorCode  ierr;
463 
464   PetscFunctionBegin;
465   if (A->spd) {
466     if (PetscDefined(USE_COMPLEX) && T) {ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr);}
467     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
468     PetscStackCallBLAS("LAPACKpotrs",LAPACKpotrs_("L",&m,&nrhs,mat->v,&mat->lda,x,&m,&info));
469     ierr = PetscFPTrapPop();CHKERRQ(ierr);
470     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"POTRS Bad solve");
471     if (PetscDefined(USE_COMPLEX) && T) {ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr);}
472 #if defined(PETSC_USE_COMPLEX)
473   } else if (A->hermitian) {
474     if (T) {ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr);}
475     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
476     PetscStackCallBLAS("LAPACKhetrs",LAPACKhetrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
477     ierr = PetscFPTrapPop();CHKERRQ(ierr);
478     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"HETRS Bad solve");
479     if (T) {ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr);}
480 #endif
481   } else { /* symmetric case */
482     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
483     PetscStackCallBLAS("LAPACKsytrs",LAPACKsytrs_("L",&m,&nrhs,mat->v,&mat->lda,mat->pivots,x,&m,&info));
484     ierr = PetscFPTrapPop();CHKERRQ(ierr);
485     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"SYTRS Bad solve");
486   }
487   ierr = PetscLogFlops(nrhs*(2.0*m*m - m));CHKERRQ(ierr);
488   PetscFunctionReturn(0);
489 }
490 
491 static PetscErrorCode MatSolve_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
492 {
493   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
494   PetscBLASInt    info;
495   char            trans;
496   PetscErrorCode  ierr;
497 
498   PetscFunctionBegin;
499   if (PetscDefined(USE_COMPLEX)) {
500     trans = 'C';
501   } else {
502     trans = 'T';
503   }
504   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
505   PetscStackCallBLAS("LAPACKormqr",LAPACKormqr_("L", &trans, &m,&nrhs,&mat->rank,mat->v,&mat->lda,mat->tau,x,&ldx,mat->fwork,&mat->lfwork,&info));
506   ierr = PetscFPTrapPop();CHKERRQ(ierr);
507   if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ORMQR - Bad orthogonal transform");
508   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
509   PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U", "N", "N", &mat->rank,&nrhs,mat->v,&mat->lda,x,&ldx,&info));
510   ierr = PetscFPTrapPop();CHKERRQ(ierr);
511   if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"TRTRS - Bad triangular solve");
512   for (PetscInt j = 0; j < nrhs; j++) {
513     for (PetscInt i = mat->rank; i < k; i++) {
514       x[j*ldx + i] = 0.;
515     }
516   }
517   ierr = PetscLogFlops(nrhs*(4.0*m*mat->rank - PetscSqr(mat->rank)));CHKERRQ(ierr);
518   PetscFunctionReturn(0);
519 }
520 
521 static PetscErrorCode MatSolveTranspose_SeqDense_Internal_QR(Mat A, PetscScalar *x, PetscBLASInt ldx, PetscBLASInt m, PetscBLASInt nrhs, PetscBLASInt k)
522 {
523   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
524   PetscBLASInt      info;
525   PetscErrorCode    ierr;
526 
527   PetscFunctionBegin;
528   if (A->rmap->n == A->cmap->n && mat->rank == A->rmap->n) {
529     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
530     PetscStackCallBLAS("LAPACKtrtrs",LAPACKtrtrs_("U", "T", "N", &m,&nrhs,mat->v,&mat->lda,x,&ldx,&info));
531     ierr = PetscFPTrapPop();CHKERRQ(ierr);
532     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"TRTRS - Bad triangular solve");
533     if (PetscDefined(USE_COMPLEX)) {ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr);}
534     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
535     PetscStackCallBLAS("LAPACKormqr",LAPACKormqr_("L", "N", &m,&nrhs,&mat->rank,mat->v,&mat->lda,mat->tau,x,&ldx,mat->fwork,&mat->lfwork,&info));
536     ierr = PetscFPTrapPop();CHKERRQ(ierr);
537     if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ORMQR - Bad orthogonal transform");
538     if (PetscDefined(USE_COMPLEX)) {ierr = MatConjugate_SeqDense(A);CHKERRQ(ierr);}
539   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"QR factored matrix cannot be used for transpose solve");
540   ierr = PetscLogFlops(nrhs*(4.0*m*mat->rank - PetscSqr(mat->rank)));CHKERRQ(ierr);
541   PetscFunctionReturn(0);
542 }
543 
544 static PetscErrorCode MatSolve_SeqDense_SetUp(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
545 {
546   Mat_SeqDense      *mat = (Mat_SeqDense *) A->data;
547   PetscScalar       *y;
548   PetscBLASInt      m=0, k=0;
549   PetscErrorCode    ierr;
550 
551   PetscFunctionBegin;
552   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
553   ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr);
554   if (k < m) {
555     ierr = VecCopy(xx, mat->qrrhs);CHKERRQ(ierr);
556     ierr = VecGetArray(mat->qrrhs,&y);CHKERRQ(ierr);
557   } else {
558     ierr = VecCopy(xx, yy);CHKERRQ(ierr);
559     ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
560   }
561   *_y = y;
562   *_k = k;
563   *_m = m;
564   PetscFunctionReturn(0);
565 }
566 
567 static PetscErrorCode MatSolve_SeqDense_TearDown(Mat A, Vec xx, Vec yy, PetscScalar **_y, PetscBLASInt *_m, PetscBLASInt *_k)
568 {
569   Mat_SeqDense   *mat = (Mat_SeqDense *) A->data;
570   PetscScalar    *y = NULL;
571   PetscBLASInt   m, k;
572   PetscErrorCode ierr;
573 
574   PetscFunctionBegin;
575   y   = *_y;
576   *_y = NULL;
577   k   = *_k;
578   m   = *_m;
579   if (k < m) {
580     PetscScalar *yv;
581     ierr = VecGetArray(yy,&yv);CHKERRQ(ierr);
582     ierr = PetscArraycpy(yv, y, k);CHKERRQ(ierr);
583     ierr = VecRestoreArray(yy,&yv);CHKERRQ(ierr);
584     ierr = VecRestoreArray(mat->qrrhs, &y);CHKERRQ(ierr);
585   } else {
586     ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
587   }
588   PetscFunctionReturn(0);
589 }
590 
591 static PetscErrorCode MatSolve_SeqDense_LU(Mat A, Vec xx, Vec yy)
592 {
593   PetscScalar    *y = NULL;
594   PetscBLASInt   m = 0, k = 0;
595   PetscErrorCode ierr;
596 
597   PetscFunctionBegin;
598   ierr = MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
599   ierr = MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_FALSE);CHKERRQ(ierr);
600   ierr = MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
601   PetscFunctionReturn(0);
602 }
603 
604 static PetscErrorCode MatSolveTranspose_SeqDense_LU(Mat A, Vec xx, Vec yy)
605 {
606   PetscScalar    *y = NULL;
607   PetscBLASInt   m = 0, k = 0;
608   PetscErrorCode ierr;
609 
610   PetscFunctionBegin;
611   ierr = MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
612   ierr = MatSolve_SeqDense_Internal_LU(A, y, m, m, 1, k, PETSC_TRUE);CHKERRQ(ierr);
613   ierr = MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
614   PetscFunctionReturn(0);
615 }
616 
617 static PetscErrorCode MatSolve_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
618 {
619   PetscScalar    *y = NULL;
620   PetscBLASInt   m = 0, k = 0;
621   PetscErrorCode ierr;
622 
623   PetscFunctionBegin;
624   ierr = MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
625   ierr = MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_FALSE);CHKERRQ(ierr);
626   ierr = MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
627   PetscFunctionReturn(0);
628 }
629 
630 static PetscErrorCode MatSolveTranspose_SeqDense_Cholesky(Mat A, Vec xx, Vec yy)
631 {
632   PetscScalar    *y = NULL;
633   PetscBLASInt   m = 0, k = 0;
634   PetscErrorCode ierr;
635 
636   PetscFunctionBegin;
637   ierr = MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
638   ierr = MatSolve_SeqDense_Internal_Cholesky(A, y, m, m, 1, k, PETSC_TRUE);CHKERRQ(ierr);
639   ierr = MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
640   PetscFunctionReturn(0);
641 }
642 
643 static PetscErrorCode MatSolve_SeqDense_QR(Mat A, Vec xx, Vec yy)
644 {
645   PetscScalar    *y = NULL;
646   PetscBLASInt   m = 0, k = 0;
647   PetscErrorCode ierr;
648 
649   PetscFunctionBegin;
650   ierr = MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
651   ierr = MatSolve_SeqDense_Internal_QR(A, y, PetscMax(m,k), m, 1, k);CHKERRQ(ierr);
652   ierr = MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
653   PetscFunctionReturn(0);
654 }
655 
656 static PetscErrorCode MatSolveTranspose_SeqDense_QR(Mat A, Vec xx, Vec yy)
657 {
658   PetscScalar    *y = NULL;
659   PetscBLASInt   m = 0, k = 0;
660   PetscErrorCode ierr;
661 
662   PetscFunctionBegin;
663   ierr = MatSolve_SeqDense_SetUp(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
664   ierr = MatSolveTranspose_SeqDense_Internal_QR(A, y, PetscMax(m,k), m, 1, k);CHKERRQ(ierr);
665   ierr = MatSolve_SeqDense_TearDown(A, xx, yy, &y, &m, &k);CHKERRQ(ierr);
666   PetscFunctionReturn(0);
667 }
668 
669 static PetscErrorCode MatMatSolve_SeqDense_SetUp(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
670 {
671   PetscErrorCode    ierr;
672   const PetscScalar *b;
673   PetscScalar       *y;
674   PetscInt          n, _ldb, _ldx;
675   PetscBLASInt      nrhs=0,m=0,k=0,ldb=0,ldx=0,ldy=0;
676 
677   PetscFunctionBegin;
678   *_ldy=0; *_m=0; *_nrhs=0; *_k=0; *_y = NULL;
679   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
680   ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr);
681   ierr = MatGetSize(B,NULL,&n);CHKERRQ(ierr);
682   ierr = PetscBLASIntCast(n,&nrhs);CHKERRQ(ierr);
683   ierr = MatDenseGetLDA(B,&_ldb);CHKERRQ(ierr);
684   ierr = PetscBLASIntCast(_ldb, &ldb);CHKERRQ(ierr);
685   ierr = MatDenseGetLDA(X,&_ldx);CHKERRQ(ierr);
686   ierr = PetscBLASIntCast(_ldx, &ldx);CHKERRQ(ierr);
687   if (ldx < m) {
688     ierr = MatDenseGetArrayRead(B,&b);CHKERRQ(ierr);
689     ierr = PetscMalloc1(nrhs * m, &y);CHKERRQ(ierr);
690     if (ldb == m) {
691       ierr = PetscArraycpy(y,b,ldb*nrhs);CHKERRQ(ierr);
692     } else {
693       for (PetscInt j = 0; j < nrhs; j++) {
694         ierr = PetscArraycpy(&y[j*m],&b[j*ldb],m);CHKERRQ(ierr);
695       }
696     }
697     ldy = m;
698     ierr = MatDenseRestoreArrayRead(B,&b);CHKERRQ(ierr);
699   } else {
700     if (ldb == ldx) {
701       ierr = MatCopy(B, X, SAME_NONZERO_PATTERN);CHKERRQ(ierr);
702       ierr = MatDenseGetArray(X,&y);CHKERRQ(ierr);
703     } else {
704       ierr = MatDenseGetArray(X,&y);CHKERRQ(ierr);
705       ierr = MatDenseGetArrayRead(B,&b);CHKERRQ(ierr);
706       for (PetscInt j = 0; j < nrhs; j++) {
707         ierr = PetscArraycpy(&y[j*ldx],&b[j*ldb],m);CHKERRQ(ierr);
708       }
709       ierr = MatDenseRestoreArrayRead(B,&b);CHKERRQ(ierr);
710     }
711     ldy = ldx;
712   }
713   *_y    = y;
714   *_ldy = ldy;
715   *_k    = k;
716   *_m    = m;
717   *_nrhs = nrhs;
718   PetscFunctionReturn(0);
719 }
720 
721 static PetscErrorCode MatMatSolve_SeqDense_TearDown(Mat A, Mat B, Mat X, PetscScalar **_y, PetscBLASInt *_ldy, PetscBLASInt *_m, PetscBLASInt *_nrhs, PetscBLASInt *_k)
722 {
723   PetscScalar       *y;
724   PetscInt          _ldx;
725   PetscBLASInt      k,ldy,nrhs,ldx=0;
726   PetscErrorCode    ierr;
727 
728   PetscFunctionBegin;
729   y    = *_y;
730   *_y  = NULL;
731   k    = *_k;
732   ldy = *_ldy;
733   nrhs = *_nrhs;
734   ierr = MatDenseGetLDA(X,&_ldx);CHKERRQ(ierr);
735   ierr = PetscBLASIntCast(_ldx, &ldx);CHKERRQ(ierr);
736   if (ldx != ldy) {
737     PetscScalar *xv;
738     ierr = MatDenseGetArray(X,&xv);CHKERRQ(ierr);
739     for (PetscInt j = 0; j < nrhs; j++) {
740       ierr = PetscArraycpy(&xv[j*ldx],&y[j*ldy],k);CHKERRQ(ierr);
741     }
742     ierr = MatDenseRestoreArray(X,&xv);CHKERRQ(ierr);
743     ierr = PetscFree(y);CHKERRQ(ierr);
744   } else {
745     ierr = MatDenseRestoreArray(X,&y);CHKERRQ(ierr);
746   }
747   PetscFunctionReturn(0);
748 }
749 
750 static PetscErrorCode MatMatSolve_SeqDense_LU(Mat A, Mat B, Mat X)
751 {
752   PetscScalar    *y;
753   PetscBLASInt   m, k, ldy, nrhs;
754   PetscErrorCode ierr;
755 
756   PetscFunctionBegin;
757   ierr = MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
758   ierr = MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_FALSE);CHKERRQ(ierr);
759   ierr = MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
760   PetscFunctionReturn(0);
761 }
762 
763 static PetscErrorCode MatMatSolveTranspose_SeqDense_LU(Mat A, Mat B, Mat X)
764 {
765   PetscScalar    *y;
766   PetscBLASInt   m, k, ldy, nrhs;
767   PetscErrorCode ierr;
768 
769   PetscFunctionBegin;
770   ierr = MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
771   ierr = MatSolve_SeqDense_Internal_LU(A, y, ldy, m, nrhs, k, PETSC_TRUE);CHKERRQ(ierr);
772   ierr = MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
773   PetscFunctionReturn(0);
774 }
775 
776 static PetscErrorCode MatMatSolve_SeqDense_Cholesky(Mat A, Mat B, Mat X)
777 {
778   PetscScalar    *y;
779   PetscBLASInt   m, k, ldy, nrhs;
780   PetscErrorCode ierr;
781 
782   PetscFunctionBegin;
783   ierr = MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
784   ierr = MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_FALSE);CHKERRQ(ierr);
785   ierr = MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
786   PetscFunctionReturn(0);
787 }
788 
789 static PetscErrorCode MatMatSolveTranspose_SeqDense_Cholesky(Mat A, Mat B, Mat X)
790 {
791   PetscScalar    *y;
792   PetscBLASInt   m, k, ldy, nrhs;
793   PetscErrorCode ierr;
794 
795   PetscFunctionBegin;
796   ierr = MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
797   ierr = MatSolve_SeqDense_Internal_Cholesky(A, y, ldy, m, nrhs, k, PETSC_TRUE);CHKERRQ(ierr);
798   ierr = MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
799   PetscFunctionReturn(0);
800 }
801 
802 static PetscErrorCode MatMatSolve_SeqDense_QR(Mat A, Mat B, Mat X)
803 {
804   PetscScalar    *y;
805   PetscBLASInt   m, k, ldy, nrhs;
806   PetscErrorCode ierr;
807 
808   PetscFunctionBegin;
809   ierr = MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
810   ierr = MatSolve_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k);CHKERRQ(ierr);
811   ierr = MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
812   PetscFunctionReturn(0);
813 }
814 
815 static PetscErrorCode MatMatSolveTranspose_SeqDense_QR(Mat A, Mat B, Mat X)
816 {
817   PetscScalar    *y;
818   PetscBLASInt   m, k, ldy, nrhs;
819   PetscErrorCode ierr;
820 
821   PetscFunctionBegin;
822   ierr = MatMatSolve_SeqDense_SetUp(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
823   ierr = MatSolveTranspose_SeqDense_Internal_QR(A, y, ldy, m, nrhs, k);CHKERRQ(ierr);
824   ierr = MatMatSolve_SeqDense_TearDown(A, B, X, &y, &ldy, &m, &nrhs, &k);CHKERRQ(ierr);
825   PetscFunctionReturn(0);
826 }
827 
828 static PetscErrorCode MatConjugate_SeqDense(Mat);
829 
830 /* ---------------------------------------------------------------*/
831 /* COMMENT: I have chosen to hide row permutation in the pivots,
832    rather than put it in the Mat->row slot.*/
833 PetscErrorCode MatLUFactor_SeqDense(Mat A,IS row,IS col,const MatFactorInfo *minfo)
834 {
835   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
836   PetscErrorCode ierr;
837   PetscBLASInt   n,m,info;
838 
839   PetscFunctionBegin;
840   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
841   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
842   if (!mat->pivots) {
843     ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr);
844     ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr);
845   }
846   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
847   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
848   PetscStackCallBLAS("LAPACKgetrf",LAPACKgetrf_(&m,&n,mat->v,&mat->lda,mat->pivots,&info));
849   ierr = PetscFPTrapPop();CHKERRQ(ierr);
850 
851   if (info<0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to LU factorization");
852   if (info>0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
853 
854   A->ops->solve             = MatSolve_SeqDense_LU;
855   A->ops->matsolve          = MatMatSolve_SeqDense_LU;
856   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_LU;
857   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_LU;
858   A->factortype             = MAT_FACTOR_LU;
859 
860   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
861   ierr = PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);CHKERRQ(ierr);
862 
863   ierr = PetscLogFlops((2.0*A->cmap->n*A->cmap->n*A->cmap->n)/3);CHKERRQ(ierr);
864   PetscFunctionReturn(0);
865 }
866 
867 static PetscErrorCode MatLUFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy)
868 {
869   MatFactorInfo  info;
870   PetscErrorCode ierr;
871 
872   PetscFunctionBegin;
873   ierr = MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);CHKERRQ(ierr);
874   ierr = (*fact->ops->lufactor)(fact,NULL,NULL,&info);CHKERRQ(ierr);
875   PetscFunctionReturn(0);
876 }
877 
878 PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,IS col,const MatFactorInfo *info)
879 {
880   PetscFunctionBegin;
881   fact->preallocated           = PETSC_TRUE;
882   fact->assembled              = PETSC_TRUE;
883   fact->ops->lufactornumeric   = MatLUFactorNumeric_SeqDense;
884   PetscFunctionReturn(0);
885 }
886 
887 /* Cholesky as L*L^T or L*D*L^T and the symmetric/hermitian complex variants */
888 PetscErrorCode MatCholeskyFactor_SeqDense(Mat A,IS perm,const MatFactorInfo *factinfo)
889 {
890   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
891   PetscErrorCode ierr;
892   PetscBLASInt   info,n;
893 
894   PetscFunctionBegin;
895   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
896   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
897   if (A->spd) {
898     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
899     PetscStackCallBLAS("LAPACKpotrf",LAPACKpotrf_("L",&n,mat->v,&mat->lda,&info));
900     ierr = PetscFPTrapPop();CHKERRQ(ierr);
901 #if defined(PETSC_USE_COMPLEX)
902   } else if (A->hermitian) {
903     if (!mat->pivots) {
904       ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr);
905       ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr);
906     }
907     if (!mat->fwork) {
908       PetscScalar dummy;
909 
910       mat->lfwork = -1;
911       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
912       PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info));
913       ierr = PetscFPTrapPop();CHKERRQ(ierr);
914       mat->lfwork = (PetscInt)PetscRealPart(dummy);
915       ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr);
916       ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr);
917     }
918     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
919     PetscStackCallBLAS("LAPACKhetrf",LAPACKhetrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
920     ierr = PetscFPTrapPop();CHKERRQ(ierr);
921 #endif
922   } else { /* symmetric case */
923     if (!mat->pivots) {
924       ierr = PetscMalloc1(A->rmap->n,&mat->pivots);CHKERRQ(ierr);
925       ierr = PetscLogObjectMemory((PetscObject)A,A->rmap->n*sizeof(PetscBLASInt));CHKERRQ(ierr);
926     }
927     if (!mat->fwork) {
928       PetscScalar dummy;
929 
930       mat->lfwork = -1;
931       ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
932       PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,&dummy,&mat->lfwork,&info));
933       ierr = PetscFPTrapPop();CHKERRQ(ierr);
934       mat->lfwork = (PetscInt)PetscRealPart(dummy);
935       ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr);
936       ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr);
937     }
938     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
939     PetscStackCallBLAS("LAPACKsytrf",LAPACKsytrf_("L",&n,mat->v,&mat->lda,mat->pivots,mat->fwork,&mat->lfwork,&info));
940     ierr = PetscFPTrapPop();CHKERRQ(ierr);
941   }
942   if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_MAT_CH_ZRPVT,"Bad factorization: zero pivot in row %D",(PetscInt)info-1);
943 
944   A->ops->solve             = MatSolve_SeqDense_Cholesky;
945   A->ops->matsolve          = MatMatSolve_SeqDense_Cholesky;
946   A->ops->solvetranspose    = MatSolveTranspose_SeqDense_Cholesky;
947   A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_Cholesky;
948   A->factortype             = MAT_FACTOR_CHOLESKY;
949 
950   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
951   ierr = PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);CHKERRQ(ierr);
952 
953   ierr = PetscLogFlops((1.0*A->cmap->n*A->cmap->n*A->cmap->n)/3.0);CHKERRQ(ierr);
954   PetscFunctionReturn(0);
955 }
956 
957 static PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy)
958 {
959   PetscErrorCode ierr;
960   MatFactorInfo  info;
961 
962   PetscFunctionBegin;
963   info.fill = 1.0;
964 
965   ierr = MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);CHKERRQ(ierr);
966   ierr = (*fact->ops->choleskyfactor)(fact,NULL,&info);CHKERRQ(ierr);
967   PetscFunctionReturn(0);
968 }
969 
970 PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,const MatFactorInfo *info)
971 {
972   PetscFunctionBegin;
973   fact->assembled                  = PETSC_TRUE;
974   fact->preallocated               = PETSC_TRUE;
975   fact->ops->choleskyfactornumeric = MatCholeskyFactorNumeric_SeqDense;
976   PetscFunctionReturn(0);
977 }
978 
979 PetscErrorCode MatQRFactor_SeqDense(Mat A,IS col,const MatFactorInfo *minfo)
980 {
981   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
982   PetscErrorCode ierr;
983   PetscBLASInt   n,m,info, min, max;
984 
985   PetscFunctionBegin;
986   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
987   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
988   max = PetscMax(m, n);
989   min = PetscMin(m, n);
990   if (!mat->tau) {
991     ierr = PetscMalloc1(min,&mat->tau);CHKERRQ(ierr);
992     ierr = PetscLogObjectMemory((PetscObject)A,min*sizeof(PetscScalar));CHKERRQ(ierr);
993   }
994   if (!mat->pivots) {
995     ierr = PetscMalloc1(n,&mat->pivots);CHKERRQ(ierr);
996     ierr = PetscLogObjectMemory((PetscObject)A,n*sizeof(PetscScalar));CHKERRQ(ierr);
997   }
998   if (!mat->qrrhs) {
999     ierr = MatCreateVecs(A, NULL, &(mat->qrrhs));CHKERRQ(ierr);
1000   }
1001   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
1002   if (!mat->fwork) {
1003     PetscScalar dummy;
1004 
1005     mat->lfwork = -1;
1006     ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1007     PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&m,&n,mat->v,&mat->lda,mat->tau,&dummy,&mat->lfwork,&info));
1008     ierr = PetscFPTrapPop();CHKERRQ(ierr);
1009     mat->lfwork = (PetscInt)PetscRealPart(dummy);
1010     ierr = PetscMalloc1(mat->lfwork,&mat->fwork);CHKERRQ(ierr);
1011     ierr = PetscLogObjectMemory((PetscObject)A,mat->lfwork*sizeof(PetscBLASInt));CHKERRQ(ierr);
1012   }
1013   ierr = PetscFPTrapPush(PETSC_FP_TRAP_OFF);CHKERRQ(ierr);
1014   PetscStackCallBLAS("LAPACKgeqrf",LAPACKgeqrf_(&m,&n,mat->v,&mat->lda,mat->tau,mat->fwork,&mat->lfwork,&info));
1015   ierr = PetscFPTrapPop();CHKERRQ(ierr);
1016   if (info) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Bad argument to QR factorization");
1017   // TODO: try to estimate rank or test for and use geqp3 for rank revealing QR.  For now just say rank is min of m and n
1018   mat->rank = min;
1019 
1020   A->ops->solve             = MatSolve_SeqDense_QR;
1021   A->ops->matsolve          = MatMatSolve_SeqDense_QR;
1022   A->factortype             = MAT_FACTOR_QR;
1023   if (m == n) {
1024     A->ops->solvetranspose    = MatSolveTranspose_SeqDense_QR;
1025     A->ops->matsolvetranspose = MatMatSolveTranspose_SeqDense_QR;
1026   }
1027 
1028   ierr = PetscFree(A->solvertype);CHKERRQ(ierr);
1029   ierr = PetscStrallocpy(MATSOLVERPETSC,&A->solvertype);CHKERRQ(ierr);
1030 
1031   ierr = PetscLogFlops(2.0*min*min*(max-min/3.0));CHKERRQ(ierr);
1032   PetscFunctionReturn(0);
1033 }
1034 
1035 static PetscErrorCode MatQRFactorNumeric_SeqDense(Mat fact,Mat A,const MatFactorInfo *info_dummy)
1036 {
1037   PetscErrorCode ierr;
1038   MatFactorInfo  info;
1039 
1040   PetscFunctionBegin;
1041   info.fill = 1.0;
1042 
1043   ierr = MatDuplicateNoCreate_SeqDense(fact,A,MAT_COPY_VALUES);CHKERRQ(ierr);
1044   ierr = PetscUseMethod(fact,"MatQRFactor_C",(Mat,IS,const MatFactorInfo *),(fact,NULL,&info));CHKERRQ(ierr);
1045   PetscFunctionReturn(0);
1046 }
1047 
1048 PetscErrorCode MatQRFactorSymbolic_SeqDense(Mat fact,Mat A,IS row,const MatFactorInfo *info)
1049 {
1050   PetscErrorCode ierr;
1051 
1052   PetscFunctionBegin;
1053   fact->assembled                  = PETSC_TRUE;
1054   fact->preallocated               = PETSC_TRUE;
1055   ierr = PetscObjectComposeFunction((PetscObject)fact,"MatQRFactorNumeric_C",MatQRFactorNumeric_SeqDense);CHKERRQ(ierr);
1056   PetscFunctionReturn(0);
1057 }
1058 
1059 /* uses LAPACK */
1060 PETSC_INTERN PetscErrorCode MatGetFactor_seqdense_petsc(Mat A,MatFactorType ftype,Mat *fact)
1061 {
1062   PetscErrorCode ierr;
1063 
1064   PetscFunctionBegin;
1065   ierr = MatCreate(PetscObjectComm((PetscObject)A),fact);CHKERRQ(ierr);
1066   ierr = MatSetSizes(*fact,A->rmap->n,A->cmap->n,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
1067   ierr = MatSetType(*fact,MATDENSE);CHKERRQ(ierr);
1068   (*fact)->trivialsymbolic = PETSC_TRUE;
1069   if (ftype == MAT_FACTOR_LU || ftype == MAT_FACTOR_ILU) {
1070     (*fact)->ops->lufactorsymbolic = MatLUFactorSymbolic_SeqDense;
1071     (*fact)->ops->ilufactorsymbolic = MatLUFactorSymbolic_SeqDense;
1072   } else if (ftype == MAT_FACTOR_CHOLESKY || ftype == MAT_FACTOR_ICC) {
1073     (*fact)->ops->choleskyfactorsymbolic = MatCholeskyFactorSymbolic_SeqDense;
1074   } else if (ftype == MAT_FACTOR_QR) {
1075     ierr = PetscObjectComposeFunction((PetscObject)(*fact),"MatQRFactorSymbolic_C",MatQRFactorSymbolic_SeqDense);CHKERRQ(ierr);
1076   }
1077   (*fact)->factortype = ftype;
1078 
1079   ierr = PetscFree((*fact)->solvertype);CHKERRQ(ierr);
1080   ierr = PetscStrallocpy(MATSOLVERPETSC,&(*fact)->solvertype);CHKERRQ(ierr);
1081   ierr = PetscStrallocpy(MATORDERINGEXTERNAL,(char**)&(*fact)->preferredordering[MAT_FACTOR_LU]);CHKERRQ(ierr);
1082   ierr = PetscStrallocpy(MATORDERINGEXTERNAL,(char**)&(*fact)->preferredordering[MAT_FACTOR_ILU]);CHKERRQ(ierr);
1083   ierr = PetscStrallocpy(MATORDERINGEXTERNAL,(char**)&(*fact)->preferredordering[MAT_FACTOR_CHOLESKY]);CHKERRQ(ierr);
1084   ierr = PetscStrallocpy(MATORDERINGEXTERNAL,(char**)&(*fact)->preferredordering[MAT_FACTOR_ICC]);CHKERRQ(ierr);
1085   PetscFunctionReturn(0);
1086 }
1087 
1088 /* ------------------------------------------------------------------*/
1089 static PetscErrorCode MatSOR_SeqDense(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec xx)
1090 {
1091   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1092   PetscScalar       *x,*v = mat->v,zero = 0.0,xt;
1093   const PetscScalar *b;
1094   PetscErrorCode    ierr;
1095   PetscInt          m = A->rmap->n,i;
1096   PetscBLASInt      o = 1,bm = 0;
1097 
1098   PetscFunctionBegin;
1099 #if defined(PETSC_HAVE_CUDA)
1100   if (A->offloadmask == PETSC_OFFLOAD_GPU) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented");
1101 #endif
1102   if (shift == -1) shift = 0.0; /* negative shift indicates do not error on zero diagonal; this code never zeros on zero diagonal */
1103   ierr = PetscBLASIntCast(m,&bm);CHKERRQ(ierr);
1104   if (flag & SOR_ZERO_INITIAL_GUESS) {
1105     /* this is a hack fix, should have another version without the second BLASdotu */
1106     ierr = VecSet(xx,zero);CHKERRQ(ierr);
1107   }
1108   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
1109   ierr = VecGetArrayRead(bb,&b);CHKERRQ(ierr);
1110   its  = its*lits;
1111   if (its <= 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
1112   while (its--) {
1113     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP) {
1114       for (i=0; i<m; i++) {
1115         PetscStackCallBLAS("BLASdotu",xt   = b[i] - BLASdotu_(&bm,v+i,&bm,x,&o));
1116         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
1117       }
1118     }
1119     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP) {
1120       for (i=m-1; i>=0; i--) {
1121         PetscStackCallBLAS("BLASdotu",xt   = b[i] - BLASdotu_(&bm,v+i,&bm,x,&o));
1122         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
1123       }
1124     }
1125   }
1126   ierr = VecRestoreArrayRead(bb,&b);CHKERRQ(ierr);
1127   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
1128   PetscFunctionReturn(0);
1129 }
1130 
1131 /* -----------------------------------------------------------------*/
1132 PetscErrorCode MatMultTranspose_SeqDense(Mat A,Vec xx,Vec yy)
1133 {
1134   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1135   const PetscScalar *v   = mat->v,*x;
1136   PetscScalar       *y;
1137   PetscErrorCode    ierr;
1138   PetscBLASInt      m, n,_One=1;
1139   PetscScalar       _DOne=1.0,_DZero=0.0;
1140 
1141   PetscFunctionBegin;
1142   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
1143   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
1144   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1145   ierr = VecGetArrayWrite(yy,&y);CHKERRQ(ierr);
1146   if (!A->rmap->n || !A->cmap->n) {
1147     PetscBLASInt i;
1148     for (i=0; i<n; i++) y[i] = 0.0;
1149   } else {
1150     PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&mat->lda,x,&_One,&_DZero,y,&_One));
1151     ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->cmap->n);CHKERRQ(ierr);
1152   }
1153   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1154   ierr = VecRestoreArrayWrite(yy,&y);CHKERRQ(ierr);
1155   PetscFunctionReturn(0);
1156 }
1157 
1158 PetscErrorCode MatMult_SeqDense(Mat A,Vec xx,Vec yy)
1159 {
1160   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1161   PetscScalar       *y,_DOne=1.0,_DZero=0.0;
1162   PetscErrorCode    ierr;
1163   PetscBLASInt      m, n, _One=1;
1164   const PetscScalar *v = mat->v,*x;
1165 
1166   PetscFunctionBegin;
1167   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
1168   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
1169   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1170   ierr = VecGetArrayWrite(yy,&y);CHKERRQ(ierr);
1171   if (!A->rmap->n || !A->cmap->n) {
1172     PetscBLASInt i;
1173     for (i=0; i<m; i++) y[i] = 0.0;
1174   } else {
1175     PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DZero,y,&_One));
1176     ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n - A->rmap->n);CHKERRQ(ierr);
1177   }
1178   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1179   ierr = VecRestoreArrayWrite(yy,&y);CHKERRQ(ierr);
1180   PetscFunctionReturn(0);
1181 }
1182 
1183 PetscErrorCode MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
1184 {
1185   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1186   const PetscScalar *v = mat->v,*x;
1187   PetscScalar       *y,_DOne=1.0;
1188   PetscErrorCode    ierr;
1189   PetscBLASInt      m, n, _One=1;
1190 
1191   PetscFunctionBegin;
1192   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
1193   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
1194   ierr = VecCopy(zz,yy);CHKERRQ(ierr);
1195   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
1196   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1197   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1198   PetscStackCallBLAS("BLASgemv",BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One));
1199   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1200   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1201   ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n);CHKERRQ(ierr);
1202   PetscFunctionReturn(0);
1203 }
1204 
1205 PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
1206 {
1207   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1208   const PetscScalar *v = mat->v,*x;
1209   PetscScalar       *y;
1210   PetscErrorCode    ierr;
1211   PetscBLASInt      m, n, _One=1;
1212   PetscScalar       _DOne=1.0;
1213 
1214   PetscFunctionBegin;
1215   ierr = PetscBLASIntCast(A->rmap->n,&m);CHKERRQ(ierr);
1216   ierr = PetscBLASIntCast(A->cmap->n,&n);CHKERRQ(ierr);
1217   ierr = VecCopy(zz,yy);CHKERRQ(ierr);
1218   if (!A->rmap->n || !A->cmap->n) PetscFunctionReturn(0);
1219   ierr = VecGetArrayRead(xx,&x);CHKERRQ(ierr);
1220   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
1221   PetscStackCallBLAS("BLASgemv",BLASgemv_("T",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One));
1222   ierr = VecRestoreArrayRead(xx,&x);CHKERRQ(ierr);
1223   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
1224   ierr = PetscLogFlops(2.0*A->rmap->n*A->cmap->n);CHKERRQ(ierr);
1225   PetscFunctionReturn(0);
1226 }
1227 
1228 /* -----------------------------------------------------------------*/
1229 static PetscErrorCode MatGetRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
1230 {
1231   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1232   PetscErrorCode ierr;
1233   PetscInt       i;
1234 
1235   PetscFunctionBegin;
1236   *ncols = A->cmap->n;
1237   if (cols) {
1238     ierr = PetscMalloc1(A->cmap->n,cols);CHKERRQ(ierr);
1239     for (i=0; i<A->cmap->n; i++) (*cols)[i] = i;
1240   }
1241   if (vals) {
1242     const PetscScalar *v;
1243 
1244     ierr = MatDenseGetArrayRead(A,&v);CHKERRQ(ierr);
1245     ierr = PetscMalloc1(A->cmap->n,vals);CHKERRQ(ierr);
1246     v   += row;
1247     for (i=0; i<A->cmap->n; i++) {(*vals)[i] = *v; v += mat->lda;}
1248     ierr = MatDenseRestoreArrayRead(A,&v);CHKERRQ(ierr);
1249   }
1250   PetscFunctionReturn(0);
1251 }
1252 
1253 static PetscErrorCode MatRestoreRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
1254 {
1255   PetscErrorCode ierr;
1256 
1257   PetscFunctionBegin;
1258   if (ncols) *ncols = 0;
1259   if (cols) {ierr = PetscFree(*cols);CHKERRQ(ierr);}
1260   if (vals) {ierr = PetscFree(*vals);CHKERRQ(ierr); }
1261   PetscFunctionReturn(0);
1262 }
1263 /* ----------------------------------------------------------------*/
1264 static PetscErrorCode MatSetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],const PetscScalar v[],InsertMode addv)
1265 {
1266   Mat_SeqDense     *mat = (Mat_SeqDense*)A->data;
1267   PetscScalar      *av;
1268   PetscInt         i,j,idx=0;
1269 #if defined(PETSC_HAVE_CUDA)
1270   PetscOffloadMask oldf;
1271 #endif
1272   PetscErrorCode   ierr;
1273 
1274   PetscFunctionBegin;
1275   ierr = MatDenseGetArray(A,&av);CHKERRQ(ierr);
1276   if (!mat->roworiented) {
1277     if (addv == INSERT_VALUES) {
1278       for (j=0; j<n; j++) {
1279         if (indexn[j] < 0) {idx += m; continue;}
1280         if (PetscUnlikelyDebug(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);
1281         for (i=0; i<m; i++) {
1282           if (indexm[i] < 0) {idx++; continue;}
1283           if (PetscUnlikelyDebug(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);
1284           av[indexn[j]*mat->lda + indexm[i]] = v[idx++];
1285         }
1286       }
1287     } else {
1288       for (j=0; j<n; j++) {
1289         if (indexn[j] < 0) {idx += m; continue;}
1290         if (PetscUnlikelyDebug(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);
1291         for (i=0; i<m; i++) {
1292           if (indexm[i] < 0) {idx++; continue;}
1293           if (PetscUnlikelyDebug(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);
1294           av[indexn[j]*mat->lda + indexm[i]] += v[idx++];
1295         }
1296       }
1297     }
1298   } else {
1299     if (addv == INSERT_VALUES) {
1300       for (i=0; i<m; i++) {
1301         if (indexm[i] < 0) { idx += n; continue;}
1302         if (PetscUnlikelyDebug(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);
1303         for (j=0; j<n; j++) {
1304           if (indexn[j] < 0) { idx++; continue;}
1305           if (PetscUnlikelyDebug(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);
1306           av[indexn[j]*mat->lda + indexm[i]] = v[idx++];
1307         }
1308       }
1309     } else {
1310       for (i=0; i<m; i++) {
1311         if (indexm[i] < 0) { idx += n; continue;}
1312         if (PetscUnlikelyDebug(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);
1313         for (j=0; j<n; j++) {
1314           if (indexn[j] < 0) { idx++; continue;}
1315           if (PetscUnlikelyDebug(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);
1316           av[indexn[j]*mat->lda + indexm[i]] += v[idx++];
1317         }
1318       }
1319     }
1320   }
1321   /* hack to prevent unneeded copy to the GPU while returning the array */
1322 #if defined(PETSC_HAVE_CUDA)
1323   oldf = A->offloadmask;
1324   A->offloadmask = PETSC_OFFLOAD_GPU;
1325 #endif
1326   ierr = MatDenseRestoreArray(A,&av);CHKERRQ(ierr);
1327 #if defined(PETSC_HAVE_CUDA)
1328   A->offloadmask = (oldf == PETSC_OFFLOAD_UNALLOCATED ? PETSC_OFFLOAD_UNALLOCATED : PETSC_OFFLOAD_CPU);
1329 #endif
1330   PetscFunctionReturn(0);
1331 }
1332 
1333 static PetscErrorCode MatGetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],PetscScalar v[])
1334 {
1335   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1336   const PetscScalar *vv;
1337   PetscInt          i,j;
1338   PetscErrorCode    ierr;
1339 
1340   PetscFunctionBegin;
1341   ierr = MatDenseGetArrayRead(A,&vv);CHKERRQ(ierr);
1342   /* row-oriented output */
1343   for (i=0; i<m; i++) {
1344     if (indexm[i] < 0) {v += n;continue;}
1345     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);
1346     for (j=0; j<n; j++) {
1347       if (indexn[j] < 0) {v++; continue;}
1348       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);
1349       *v++ = vv[indexn[j]*mat->lda + indexm[i]];
1350     }
1351   }
1352   ierr = MatDenseRestoreArrayRead(A,&vv);CHKERRQ(ierr);
1353   PetscFunctionReturn(0);
1354 }
1355 
1356 /* -----------------------------------------------------------------*/
1357 
1358 PetscErrorCode MatView_Dense_Binary(Mat mat,PetscViewer viewer)
1359 {
1360   PetscErrorCode    ierr;
1361   PetscBool         skipHeader;
1362   PetscViewerFormat format;
1363   PetscInt          header[4],M,N,m,lda,i,j,k;
1364   const PetscScalar *v;
1365   PetscScalar       *vwork;
1366 
1367   PetscFunctionBegin;
1368   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1369   ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);CHKERRQ(ierr);
1370   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1371   if (skipHeader) format = PETSC_VIEWER_NATIVE;
1372 
1373   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1374 
1375   /* write matrix header */
1376   header[0] = MAT_FILE_CLASSID; header[1] = M; header[2] = N;
1377   header[3] = (format == PETSC_VIEWER_NATIVE) ? MATRIX_BINARY_FORMAT_DENSE : M*N;
1378   if (!skipHeader) {ierr = PetscViewerBinaryWrite(viewer,header,4,PETSC_INT);CHKERRQ(ierr);}
1379 
1380   ierr = MatGetLocalSize(mat,&m,NULL);CHKERRQ(ierr);
1381   if (format != PETSC_VIEWER_NATIVE) {
1382     PetscInt nnz = m*N, *iwork;
1383     /* store row lengths for each row */
1384     ierr = PetscMalloc1(nnz,&iwork);CHKERRQ(ierr);
1385     for (i=0; i<m; i++) iwork[i] = N;
1386     ierr = PetscViewerBinaryWriteAll(viewer,iwork,m,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_INT);CHKERRQ(ierr);
1387     /* store column indices (zero start index) */
1388     for (k=0, i=0; i<m; i++)
1389       for (j=0; j<N; j++, k++)
1390         iwork[k] = j;
1391     ierr = PetscViewerBinaryWriteAll(viewer,iwork,nnz,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_INT);CHKERRQ(ierr);
1392     ierr = PetscFree(iwork);CHKERRQ(ierr);
1393   }
1394   /* store matrix values as a dense matrix in row major order */
1395   ierr = PetscMalloc1(m*N,&vwork);CHKERRQ(ierr);
1396   ierr = MatDenseGetArrayRead(mat,&v);CHKERRQ(ierr);
1397   ierr = MatDenseGetLDA(mat,&lda);CHKERRQ(ierr);
1398   for (k=0, i=0; i<m; i++)
1399     for (j=0; j<N; j++, k++)
1400       vwork[k] = v[i+lda*j];
1401   ierr = MatDenseRestoreArrayRead(mat,&v);CHKERRQ(ierr);
1402   ierr = PetscViewerBinaryWriteAll(viewer,vwork,m*N,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_SCALAR);CHKERRQ(ierr);
1403   ierr = PetscFree(vwork);CHKERRQ(ierr);
1404   PetscFunctionReturn(0);
1405 }
1406 
1407 PetscErrorCode MatLoad_Dense_Binary(Mat mat,PetscViewer viewer)
1408 {
1409   PetscErrorCode ierr;
1410   PetscBool      skipHeader;
1411   PetscInt       header[4],M,N,m,nz,lda,i,j,k;
1412   PetscInt       rows,cols;
1413   PetscScalar    *v,*vwork;
1414 
1415   PetscFunctionBegin;
1416   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1417   ierr = PetscViewerBinaryGetSkipHeader(viewer,&skipHeader);CHKERRQ(ierr);
1418 
1419   if (!skipHeader) {
1420     ierr = PetscViewerBinaryRead(viewer,header,4,NULL,PETSC_INT);CHKERRQ(ierr);
1421     if (header[0] != MAT_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Not a matrix object in file");
1422     M = header[1]; N = header[2];
1423     if (M < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix row size (%D) in file is negative",M);
1424     if (N < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Matrix column size (%D) in file is negative",N);
1425     nz = header[3];
1426     if (nz != MATRIX_BINARY_FORMAT_DENSE && nz < 0) SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED,"Unknown matrix format %D in file",nz);
1427   } else {
1428     ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
1429     if (M < 0 || N < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Matrix binary file header was skipped, thus the user must specify the global sizes of input matrix");
1430     nz = MATRIX_BINARY_FORMAT_DENSE;
1431   }
1432 
1433   /* setup global sizes if not set */
1434   if (mat->rmap->N < 0) mat->rmap->N = M;
1435   if (mat->cmap->N < 0) mat->cmap->N = N;
1436   ierr = MatSetUp(mat);CHKERRQ(ierr);
1437   /* check if global sizes are correct */
1438   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
1439   if (M != rows || N != cols) SETERRQ4(PetscObjectComm((PetscObject)viewer),PETSC_ERR_FILE_UNEXPECTED, "Matrix in file of different sizes (%d, %d) than the input matrix (%d, %d)",M,N,rows,cols);
1440 
1441   ierr = MatGetSize(mat,NULL,&N);CHKERRQ(ierr);
1442   ierr = MatGetLocalSize(mat,&m,NULL);CHKERRQ(ierr);
1443   ierr = MatDenseGetArray(mat,&v);CHKERRQ(ierr);
1444   ierr = MatDenseGetLDA(mat,&lda);CHKERRQ(ierr);
1445   if (nz == MATRIX_BINARY_FORMAT_DENSE) {  /* matrix in file is dense format */
1446     PetscInt nnz = m*N;
1447     /* read in matrix values */
1448     ierr = PetscMalloc1(nnz,&vwork);CHKERRQ(ierr);
1449     ierr = PetscViewerBinaryReadAll(viewer,vwork,nnz,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_SCALAR);CHKERRQ(ierr);
1450     /* store values in column major order */
1451     for (j=0; j<N; j++)
1452       for (i=0; i<m; i++)
1453         v[i+lda*j] = vwork[i*N+j];
1454     ierr = PetscFree(vwork);CHKERRQ(ierr);
1455   } else { /* matrix in file is sparse format */
1456     PetscInt nnz = 0, *rlens, *icols;
1457     /* read in row lengths */
1458     ierr = PetscMalloc1(m,&rlens);CHKERRQ(ierr);
1459     ierr = PetscViewerBinaryReadAll(viewer,rlens,m,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_INT);CHKERRQ(ierr);
1460     for (i=0; i<m; i++) nnz += rlens[i];
1461     /* read in column indices and values */
1462     ierr = PetscMalloc2(nnz,&icols,nnz,&vwork);CHKERRQ(ierr);
1463     ierr = PetscViewerBinaryReadAll(viewer,icols,nnz,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_INT);CHKERRQ(ierr);
1464     ierr = PetscViewerBinaryReadAll(viewer,vwork,nnz,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_SCALAR);CHKERRQ(ierr);
1465     /* store values in column major order */
1466     for (k=0, i=0; i<m; i++)
1467       for (j=0; j<rlens[i]; j++, k++)
1468         v[i+lda*icols[k]] = vwork[k];
1469     ierr = PetscFree(rlens);CHKERRQ(ierr);
1470     ierr = PetscFree2(icols,vwork);CHKERRQ(ierr);
1471   }
1472   ierr = MatDenseRestoreArray(mat,&v);CHKERRQ(ierr);
1473   ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1474   ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1475   PetscFunctionReturn(0);
1476 }
1477 
1478 PetscErrorCode MatLoad_SeqDense(Mat newMat, PetscViewer viewer)
1479 {
1480   PetscBool      isbinary, ishdf5;
1481   PetscErrorCode ierr;
1482 
1483   PetscFunctionBegin;
1484   PetscValidHeaderSpecific(newMat,MAT_CLASSID,1);
1485   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1486   /* force binary viewer to load .info file if it has not yet done so */
1487   ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr);
1488   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1489   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1490   if (isbinary) {
1491     ierr = MatLoad_Dense_Binary(newMat,viewer);CHKERRQ(ierr);
1492   } else if (ishdf5) {
1493 #if defined(PETSC_HAVE_HDF5)
1494     ierr = MatLoad_Dense_HDF5(newMat,viewer);CHKERRQ(ierr);
1495 #else
1496     SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
1497 #endif
1498   } else {
1499     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);
1500   }
1501   PetscFunctionReturn(0);
1502 }
1503 
1504 static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer)
1505 {
1506   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
1507   PetscErrorCode    ierr;
1508   PetscInt          i,j;
1509   const char        *name;
1510   PetscScalar       *v,*av;
1511   PetscViewerFormat format;
1512 #if defined(PETSC_USE_COMPLEX)
1513   PetscBool         allreal = PETSC_TRUE;
1514 #endif
1515 
1516   PetscFunctionBegin;
1517   ierr = MatDenseGetArrayRead(A,(const PetscScalar**)&av);CHKERRQ(ierr);
1518   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1519   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1520     PetscFunctionReturn(0);  /* do nothing for now */
1521   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
1522     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1523     for (i=0; i<A->rmap->n; i++) {
1524       v    = av + i;
1525       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
1526       for (j=0; j<A->cmap->n; j++) {
1527 #if defined(PETSC_USE_COMPLEX)
1528         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
1529           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i) ",j,(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));CHKERRQ(ierr);
1530         } else if (PetscRealPart(*v)) {
1531           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)PetscRealPart(*v));CHKERRQ(ierr);
1532         }
1533 #else
1534         if (*v) {
1535           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,(double)*v);CHKERRQ(ierr);
1536         }
1537 #endif
1538         v += a->lda;
1539       }
1540       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
1541     }
1542     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1543   } else {
1544     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
1545 #if defined(PETSC_USE_COMPLEX)
1546     /* determine if matrix has all real values */
1547     v = av;
1548     for (i=0; i<A->rmap->n*A->cmap->n; i++) {
1549       if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break;}
1550     }
1551 #endif
1552     if (format == PETSC_VIEWER_ASCII_MATLAB) {
1553       ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
1554       ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->rmap->n,A->cmap->n);CHKERRQ(ierr);
1555       ierr = PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->rmap->n,A->cmap->n);CHKERRQ(ierr);
1556       ierr = PetscViewerASCIIPrintf(viewer,"%s = [\n",name);CHKERRQ(ierr);
1557     }
1558 
1559     for (i=0; i<A->rmap->n; i++) {
1560       v = av + i;
1561       for (j=0; j<A->cmap->n; j++) {
1562 #if defined(PETSC_USE_COMPLEX)
1563         if (allreal) {
1564           ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)PetscRealPart(*v));CHKERRQ(ierr);
1565         } else {
1566           ierr = PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16ei ",(double)PetscRealPart(*v),(double)PetscImaginaryPart(*v));CHKERRQ(ierr);
1567         }
1568 #else
1569         ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",(double)*v);CHKERRQ(ierr);
1570 #endif
1571         v += a->lda;
1572       }
1573       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
1574     }
1575     if (format == PETSC_VIEWER_ASCII_MATLAB) {
1576       ierr = PetscViewerASCIIPrintf(viewer,"];\n");CHKERRQ(ierr);
1577     }
1578     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
1579   }
1580   ierr = MatDenseRestoreArrayRead(A,(const PetscScalar**)&av);CHKERRQ(ierr);
1581   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
1582   PetscFunctionReturn(0);
1583 }
1584 
1585 #include <petscdraw.h>
1586 static PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa)
1587 {
1588   Mat               A  = (Mat) Aa;
1589   PetscErrorCode    ierr;
1590   PetscInt          m  = A->rmap->n,n = A->cmap->n,i,j;
1591   int               color = PETSC_DRAW_WHITE;
1592   const PetscScalar *v;
1593   PetscViewer       viewer;
1594   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r;
1595   PetscViewerFormat format;
1596 
1597   PetscFunctionBegin;
1598   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
1599   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
1600   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
1601 
1602   /* Loop over matrix elements drawing boxes */
1603   ierr = MatDenseGetArrayRead(A,&v);CHKERRQ(ierr);
1604   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
1605     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
1606     /* Blue for negative and Red for positive */
1607     for (j = 0; j < n; j++) {
1608       x_l = j; x_r = x_l + 1.0;
1609       for (i = 0; i < m; i++) {
1610         y_l = m - i - 1.0;
1611         y_r = y_l + 1.0;
1612         if (PetscRealPart(v[j*m+i]) >  0.) color = PETSC_DRAW_RED;
1613         else if (PetscRealPart(v[j*m+i]) <  0.) color = PETSC_DRAW_BLUE;
1614         else continue;
1615         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1616       }
1617     }
1618     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
1619   } else {
1620     /* use contour shading to indicate magnitude of values */
1621     /* first determine max of all nonzero values */
1622     PetscReal minv = 0.0, maxv = 0.0;
1623     PetscDraw popup;
1624 
1625     for (i=0; i < m*n; i++) {
1626       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
1627     }
1628     if (minv >= maxv) maxv = minv + PETSC_SMALL;
1629     ierr = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
1630     ierr = PetscDrawScalePopup(popup,minv,maxv);CHKERRQ(ierr);
1631 
1632     ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
1633     for (j=0; j<n; j++) {
1634       x_l = j;
1635       x_r = x_l + 1.0;
1636       for (i=0; i<m; i++) {
1637         y_l   = m - i - 1.0;
1638         y_r   = y_l + 1.0;
1639         color = PetscDrawRealToColor(PetscAbsScalar(v[j*m+i]),minv,maxv);
1640         ierr  = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1641       }
1642     }
1643     ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
1644   }
1645   ierr = MatDenseRestoreArrayRead(A,&v);CHKERRQ(ierr);
1646   PetscFunctionReturn(0);
1647 }
1648 
1649 static PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer)
1650 {
1651   PetscDraw      draw;
1652   PetscBool      isnull;
1653   PetscReal      xr,yr,xl,yl,h,w;
1654   PetscErrorCode ierr;
1655 
1656   PetscFunctionBegin;
1657   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1658   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1659   if (isnull) PetscFunctionReturn(0);
1660 
1661   xr   = A->cmap->n; yr = A->rmap->n; h = yr/10.0; w = xr/10.0;
1662   xr  += w;          yr += h;        xl = -w;     yl = -h;
1663   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1664   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1665   ierr = PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);CHKERRQ(ierr);
1666   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",NULL);CHKERRQ(ierr);
1667   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1668   PetscFunctionReturn(0);
1669 }
1670 
1671 PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer)
1672 {
1673   PetscErrorCode ierr;
1674   PetscBool      iascii,isbinary,isdraw;
1675 
1676   PetscFunctionBegin;
1677   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
1678   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
1679   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr);
1680 
1681   if (iascii) {
1682     ierr = MatView_SeqDense_ASCII(A,viewer);CHKERRQ(ierr);
1683   } else if (isbinary) {
1684     ierr = MatView_Dense_Binary(A,viewer);CHKERRQ(ierr);
1685   } else if (isdraw) {
1686     ierr = MatView_SeqDense_Draw(A,viewer);CHKERRQ(ierr);
1687   }
1688   PetscFunctionReturn(0);
1689 }
1690 
1691 static PetscErrorCode MatDensePlaceArray_SeqDense(Mat A,const PetscScalar *array)
1692 {
1693   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1694 
1695   PetscFunctionBegin;
1696   if (a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
1697   if (a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
1698   if (a->unplacedarray) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreArray() first");
1699   a->unplacedarray       = a->v;
1700   a->unplaced_user_alloc = a->user_alloc;
1701   a->v                   = (PetscScalar*) array;
1702   a->user_alloc          = PETSC_TRUE;
1703 #if defined(PETSC_HAVE_CUDA)
1704   A->offloadmask = PETSC_OFFLOAD_CPU;
1705 #endif
1706   PetscFunctionReturn(0);
1707 }
1708 
1709 static PetscErrorCode MatDenseResetArray_SeqDense(Mat A)
1710 {
1711   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
1712 
1713   PetscFunctionBegin;
1714   if (a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
1715   if (a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
1716   a->v             = a->unplacedarray;
1717   a->user_alloc    = a->unplaced_user_alloc;
1718   a->unplacedarray = NULL;
1719 #if defined(PETSC_HAVE_CUDA)
1720   A->offloadmask = PETSC_OFFLOAD_CPU;
1721 #endif
1722   PetscFunctionReturn(0);
1723 }
1724 
1725 static PetscErrorCode MatDenseReplaceArray_SeqDense(Mat A,const PetscScalar *array)
1726 {
1727   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1728   PetscErrorCode ierr;
1729 
1730   PetscFunctionBegin;
1731   if (a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
1732   if (a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
1733   if (!a->user_alloc) { ierr = PetscFree(a->v);CHKERRQ(ierr); }
1734   a->v           = (PetscScalar*) array;
1735   a->user_alloc  = PETSC_FALSE;
1736 #if defined(PETSC_HAVE_CUDA)
1737   A->offloadmask = PETSC_OFFLOAD_CPU;
1738 #endif
1739   PetscFunctionReturn(0);
1740 }
1741 
1742 PetscErrorCode MatDestroy_SeqDense(Mat mat)
1743 {
1744   Mat_SeqDense   *l = (Mat_SeqDense*)mat->data;
1745   PetscErrorCode ierr;
1746 
1747   PetscFunctionBegin;
1748 #if defined(PETSC_USE_LOG)
1749   PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->rmap->n,mat->cmap->n);
1750 #endif
1751   ierr = VecDestroy(&(l->qrrhs));CHKERRQ(ierr);
1752   ierr = PetscFree(l->tau);CHKERRQ(ierr);
1753   ierr = PetscFree(l->pivots);CHKERRQ(ierr);
1754   ierr = PetscFree(l->fwork);CHKERRQ(ierr);
1755   ierr = MatDestroy(&l->ptapwork);CHKERRQ(ierr);
1756   if (!l->user_alloc) {ierr = PetscFree(l->v);CHKERRQ(ierr);}
1757   if (!l->unplaced_user_alloc) {ierr = PetscFree(l->unplacedarray);CHKERRQ(ierr);}
1758   if (l->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
1759   if (l->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
1760   ierr = VecDestroy(&l->cvec);CHKERRQ(ierr);
1761   ierr = MatDestroy(&l->cmat);CHKERRQ(ierr);
1762   ierr = PetscFree(mat->data);CHKERRQ(ierr);
1763 
1764   ierr = PetscObjectChangeTypeName((PetscObject)mat,NULL);CHKERRQ(ierr);
1765   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatQRFactor_C",NULL);CHKERRQ(ierr);
1766   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetLDA_C",NULL);CHKERRQ(ierr);
1767   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseSetLDA_C",NULL);CHKERRQ(ierr);
1768   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArray_C",NULL);CHKERRQ(ierr);
1769   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArray_C",NULL);CHKERRQ(ierr);
1770   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDensePlaceArray_C",NULL);CHKERRQ(ierr);
1771   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseResetArray_C",NULL);CHKERRQ(ierr);
1772   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseReplaceArray_C",NULL);CHKERRQ(ierr);
1773   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArrayRead_C",NULL);CHKERRQ(ierr);
1774   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArrayRead_C",NULL);CHKERRQ(ierr);
1775   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetArrayWrite_C",NULL);CHKERRQ(ierr);
1776   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreArrayWrite_C",NULL);CHKERRQ(ierr);
1777   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_seqaij_C",NULL);CHKERRQ(ierr);
1778 #if defined(PETSC_HAVE_ELEMENTAL)
1779   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_elemental_C",NULL);CHKERRQ(ierr);
1780 #endif
1781 #if defined(PETSC_HAVE_SCALAPACK)
1782   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_scalapack_C",NULL);CHKERRQ(ierr);
1783 #endif
1784 #if defined(PETSC_HAVE_CUDA)
1785   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_seqdense_seqdensecuda_C",NULL);CHKERRQ(ierr);
1786   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatProductSetFromOptions_seqdensecuda_seqdensecuda_C",NULL);CHKERRQ(ierr);
1787   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatProductSetFromOptions_seqdensecuda_seqdense_C",NULL);CHKERRQ(ierr);
1788 #endif
1789   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatSeqDenseSetPreallocation_C",NULL);CHKERRQ(ierr);
1790   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatProductSetFromOptions_seqaij_seqdense_C",NULL);CHKERRQ(ierr);
1791   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatProductSetFromOptions_seqdense_seqdense_C",NULL);CHKERRQ(ierr);
1792   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatProductSetFromOptions_seqbaij_seqdense_C",NULL);CHKERRQ(ierr);
1793   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatProductSetFromOptions_seqsbaij_seqdense_C",NULL);CHKERRQ(ierr);
1794 
1795   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumn_C",NULL);CHKERRQ(ierr);
1796   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumn_C",NULL);CHKERRQ(ierr);
1797   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumnVec_C",NULL);CHKERRQ(ierr);
1798   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumnVec_C",NULL);CHKERRQ(ierr);
1799   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumnVecRead_C",NULL);CHKERRQ(ierr);
1800   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumnVecRead_C",NULL);CHKERRQ(ierr);
1801   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetColumnVecWrite_C",NULL);CHKERRQ(ierr);
1802   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreColumnVecWrite_C",NULL);CHKERRQ(ierr);
1803   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseGetSubMatrix_C",NULL);CHKERRQ(ierr);
1804   ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDenseRestoreSubMatrix_C",NULL);CHKERRQ(ierr);
1805   PetscFunctionReturn(0);
1806 }
1807 
1808 static PetscErrorCode MatTranspose_SeqDense(Mat A,MatReuse reuse,Mat *matout)
1809 {
1810   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1811   PetscErrorCode ierr;
1812   PetscInt       k,j,m = A->rmap->n, M = mat->lda, n = A->cmap->n;
1813   PetscScalar    *v,tmp;
1814 
1815   PetscFunctionBegin;
1816   if (reuse == MAT_INPLACE_MATRIX) {
1817     if (m == n) { /* in place transpose */
1818       ierr = MatDenseGetArray(A,&v);CHKERRQ(ierr);
1819       for (j=0; j<m; j++) {
1820         for (k=0; k<j; k++) {
1821           tmp        = v[j + k*M];
1822           v[j + k*M] = v[k + j*M];
1823           v[k + j*M] = tmp;
1824         }
1825       }
1826       ierr = MatDenseRestoreArray(A,&v);CHKERRQ(ierr);
1827     } else { /* reuse memory, temporary allocates new memory */
1828       PetscScalar *v2;
1829       PetscLayout tmplayout;
1830 
1831       ierr = PetscMalloc1((size_t)m*n,&v2);CHKERRQ(ierr);
1832       ierr = MatDenseGetArray(A,&v);CHKERRQ(ierr);
1833       for (j=0; j<n; j++) {
1834         for (k=0; k<m; k++) v2[j + (size_t)k*n] = v[k + (size_t)j*M];
1835       }
1836       ierr = PetscArraycpy(v,v2,(size_t)m*n);CHKERRQ(ierr);
1837       ierr = PetscFree(v2);CHKERRQ(ierr);
1838       ierr = MatDenseRestoreArray(A,&v);CHKERRQ(ierr);
1839       /* cleanup size dependent quantities */
1840       ierr = VecDestroy(&mat->cvec);CHKERRQ(ierr);
1841       ierr = MatDestroy(&mat->cmat);CHKERRQ(ierr);
1842       ierr = PetscFree(mat->pivots);CHKERRQ(ierr);
1843       ierr = PetscFree(mat->fwork);CHKERRQ(ierr);
1844       ierr = MatDestroy(&mat->ptapwork);CHKERRQ(ierr);
1845       /* swap row/col layouts */
1846       mat->lda  = n;
1847       tmplayout = A->rmap;
1848       A->rmap   = A->cmap;
1849       A->cmap   = tmplayout;
1850     }
1851   } else { /* out-of-place transpose */
1852     Mat          tmat;
1853     Mat_SeqDense *tmatd;
1854     PetscScalar  *v2;
1855     PetscInt     M2;
1856 
1857     if (reuse == MAT_INITIAL_MATRIX) {
1858       ierr = MatCreate(PetscObjectComm((PetscObject)A),&tmat);CHKERRQ(ierr);
1859       ierr = MatSetSizes(tmat,A->cmap->n,A->rmap->n,A->cmap->n,A->rmap->n);CHKERRQ(ierr);
1860       ierr = MatSetType(tmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
1861       ierr = MatSeqDenseSetPreallocation(tmat,NULL);CHKERRQ(ierr);
1862     } else tmat = *matout;
1863 
1864     ierr  = MatDenseGetArrayRead(A,(const PetscScalar**)&v);CHKERRQ(ierr);
1865     ierr  = MatDenseGetArray(tmat,&v2);CHKERRQ(ierr);
1866     tmatd = (Mat_SeqDense*)tmat->data;
1867     M2    = tmatd->lda;
1868     for (j=0; j<n; j++) {
1869       for (k=0; k<m; k++) v2[j + k*M2] = v[k + j*M];
1870     }
1871     ierr = MatDenseRestoreArray(tmat,&v2);CHKERRQ(ierr);
1872     ierr = MatDenseRestoreArrayRead(A,(const PetscScalar**)&v);CHKERRQ(ierr);
1873     ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1874     ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1875     *matout = tmat;
1876   }
1877   PetscFunctionReturn(0);
1878 }
1879 
1880 static PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscBool  *flg)
1881 {
1882   Mat_SeqDense      *mat1 = (Mat_SeqDense*)A1->data;
1883   Mat_SeqDense      *mat2 = (Mat_SeqDense*)A2->data;
1884   PetscInt          i;
1885   const PetscScalar *v1,*v2;
1886   PetscErrorCode    ierr;
1887 
1888   PetscFunctionBegin;
1889   if (A1->rmap->n != A2->rmap->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1890   if (A1->cmap->n != A2->cmap->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1891   ierr = MatDenseGetArrayRead(A1,&v1);CHKERRQ(ierr);
1892   ierr = MatDenseGetArrayRead(A2,&v2);CHKERRQ(ierr);
1893   for (i=0; i<A1->cmap->n; i++) {
1894     ierr = PetscArraycmp(v1,v2,A1->rmap->n,flg);CHKERRQ(ierr);
1895     if (*flg == PETSC_FALSE) PetscFunctionReturn(0);
1896     v1 += mat1->lda;
1897     v2 += mat2->lda;
1898   }
1899   ierr = MatDenseRestoreArrayRead(A1,&v1);CHKERRQ(ierr);
1900   ierr = MatDenseRestoreArrayRead(A2,&v2);CHKERRQ(ierr);
1901   *flg = PETSC_TRUE;
1902   PetscFunctionReturn(0);
1903 }
1904 
1905 static PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v)
1906 {
1907   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1908   PetscInt          i,n,len;
1909   PetscScalar       *x;
1910   const PetscScalar *vv;
1911   PetscErrorCode    ierr;
1912 
1913   PetscFunctionBegin;
1914   ierr = VecGetSize(v,&n);CHKERRQ(ierr);
1915   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1916   len  = PetscMin(A->rmap->n,A->cmap->n);
1917   ierr = MatDenseGetArrayRead(A,&vv);CHKERRQ(ierr);
1918   if (n != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
1919   for (i=0; i<len; i++) {
1920     x[i] = vv[i*mat->lda + i];
1921   }
1922   ierr = MatDenseRestoreArrayRead(A,&vv);CHKERRQ(ierr);
1923   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1924   PetscFunctionReturn(0);
1925 }
1926 
1927 static PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr)
1928 {
1929   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1930   const PetscScalar *l,*r;
1931   PetscScalar       x,*v,*vv;
1932   PetscErrorCode    ierr;
1933   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n;
1934 
1935   PetscFunctionBegin;
1936   ierr = MatDenseGetArray(A,&vv);CHKERRQ(ierr);
1937   if (ll) {
1938     ierr = VecGetSize(ll,&m);CHKERRQ(ierr);
1939     ierr = VecGetArrayRead(ll,&l);CHKERRQ(ierr);
1940     if (m != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size");
1941     for (i=0; i<m; i++) {
1942       x = l[i];
1943       v = vv + i;
1944       for (j=0; j<n; j++) { (*v) *= x; v+= mat->lda;}
1945     }
1946     ierr = VecRestoreArrayRead(ll,&l);CHKERRQ(ierr);
1947     ierr = PetscLogFlops(1.0*n*m);CHKERRQ(ierr);
1948   }
1949   if (rr) {
1950     ierr = VecGetSize(rr,&n);CHKERRQ(ierr);
1951     ierr = VecGetArrayRead(rr,&r);CHKERRQ(ierr);
1952     if (n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size");
1953     for (i=0; i<n; i++) {
1954       x = r[i];
1955       v = vv + i*mat->lda;
1956       for (j=0; j<m; j++) (*v++) *= x;
1957     }
1958     ierr = VecRestoreArrayRead(rr,&r);CHKERRQ(ierr);
1959     ierr = PetscLogFlops(1.0*n*m);CHKERRQ(ierr);
1960   }
1961   ierr = MatDenseRestoreArray(A,&vv);CHKERRQ(ierr);
1962   PetscFunctionReturn(0);
1963 }
1964 
1965 PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm)
1966 {
1967   Mat_SeqDense      *mat = (Mat_SeqDense*)A->data;
1968   PetscScalar       *v,*vv;
1969   PetscReal         sum  = 0.0;
1970   PetscInt          lda  =mat->lda,m=A->rmap->n,i,j;
1971   PetscErrorCode    ierr;
1972 
1973   PetscFunctionBegin;
1974   ierr = MatDenseGetArrayRead(A,(const PetscScalar**)&vv);CHKERRQ(ierr);
1975   v    = vv;
1976   if (type == NORM_FROBENIUS) {
1977     if (lda>m) {
1978       for (j=0; j<A->cmap->n; j++) {
1979         v = vv+j*lda;
1980         for (i=0; i<m; i++) {
1981           sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1982         }
1983       }
1984     } else {
1985 #if defined(PETSC_USE_REAL___FP16)
1986       PetscBLASInt one = 1,cnt = A->cmap->n*A->rmap->n;
1987       PetscStackCallBLAS("BLASnrm2",*nrm = BLASnrm2_(&cnt,v,&one));
1988     }
1989 #else
1990       for (i=0; i<A->cmap->n*A->rmap->n; i++) {
1991         sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1992       }
1993     }
1994     *nrm = PetscSqrtReal(sum);
1995 #endif
1996     ierr = PetscLogFlops(2.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr);
1997   } else if (type == NORM_1) {
1998     *nrm = 0.0;
1999     for (j=0; j<A->cmap->n; j++) {
2000       v   = vv + j*mat->lda;
2001       sum = 0.0;
2002       for (i=0; i<A->rmap->n; i++) {
2003         sum += PetscAbsScalar(*v);  v++;
2004       }
2005       if (sum > *nrm) *nrm = sum;
2006     }
2007     ierr = PetscLogFlops(1.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr);
2008   } else if (type == NORM_INFINITY) {
2009     *nrm = 0.0;
2010     for (j=0; j<A->rmap->n; j++) {
2011       v   = vv + j;
2012       sum = 0.0;
2013       for (i=0; i<A->cmap->n; i++) {
2014         sum += PetscAbsScalar(*v); v += mat->lda;
2015       }
2016       if (sum > *nrm) *nrm = sum;
2017     }
2018     ierr = PetscLogFlops(1.0*A->cmap->n*A->rmap->n);CHKERRQ(ierr);
2019   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No two norm");
2020   ierr = MatDenseRestoreArrayRead(A,(const PetscScalar**)&vv);CHKERRQ(ierr);
2021   PetscFunctionReturn(0);
2022 }
2023 
2024 static PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op,PetscBool flg)
2025 {
2026   Mat_SeqDense   *aij = (Mat_SeqDense*)A->data;
2027   PetscErrorCode ierr;
2028 
2029   PetscFunctionBegin;
2030   switch (op) {
2031   case MAT_ROW_ORIENTED:
2032     aij->roworiented = flg;
2033     break;
2034   case MAT_NEW_NONZERO_LOCATIONS:
2035   case MAT_NEW_NONZERO_LOCATION_ERR:
2036   case MAT_NEW_NONZERO_ALLOCATION_ERR:
2037   case MAT_FORCE_DIAGONAL_ENTRIES:
2038   case MAT_KEEP_NONZERO_PATTERN:
2039   case MAT_IGNORE_OFF_PROC_ENTRIES:
2040   case MAT_USE_HASH_TABLE:
2041   case MAT_IGNORE_ZERO_ENTRIES:
2042   case MAT_IGNORE_LOWER_TRIANGULAR:
2043   case MAT_SORTED_FULL:
2044     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
2045     break;
2046   case MAT_SPD:
2047   case MAT_SYMMETRIC:
2048   case MAT_STRUCTURALLY_SYMMETRIC:
2049   case MAT_HERMITIAN:
2050   case MAT_SYMMETRY_ETERNAL:
2051     /* These options are handled directly by MatSetOption() */
2052     break;
2053   default:
2054     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
2055   }
2056   PetscFunctionReturn(0);
2057 }
2058 
2059 PetscErrorCode MatZeroEntries_SeqDense(Mat A)
2060 {
2061   Mat_SeqDense   *l = (Mat_SeqDense*)A->data;
2062   PetscErrorCode ierr;
2063   PetscInt       lda=l->lda,m=A->rmap->n,n=A->cmap->n,j;
2064   PetscScalar    *v;
2065 
2066   PetscFunctionBegin;
2067   ierr = MatDenseGetArrayWrite(A,&v);CHKERRQ(ierr);
2068   if (lda>m) {
2069     for (j=0; j<n; j++) {
2070       ierr = PetscArrayzero(v+j*lda,m);CHKERRQ(ierr);
2071     }
2072   } else {
2073     ierr = PetscArrayzero(v,PetscInt64Mult(m,n));CHKERRQ(ierr);
2074   }
2075   ierr = MatDenseRestoreArrayWrite(A,&v);CHKERRQ(ierr);
2076   PetscFunctionReturn(0);
2077 }
2078 
2079 static PetscErrorCode MatZeroRows_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2080 {
2081   PetscErrorCode    ierr;
2082   Mat_SeqDense      *l = (Mat_SeqDense*)A->data;
2083   PetscInt          m  = l->lda, n = A->cmap->n, i,j;
2084   PetscScalar       *slot,*bb,*v;
2085   const PetscScalar *xx;
2086 
2087   PetscFunctionBegin;
2088   if (PetscDefined(USE_DEBUG)) {
2089     for (i=0; i<N; i++) {
2090       if (rows[i] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row requested to be zeroed");
2091       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);
2092     }
2093   }
2094   if (!N) PetscFunctionReturn(0);
2095 
2096   /* fix right hand side if needed */
2097   if (x && b) {
2098     ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr);
2099     ierr = VecGetArray(b,&bb);CHKERRQ(ierr);
2100     for (i=0; i<N; i++) bb[rows[i]] = diag*xx[rows[i]];
2101     ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr);
2102     ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr);
2103   }
2104 
2105   ierr = MatDenseGetArray(A,&v);CHKERRQ(ierr);
2106   for (i=0; i<N; i++) {
2107     slot = v + rows[i];
2108     for (j=0; j<n; j++) { *slot = 0.0; slot += m;}
2109   }
2110   if (diag != 0.0) {
2111     if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only coded for square matrices");
2112     for (i=0; i<N; i++) {
2113       slot  = v + (m+1)*rows[i];
2114       *slot = diag;
2115     }
2116   }
2117   ierr = MatDenseRestoreArray(A,&v);CHKERRQ(ierr);
2118   PetscFunctionReturn(0);
2119 }
2120 
2121 static PetscErrorCode MatDenseGetLDA_SeqDense(Mat A,PetscInt *lda)
2122 {
2123   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
2124 
2125   PetscFunctionBegin;
2126   *lda = mat->lda;
2127   PetscFunctionReturn(0);
2128 }
2129 
2130 PetscErrorCode MatDenseGetArray_SeqDense(Mat A,PetscScalar **array)
2131 {
2132   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
2133 
2134   PetscFunctionBegin;
2135   if (mat->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
2136   *array = mat->v;
2137   PetscFunctionReturn(0);
2138 }
2139 
2140 PetscErrorCode MatDenseRestoreArray_SeqDense(Mat A,PetscScalar **array)
2141 {
2142   PetscFunctionBegin;
2143   *array = NULL;
2144   PetscFunctionReturn(0);
2145 }
2146 
2147 /*@
2148    MatDenseGetLDA - gets the leading dimension of the array returned from MatDenseGetArray()
2149 
2150    Not collective
2151 
2152    Input Parameter:
2153 .  mat - a MATSEQDENSE or MATMPIDENSE matrix
2154 
2155    Output Parameter:
2156 .   lda - the leading dimension
2157 
2158    Level: intermediate
2159 
2160 .seealso: MatDenseGetArray(), MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead(), MatDenseSetLDA()
2161 @*/
2162 PetscErrorCode  MatDenseGetLDA(Mat A,PetscInt *lda)
2163 {
2164   PetscErrorCode ierr;
2165 
2166   PetscFunctionBegin;
2167   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2168   PetscValidPointer(lda,2);
2169   ierr = PetscUseMethod(A,"MatDenseGetLDA_C",(Mat,PetscInt*),(A,lda));CHKERRQ(ierr);
2170   PetscFunctionReturn(0);
2171 }
2172 
2173 /*@
2174    MatDenseSetLDA - Sets the leading dimension of the array used by the dense matrix
2175 
2176    Not collective
2177 
2178    Input Parameters:
2179 +  mat - a MATSEQDENSE or MATMPIDENSE matrix
2180 -  lda - the leading dimension
2181 
2182    Level: intermediate
2183 
2184 .seealso: MatDenseGetArray(), MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead(), MatDenseGetLDA()
2185 @*/
2186 PetscErrorCode  MatDenseSetLDA(Mat A,PetscInt lda)
2187 {
2188   PetscErrorCode ierr;
2189 
2190   PetscFunctionBegin;
2191   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2192   ierr = PetscTryMethod(A,"MatDenseSetLDA_C",(Mat,PetscInt),(A,lda));CHKERRQ(ierr);
2193   PetscFunctionReturn(0);
2194 }
2195 
2196 /*@C
2197    MatDenseGetArray - gives read-write access to the array where the data for a dense matrix is stored
2198 
2199    Logically Collective on Mat
2200 
2201    Input Parameter:
2202 .  mat - a dense matrix
2203 
2204    Output Parameter:
2205 .   array - pointer to the data
2206 
2207    Level: intermediate
2208 
2209 .seealso: MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead(), MatDenseGetArrayWrite(), MatDenseRestoreArrayWrite()
2210 @*/
2211 PetscErrorCode  MatDenseGetArray(Mat A,PetscScalar **array)
2212 {
2213   PetscErrorCode ierr;
2214 
2215   PetscFunctionBegin;
2216   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2217   PetscValidPointer(array,2);
2218   ierr = PetscUseMethod(A,"MatDenseGetArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
2219   PetscFunctionReturn(0);
2220 }
2221 
2222 /*@C
2223    MatDenseRestoreArray - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArray()
2224 
2225    Logically Collective on Mat
2226 
2227    Input Parameters:
2228 +  mat - a dense matrix
2229 -  array - pointer to the data
2230 
2231    Level: intermediate
2232 
2233 .seealso: MatDenseGetArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead(), MatDenseGetArrayWrite(), MatDenseRestoreArrayWrite()
2234 @*/
2235 PetscErrorCode  MatDenseRestoreArray(Mat A,PetscScalar **array)
2236 {
2237   PetscErrorCode ierr;
2238 
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2241   PetscValidPointer(array,2);
2242   ierr = PetscUseMethod(A,"MatDenseRestoreArray_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
2243   ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr);
2244 #if defined(PETSC_HAVE_CUDA)
2245   A->offloadmask = PETSC_OFFLOAD_CPU;
2246 #endif
2247   PetscFunctionReturn(0);
2248 }
2249 
2250 /*@C
2251    MatDenseGetArrayRead - gives read-only access to the array where the data for a dense matrix is stored
2252 
2253    Not Collective
2254 
2255    Input Parameter:
2256 .  mat - a dense matrix
2257 
2258    Output Parameter:
2259 .   array - pointer to the data
2260 
2261    Level: intermediate
2262 
2263 .seealso: MatDenseRestoreArrayRead(), MatDenseGetArray(), MatDenseRestoreArray(), MatDenseGetArrayWrite(), MatDenseRestoreArrayWrite()
2264 @*/
2265 PetscErrorCode  MatDenseGetArrayRead(Mat A,const PetscScalar **array)
2266 {
2267   PetscErrorCode ierr;
2268 
2269   PetscFunctionBegin;
2270   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2271   PetscValidPointer(array,2);
2272   ierr = PetscUseMethod(A,"MatDenseGetArrayRead_C",(Mat,const PetscScalar**),(A,array));CHKERRQ(ierr);
2273   PetscFunctionReturn(0);
2274 }
2275 
2276 /*@C
2277    MatDenseRestoreArrayRead - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArrayRead()
2278 
2279    Not Collective
2280 
2281    Input Parameters:
2282 +  mat - a dense matrix
2283 -  array - pointer to the data
2284 
2285    Level: intermediate
2286 
2287 .seealso: MatDenseGetArrayRead(), MatDenseGetArray(), MatDenseRestoreArray(), MatDenseGetArrayWrite(), MatDenseRestoreArrayWrite()
2288 @*/
2289 PetscErrorCode  MatDenseRestoreArrayRead(Mat A,const PetscScalar **array)
2290 {
2291   PetscErrorCode ierr;
2292 
2293   PetscFunctionBegin;
2294   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2295   PetscValidPointer(array,2);
2296   ierr = PetscUseMethod(A,"MatDenseRestoreArrayRead_C",(Mat,const PetscScalar**),(A,array));CHKERRQ(ierr);
2297   PetscFunctionReturn(0);
2298 }
2299 
2300 /*@C
2301    MatDenseGetArrayWrite - gives write-only access to the array where the data for a dense matrix is stored
2302 
2303    Not Collective
2304 
2305    Input Parameter:
2306 .  mat - a dense matrix
2307 
2308    Output Parameter:
2309 .   array - pointer to the data
2310 
2311    Level: intermediate
2312 
2313 .seealso: MatDenseRestoreArrayWrite(), MatDenseGetArray(), MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead()
2314 @*/
2315 PetscErrorCode  MatDenseGetArrayWrite(Mat A,PetscScalar **array)
2316 {
2317   PetscErrorCode ierr;
2318 
2319   PetscFunctionBegin;
2320   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2321   PetscValidPointer(array,2);
2322   ierr = PetscUseMethod(A,"MatDenseGetArrayWrite_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
2323   PetscFunctionReturn(0);
2324 }
2325 
2326 /*@C
2327    MatDenseRestoreArrayWrite - returns access to the array where the data for a dense matrix is stored obtained by MatDenseGetArrayWrite()
2328 
2329    Not Collective
2330 
2331    Input Parameters:
2332 +  mat - a dense matrix
2333 -  array - pointer to the data
2334 
2335    Level: intermediate
2336 
2337 .seealso: MatDenseGetArrayWrite(), MatDenseGetArray(), MatDenseRestoreArray(), MatDenseGetArrayRead(), MatDenseRestoreArrayRead()
2338 @*/
2339 PetscErrorCode  MatDenseRestoreArrayWrite(Mat A,PetscScalar **array)
2340 {
2341   PetscErrorCode ierr;
2342 
2343   PetscFunctionBegin;
2344   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
2345   PetscValidPointer(array,2);
2346   ierr = PetscUseMethod(A,"MatDenseRestoreArrayWrite_C",(Mat,PetscScalar**),(A,array));CHKERRQ(ierr);
2347   ierr = PetscObjectStateIncrease((PetscObject)A);CHKERRQ(ierr);
2348 #if defined(PETSC_HAVE_CUDA)
2349   A->offloadmask = PETSC_OFFLOAD_CPU;
2350 #endif
2351   PetscFunctionReturn(0);
2352 }
2353 
2354 static PetscErrorCode MatCreateSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,MatReuse scall,Mat *B)
2355 {
2356   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
2357   PetscErrorCode ierr;
2358   PetscInt       i,j,nrows,ncols,ldb;
2359   const PetscInt *irow,*icol;
2360   PetscScalar    *av,*bv,*v = mat->v;
2361   Mat            newmat;
2362 
2363   PetscFunctionBegin;
2364   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
2365   ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
2366   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
2367   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
2368 
2369   /* Check submatrixcall */
2370   if (scall == MAT_REUSE_MATRIX) {
2371     PetscInt n_cols,n_rows;
2372     ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
2373     if (n_rows != nrows || n_cols != ncols) {
2374       /* resize the result matrix to match number of requested rows/columns */
2375       ierr = MatSetSizes(*B,nrows,ncols,nrows,ncols);CHKERRQ(ierr);
2376     }
2377     newmat = *B;
2378   } else {
2379     /* Create and fill new matrix */
2380     ierr = MatCreate(PetscObjectComm((PetscObject)A),&newmat);CHKERRQ(ierr);
2381     ierr = MatSetSizes(newmat,nrows,ncols,nrows,ncols);CHKERRQ(ierr);
2382     ierr = MatSetType(newmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
2383     ierr = MatSeqDenseSetPreallocation(newmat,NULL);CHKERRQ(ierr);
2384   }
2385 
2386   /* Now extract the data pointers and do the copy,column at a time */
2387   ierr = MatDenseGetArray(newmat,&bv);CHKERRQ(ierr);
2388   ierr = MatDenseGetLDA(newmat,&ldb);CHKERRQ(ierr);
2389   for (i=0; i<ncols; i++) {
2390     av = v + mat->lda*icol[i];
2391     for (j=0; j<nrows; j++) bv[j] = av[irow[j]];
2392     bv += ldb;
2393   }
2394   ierr = MatDenseRestoreArray(newmat,&bv);CHKERRQ(ierr);
2395 
2396   /* Assemble the matrices so that the correct flags are set */
2397   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2398   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2399 
2400   /* Free work space */
2401   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
2402   ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
2403   *B   = newmat;
2404   PetscFunctionReturn(0);
2405 }
2406 
2407 static PetscErrorCode MatCreateSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
2408 {
2409   PetscErrorCode ierr;
2410   PetscInt       i;
2411 
2412   PetscFunctionBegin;
2413   if (scall == MAT_INITIAL_MATRIX) {
2414     ierr = PetscCalloc1(n,B);CHKERRQ(ierr);
2415   }
2416 
2417   for (i=0; i<n; i++) {
2418     ierr = MatCreateSubMatrix_SeqDense(A,irow[i],icol[i],scall,&(*B)[i]);CHKERRQ(ierr);
2419   }
2420   PetscFunctionReturn(0);
2421 }
2422 
2423 static PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat,MatAssemblyType mode)
2424 {
2425   PetscFunctionBegin;
2426   PetscFunctionReturn(0);
2427 }
2428 
2429 static PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat,MatAssemblyType mode)
2430 {
2431   PetscFunctionBegin;
2432   PetscFunctionReturn(0);
2433 }
2434 
2435 PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str)
2436 {
2437   Mat_SeqDense      *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense*)B->data;
2438   PetscErrorCode    ierr;
2439   const PetscScalar *va;
2440   PetscScalar       *vb;
2441   PetscInt          lda1=a->lda,lda2=b->lda, m=A->rmap->n,n=A->cmap->n, j;
2442 
2443   PetscFunctionBegin;
2444   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
2445   if (A->ops->copy != B->ops->copy) {
2446     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
2447     PetscFunctionReturn(0);
2448   }
2449   if (m != B->rmap->n || n != B->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"size(B) != size(A)");
2450   ierr = MatDenseGetArrayRead(A,&va);CHKERRQ(ierr);
2451   ierr = MatDenseGetArray(B,&vb);CHKERRQ(ierr);
2452   if (lda1>m || lda2>m) {
2453     for (j=0; j<n; j++) {
2454       ierr = PetscArraycpy(vb+j*lda2,va+j*lda1,m);CHKERRQ(ierr);
2455     }
2456   } else {
2457     ierr = PetscArraycpy(vb,va,A->rmap->n*A->cmap->n);CHKERRQ(ierr);
2458   }
2459   ierr = MatDenseRestoreArray(B,&vb);CHKERRQ(ierr);
2460   ierr = MatDenseRestoreArrayRead(A,&va);CHKERRQ(ierr);
2461   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2462   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2463   PetscFunctionReturn(0);
2464 }
2465 
2466 static PetscErrorCode MatSetUp_SeqDense(Mat A)
2467 {
2468   PetscErrorCode ierr;
2469 
2470   PetscFunctionBegin;
2471   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2472   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2473   if (!A->preallocated) {
2474     ierr = MatSeqDenseSetPreallocation(A,NULL);CHKERRQ(ierr);
2475   }
2476   PetscFunctionReturn(0);
2477 }
2478 
2479 static PetscErrorCode MatConjugate_SeqDense(Mat A)
2480 {
2481   Mat_SeqDense   *mat = (Mat_SeqDense *) A->data;
2482   PetscInt       i,nz = A->rmap->n*A->cmap->n;
2483   PetscInt       min = PetscMin(A->rmap->n,A->cmap->n);
2484   PetscScalar    *aa;
2485   PetscErrorCode ierr;
2486 
2487   PetscFunctionBegin;
2488   ierr = MatDenseGetArray(A,&aa);CHKERRQ(ierr);
2489   for (i=0; i<nz; i++) aa[i] = PetscConj(aa[i]);
2490   ierr = MatDenseRestoreArray(A,&aa);CHKERRQ(ierr);
2491   if (mat->tau) for (i = 0; i < min; i++) mat->tau[i] = PetscConj(mat->tau[i]);
2492   PetscFunctionReturn(0);
2493 }
2494 
2495 static PetscErrorCode MatRealPart_SeqDense(Mat A)
2496 {
2497   PetscInt       i,nz = A->rmap->n*A->cmap->n;
2498   PetscScalar    *aa;
2499   PetscErrorCode ierr;
2500 
2501   PetscFunctionBegin;
2502   ierr = MatDenseGetArray(A,&aa);CHKERRQ(ierr);
2503   for (i=0; i<nz; i++) aa[i] = PetscRealPart(aa[i]);
2504   ierr = MatDenseRestoreArray(A,&aa);CHKERRQ(ierr);
2505   PetscFunctionReturn(0);
2506 }
2507 
2508 static PetscErrorCode MatImaginaryPart_SeqDense(Mat A)
2509 {
2510   PetscInt       i,nz = A->rmap->n*A->cmap->n;
2511   PetscScalar    *aa;
2512   PetscErrorCode ierr;
2513 
2514   PetscFunctionBegin;
2515   ierr = MatDenseGetArray(A,&aa);CHKERRQ(ierr);
2516   for (i=0; i<nz; i++) aa[i] = PetscImaginaryPart(aa[i]);
2517   ierr = MatDenseRestoreArray(A,&aa);CHKERRQ(ierr);
2518   PetscFunctionReturn(0);
2519 }
2520 
2521 /* ----------------------------------------------------------------*/
2522 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat C)
2523 {
2524   PetscErrorCode ierr;
2525   PetscInt       m=A->rmap->n,n=B->cmap->n;
2526   PetscBool      cisdense;
2527 
2528   PetscFunctionBegin;
2529   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
2530   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
2531   if (!cisdense) {
2532     PetscBool flg;
2533 
2534     ierr = PetscObjectTypeCompare((PetscObject)B,((PetscObject)A)->type_name,&flg);CHKERRQ(ierr);
2535     ierr = MatSetType(C,flg ? ((PetscObject)A)->type_name : MATDENSE);CHKERRQ(ierr);
2536   }
2537   ierr = MatSetUp(C);CHKERRQ(ierr);
2538   PetscFunctionReturn(0);
2539 }
2540 
2541 PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2542 {
2543   Mat_SeqDense       *a=(Mat_SeqDense*)A->data,*b=(Mat_SeqDense*)B->data,*c=(Mat_SeqDense*)C->data;
2544   PetscBLASInt       m,n,k;
2545   const PetscScalar *av,*bv;
2546   PetscScalar       *cv;
2547   PetscScalar       _DOne=1.0,_DZero=0.0;
2548   PetscErrorCode    ierr;
2549 
2550   PetscFunctionBegin;
2551   ierr = PetscBLASIntCast(C->rmap->n,&m);CHKERRQ(ierr);
2552   ierr = PetscBLASIntCast(C->cmap->n,&n);CHKERRQ(ierr);
2553   ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr);
2554   if (!m || !n || !k) PetscFunctionReturn(0);
2555   ierr = MatDenseGetArrayRead(A,&av);CHKERRQ(ierr);
2556   ierr = MatDenseGetArrayRead(B,&bv);CHKERRQ(ierr);
2557   ierr = MatDenseGetArrayWrite(C,&cv);CHKERRQ(ierr);
2558   PetscStackCallBLAS("BLASgemm",BLASgemm_("N","N",&m,&n,&k,&_DOne,av,&a->lda,bv,&b->lda,&_DZero,cv,&c->lda));
2559   ierr = PetscLogFlops(1.0*m*n*k + 1.0*m*n*(k-1));CHKERRQ(ierr);
2560   ierr = MatDenseRestoreArrayRead(A,&av);CHKERRQ(ierr);
2561   ierr = MatDenseRestoreArrayRead(B,&bv);CHKERRQ(ierr);
2562   ierr = MatDenseRestoreArrayWrite(C,&cv);CHKERRQ(ierr);
2563   PetscFunctionReturn(0);
2564 }
2565 
2566 PetscErrorCode MatMatTransposeMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat C)
2567 {
2568   PetscErrorCode ierr;
2569   PetscInt       m=A->rmap->n,n=B->rmap->n;
2570   PetscBool      cisdense;
2571 
2572   PetscFunctionBegin;
2573   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
2574   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
2575   if (!cisdense) {
2576     PetscBool flg;
2577 
2578     ierr = PetscObjectTypeCompare((PetscObject)B,((PetscObject)A)->type_name,&flg);CHKERRQ(ierr);
2579     ierr = MatSetType(C,flg ? ((PetscObject)A)->type_name : MATDENSE);CHKERRQ(ierr);
2580   }
2581   ierr = MatSetUp(C);CHKERRQ(ierr);
2582   PetscFunctionReturn(0);
2583 }
2584 
2585 PetscErrorCode MatMatTransposeMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2586 {
2587   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
2588   Mat_SeqDense      *b = (Mat_SeqDense*)B->data;
2589   Mat_SeqDense      *c = (Mat_SeqDense*)C->data;
2590   const PetscScalar *av,*bv;
2591   PetscScalar       *cv;
2592   PetscBLASInt      m,n,k;
2593   PetscScalar       _DOne=1.0,_DZero=0.0;
2594   PetscErrorCode    ierr;
2595 
2596   PetscFunctionBegin;
2597   ierr = PetscBLASIntCast(C->rmap->n,&m);CHKERRQ(ierr);
2598   ierr = PetscBLASIntCast(C->cmap->n,&n);CHKERRQ(ierr);
2599   ierr = PetscBLASIntCast(A->cmap->n,&k);CHKERRQ(ierr);
2600   if (!m || !n || !k) PetscFunctionReturn(0);
2601   ierr = MatDenseGetArrayRead(A,&av);CHKERRQ(ierr);
2602   ierr = MatDenseGetArrayRead(B,&bv);CHKERRQ(ierr);
2603   ierr = MatDenseGetArrayWrite(C,&cv);CHKERRQ(ierr);
2604   PetscStackCallBLAS("BLASgemm",BLASgemm_("N","T",&m,&n,&k,&_DOne,av,&a->lda,bv,&b->lda,&_DZero,cv,&c->lda));
2605   ierr = MatDenseRestoreArrayRead(A,&av);CHKERRQ(ierr);
2606   ierr = MatDenseRestoreArrayRead(B,&bv);CHKERRQ(ierr);
2607   ierr = MatDenseRestoreArrayWrite(C,&cv);CHKERRQ(ierr);
2608   ierr = PetscLogFlops(1.0*m*n*k + 1.0*m*n*(k-1));CHKERRQ(ierr);
2609   PetscFunctionReturn(0);
2610 }
2611 
2612 PetscErrorCode MatTransposeMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat C)
2613 {
2614   PetscErrorCode ierr;
2615   PetscInt       m=A->cmap->n,n=B->cmap->n;
2616   PetscBool      cisdense;
2617 
2618   PetscFunctionBegin;
2619   ierr = MatSetSizes(C,m,n,m,n);CHKERRQ(ierr);
2620   ierr = PetscObjectTypeCompareAny((PetscObject)C,&cisdense,MATSEQDENSE,MATSEQDENSECUDA,"");CHKERRQ(ierr);
2621   if (!cisdense) {
2622     PetscBool flg;
2623 
2624     ierr = PetscObjectTypeCompare((PetscObject)B,((PetscObject)A)->type_name,&flg);CHKERRQ(ierr);
2625     ierr = MatSetType(C,flg ? ((PetscObject)A)->type_name : MATDENSE);CHKERRQ(ierr);
2626   }
2627   ierr = MatSetUp(C);CHKERRQ(ierr);
2628   PetscFunctionReturn(0);
2629 }
2630 
2631 PetscErrorCode MatTransposeMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
2632 {
2633   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
2634   Mat_SeqDense      *b = (Mat_SeqDense*)B->data;
2635   Mat_SeqDense      *c = (Mat_SeqDense*)C->data;
2636   const PetscScalar *av,*bv;
2637   PetscScalar       *cv;
2638   PetscBLASInt      m,n,k;
2639   PetscScalar       _DOne=1.0,_DZero=0.0;
2640   PetscErrorCode    ierr;
2641 
2642   PetscFunctionBegin;
2643   ierr = PetscBLASIntCast(C->rmap->n,&m);CHKERRQ(ierr);
2644   ierr = PetscBLASIntCast(C->cmap->n,&n);CHKERRQ(ierr);
2645   ierr = PetscBLASIntCast(A->rmap->n,&k);CHKERRQ(ierr);
2646   if (!m || !n || !k) PetscFunctionReturn(0);
2647   ierr = MatDenseGetArrayRead(A,&av);CHKERRQ(ierr);
2648   ierr = MatDenseGetArrayRead(B,&bv);CHKERRQ(ierr);
2649   ierr = MatDenseGetArrayWrite(C,&cv);CHKERRQ(ierr);
2650   PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&m,&n,&k,&_DOne,av,&a->lda,bv,&b->lda,&_DZero,cv,&c->lda));
2651   ierr = MatDenseRestoreArrayRead(A,&av);CHKERRQ(ierr);
2652   ierr = MatDenseRestoreArrayRead(B,&bv);CHKERRQ(ierr);
2653   ierr = MatDenseRestoreArrayWrite(C,&cv);CHKERRQ(ierr);
2654   ierr = PetscLogFlops(1.0*m*n*k + 1.0*m*n*(k-1));CHKERRQ(ierr);
2655   PetscFunctionReturn(0);
2656 }
2657 
2658 /* ----------------------------------------------- */
2659 static PetscErrorCode MatProductSetFromOptions_SeqDense_AB(Mat C)
2660 {
2661   PetscFunctionBegin;
2662   C->ops->matmultsymbolic = MatMatMultSymbolic_SeqDense_SeqDense;
2663   C->ops->productsymbolic = MatProductSymbolic_AB;
2664   PetscFunctionReturn(0);
2665 }
2666 
2667 static PetscErrorCode MatProductSetFromOptions_SeqDense_AtB(Mat C)
2668 {
2669   PetscFunctionBegin;
2670   C->ops->transposematmultsymbolic = MatTransposeMatMultSymbolic_SeqDense_SeqDense;
2671   C->ops->productsymbolic          = MatProductSymbolic_AtB;
2672   PetscFunctionReturn(0);
2673 }
2674 
2675 static PetscErrorCode MatProductSetFromOptions_SeqDense_ABt(Mat C)
2676 {
2677   PetscFunctionBegin;
2678   C->ops->mattransposemultsymbolic = MatMatTransposeMultSymbolic_SeqDense_SeqDense;
2679   C->ops->productsymbolic          = MatProductSymbolic_ABt;
2680   PetscFunctionReturn(0);
2681 }
2682 
2683 PETSC_INTERN PetscErrorCode MatProductSetFromOptions_SeqDense(Mat C)
2684 {
2685   PetscErrorCode ierr;
2686   Mat_Product    *product = C->product;
2687 
2688   PetscFunctionBegin;
2689   switch (product->type) {
2690   case MATPRODUCT_AB:
2691     ierr = MatProductSetFromOptions_SeqDense_AB(C);CHKERRQ(ierr);
2692     break;
2693   case MATPRODUCT_AtB:
2694     ierr = MatProductSetFromOptions_SeqDense_AtB(C);CHKERRQ(ierr);
2695     break;
2696   case MATPRODUCT_ABt:
2697     ierr = MatProductSetFromOptions_SeqDense_ABt(C);CHKERRQ(ierr);
2698     break;
2699   default:
2700     break;
2701   }
2702   PetscFunctionReturn(0);
2703 }
2704 /* ----------------------------------------------- */
2705 
2706 static PetscErrorCode MatGetRowMax_SeqDense(Mat A,Vec v,PetscInt idx[])
2707 {
2708   Mat_SeqDense       *a = (Mat_SeqDense*)A->data;
2709   PetscErrorCode     ierr;
2710   PetscInt           i,j,m = A->rmap->n,n = A->cmap->n,p;
2711   PetscScalar        *x;
2712   const PetscScalar *aa;
2713 
2714   PetscFunctionBegin;
2715   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2716   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2717   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
2718   ierr = MatDenseGetArrayRead(A,&aa);CHKERRQ(ierr);
2719   if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2720   for (i=0; i<m; i++) {
2721     x[i] = aa[i]; if (idx) idx[i] = 0;
2722     for (j=1; j<n; j++) {
2723       if (PetscRealPart(x[i]) < PetscRealPart(aa[i+a->lda*j])) {x[i] = aa[i + a->lda*j]; if (idx) idx[i] = j;}
2724     }
2725   }
2726   ierr = MatDenseRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2727   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2728   PetscFunctionReturn(0);
2729 }
2730 
2731 static PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A,Vec v,PetscInt idx[])
2732 {
2733   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
2734   PetscErrorCode    ierr;
2735   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,p;
2736   PetscScalar       *x;
2737   PetscReal         atmp;
2738   const PetscScalar *aa;
2739 
2740   PetscFunctionBegin;
2741   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2742   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2743   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
2744   ierr = MatDenseGetArrayRead(A,&aa);CHKERRQ(ierr);
2745   if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2746   for (i=0; i<m; i++) {
2747     x[i] = PetscAbsScalar(aa[i]);
2748     for (j=1; j<n; j++) {
2749       atmp = PetscAbsScalar(aa[i+a->lda*j]);
2750       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = j;}
2751     }
2752   }
2753   ierr = MatDenseRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2754   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2755   PetscFunctionReturn(0);
2756 }
2757 
2758 static PetscErrorCode MatGetRowMin_SeqDense(Mat A,Vec v,PetscInt idx[])
2759 {
2760   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
2761   PetscErrorCode    ierr;
2762   PetscInt          i,j,m = A->rmap->n,n = A->cmap->n,p;
2763   PetscScalar       *x;
2764   const PetscScalar *aa;
2765 
2766   PetscFunctionBegin;
2767   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2768   ierr = MatDenseGetArrayRead(A,&aa);CHKERRQ(ierr);
2769   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2770   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
2771   if (p != A->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
2772   for (i=0; i<m; i++) {
2773     x[i] = aa[i]; if (idx) idx[i] = 0;
2774     for (j=1; j<n; j++) {
2775       if (PetscRealPart(x[i]) > PetscRealPart(aa[i+a->lda*j])) {x[i] = aa[i + a->lda*j]; if (idx) idx[i] = j;}
2776     }
2777   }
2778   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2779   ierr = MatDenseRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2780   PetscFunctionReturn(0);
2781 }
2782 
2783 PetscErrorCode MatGetColumnVector_SeqDense(Mat A,Vec v,PetscInt col)
2784 {
2785   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
2786   PetscErrorCode    ierr;
2787   PetscScalar       *x;
2788   const PetscScalar *aa;
2789 
2790   PetscFunctionBegin;
2791   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2792   ierr = MatDenseGetArrayRead(A,&aa);CHKERRQ(ierr);
2793   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
2794   ierr = PetscArraycpy(x,aa+col*a->lda,A->rmap->n);CHKERRQ(ierr);
2795   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
2796   ierr = MatDenseRestoreArrayRead(A,&aa);CHKERRQ(ierr);
2797   PetscFunctionReturn(0);
2798 }
2799 
2800 PETSC_INTERN PetscErrorCode MatGetColumnReductions_SeqDense(Mat A,PetscInt type,PetscReal *reductions)
2801 {
2802   PetscErrorCode    ierr;
2803   PetscInt          i,j,m,n;
2804   const PetscScalar *a;
2805 
2806   PetscFunctionBegin;
2807   ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr);
2808   ierr = PetscArrayzero(reductions,n);CHKERRQ(ierr);
2809   ierr = MatDenseGetArrayRead(A,&a);CHKERRQ(ierr);
2810   if (type == NORM_2) {
2811     for (i=0; i<n; i++) {
2812       for (j=0; j<m; j++) {
2813         reductions[i] += PetscAbsScalar(a[j]*a[j]);
2814       }
2815       a += m;
2816     }
2817   } else if (type == NORM_1) {
2818     for (i=0; i<n; i++) {
2819       for (j=0; j<m; j++) {
2820         reductions[i] += PetscAbsScalar(a[j]);
2821       }
2822       a += m;
2823     }
2824   } else if (type == NORM_INFINITY) {
2825     for (i=0; i<n; i++) {
2826       for (j=0; j<m; j++) {
2827         reductions[i] = PetscMax(PetscAbsScalar(a[j]),reductions[i]);
2828       }
2829       a += m;
2830     }
2831   } else if (type == REDUCTION_SUM_REALPART || type == REDUCTION_MEAN_REALPART) {
2832     for (i=0; i<n; i++) {
2833       for (j=0; j<m; j++) {
2834         reductions[i] += PetscRealPart(a[j]);
2835       }
2836       a += m;
2837     }
2838   } else if (type == REDUCTION_SUM_IMAGINARYPART || type == REDUCTION_MEAN_IMAGINARYPART) {
2839     for (i=0; i<n; i++) {
2840       for (j=0; j<m; j++) {
2841         reductions[i] += PetscImaginaryPart(a[j]);
2842       }
2843       a += m;
2844     }
2845   } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Unknown reduction type");
2846   ierr = MatDenseRestoreArrayRead(A,&a);CHKERRQ(ierr);
2847   if (type == NORM_2) {
2848     for (i=0; i<n; i++) reductions[i] = PetscSqrtReal(reductions[i]);
2849   } else if (type == REDUCTION_MEAN_REALPART || type == REDUCTION_MEAN_IMAGINARYPART) {
2850     for (i=0; i<n; i++) reductions[i] /= m;
2851   }
2852   PetscFunctionReturn(0);
2853 }
2854 
2855 static PetscErrorCode  MatSetRandom_SeqDense(Mat x,PetscRandom rctx)
2856 {
2857   PetscErrorCode ierr;
2858   PetscScalar    *a;
2859   PetscInt       lda,m,n,i,j;
2860 
2861   PetscFunctionBegin;
2862   ierr = MatGetSize(x,&m,&n);CHKERRQ(ierr);
2863   ierr = MatDenseGetLDA(x,&lda);CHKERRQ(ierr);
2864   ierr = MatDenseGetArray(x,&a);CHKERRQ(ierr);
2865   for (j=0; j<n; j++) {
2866     for (i=0; i<m; i++) {
2867       ierr = PetscRandomGetValue(rctx,a+j*lda+i);CHKERRQ(ierr);
2868     }
2869   }
2870   ierr = MatDenseRestoreArray(x,&a);CHKERRQ(ierr);
2871   PetscFunctionReturn(0);
2872 }
2873 
2874 static PetscErrorCode MatMissingDiagonal_SeqDense(Mat A,PetscBool  *missing,PetscInt *d)
2875 {
2876   PetscFunctionBegin;
2877   *missing = PETSC_FALSE;
2878   PetscFunctionReturn(0);
2879 }
2880 
2881 /* vals is not const */
2882 static PetscErrorCode MatDenseGetColumn_SeqDense(Mat A,PetscInt col,PetscScalar **vals)
2883 {
2884   PetscErrorCode ierr;
2885   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
2886   PetscScalar    *v;
2887 
2888   PetscFunctionBegin;
2889   if (A->factortype) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
2890   ierr  = MatDenseGetArray(A,&v);CHKERRQ(ierr);
2891   *vals = v+col*a->lda;
2892   ierr  = MatDenseRestoreArray(A,&v);CHKERRQ(ierr);
2893   PetscFunctionReturn(0);
2894 }
2895 
2896 static PetscErrorCode MatDenseRestoreColumn_SeqDense(Mat A,PetscScalar **vals)
2897 {
2898   PetscFunctionBegin;
2899   *vals = NULL; /* user cannot accidentally use the array later */
2900   PetscFunctionReturn(0);
2901 }
2902 
2903 /* -------------------------------------------------------------------*/
2904 static struct _MatOps MatOps_Values = { MatSetValues_SeqDense,
2905                                         MatGetRow_SeqDense,
2906                                         MatRestoreRow_SeqDense,
2907                                         MatMult_SeqDense,
2908                                 /*  4*/ MatMultAdd_SeqDense,
2909                                         MatMultTranspose_SeqDense,
2910                                         MatMultTransposeAdd_SeqDense,
2911                                         NULL,
2912                                         NULL,
2913                                         NULL,
2914                                 /* 10*/ NULL,
2915                                         MatLUFactor_SeqDense,
2916                                         MatCholeskyFactor_SeqDense,
2917                                         MatSOR_SeqDense,
2918                                         MatTranspose_SeqDense,
2919                                 /* 15*/ MatGetInfo_SeqDense,
2920                                         MatEqual_SeqDense,
2921                                         MatGetDiagonal_SeqDense,
2922                                         MatDiagonalScale_SeqDense,
2923                                         MatNorm_SeqDense,
2924                                 /* 20*/ MatAssemblyBegin_SeqDense,
2925                                         MatAssemblyEnd_SeqDense,
2926                                         MatSetOption_SeqDense,
2927                                         MatZeroEntries_SeqDense,
2928                                 /* 24*/ MatZeroRows_SeqDense,
2929                                         NULL,
2930                                         NULL,
2931                                         NULL,
2932                                         NULL,
2933                                 /* 29*/ MatSetUp_SeqDense,
2934                                         NULL,
2935                                         NULL,
2936                                         NULL,
2937                                         NULL,
2938                                 /* 34*/ MatDuplicate_SeqDense,
2939                                         NULL,
2940                                         NULL,
2941                                         NULL,
2942                                         NULL,
2943                                 /* 39*/ MatAXPY_SeqDense,
2944                                         MatCreateSubMatrices_SeqDense,
2945                                         NULL,
2946                                         MatGetValues_SeqDense,
2947                                         MatCopy_SeqDense,
2948                                 /* 44*/ MatGetRowMax_SeqDense,
2949                                         MatScale_SeqDense,
2950                                         MatShift_Basic,
2951                                         NULL,
2952                                         MatZeroRowsColumns_SeqDense,
2953                                 /* 49*/ MatSetRandom_SeqDense,
2954                                         NULL,
2955                                         NULL,
2956                                         NULL,
2957                                         NULL,
2958                                 /* 54*/ NULL,
2959                                         NULL,
2960                                         NULL,
2961                                         NULL,
2962                                         NULL,
2963                                 /* 59*/ MatCreateSubMatrix_SeqDense,
2964                                         MatDestroy_SeqDense,
2965                                         MatView_SeqDense,
2966                                         NULL,
2967                                         NULL,
2968                                 /* 64*/ NULL,
2969                                         NULL,
2970                                         NULL,
2971                                         NULL,
2972                                         NULL,
2973                                 /* 69*/ MatGetRowMaxAbs_SeqDense,
2974                                         NULL,
2975                                         NULL,
2976                                         NULL,
2977                                         NULL,
2978                                 /* 74*/ NULL,
2979                                         NULL,
2980                                         NULL,
2981                                         NULL,
2982                                         NULL,
2983                                 /* 79*/ NULL,
2984                                         NULL,
2985                                         NULL,
2986                                         NULL,
2987                                 /* 83*/ MatLoad_SeqDense,
2988                                         MatIsSymmetric_SeqDense,
2989                                         MatIsHermitian_SeqDense,
2990                                         NULL,
2991                                         NULL,
2992                                         NULL,
2993                                 /* 89*/ NULL,
2994                                         NULL,
2995                                         MatMatMultNumeric_SeqDense_SeqDense,
2996                                         NULL,
2997                                         NULL,
2998                                 /* 94*/ NULL,
2999                                         NULL,
3000                                         NULL,
3001                                         MatMatTransposeMultNumeric_SeqDense_SeqDense,
3002                                         NULL,
3003                                 /* 99*/ MatProductSetFromOptions_SeqDense,
3004                                         NULL,
3005                                         NULL,
3006                                         MatConjugate_SeqDense,
3007                                         NULL,
3008                                 /*104*/ NULL,
3009                                         MatRealPart_SeqDense,
3010                                         MatImaginaryPart_SeqDense,
3011                                         NULL,
3012                                         NULL,
3013                                 /*109*/ NULL,
3014                                         NULL,
3015                                         MatGetRowMin_SeqDense,
3016                                         MatGetColumnVector_SeqDense,
3017                                         MatMissingDiagonal_SeqDense,
3018                                 /*114*/ NULL,
3019                                         NULL,
3020                                         NULL,
3021                                         NULL,
3022                                         NULL,
3023                                 /*119*/ NULL,
3024                                         NULL,
3025                                         NULL,
3026                                         NULL,
3027                                         NULL,
3028                                 /*124*/ NULL,
3029                                         MatGetColumnReductions_SeqDense,
3030                                         NULL,
3031                                         NULL,
3032                                         NULL,
3033                                 /*129*/ NULL,
3034                                         NULL,
3035                                         NULL,
3036                                         MatTransposeMatMultNumeric_SeqDense_SeqDense,
3037                                         NULL,
3038                                 /*134*/ NULL,
3039                                         NULL,
3040                                         NULL,
3041                                         NULL,
3042                                         NULL,
3043                                 /*139*/ NULL,
3044                                         NULL,
3045                                         NULL,
3046                                         NULL,
3047                                         NULL,
3048                                         MatCreateMPIMatConcatenateSeqMat_SeqDense,
3049                                 /*145*/ NULL,
3050                                         NULL,
3051                                         NULL
3052 };
3053 
3054 /*@C
3055    MatCreateSeqDense - Creates a sequential dense matrix that
3056    is stored in column major order (the usual Fortran 77 manner). Many
3057    of the matrix operations use the BLAS and LAPACK routines.
3058 
3059    Collective
3060 
3061    Input Parameters:
3062 +  comm - MPI communicator, set to PETSC_COMM_SELF
3063 .  m - number of rows
3064 .  n - number of columns
3065 -  data - optional location of matrix data in column major order.  Set data=NULL for PETSc
3066    to control all matrix memory allocation.
3067 
3068    Output Parameter:
3069 .  A - the matrix
3070 
3071    Notes:
3072    The data input variable is intended primarily for Fortran programmers
3073    who wish to allocate their own matrix memory space.  Most users should
3074    set data=NULL.
3075 
3076    Level: intermediate
3077 
3078 .seealso: MatCreate(), MatCreateDense(), MatSetValues()
3079 @*/
3080 PetscErrorCode  MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A)
3081 {
3082   PetscErrorCode ierr;
3083 
3084   PetscFunctionBegin;
3085   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3086   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
3087   ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr);
3088   ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr);
3089   PetscFunctionReturn(0);
3090 }
3091 
3092 /*@C
3093    MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements
3094 
3095    Collective
3096 
3097    Input Parameters:
3098 +  B - the matrix
3099 -  data - the array (or NULL)
3100 
3101    Notes:
3102    The data input variable is intended primarily for Fortran programmers
3103    who wish to allocate their own matrix memory space.  Most users should
3104    need not call this routine.
3105 
3106    Level: intermediate
3107 
3108 .seealso: MatCreate(), MatCreateDense(), MatSetValues(), MatDenseSetLDA()
3109 
3110 @*/
3111 PetscErrorCode  MatSeqDenseSetPreallocation(Mat B,PetscScalar data[])
3112 {
3113   PetscErrorCode ierr;
3114 
3115   PetscFunctionBegin;
3116   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
3117   ierr = PetscTryMethod(B,"MatSeqDenseSetPreallocation_C",(Mat,PetscScalar[]),(B,data));CHKERRQ(ierr);
3118   PetscFunctionReturn(0);
3119 }
3120 
3121 PetscErrorCode  MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data)
3122 {
3123   Mat_SeqDense   *b = (Mat_SeqDense*)B->data;
3124   PetscErrorCode ierr;
3125 
3126   PetscFunctionBegin;
3127   if (b->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
3128   B->preallocated = PETSC_TRUE;
3129 
3130   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
3131   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
3132 
3133   if (b->lda <= 0) b->lda = B->rmap->n;
3134 
3135   ierr = PetscIntMultError(b->lda,B->cmap->n,NULL);CHKERRQ(ierr);
3136   if (!data) { /* petsc-allocated storage */
3137     if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); }
3138     ierr = PetscCalloc1((size_t)b->lda*B->cmap->n,&b->v);CHKERRQ(ierr);
3139     ierr = PetscLogObjectMemory((PetscObject)B,b->lda*B->cmap->n*sizeof(PetscScalar));CHKERRQ(ierr);
3140 
3141     b->user_alloc = PETSC_FALSE;
3142   } else { /* user-allocated storage */
3143     if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); }
3144     b->v          = data;
3145     b->user_alloc = PETSC_TRUE;
3146   }
3147   B->assembled = PETSC_TRUE;
3148   PetscFunctionReturn(0);
3149 }
3150 
3151 #if defined(PETSC_HAVE_ELEMENTAL)
3152 PETSC_INTERN PetscErrorCode MatConvert_SeqDense_Elemental(Mat A, MatType newtype,MatReuse reuse,Mat *newmat)
3153 {
3154   Mat               mat_elemental;
3155   PetscErrorCode    ierr;
3156   const PetscScalar *array;
3157   PetscScalar       *v_colwise;
3158   PetscInt          M=A->rmap->N,N=A->cmap->N,i,j,k,*rows,*cols;
3159 
3160   PetscFunctionBegin;
3161   ierr = PetscMalloc3(M*N,&v_colwise,M,&rows,N,&cols);CHKERRQ(ierr);
3162   ierr = MatDenseGetArrayRead(A,&array);CHKERRQ(ierr);
3163   /* convert column-wise array into row-wise v_colwise, see MatSetValues_Elemental() */
3164   k = 0;
3165   for (j=0; j<N; j++) {
3166     cols[j] = j;
3167     for (i=0; i<M; i++) {
3168       v_colwise[j*M+i] = array[k++];
3169     }
3170   }
3171   for (i=0; i<M; i++) {
3172     rows[i] = i;
3173   }
3174   ierr = MatDenseRestoreArrayRead(A,&array);CHKERRQ(ierr);
3175 
3176   ierr = MatCreate(PetscObjectComm((PetscObject)A), &mat_elemental);CHKERRQ(ierr);
3177   ierr = MatSetSizes(mat_elemental,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3178   ierr = MatSetType(mat_elemental,MATELEMENTAL);CHKERRQ(ierr);
3179   ierr = MatSetUp(mat_elemental);CHKERRQ(ierr);
3180 
3181   /* PETSc-Elemental interaface uses axpy for setting off-processor entries, only ADD_VALUES is allowed */
3182   ierr = MatSetValues(mat_elemental,M,rows,N,cols,v_colwise,ADD_VALUES);CHKERRQ(ierr);
3183   ierr = MatAssemblyBegin(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3184   ierr = MatAssemblyEnd(mat_elemental, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3185   ierr = PetscFree3(v_colwise,rows,cols);CHKERRQ(ierr);
3186 
3187   if (reuse == MAT_INPLACE_MATRIX) {
3188     ierr = MatHeaderReplace(A,&mat_elemental);CHKERRQ(ierr);
3189   } else {
3190     *newmat = mat_elemental;
3191   }
3192   PetscFunctionReturn(0);
3193 }
3194 #endif
3195 
3196 PetscErrorCode  MatDenseSetLDA_SeqDense(Mat B,PetscInt lda)
3197 {
3198   Mat_SeqDense *b = (Mat_SeqDense*)B->data;
3199   PetscBool    data;
3200 
3201   PetscFunctionBegin;
3202   data = (PetscBool)((B->rmap->n > 0 && B->cmap->n > 0) ? (b->v ? PETSC_TRUE : PETSC_FALSE) : PETSC_FALSE);
3203   if (!b->user_alloc && data && b->lda!=lda) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"LDA cannot be changed after allocation of internal storage");
3204   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);
3205   b->lda = lda;
3206   PetscFunctionReturn(0);
3207 }
3208 
3209 PetscErrorCode MatCreateMPIMatConcatenateSeqMat_SeqDense(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat)
3210 {
3211   PetscErrorCode ierr;
3212   PetscMPIInt    size;
3213 
3214   PetscFunctionBegin;
3215   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
3216   if (size == 1) {
3217     if (scall == MAT_INITIAL_MATRIX) {
3218       ierr = MatDuplicate(inmat,MAT_COPY_VALUES,outmat);CHKERRQ(ierr);
3219     } else {
3220       ierr = MatCopy(inmat,*outmat,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
3221     }
3222   } else {
3223     ierr = MatCreateMPIMatConcatenateSeqMat_MPIDense(comm,inmat,n,scall,outmat);CHKERRQ(ierr);
3224   }
3225   PetscFunctionReturn(0);
3226 }
3227 
3228 PetscErrorCode MatDenseGetColumnVec_SeqDense(Mat A,PetscInt col,Vec *v)
3229 {
3230   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3231   PetscErrorCode ierr;
3232 
3233   PetscFunctionBegin;
3234   if (a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
3235   if (a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
3236   if (!a->cvec) {
3237     ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)A),A->rmap->bs,A->rmap->n,NULL,&a->cvec);CHKERRQ(ierr);
3238     ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)a->cvec);CHKERRQ(ierr);
3239   }
3240   a->vecinuse = col + 1;
3241   ierr = MatDenseGetArray(A,(PetscScalar**)&a->ptrinuse);CHKERRQ(ierr);
3242   ierr = VecPlaceArray(a->cvec,a->ptrinuse + (size_t)col * (size_t)a->lda);CHKERRQ(ierr);
3243   *v   = a->cvec;
3244   PetscFunctionReturn(0);
3245 }
3246 
3247 PetscErrorCode MatDenseRestoreColumnVec_SeqDense(Mat A,PetscInt col,Vec *v)
3248 {
3249   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3250   PetscErrorCode ierr;
3251 
3252   PetscFunctionBegin;
3253   if (!a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseGetColumnVec() first");
3254   if (!a->cvec) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing internal column vector");
3255   a->vecinuse = 0;
3256   ierr = MatDenseRestoreArray(A,(PetscScalar**)&a->ptrinuse);CHKERRQ(ierr);
3257   ierr = VecResetArray(a->cvec);CHKERRQ(ierr);
3258   *v   = NULL;
3259   PetscFunctionReturn(0);
3260 }
3261 
3262 PetscErrorCode MatDenseGetColumnVecRead_SeqDense(Mat A,PetscInt col,Vec *v)
3263 {
3264   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3265   PetscErrorCode ierr;
3266 
3267   PetscFunctionBegin;
3268   if (a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
3269   if (a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
3270   if (!a->cvec) {
3271     ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)A),A->rmap->bs,A->rmap->n,NULL,&a->cvec);CHKERRQ(ierr);
3272     ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)a->cvec);CHKERRQ(ierr);
3273   }
3274   a->vecinuse = col + 1;
3275   ierr = MatDenseGetArrayRead(A,&a->ptrinuse);CHKERRQ(ierr);
3276   ierr = VecPlaceArray(a->cvec,a->ptrinuse + (size_t)col * (size_t)a->lda);CHKERRQ(ierr);
3277   ierr = VecLockReadPush(a->cvec);CHKERRQ(ierr);
3278   *v   = a->cvec;
3279   PetscFunctionReturn(0);
3280 }
3281 
3282 PetscErrorCode MatDenseRestoreColumnVecRead_SeqDense(Mat A,PetscInt col,Vec *v)
3283 {
3284   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3285   PetscErrorCode ierr;
3286 
3287   PetscFunctionBegin;
3288   if (!a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseGetColumnVec() first");
3289   if (!a->cvec) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing internal column vector");
3290   a->vecinuse = 0;
3291   ierr = MatDenseRestoreArrayRead(A,&a->ptrinuse);CHKERRQ(ierr);
3292   ierr = VecLockReadPop(a->cvec);CHKERRQ(ierr);
3293   ierr = VecResetArray(a->cvec);CHKERRQ(ierr);
3294   *v   = NULL;
3295   PetscFunctionReturn(0);
3296 }
3297 
3298 PetscErrorCode MatDenseGetColumnVecWrite_SeqDense(Mat A,PetscInt col,Vec *v)
3299 {
3300   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3301   PetscErrorCode ierr;
3302 
3303   PetscFunctionBegin;
3304   if (a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
3305   if (a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
3306   if (!a->cvec) {
3307     ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)A),A->rmap->bs,A->rmap->n,NULL,&a->cvec);CHKERRQ(ierr);
3308     ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)a->cvec);CHKERRQ(ierr);
3309   }
3310   a->vecinuse = col + 1;
3311   ierr = MatDenseGetArrayWrite(A,(PetscScalar**)&a->ptrinuse);CHKERRQ(ierr);
3312   ierr = VecPlaceArray(a->cvec,a->ptrinuse + (size_t)col * (size_t)a->lda);CHKERRQ(ierr);
3313   *v   = a->cvec;
3314   PetscFunctionReturn(0);
3315 }
3316 
3317 PetscErrorCode MatDenseRestoreColumnVecWrite_SeqDense(Mat A,PetscInt col,Vec *v)
3318 {
3319   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3320   PetscErrorCode ierr;
3321 
3322   PetscFunctionBegin;
3323   if (!a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseGetColumnVec() first");
3324   if (!a->cvec) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing internal column vector");
3325   a->vecinuse = 0;
3326   ierr = MatDenseRestoreArrayWrite(A,(PetscScalar**)&a->ptrinuse);CHKERRQ(ierr);
3327   ierr = VecResetArray(a->cvec);CHKERRQ(ierr);
3328   *v   = NULL;
3329   PetscFunctionReturn(0);
3330 }
3331 
3332 PetscErrorCode MatDenseGetSubMatrix_SeqDense(Mat A,PetscInt cbegin,PetscInt cend,Mat *v)
3333 {
3334   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3335   PetscErrorCode ierr;
3336 
3337   PetscFunctionBegin;
3338   if (a->vecinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreColumnVec() first");
3339   if (a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseRestoreSubMatrix() first");
3340   if (a->cmat && cend-cbegin != a->cmat->cmap->N) {
3341     ierr = MatDestroy(&a->cmat);CHKERRQ(ierr);
3342   }
3343   if (!a->cmat) {
3344     ierr = MatCreateDense(PetscObjectComm((PetscObject)A),A->rmap->n,PETSC_DECIDE,A->rmap->N,cend-cbegin,(PetscScalar*)a->v + (size_t)cbegin * (size_t)a->lda,&a->cmat);CHKERRQ(ierr);
3345     ierr = PetscLogObjectParent((PetscObject)A,(PetscObject)a->cmat);CHKERRQ(ierr);
3346   } else {
3347     ierr = MatDensePlaceArray(a->cmat,a->v + (size_t)cbegin * (size_t)a->lda);CHKERRQ(ierr);
3348   }
3349   ierr = MatDenseSetLDA(a->cmat,a->lda);CHKERRQ(ierr);
3350   a->matinuse = cbegin + 1;
3351   *v = a->cmat;
3352   PetscFunctionReturn(0);
3353 }
3354 
3355 PetscErrorCode MatDenseRestoreSubMatrix_SeqDense(Mat A,Mat *v)
3356 {
3357   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
3358   PetscErrorCode ierr;
3359 
3360   PetscFunctionBegin;
3361   if (!a->matinuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER,"Need to call MatDenseGetSubMatrix() first");
3362   if (!a->cmat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing internal column matrix");
3363   if (*v != a->cmat) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not the matrix obtained from MatDenseGetSubMatrix()");
3364   a->matinuse = 0;
3365   ierr = MatDenseResetArray(a->cmat);CHKERRQ(ierr);
3366   *v   = NULL;
3367   PetscFunctionReturn(0);
3368 }
3369 
3370 /*MC
3371    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
3372 
3373    Options Database Keys:
3374 . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions()
3375 
3376   Level: beginner
3377 
3378 .seealso: MatCreateSeqDense()
3379 
3380 M*/
3381 PetscErrorCode MatCreate_SeqDense(Mat B)
3382 {
3383   Mat_SeqDense   *b;
3384   PetscErrorCode ierr;
3385   PetscMPIInt    size;
3386 
3387   PetscFunctionBegin;
3388   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRMPI(ierr);
3389   if (size > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
3390 
3391   ierr    = PetscNewLog(B,&b);CHKERRQ(ierr);
3392   ierr    = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
3393   B->data = (void*)b;
3394 
3395   b->roworiented = PETSC_TRUE;
3396 
3397   ierr = PetscObjectComposeFunction((PetscObject)B,"MatQRFactor_C",MatQRFactor_SeqDense);CHKERRQ(ierr);
3398   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetLDA_C",MatDenseGetLDA_SeqDense);CHKERRQ(ierr);
3399   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseSetLDA_C",MatDenseSetLDA_SeqDense);CHKERRQ(ierr);
3400   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArray_C",MatDenseGetArray_SeqDense);CHKERRQ(ierr);
3401   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArray_C",MatDenseRestoreArray_SeqDense);CHKERRQ(ierr);
3402   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDensePlaceArray_C",MatDensePlaceArray_SeqDense);CHKERRQ(ierr);
3403   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseResetArray_C",MatDenseResetArray_SeqDense);CHKERRQ(ierr);
3404   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseReplaceArray_C",MatDenseReplaceArray_SeqDense);CHKERRQ(ierr);
3405   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArrayRead_C",MatDenseGetArray_SeqDense);CHKERRQ(ierr);
3406   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArrayRead_C",MatDenseRestoreArray_SeqDense);CHKERRQ(ierr);
3407   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetArrayWrite_C",MatDenseGetArray_SeqDense);CHKERRQ(ierr);
3408   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreArrayWrite_C",MatDenseRestoreArray_SeqDense);CHKERRQ(ierr);
3409   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_seqaij_C",MatConvert_SeqDense_SeqAIJ);CHKERRQ(ierr);
3410 #if defined(PETSC_HAVE_ELEMENTAL)
3411   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_elemental_C",MatConvert_SeqDense_Elemental);CHKERRQ(ierr);
3412 #endif
3413 #if defined(PETSC_HAVE_SCALAPACK)
3414   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_scalapack_C",MatConvert_Dense_ScaLAPACK);CHKERRQ(ierr);
3415 #endif
3416 #if defined(PETSC_HAVE_CUDA)
3417   ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_seqdense_seqdensecuda_C",MatConvert_SeqDense_SeqDenseCUDA);CHKERRQ(ierr);
3418   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdensecuda_seqdensecuda_C",MatProductSetFromOptions_SeqDense);CHKERRQ(ierr);
3419   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdensecuda_seqdense_C",MatProductSetFromOptions_SeqDense);CHKERRQ(ierr);
3420   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqdensecuda_C",MatProductSetFromOptions_SeqDense);CHKERRQ(ierr);
3421 #endif
3422   ierr = PetscObjectComposeFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",MatSeqDenseSetPreallocation_SeqDense);CHKERRQ(ierr);
3423   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqaij_seqdense_C",MatProductSetFromOptions_SeqAIJ_SeqDense);CHKERRQ(ierr);
3424   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqdense_seqdense_C",MatProductSetFromOptions_SeqDense);CHKERRQ(ierr);
3425   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqbaij_seqdense_C",MatProductSetFromOptions_SeqXBAIJ_SeqDense);CHKERRQ(ierr);
3426   ierr = PetscObjectComposeFunction((PetscObject)B,"MatProductSetFromOptions_seqsbaij_seqdense_C",MatProductSetFromOptions_SeqXBAIJ_SeqDense);CHKERRQ(ierr);
3427 
3428   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetColumn_C",MatDenseGetColumn_SeqDense);CHKERRQ(ierr);
3429   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreColumn_C",MatDenseRestoreColumn_SeqDense);CHKERRQ(ierr);
3430   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetColumnVec_C",MatDenseGetColumnVec_SeqDense);CHKERRQ(ierr);
3431   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreColumnVec_C",MatDenseRestoreColumnVec_SeqDense);CHKERRQ(ierr);
3432   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetColumnVecRead_C",MatDenseGetColumnVecRead_SeqDense);CHKERRQ(ierr);
3433   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreColumnVecRead_C",MatDenseRestoreColumnVecRead_SeqDense);CHKERRQ(ierr);
3434   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetColumnVecWrite_C",MatDenseGetColumnVecWrite_SeqDense);CHKERRQ(ierr);
3435   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreColumnVecWrite_C",MatDenseRestoreColumnVecWrite_SeqDense);CHKERRQ(ierr);
3436   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseGetSubMatrix_C",MatDenseGetSubMatrix_SeqDense);CHKERRQ(ierr);
3437   ierr = PetscObjectComposeFunction((PetscObject)B,"MatDenseRestoreSubMatrix_C",MatDenseRestoreSubMatrix_SeqDense);CHKERRQ(ierr);
3438   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQDENSE);CHKERRQ(ierr);
3439   PetscFunctionReturn(0);
3440 }
3441 
3442 /*@C
3443    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.
3444 
3445    Not Collective
3446 
3447    Input Parameters:
3448 +  mat - a MATSEQDENSE or MATMPIDENSE matrix
3449 -  col - column index
3450 
3451    Output Parameter:
3452 .  vals - pointer to the data
3453 
3454    Level: intermediate
3455 
3456 .seealso: MatDenseRestoreColumn()
3457 @*/
3458 PetscErrorCode MatDenseGetColumn(Mat A,PetscInt col,PetscScalar **vals)
3459 {
3460   PetscErrorCode ierr;
3461 
3462   PetscFunctionBegin;
3463   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3464   PetscValidLogicalCollectiveInt(A,col,2);
3465   PetscValidPointer(vals,3);
3466   ierr = PetscUseMethod(A,"MatDenseGetColumn_C",(Mat,PetscInt,PetscScalar**),(A,col,vals));CHKERRQ(ierr);
3467   PetscFunctionReturn(0);
3468 }
3469 
3470 /*@C
3471    MatDenseRestoreColumn - returns access to a column of a dense matrix which is returned by MatDenseGetColumn().
3472 
3473    Not Collective
3474 
3475    Input Parameter:
3476 .  mat - a MATSEQDENSE or MATMPIDENSE matrix
3477 
3478    Output Parameter:
3479 .  vals - pointer to the data
3480 
3481    Level: intermediate
3482 
3483 .seealso: MatDenseGetColumn()
3484 @*/
3485 PetscErrorCode MatDenseRestoreColumn(Mat A,PetscScalar **vals)
3486 {
3487   PetscErrorCode ierr;
3488 
3489   PetscFunctionBegin;
3490   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3491   PetscValidPointer(vals,2);
3492   ierr = PetscUseMethod(A,"MatDenseRestoreColumn_C",(Mat,PetscScalar**),(A,vals));CHKERRQ(ierr);
3493   PetscFunctionReturn(0);
3494 }
3495 
3496 /*@
3497    MatDenseGetColumnVec - Gives read-write access to a column of a dense matrix, represented as a Vec.
3498 
3499    Collective
3500 
3501    Input Parameters:
3502 +  mat - the Mat object
3503 -  col - the column index
3504 
3505    Output Parameter:
3506 .  v - the vector
3507 
3508    Notes:
3509      The vector is owned by PETSc. Users need to call MatDenseRestoreColumnVec() when the vector is no longer needed.
3510      Use MatDenseGetColumnVecRead() to obtain read-only access or MatDenseGetColumnVecWrite() for write-only access.
3511 
3512    Level: intermediate
3513 
3514 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVecRead(), MatDenseGetColumnVecWrite(), MatDenseRestoreColumnVec(), MatDenseRestoreColumnVecRead(), MatDenseRestoreColumnVecWrite()
3515 @*/
3516 PetscErrorCode MatDenseGetColumnVec(Mat A,PetscInt col,Vec *v)
3517 {
3518   PetscErrorCode ierr;
3519 
3520   PetscFunctionBegin;
3521   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3522   PetscValidType(A,1);
3523   PetscValidLogicalCollectiveInt(A,col,2);
3524   PetscValidPointer(v,3);
3525   if (!A->preallocated) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Matrix not preallocated");
3526   if (col < 0 || col > A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid col %D, should be in [0,%D)",col,A->cmap->N);
3527   ierr = PetscUseMethod(A,"MatDenseGetColumnVec_C",(Mat,PetscInt,Vec*),(A,col,v));CHKERRQ(ierr);
3528   PetscFunctionReturn(0);
3529 }
3530 
3531 /*@
3532    MatDenseRestoreColumnVec - Returns access to a column of a dense matrix obtained from MatDenseGetColumnVec().
3533 
3534    Collective
3535 
3536    Input Parameters:
3537 +  mat - the Mat object
3538 .  col - the column index
3539 -  v - the Vec object
3540 
3541    Level: intermediate
3542 
3543 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVec(), MatDenseGetColumnVecRead(), MatDenseGetColumnVecWrite(), MatDenseRestoreColumnVecRead(), MatDenseRestoreColumnVecWrite()
3544 @*/
3545 PetscErrorCode MatDenseRestoreColumnVec(Mat A,PetscInt col,Vec *v)
3546 {
3547   PetscErrorCode ierr;
3548 
3549   PetscFunctionBegin;
3550   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3551   PetscValidType(A,1);
3552   PetscValidLogicalCollectiveInt(A,col,2);
3553   PetscValidPointer(v,3);
3554   if (!A->preallocated) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Matrix not preallocated");
3555   if (col < 0 || col > A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid col %D, should be in [0,%D)",col,A->cmap->N);
3556   ierr = PetscUseMethod(A,"MatDenseRestoreColumnVec_C",(Mat,PetscInt,Vec*),(A,col,v));CHKERRQ(ierr);
3557   PetscFunctionReturn(0);
3558 }
3559 
3560 /*@
3561    MatDenseGetColumnVecRead - Gives read-only access to a column of a dense matrix, represented as a Vec.
3562 
3563    Collective
3564 
3565    Input Parameters:
3566 +  mat - the Mat object
3567 -  col - the column index
3568 
3569    Output Parameter:
3570 .  v - the vector
3571 
3572    Notes:
3573      The vector is owned by PETSc and users cannot modify it.
3574      Users need to call MatDenseRestoreColumnVecRead() when the vector is no longer needed.
3575      Use MatDenseGetColumnVec() to obtain read-write access or MatDenseGetColumnVecWrite() for write-only access.
3576 
3577    Level: intermediate
3578 
3579 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVec(), MatDenseGetColumnVecWrite(), MatDenseRestoreColumnVec(), MatDenseRestoreColumnVecRead(), MatDenseRestoreColumnVecWrite()
3580 @*/
3581 PetscErrorCode MatDenseGetColumnVecRead(Mat A,PetscInt col,Vec *v)
3582 {
3583   PetscErrorCode ierr;
3584 
3585   PetscFunctionBegin;
3586   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3587   PetscValidType(A,1);
3588   PetscValidLogicalCollectiveInt(A,col,2);
3589   PetscValidPointer(v,3);
3590   if (!A->preallocated) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Matrix not preallocated");
3591   if (col < 0 || col > A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid col %D, should be in [0,%D)",col,A->cmap->N);
3592   ierr = PetscUseMethod(A,"MatDenseGetColumnVecRead_C",(Mat,PetscInt,Vec*),(A,col,v));CHKERRQ(ierr);
3593   PetscFunctionReturn(0);
3594 }
3595 
3596 /*@
3597    MatDenseRestoreColumnVecRead - Returns access to a column of a dense matrix obtained from MatDenseGetColumnVecRead().
3598 
3599    Collective
3600 
3601    Input Parameters:
3602 +  mat - the Mat object
3603 .  col - the column index
3604 -  v - the Vec object
3605 
3606    Level: intermediate
3607 
3608 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVec(), MatDenseGetColumnVecRead(), MatDenseGetColumnVecWrite(), MatDenseRestoreColumnVec(), MatDenseRestoreColumnVecWrite()
3609 @*/
3610 PetscErrorCode MatDenseRestoreColumnVecRead(Mat A,PetscInt col,Vec *v)
3611 {
3612   PetscErrorCode ierr;
3613 
3614   PetscFunctionBegin;
3615   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3616   PetscValidType(A,1);
3617   PetscValidLogicalCollectiveInt(A,col,2);
3618   PetscValidPointer(v,3);
3619   if (!A->preallocated) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Matrix not preallocated");
3620   if (col < 0 || col > A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid col %D, should be in [0,%D)",col,A->cmap->N);
3621   ierr = PetscUseMethod(A,"MatDenseRestoreColumnVecRead_C",(Mat,PetscInt,Vec*),(A,col,v));CHKERRQ(ierr);
3622   PetscFunctionReturn(0);
3623 }
3624 
3625 /*@
3626    MatDenseGetColumnVecWrite - Gives write-only access to a column of a dense matrix, represented as a Vec.
3627 
3628    Collective
3629 
3630    Input Parameters:
3631 +  mat - the Mat object
3632 -  col - the column index
3633 
3634    Output Parameter:
3635 .  v - the vector
3636 
3637    Notes:
3638      The vector is owned by PETSc. Users need to call MatDenseRestoreColumnVecWrite() when the vector is no longer needed.
3639      Use MatDenseGetColumnVec() to obtain read-write access or MatDenseGetColumnVecRead() for read-only access.
3640 
3641    Level: intermediate
3642 
3643 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVec(), MatDenseGetColumnVecRead(), MatDenseRestoreColumnVec(), MatDenseRestoreColumnVecRead(), MatDenseRestoreColumnVecWrite()
3644 @*/
3645 PetscErrorCode MatDenseGetColumnVecWrite(Mat A,PetscInt col,Vec *v)
3646 {
3647   PetscErrorCode ierr;
3648 
3649   PetscFunctionBegin;
3650   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3651   PetscValidType(A,1);
3652   PetscValidLogicalCollectiveInt(A,col,2);
3653   PetscValidPointer(v,3);
3654   if (!A->preallocated) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Matrix not preallocated");
3655   if (col < 0 || col > A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid col %D, should be in [0,%D)",col,A->cmap->N);
3656   ierr = PetscUseMethod(A,"MatDenseGetColumnVecWrite_C",(Mat,PetscInt,Vec*),(A,col,v));CHKERRQ(ierr);
3657   PetscFunctionReturn(0);
3658 }
3659 
3660 /*@
3661    MatDenseRestoreColumnVecWrite - Returns access to a column of a dense matrix obtained from MatDenseGetColumnVecWrite().
3662 
3663    Collective
3664 
3665    Input Parameters:
3666 +  mat - the Mat object
3667 .  col - the column index
3668 -  v - the Vec object
3669 
3670    Level: intermediate
3671 
3672 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVec(), MatDenseGetColumnVecRead(), MatDenseGetColumnVecWrite(), MatDenseRestoreColumnVec(), MatDenseRestoreColumnVecRead()
3673 @*/
3674 PetscErrorCode MatDenseRestoreColumnVecWrite(Mat A,PetscInt col,Vec *v)
3675 {
3676   PetscErrorCode ierr;
3677 
3678   PetscFunctionBegin;
3679   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3680   PetscValidType(A,1);
3681   PetscValidLogicalCollectiveInt(A,col,2);
3682   PetscValidPointer(v,3);
3683   if (!A->preallocated) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Matrix not preallocated");
3684   if (col < 0 || col > A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid col %D, should be in [0,%D)",col,A->cmap->N);
3685   ierr = PetscUseMethod(A,"MatDenseRestoreColumnVecWrite_C",(Mat,PetscInt,Vec*),(A,col,v));CHKERRQ(ierr);
3686   PetscFunctionReturn(0);
3687 }
3688 
3689 /*@
3690    MatDenseGetSubMatrix - Gives access to a block of columns of a dense matrix, represented as a Mat.
3691 
3692    Collective
3693 
3694    Input Parameters:
3695 +  mat - the Mat object
3696 .  cbegin - the first index in the block
3697 -  cend - the last index in the block
3698 
3699    Output Parameter:
3700 .  v - the matrix
3701 
3702    Notes:
3703      The matrix is owned by PETSc. Users need to call MatDenseRestoreSubMatrix() when the matrix is no longer needed.
3704 
3705    Level: intermediate
3706 
3707 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVec(), MatDenseRestoreColumnVec(), MatDenseRestoreSubMatrix()
3708 @*/
3709 PetscErrorCode MatDenseGetSubMatrix(Mat A,PetscInt cbegin,PetscInt cend,Mat *v)
3710 {
3711   PetscErrorCode ierr;
3712 
3713   PetscFunctionBegin;
3714   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3715   PetscValidType(A,1);
3716   PetscValidLogicalCollectiveInt(A,cbegin,2);
3717   PetscValidLogicalCollectiveInt(A,cend,3);
3718   PetscValidPointer(v,4);
3719   if (!A->preallocated) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ORDER,"Matrix not preallocated");
3720   if (cbegin < 0 || cbegin > A->cmap->N) SETERRQ2(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid cbegin %D, should be in [0,%D)",cbegin,A->cmap->N);
3721   if (cend < cbegin || cend > A->cmap->N) SETERRQ3(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Invalid cend %D, should be in [%D,%D)",cend,cbegin,A->cmap->N);
3722   ierr = PetscUseMethod(A,"MatDenseGetSubMatrix_C",(Mat,PetscInt,PetscInt,Mat*),(A,cbegin,cend,v));CHKERRQ(ierr);
3723   PetscFunctionReturn(0);
3724 }
3725 
3726 /*@
3727    MatDenseRestoreSubMatrix - Returns access to a block of columns of a dense matrix obtained from MatDenseGetSubMatrix().
3728 
3729    Collective
3730 
3731    Input Parameters:
3732 +  mat - the Mat object
3733 -  v - the Mat object
3734 
3735    Level: intermediate
3736 
3737 .seealso: MATDENSE, MATDENSECUDA, MatDenseGetColumnVec(), MatDenseRestoreColumnVec(), MatDenseGetSubMatrix()
3738 @*/
3739 PetscErrorCode MatDenseRestoreSubMatrix(Mat A,Mat *v)
3740 {
3741   PetscErrorCode ierr;
3742 
3743   PetscFunctionBegin;
3744   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
3745   PetscValidType(A,1);
3746   PetscValidPointer(v,2);
3747   ierr = PetscUseMethod(A,"MatDenseRestoreSubMatrix_C",(Mat,Mat*),(A,v));CHKERRQ(ierr);
3748   PetscFunctionReturn(0);
3749 }
3750