xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 8cda6cd7047ed8bb2d68b8e371c012553cb590ce)
1 #define PETSCMAT_DLL
2 
3 /*
4      Defines the basic matrix operations for sequential dense.
5 */
6 
7 #include "src/mat/impls/dense/seq/dense.h"
8 #include "petscblaslapack.h"
9 
10 #undef __FUNCT__
11 #define __FUNCT__ "MatAXPY_SeqDense"
12 PetscErrorCode MatAXPY_SeqDense(Mat Y,PetscScalar alpha,Mat X,MatStructure str)
13 {
14   Mat_SeqDense   *x = (Mat_SeqDense*)X->data,*y = (Mat_SeqDense*)Y->data;
15   PetscScalar    oalpha = alpha;
16   PetscInt       j;
17   PetscBLASInt   N,m,ldax,lday,one = 1;
18   PetscErrorCode ierr;
19 
20   PetscFunctionBegin;
21   N    = PetscBLASIntCast(X->rmap.n*X->cmap.n);
22   m    = PetscBLASIntCast(X->rmap.n);
23   ldax = PetscBLASIntCast(x->lda);
24   lday = PetscBLASIntCast(y->lda);
25   if (ldax>m || lday>m) {
26     for (j=0; j<X->cmap.n; j++) {
27       BLASaxpy_(&m,&oalpha,x->v+j*ldax,&one,y->v+j*lday,&one);
28     }
29   } else {
30     BLASaxpy_(&N,&oalpha,x->v,&one,y->v,&one);
31   }
32   ierr = PetscLogFlops(2*N-1);CHKERRQ(ierr);
33   PetscFunctionReturn(0);
34 }
35 
36 #undef __FUNCT__
37 #define __FUNCT__ "MatGetInfo_SeqDense"
38 PetscErrorCode MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info)
39 {
40   PetscInt     N = A->rmap.n*A->cmap.n;
41 
42   PetscFunctionBegin;
43   info->rows_global       = (double)A->rmap.n;
44   info->columns_global    = (double)A->cmap.n;
45   info->rows_local        = (double)A->rmap.n;
46   info->columns_local     = (double)A->cmap.n;
47   info->block_size        = 1.0;
48   info->nz_allocated      = (double)N;
49   info->nz_used           = (double)N;
50   info->nz_unneeded       = (double)0;
51   info->assemblies        = (double)A->num_ass;
52   info->mallocs           = 0;
53   info->memory            = ((PetscObject)A)->mem;
54   info->fill_ratio_given  = 0;
55   info->fill_ratio_needed = 0;
56   info->factor_mallocs    = 0;
57   PetscFunctionReturn(0);
58 }
59 
60 #undef __FUNCT__
61 #define __FUNCT__ "MatScale_SeqDense"
62 PetscErrorCode MatScale_SeqDense(Mat A,PetscScalar alpha)
63 {
64   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
65   PetscScalar    oalpha = alpha;
66   PetscErrorCode ierr;
67   PetscBLASInt   one = 1,j,nz,lda = PetscBLASIntCast(a->lda);
68 
69   PetscFunctionBegin;
70   if (lda>A->rmap.n) {
71     nz = PetscBLASIntCast(A->rmap.n);
72     for (j=0; j<A->cmap.n; j++) {
73       BLASscal_(&nz,&oalpha,a->v+j*lda,&one);
74     }
75   } else {
76     nz = PetscBLASIntCast(A->rmap.n*A->cmap.n);
77     BLASscal_(&nz,&oalpha,a->v,&one);
78   }
79   ierr = PetscLogFlops(nz);CHKERRQ(ierr);
80   PetscFunctionReturn(0);
81 }
82 
83 #undef __FUNCT__
84 #define __FUNCT__ "MatIsHermitian_SeqDense"
85 PetscErrorCode MatIsHermitian_SeqDense(Mat A,PetscReal rtol,PetscTruth *fl)
86 {
87   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
88   PetscInt       i,j,m = A->rmap.n,N;
89   PetscScalar    *v = a->v;
90 
91   PetscFunctionBegin;
92   *fl = PETSC_FALSE;
93   if (A->rmap.n != A->cmap.n) PetscFunctionReturn(0);
94   N = a->lda;
95 
96   for (i=0; i<m; i++) {
97     for (j=i+1; j<m; j++) {
98       if (PetscAbsScalar(v[i+j*N] - PetscConj(v[j+i*N])) > rtol) PetscFunctionReturn(0);
99     }
100   }
101   *fl = PETSC_TRUE;
102   PetscFunctionReturn(0);
103 }
104 
105 /* ---------------------------------------------------------------*/
106 /* COMMENT: I have chosen to hide row permutation in the pivots,
107    rather than put it in the Mat->row slot.*/
108 #undef __FUNCT__
109 #define __FUNCT__ "MatLUFactor_SeqDense"
110 PetscErrorCode MatLUFactor_SeqDense(Mat A,IS row,IS col,MatFactorInfo *minfo)
111 {
112 #if defined(PETSC_MISSING_LAPACK_GETRF)
113   PetscFunctionBegin;
114   SETERRQ(PETSC_ERR_SUP,"GETRF - Lapack routine is unavailable.");
115 #else
116   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
117   PetscErrorCode ierr;
118   PetscBLASInt   n,m,info;
119 
120   PetscFunctionBegin;
121   n = PetscBLASIntCast(A->cmap.n);
122   m = PetscBLASIntCast(A->rmap.n);
123   if (!mat->pivots) {
124     ierr = PetscMalloc((A->rmap.n+1)*sizeof(PetscBLASInt),&mat->pivots);CHKERRQ(ierr);
125     ierr = PetscLogObjectMemory(A,A->rmap.n*sizeof(PetscBLASInt));CHKERRQ(ierr);
126   }
127   A->factor = FACTOR_LU;
128   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
129   LAPACKgetrf_(&m,&n,mat->v,&mat->lda,mat->pivots,&info);
130   if (info<0) SETERRQ(PETSC_ERR_LIB,"Bad argument to LU factorization");
131   if (info>0) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
132   ierr = PetscLogFlops((2*A->cmap.n*A->cmap.n*A->cmap.n)/3);CHKERRQ(ierr);
133 #endif
134   PetscFunctionReturn(0);
135 }
136 
137 #undef __FUNCT__
138 #define __FUNCT__ "MatDuplicate_SeqDense"
139 PetscErrorCode MatDuplicate_SeqDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
140 {
141   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data,*l;
142   PetscErrorCode ierr;
143   PetscInt       lda = (PetscInt)mat->lda,j,m;
144   Mat            newi;
145 
146   PetscFunctionBegin;
147   ierr = MatCreate(((PetscObject)A)->comm,&newi);CHKERRQ(ierr);
148   ierr = MatSetSizes(newi,A->rmap.n,A->cmap.n,A->rmap.n,A->cmap.n);CHKERRQ(ierr);
149   ierr = MatSetType(newi,((PetscObject)A)->type_name);CHKERRQ(ierr);
150   ierr = MatSeqDenseSetPreallocation(newi,PETSC_NULL);CHKERRQ(ierr);
151   if (cpvalues == MAT_COPY_VALUES) {
152     l = (Mat_SeqDense*)newi->data;
153     if (lda>A->rmap.n) {
154       m = A->rmap.n;
155       for (j=0; j<A->cmap.n; j++) {
156 	ierr = PetscMemcpy(l->v+j*m,mat->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr);
157       }
158     } else {
159       ierr = PetscMemcpy(l->v,mat->v,A->rmap.n*A->cmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
160     }
161   }
162   newi->assembled = PETSC_TRUE;
163   *newmat = newi;
164   PetscFunctionReturn(0);
165 }
166 
167 #undef __FUNCT__
168 #define __FUNCT__ "MatLUFactorSymbolic_SeqDense"
169 PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat A,IS row,IS col,MatFactorInfo *info,Mat *fact)
170 {
171   PetscErrorCode ierr;
172 
173   PetscFunctionBegin;
174   ierr = MatDuplicate_SeqDense(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr);
175   PetscFunctionReturn(0);
176 }
177 
178 #undef __FUNCT__
179 #define __FUNCT__ "MatLUFactorNumeric_SeqDense"
180 PetscErrorCode MatLUFactorNumeric_SeqDense(Mat A,MatFactorInfo *info_dummy,Mat *fact)
181 {
182   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data,*l = (Mat_SeqDense*)(*fact)->data;
183   PetscErrorCode ierr;
184   PetscInt       lda1=mat->lda,lda2=l->lda, m=A->rmap.n,n=A->cmap.n, j;
185   MatFactorInfo  info;
186 
187   PetscFunctionBegin;
188   /* copy the numerical values */
189   if (lda1>m || lda2>m ) {
190     for (j=0; j<n; j++) {
191       ierr = PetscMemcpy(l->v+j*lda2,mat->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr);
192     }
193   } else {
194     ierr = PetscMemcpy(l->v,mat->v,A->rmap.n*A->cmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
195   }
196   (*fact)->factor = 0;
197   ierr = MatLUFactor(*fact,0,0,&info);CHKERRQ(ierr);
198   PetscFunctionReturn(0);
199 }
200 
201 #undef __FUNCT__
202 #define __FUNCT__ "MatCholeskyFactorSymbolic_SeqDense"
203 PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat A,IS row,MatFactorInfo *info,Mat *fact)
204 {
205   PetscErrorCode ierr;
206 
207   PetscFunctionBegin;
208   ierr = MatConvert(A,MATSAME,MAT_INITIAL_MATRIX,fact);CHKERRQ(ierr);
209   PetscFunctionReturn(0);
210 }
211 
212 #undef __FUNCT__
213 #define __FUNCT__ "MatCholeskyFactor_SeqDense"
214 PetscErrorCode MatCholeskyFactor_SeqDense(Mat A,IS perm,MatFactorInfo *factinfo)
215 {
216 #if defined(PETSC_MISSING_LAPACK_POTRF)
217   PetscFunctionBegin;
218   SETERRQ(PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable.");
219 #else
220   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
221   PetscErrorCode ierr;
222   PetscBLASInt   info,n = PetscBLASIntCast(A->cmap.n);
223 
224   PetscFunctionBegin;
225   ierr = PetscFree(mat->pivots);CHKERRQ(ierr);
226   mat->pivots = 0;
227 
228   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
229   LAPACKpotrf_("L",&n,mat->v,&mat->lda,&info);
230   if (info) SETERRQ1(PETSC_ERR_MAT_CH_ZRPVT,"Bad factorization: zero pivot in row %D",(PetscInt)info-1);
231   A->factor = FACTOR_CHOLESKY;
232   ierr = PetscLogFlops((A->cmap.n*A->cmap.n*A->cmap.n)/3);CHKERRQ(ierr);
233 #endif
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "MatCholeskyFactorNumeric_SeqDense"
239 PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat A,MatFactorInfo *info_dummy,Mat *fact)
240 {
241   PetscErrorCode ierr;
242   MatFactorInfo  info;
243 
244   PetscFunctionBegin;
245   info.fill = 1.0;
246   ierr = MatCholeskyFactor_SeqDense(*fact,0,&info);CHKERRQ(ierr);
247   PetscFunctionReturn(0);
248 }
249 
250 #undef __FUNCT__
251 #define __FUNCT__ "MatSolve_SeqDense"
252 PetscErrorCode MatSolve_SeqDense(Mat A,Vec xx,Vec yy)
253 {
254   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
255   PetscErrorCode ierr;
256   PetscScalar    *x,*y;
257   PetscBLASInt   one = 1,info,m = PetscBLASIntCast(A->rmap.n);
258 
259   PetscFunctionBegin;
260   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
261   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
262   ierr = PetscMemcpy(y,x,A->rmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
263   if (A->factor == FACTOR_LU) {
264 #if defined(PETSC_MISSING_LAPACK_GETRS)
265     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
266 #else
267     LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
268     if (info) SETERRQ(PETSC_ERR_LIB,"GETRS - Bad solve");
269 #endif
270   } else if (A->factor == FACTOR_CHOLESKY){
271 #if defined(PETSC_MISSING_LAPACK_POTRS)
272     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
273 #else
274     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
275     if (info) SETERRQ(PETSC_ERR_LIB,"POTRS Bad solve");
276 #endif
277   }
278   else SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
279   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
280   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
281   ierr = PetscLogFlops(2*A->cmap.n*A->cmap.n - A->cmap.n);CHKERRQ(ierr);
282   PetscFunctionReturn(0);
283 }
284 
285 #undef __FUNCT__
286 #define __FUNCT__ "MatSolveTranspose_SeqDense"
287 PetscErrorCode MatSolveTranspose_SeqDense(Mat A,Vec xx,Vec yy)
288 {
289   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
290   PetscErrorCode ierr;
291   PetscScalar    *x,*y;
292   PetscBLASInt   one = 1,info,m = PetscBLASIntCast(A->rmap.n);
293 
294   PetscFunctionBegin;
295   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
296   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
297   ierr = PetscMemcpy(y,x,A->rmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
298   /* assume if pivots exist then use LU; else Cholesky */
299   if (mat->pivots) {
300 #if defined(PETSC_MISSING_LAPACK_GETRS)
301     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
302 #else
303     LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
304     if (info) SETERRQ(PETSC_ERR_LIB,"POTRS - Bad solve");
305 #endif
306   } else {
307 #if defined(PETSC_MISSING_LAPACK_POTRS)
308     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
309 #else
310     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
311     if (info) SETERRQ(PETSC_ERR_LIB,"POTRS - Bad solve");
312 #endif
313   }
314   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
315   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
316   ierr = PetscLogFlops(2*A->cmap.n*A->cmap.n - A->cmap.n);CHKERRQ(ierr);
317   PetscFunctionReturn(0);
318 }
319 
320 #undef __FUNCT__
321 #define __FUNCT__ "MatSolveAdd_SeqDense"
322 PetscErrorCode MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
323 {
324   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
325   PetscErrorCode ierr;
326   PetscScalar    *x,*y,sone = 1.0;
327   Vec            tmp = 0;
328   PetscBLASInt   one = 1,info,m = PetscBLASIntCast(A->rmap.n);
329 
330   PetscFunctionBegin;
331   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
332   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
333   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
334   if (yy == zz) {
335     ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr);
336     ierr = PetscLogObjectParent(A,tmp);CHKERRQ(ierr);
337     ierr = VecCopy(yy,tmp);CHKERRQ(ierr);
338   }
339   ierr = PetscMemcpy(y,x,A->rmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
340   /* assume if pivots exist then use LU; else Cholesky */
341   if (mat->pivots) {
342 #if defined(PETSC_MISSING_LAPACK_GETRS)
343     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
344 #else
345     LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
346     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
347 #endif
348   } else {
349 #if defined(PETSC_MISSING_LAPACK_POTRS)
350     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
351 #else
352     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
353     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
354 #endif
355   }
356   if (tmp) {ierr = VecAXPY(yy,sone,tmp);CHKERRQ(ierr); ierr = VecDestroy(tmp);CHKERRQ(ierr);}
357   else     {ierr = VecAXPY(yy,sone,zz);CHKERRQ(ierr);}
358   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
359   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
360   ierr = PetscLogFlops(2*A->cmap.n*A->cmap.n);CHKERRQ(ierr);
361   PetscFunctionReturn(0);
362 }
363 
364 #undef __FUNCT__
365 #define __FUNCT__ "MatSolveTransposeAdd_SeqDense"
366 PetscErrorCode MatSolveTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
367 {
368   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
369   PetscErrorCode ierr;
370   PetscScalar    *x,*y,sone = 1.0;
371   Vec            tmp;
372   PetscBLASInt   one = 1,info,m = PetscBLASIntCast(A->rmap.n);
373 
374   PetscFunctionBegin;
375   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
376   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
377   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
378   if (yy == zz) {
379     ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr);
380     ierr = PetscLogObjectParent(A,tmp);CHKERRQ(ierr);
381     ierr = VecCopy(yy,tmp);CHKERRQ(ierr);
382   }
383   ierr = PetscMemcpy(y,x,A->rmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
384   /* assume if pivots exist then use LU; else Cholesky */
385   if (mat->pivots) {
386 #if defined(PETSC_MISSING_LAPACK_GETRS)
387     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
388 #else
389     LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
390     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
391 #endif
392   } else {
393 #if defined(PETSC_MISSING_LAPACK_POTRS)
394     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
395 #else
396     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
397     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
398 #endif
399   }
400   if (tmp) {
401     ierr = VecAXPY(yy,sone,tmp);CHKERRQ(ierr);
402     ierr = VecDestroy(tmp);CHKERRQ(ierr);
403   } else {
404     ierr = VecAXPY(yy,sone,zz);CHKERRQ(ierr);
405   }
406   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
407   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
408   ierr = PetscLogFlops(2*A->cmap.n*A->cmap.n);CHKERRQ(ierr);
409   PetscFunctionReturn(0);
410 }
411 /* ------------------------------------------------------------------*/
412 #undef __FUNCT__
413 #define __FUNCT__ "MatRelax_SeqDense"
414 PetscErrorCode MatRelax_SeqDense(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec xx)
415 {
416   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
417   PetscScalar    *x,*b,*v = mat->v,zero = 0.0,xt;
418   PetscErrorCode ierr;
419   PetscInt       m = A->rmap.n,i;
420 #if !defined(PETSC_USE_COMPLEX)
421   PetscBLASInt   o = 1,bm = PetscBLASIntCast(m);
422 #endif
423 
424   PetscFunctionBegin;
425   if (flag & SOR_ZERO_INITIAL_GUESS) {
426     /* this is a hack fix, should have another version without the second BLASdot */
427     ierr = VecSet(xx,zero);CHKERRQ(ierr);
428   }
429   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
430   ierr = VecGetArray(bb,&b);CHKERRQ(ierr);
431   its  = its*lits;
432   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
433   while (its--) {
434     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
435       for (i=0; i<m; i++) {
436 #if defined(PETSC_USE_COMPLEX)
437         /* cannot use BLAS dot for complex because compiler/linker is
438            not happy about returning a double complex */
439         PetscInt    _i;
440         PetscScalar sum = b[i];
441         for (_i=0; _i<m; _i++) {
442           sum -= PetscConj(v[i+_i*m])*x[_i];
443         }
444         xt = sum;
445 #else
446         xt = b[i] - BLASdot_(&bm,v+i,&bm,x,&o);
447 #endif
448         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
449       }
450     }
451     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
452       for (i=m-1; i>=0; i--) {
453 #if defined(PETSC_USE_COMPLEX)
454         /* cannot use BLAS dot for complex because compiler/linker is
455            not happy about returning a double complex */
456         PetscInt    _i;
457         PetscScalar sum = b[i];
458         for (_i=0; _i<m; _i++) {
459           sum -= PetscConj(v[i+_i*m])*x[_i];
460         }
461         xt = sum;
462 #else
463         xt = b[i] - BLASdot_(&bm,v+i,&bm,x,&o);
464 #endif
465         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
466       }
467     }
468   }
469   ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);
470   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
471   PetscFunctionReturn(0);
472 }
473 
474 /* -----------------------------------------------------------------*/
475 #undef __FUNCT__
476 #define __FUNCT__ "MatMultTranspose_SeqDense"
477 PetscErrorCode MatMultTranspose_SeqDense(Mat A,Vec xx,Vec yy)
478 {
479   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
480   PetscScalar    *v = mat->v,*x,*y;
481   PetscErrorCode ierr;
482   PetscBLASInt   m, n,_One=1;
483   PetscScalar    _DOne=1.0,_DZero=0.0;
484 
485   PetscFunctionBegin;
486   m = PetscBLASIntCast(A->rmap.n);
487   n = PetscBLASIntCast(A->cmap.n);
488   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
489   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
490   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
491   BLASgemv_("T",&m,&n,&_DOne,v,&mat->lda,x,&_One,&_DZero,y,&_One);
492   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
493   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
494   ierr = PetscLogFlops(2*A->rmap.n*A->cmap.n - A->cmap.n);CHKERRQ(ierr);
495   PetscFunctionReturn(0);
496 }
497 
498 #undef __FUNCT__
499 #define __FUNCT__ "MatMult_SeqDense"
500 PetscErrorCode MatMult_SeqDense(Mat A,Vec xx,Vec yy)
501 {
502   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
503   PetscScalar    *v = mat->v,*x,*y,_DOne=1.0,_DZero=0.0;
504   PetscErrorCode ierr;
505   PetscBLASInt   m, n, _One=1;
506 
507   PetscFunctionBegin;
508   m = PetscBLASIntCast(A->rmap.n);
509   n = PetscBLASIntCast(A->cmap.n);
510   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
511   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
512   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
513   BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DZero,y,&_One);
514   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
515   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
516   ierr = PetscLogFlops(2*A->rmap.n*A->cmap.n - A->rmap.n);CHKERRQ(ierr);
517   PetscFunctionReturn(0);
518 }
519 
520 #undef __FUNCT__
521 #define __FUNCT__ "MatMultAdd_SeqDense"
522 PetscErrorCode MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
523 {
524   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
525   PetscScalar    *v = mat->v,*x,*y,_DOne=1.0;
526   PetscErrorCode ierr;
527   PetscBLASInt   m, n, _One=1;
528 
529   PetscFunctionBegin;
530   m = PetscBLASIntCast(A->rmap.n);
531   n = PetscBLASIntCast(A->cmap.n);
532   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
533   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
534   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
535   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
536   BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One);
537   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
538   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
539   ierr = PetscLogFlops(2*A->rmap.n*A->cmap.n);CHKERRQ(ierr);
540   PetscFunctionReturn(0);
541 }
542 
543 #undef __FUNCT__
544 #define __FUNCT__ "MatMultTransposeAdd_SeqDense"
545 PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
546 {
547   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
548   PetscScalar    *v = mat->v,*x,*y;
549   PetscErrorCode ierr;
550   PetscBLASInt   m, n, _One=1;
551   PetscScalar    _DOne=1.0;
552 
553   PetscFunctionBegin;
554   m = PetscBLASIntCast(A->rmap.n);
555   n = PetscBLASIntCast(A->cmap.n);
556   if (!A->rmap.n || !A->cmap.n) PetscFunctionReturn(0);
557   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
558   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
559   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
560   BLASgemv_("T",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One);
561   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
562   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
563   ierr = PetscLogFlops(2*A->rmap.n*A->cmap.n);CHKERRQ(ierr);
564   PetscFunctionReturn(0);
565 }
566 
567 /* -----------------------------------------------------------------*/
568 #undef __FUNCT__
569 #define __FUNCT__ "MatGetRow_SeqDense"
570 PetscErrorCode MatGetRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
571 {
572   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
573   PetscScalar    *v;
574   PetscErrorCode ierr;
575   PetscInt       i;
576 
577   PetscFunctionBegin;
578   *ncols = A->cmap.n;
579   if (cols) {
580     ierr = PetscMalloc((A->cmap.n+1)*sizeof(PetscInt),cols);CHKERRQ(ierr);
581     for (i=0; i<A->cmap.n; i++) (*cols)[i] = i;
582   }
583   if (vals) {
584     ierr = PetscMalloc((A->cmap.n+1)*sizeof(PetscScalar),vals);CHKERRQ(ierr);
585     v    = mat->v + row;
586     for (i=0; i<A->cmap.n; i++) {(*vals)[i] = *v; v += mat->lda;}
587   }
588   PetscFunctionReturn(0);
589 }
590 
591 #undef __FUNCT__
592 #define __FUNCT__ "MatRestoreRow_SeqDense"
593 PetscErrorCode MatRestoreRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
594 {
595   PetscErrorCode ierr;
596   PetscFunctionBegin;
597   if (cols) {ierr = PetscFree(*cols);CHKERRQ(ierr);}
598   if (vals) {ierr = PetscFree(*vals);CHKERRQ(ierr); }
599   PetscFunctionReturn(0);
600 }
601 /* ----------------------------------------------------------------*/
602 #undef __FUNCT__
603 #define __FUNCT__ "MatSetValues_SeqDense"
604 PetscErrorCode MatSetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],const PetscScalar v[],InsertMode addv)
605 {
606   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
607   PetscInt     i,j,idx=0;
608 
609   PetscFunctionBegin;
610   if (!mat->roworiented) {
611     if (addv == INSERT_VALUES) {
612       for (j=0; j<n; j++) {
613         if (indexn[j] < 0) {idx += m; continue;}
614 #if defined(PETSC_USE_DEBUG)
615         if (indexn[j] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap.n-1);
616 #endif
617         for (i=0; i<m; i++) {
618           if (indexm[i] < 0) {idx++; continue;}
619 #if defined(PETSC_USE_DEBUG)
620           if (indexm[i] >= A->rmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap.n-1);
621 #endif
622           mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
623         }
624       }
625     } else {
626       for (j=0; j<n; j++) {
627         if (indexn[j] < 0) {idx += m; continue;}
628 #if defined(PETSC_USE_DEBUG)
629         if (indexn[j] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap.n-1);
630 #endif
631         for (i=0; i<m; i++) {
632           if (indexm[i] < 0) {idx++; continue;}
633 #if defined(PETSC_USE_DEBUG)
634           if (indexm[i] >= A->rmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap.n-1);
635 #endif
636           mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
637         }
638       }
639     }
640   } else {
641     if (addv == INSERT_VALUES) {
642       for (i=0; i<m; i++) {
643         if (indexm[i] < 0) { idx += n; continue;}
644 #if defined(PETSC_USE_DEBUG)
645         if (indexm[i] >= A->rmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap.n-1);
646 #endif
647         for (j=0; j<n; j++) {
648           if (indexn[j] < 0) { idx++; continue;}
649 #if defined(PETSC_USE_DEBUG)
650           if (indexn[j] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap.n-1);
651 #endif
652           mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
653         }
654       }
655     } else {
656       for (i=0; i<m; i++) {
657         if (indexm[i] < 0) { idx += n; continue;}
658 #if defined(PETSC_USE_DEBUG)
659         if (indexm[i] >= A->rmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->rmap.n-1);
660 #endif
661         for (j=0; j<n; j++) {
662           if (indexn[j] < 0) { idx++; continue;}
663 #if defined(PETSC_USE_DEBUG)
664           if (indexn[j] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->cmap.n-1);
665 #endif
666           mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
667         }
668       }
669     }
670   }
671   PetscFunctionReturn(0);
672 }
673 
674 #undef __FUNCT__
675 #define __FUNCT__ "MatGetValues_SeqDense"
676 PetscErrorCode MatGetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],PetscScalar v[])
677 {
678   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
679   PetscInt     i,j;
680 
681   PetscFunctionBegin;
682   /* row-oriented output */
683   for (i=0; i<m; i++) {
684     if (indexm[i] < 0) {v += n;continue;}
685     if (indexm[i] >= A->rmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row %D requested larger than number rows %D",indexm[i],A->rmap.n);
686     for (j=0; j<n; j++) {
687       if (indexn[j] < 0) {v++; continue;}
688       if (indexn[j] >= A->cmap.n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column %D requested larger than number columns %D",indexn[j],A->cmap.n);
689       *v++ = mat->v[indexn[j]*mat->lda + indexm[i]];
690     }
691   }
692   PetscFunctionReturn(0);
693 }
694 
695 /* -----------------------------------------------------------------*/
696 
697 #include "petscsys.h"
698 
699 #undef __FUNCT__
700 #define __FUNCT__ "MatLoad_SeqDense"
701 PetscErrorCode MatLoad_SeqDense(PetscViewer viewer, MatType type,Mat *A)
702 {
703   Mat_SeqDense   *a;
704   Mat            B;
705   PetscErrorCode ierr;
706   PetscInt       *scols,i,j,nz,header[4];
707   int            fd;
708   PetscMPIInt    size;
709   PetscInt       *rowlengths = 0,M,N,*cols;
710   PetscScalar    *vals,*svals,*v,*w;
711   MPI_Comm       comm = ((PetscObject)viewer)->comm;
712 
713   PetscFunctionBegin;
714   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
715   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
716   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
717   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
718   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Not matrix object");
719   M = header[1]; N = header[2]; nz = header[3];
720 
721   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */
722     ierr = MatCreate(comm,A);CHKERRQ(ierr);
723     ierr = MatSetSizes(*A,M,N,M,N);CHKERRQ(ierr);
724     ierr = MatSetType(*A,type);CHKERRQ(ierr);
725     ierr = MatSeqDenseSetPreallocation(*A,PETSC_NULL);CHKERRQ(ierr);
726     B    = *A;
727     a    = (Mat_SeqDense*)B->data;
728     v    = a->v;
729     /* Allocate some temp space to read in the values and then flip them
730        from row major to column major */
731     ierr = PetscMalloc((M*N > 0 ? M*N : 1)*sizeof(PetscScalar),&w);CHKERRQ(ierr);
732     /* read in nonzero values */
733     ierr = PetscBinaryRead(fd,w,M*N,PETSC_SCALAR);CHKERRQ(ierr);
734     /* now flip the values and store them in the matrix*/
735     for (j=0; j<N; j++) {
736       for (i=0; i<M; i++) {
737         *v++ =w[i*N+j];
738       }
739     }
740     ierr = PetscFree(w);CHKERRQ(ierr);
741     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
742     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
743   } else {
744     /* read row lengths */
745     ierr = PetscMalloc((M+1)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
746     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
747 
748     /* create our matrix */
749     ierr = MatCreate(comm,A);CHKERRQ(ierr);
750     ierr = MatSetSizes(*A,M,N,M,N);CHKERRQ(ierr);
751     ierr = MatSetType(*A,type);CHKERRQ(ierr);
752     ierr = MatSeqDenseSetPreallocation(*A,PETSC_NULL);CHKERRQ(ierr);
753     B = *A;
754     a = (Mat_SeqDense*)B->data;
755     v = a->v;
756 
757     /* read column indices and nonzeros */
758     ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&scols);CHKERRQ(ierr);
759     cols = scols;
760     ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr);
761     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&svals);CHKERRQ(ierr);
762     vals = svals;
763     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
764 
765     /* insert into matrix */
766     for (i=0; i<M; i++) {
767       for (j=0; j<rowlengths[i]; j++) v[i+M*scols[j]] = svals[j];
768       svals += rowlengths[i]; scols += rowlengths[i];
769     }
770     ierr = PetscFree(vals);CHKERRQ(ierr);
771     ierr = PetscFree(cols);CHKERRQ(ierr);
772     ierr = PetscFree(rowlengths);CHKERRQ(ierr);
773 
774     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
775     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
776   }
777   PetscFunctionReturn(0);
778 }
779 
780 #include "petscsys.h"
781 
782 #undef __FUNCT__
783 #define __FUNCT__ "MatView_SeqDense_ASCII"
784 static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer)
785 {
786   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
787   PetscErrorCode    ierr;
788   PetscInt          i,j;
789   const char        *name;
790   PetscScalar       *v;
791   PetscViewerFormat format;
792 #if defined(PETSC_USE_COMPLEX)
793   PetscTruth        allreal = PETSC_TRUE;
794 #endif
795 
796   PetscFunctionBegin;
797   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
798   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
799   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
800     PetscFunctionReturn(0);  /* do nothing for now */
801   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
802     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
803     for (i=0; i<A->rmap.n; i++) {
804       v = a->v + i;
805       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
806       for (j=0; j<A->cmap.n; j++) {
807 #if defined(PETSC_USE_COMPLEX)
808         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
809           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G + %G i) ",j,PetscRealPart(*v),PetscImaginaryPart(*v));CHKERRQ(ierr);
810         } else if (PetscRealPart(*v)) {
811           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",j,PetscRealPart(*v));CHKERRQ(ierr);
812         }
813 #else
814         if (*v) {
815           ierr = PetscViewerASCIIPrintf(viewer," (%D, %G) ",j,*v);CHKERRQ(ierr);
816         }
817 #endif
818         v += a->lda;
819       }
820       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
821     }
822     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
823   } else {
824     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
825 #if defined(PETSC_USE_COMPLEX)
826     /* determine if matrix has all real values */
827     v = a->v;
828     for (i=0; i<A->rmap.n*A->cmap.n; i++) {
829 	if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break ;}
830     }
831 #endif
832     if (format == PETSC_VIEWER_ASCII_MATLAB) {
833       ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
834       ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->rmap.n,A->cmap.n);CHKERRQ(ierr);
835       ierr = PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->rmap.n,A->cmap.n);CHKERRQ(ierr);
836       ierr = PetscViewerASCIIPrintf(viewer,"%s = [\n",name);CHKERRQ(ierr);
837     }
838 
839     for (i=0; i<A->rmap.n; i++) {
840       v = a->v + i;
841       for (j=0; j<A->cmap.n; j++) {
842 #if defined(PETSC_USE_COMPLEX)
843         if (allreal) {
844           ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",PetscRealPart(*v));CHKERRQ(ierr);
845         } else {
846           ierr = PetscViewerASCIIPrintf(viewer,"%18.16e + %18.16e i ",PetscRealPart(*v),PetscImaginaryPart(*v));CHKERRQ(ierr);
847         }
848 #else
849         ierr = PetscViewerASCIIPrintf(viewer,"%18.16e ",*v);CHKERRQ(ierr);
850 #endif
851 	v += a->lda;
852       }
853       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
854     }
855     if (format == PETSC_VIEWER_ASCII_MATLAB) {
856       ierr = PetscViewerASCIIPrintf(viewer,"];\n");CHKERRQ(ierr);
857     }
858     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
859   }
860   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
861   PetscFunctionReturn(0);
862 }
863 
864 #undef __FUNCT__
865 #define __FUNCT__ "MatView_SeqDense_Binary"
866 static PetscErrorCode MatView_SeqDense_Binary(Mat A,PetscViewer viewer)
867 {
868   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
869   PetscErrorCode    ierr;
870   int               fd;
871   PetscInt          ict,j,n = A->cmap.n,m = A->rmap.n,i,*col_lens,nz = m*n;
872   PetscScalar       *v,*anonz,*vals;
873   PetscViewerFormat format;
874 
875   PetscFunctionBegin;
876   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
877 
878   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
879   if (format == PETSC_VIEWER_BINARY_NATIVE) {
880     /* store the matrix as a dense matrix */
881     ierr = PetscMalloc(4*sizeof(PetscInt),&col_lens);CHKERRQ(ierr);
882     col_lens[0] = MAT_FILE_COOKIE;
883     col_lens[1] = m;
884     col_lens[2] = n;
885     col_lens[3] = MATRIX_BINARY_FORMAT_DENSE;
886     ierr = PetscBinaryWrite(fd,col_lens,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
887     ierr = PetscFree(col_lens);CHKERRQ(ierr);
888 
889     /* write out matrix, by rows */
890     ierr = PetscMalloc((m*n+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
891     v    = a->v;
892     for (j=0; j<n; j++) {
893       for (i=0; i<m; i++) {
894         vals[j + i*n] = *v++;
895       }
896     }
897     ierr = PetscBinaryWrite(fd,vals,n*m,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
898     ierr = PetscFree(vals);CHKERRQ(ierr);
899   } else {
900     ierr = PetscMalloc((4+nz)*sizeof(PetscInt),&col_lens);CHKERRQ(ierr);
901     col_lens[0] = MAT_FILE_COOKIE;
902     col_lens[1] = m;
903     col_lens[2] = n;
904     col_lens[3] = nz;
905 
906     /* store lengths of each row and write (including header) to file */
907     for (i=0; i<m; i++) col_lens[4+i] = n;
908     ierr = PetscBinaryWrite(fd,col_lens,4+m,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
909 
910     /* Possibly should write in smaller increments, not whole matrix at once? */
911     /* store column indices (zero start index) */
912     ict = 0;
913     for (i=0; i<m; i++) {
914       for (j=0; j<n; j++) col_lens[ict++] = j;
915     }
916     ierr = PetscBinaryWrite(fd,col_lens,nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
917     ierr = PetscFree(col_lens);CHKERRQ(ierr);
918 
919     /* store nonzero values */
920     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&anonz);CHKERRQ(ierr);
921     ict  = 0;
922     for (i=0; i<m; i++) {
923       v = a->v + i;
924       for (j=0; j<n; j++) {
925         anonz[ict++] = *v; v += a->lda;
926       }
927     }
928     ierr = PetscBinaryWrite(fd,anonz,nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
929     ierr = PetscFree(anonz);CHKERRQ(ierr);
930   }
931   PetscFunctionReturn(0);
932 }
933 
934 #undef __FUNCT__
935 #define __FUNCT__ "MatView_SeqDense_Draw_Zoom"
936 PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa)
937 {
938   Mat               A = (Mat) Aa;
939   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
940   PetscErrorCode    ierr;
941   PetscInt          m = A->rmap.n,n = A->cmap.n,color,i,j;
942   PetscScalar       *v = a->v;
943   PetscViewer       viewer;
944   PetscDraw         popup;
945   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,scale,maxv = 0.0;
946   PetscViewerFormat format;
947 
948   PetscFunctionBegin;
949 
950   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
951   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
952   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
953 
954   /* Loop over matrix elements drawing boxes */
955   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
956     /* Blue for negative and Red for positive */
957     color = PETSC_DRAW_BLUE;
958     for(j = 0; j < n; j++) {
959       x_l = j;
960       x_r = x_l + 1.0;
961       for(i = 0; i < m; i++) {
962         y_l = m - i - 1.0;
963         y_r = y_l + 1.0;
964 #if defined(PETSC_USE_COMPLEX)
965         if (PetscRealPart(v[j*m+i]) >  0.) {
966           color = PETSC_DRAW_RED;
967         } else if (PetscRealPart(v[j*m+i]) <  0.) {
968           color = PETSC_DRAW_BLUE;
969         } else {
970           continue;
971         }
972 #else
973         if (v[j*m+i] >  0.) {
974           color = PETSC_DRAW_RED;
975         } else if (v[j*m+i] <  0.) {
976           color = PETSC_DRAW_BLUE;
977         } else {
978           continue;
979         }
980 #endif
981         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
982       }
983     }
984   } else {
985     /* use contour shading to indicate magnitude of values */
986     /* first determine max of all nonzero values */
987     for(i = 0; i < m*n; i++) {
988       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
989     }
990     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
991     ierr  = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
992     if (popup) {ierr  = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);}
993     for(j = 0; j < n; j++) {
994       x_l = j;
995       x_r = x_l + 1.0;
996       for(i = 0; i < m; i++) {
997         y_l   = m - i - 1.0;
998         y_r   = y_l + 1.0;
999         color = PETSC_DRAW_BASIC_COLORS + (int)(scale*PetscAbsScalar(v[j*m+i]));
1000         ierr  = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
1001       }
1002     }
1003   }
1004   PetscFunctionReturn(0);
1005 }
1006 
1007 #undef __FUNCT__
1008 #define __FUNCT__ "MatView_SeqDense_Draw"
1009 PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer)
1010 {
1011   PetscDraw      draw;
1012   PetscTruth     isnull;
1013   PetscReal      xr,yr,xl,yl,h,w;
1014   PetscErrorCode ierr;
1015 
1016   PetscFunctionBegin;
1017   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
1018   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
1019   if (isnull) PetscFunctionReturn(0);
1020 
1021   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
1022   xr  = A->cmap.n; yr = A->rmap.n; h = yr/10.0; w = xr/10.0;
1023   xr += w;    yr += h;  xl = -w;     yl = -h;
1024   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
1025   ierr = PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);CHKERRQ(ierr);
1026   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
1027   PetscFunctionReturn(0);
1028 }
1029 
1030 #undef __FUNCT__
1031 #define __FUNCT__ "MatView_SeqDense"
1032 PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer)
1033 {
1034   PetscErrorCode ierr;
1035   PetscTruth     iascii,isbinary,isdraw;
1036 
1037   PetscFunctionBegin;
1038   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
1039   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
1040   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
1041 
1042   if (iascii) {
1043     ierr = MatView_SeqDense_ASCII(A,viewer);CHKERRQ(ierr);
1044   } else if (isbinary) {
1045     ierr = MatView_SeqDense_Binary(A,viewer);CHKERRQ(ierr);
1046   } else if (isdraw) {
1047     ierr = MatView_SeqDense_Draw(A,viewer);CHKERRQ(ierr);
1048   } else {
1049     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by dense matrix",((PetscObject)viewer)->type_name);
1050   }
1051   PetscFunctionReturn(0);
1052 }
1053 
1054 #undef __FUNCT__
1055 #define __FUNCT__ "MatDestroy_SeqDense"
1056 PetscErrorCode MatDestroy_SeqDense(Mat mat)
1057 {
1058   Mat_SeqDense   *l = (Mat_SeqDense*)mat->data;
1059   PetscErrorCode ierr;
1060 
1061   PetscFunctionBegin;
1062 #if defined(PETSC_USE_LOG)
1063   PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->rmap.n,mat->cmap.n);
1064 #endif
1065   ierr = PetscFree(l->pivots);CHKERRQ(ierr);
1066   if (!l->user_alloc) {ierr = PetscFree(l->v);CHKERRQ(ierr);}
1067   ierr = PetscFree(l);CHKERRQ(ierr);
1068 
1069   ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr);
1070   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatSeqDenseSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
1071   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMatMult_seqaij_seqdense_C","",PETSC_NULL);CHKERRQ(ierr);
1072   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMatMultSymbolic_seqaij_seqdense_C","",PETSC_NULL);CHKERRQ(ierr);
1073   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatMatMultNumeric_seqaij_seqdense_C","",PETSC_NULL);CHKERRQ(ierr);
1074   PetscFunctionReturn(0);
1075 }
1076 
1077 #undef __FUNCT__
1078 #define __FUNCT__ "MatTranspose_SeqDense"
1079 PetscErrorCode MatTranspose_SeqDense(Mat A,MatReuse reuse,Mat *matout)
1080 {
1081   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1082   PetscErrorCode ierr;
1083   PetscInt       k,j,m,n,M;
1084   PetscScalar    *v,tmp;
1085 
1086   PetscFunctionBegin;
1087   v = mat->v; m = A->rmap.n; M = mat->lda; n = A->cmap.n;
1088   if (reuse == MAT_REUSE_MATRIX && *matout == A) { /* in place transpose */
1089     if (m != n) {
1090       SETERRQ(PETSC_ERR_SUP,"Can not transpose non-square matrix in place");
1091     } else {
1092       for (j=0; j<m; j++) {
1093         for (k=0; k<j; k++) {
1094           tmp = v[j + k*M];
1095           v[j + k*M] = v[k + j*M];
1096           v[k + j*M] = tmp;
1097         }
1098       }
1099     }
1100   } else { /* out-of-place transpose */
1101     Mat          tmat;
1102     Mat_SeqDense *tmatd;
1103     PetscScalar  *v2;
1104 
1105     if (reuse == MAT_INITIAL_MATRIX) {
1106       ierr  = MatCreate(((PetscObject)A)->comm,&tmat);CHKERRQ(ierr);
1107       ierr  = MatSetSizes(tmat,A->cmap.n,A->rmap.n,A->cmap.n,A->rmap.n);CHKERRQ(ierr);
1108       ierr  = MatSetType(tmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
1109       ierr  = MatSeqDenseSetPreallocation(tmat,PETSC_NULL);CHKERRQ(ierr);
1110     } else {
1111       tmat = *matout;
1112     }
1113     tmatd = (Mat_SeqDense*)tmat->data;
1114     v = mat->v; v2 = tmatd->v;
1115     for (j=0; j<n; j++) {
1116       for (k=0; k<m; k++) v2[j + k*n] = v[k + j*M];
1117     }
1118     ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1119     ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1120     *matout = tmat;
1121   }
1122   PetscFunctionReturn(0);
1123 }
1124 
1125 #undef __FUNCT__
1126 #define __FUNCT__ "MatEqual_SeqDense"
1127 PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscTruth *flg)
1128 {
1129   Mat_SeqDense *mat1 = (Mat_SeqDense*)A1->data;
1130   Mat_SeqDense *mat2 = (Mat_SeqDense*)A2->data;
1131   PetscInt     i,j;
1132   PetscScalar  *v1 = mat1->v,*v2 = mat2->v;
1133 
1134   PetscFunctionBegin;
1135   if (A1->rmap.n != A2->rmap.n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1136   if (A1->cmap.n != A2->cmap.n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1137   for (i=0; i<A1->rmap.n; i++) {
1138     v1 = mat1->v+i; v2 = mat2->v+i;
1139     for (j=0; j<A1->cmap.n; j++) {
1140       if (*v1 != *v2) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1141       v1 += mat1->lda; v2 += mat2->lda;
1142     }
1143   }
1144   *flg = PETSC_TRUE;
1145   PetscFunctionReturn(0);
1146 }
1147 
1148 #undef __FUNCT__
1149 #define __FUNCT__ "MatGetDiagonal_SeqDense"
1150 PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v)
1151 {
1152   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1153   PetscErrorCode ierr;
1154   PetscInt       i,n,len;
1155   PetscScalar    *x,zero = 0.0;
1156 
1157   PetscFunctionBegin;
1158   ierr = VecSet(v,zero);CHKERRQ(ierr);
1159   ierr = VecGetSize(v,&n);CHKERRQ(ierr);
1160   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1161   len = PetscMin(A->rmap.n,A->cmap.n);
1162   if (n != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
1163   for (i=0; i<len; i++) {
1164     x[i] = mat->v[i*mat->lda + i];
1165   }
1166   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1167   PetscFunctionReturn(0);
1168 }
1169 
1170 #undef __FUNCT__
1171 #define __FUNCT__ "MatDiagonalScale_SeqDense"
1172 PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr)
1173 {
1174   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1175   PetscScalar    *l,*r,x,*v;
1176   PetscErrorCode ierr;
1177   PetscInt       i,j,m = A->rmap.n,n = A->cmap.n;
1178 
1179   PetscFunctionBegin;
1180   if (ll) {
1181     ierr = VecGetSize(ll,&m);CHKERRQ(ierr);
1182     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
1183     if (m != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size");
1184     for (i=0; i<m; i++) {
1185       x = l[i];
1186       v = mat->v + i;
1187       for (j=0; j<n; j++) { (*v) *= x; v+= m;}
1188     }
1189     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
1190     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
1191   }
1192   if (rr) {
1193     ierr = VecGetSize(rr,&n);CHKERRQ(ierr);
1194     ierr = VecGetArray(rr,&r);CHKERRQ(ierr);
1195     if (n != A->cmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size");
1196     for (i=0; i<n; i++) {
1197       x = r[i];
1198       v = mat->v + i*m;
1199       for (j=0; j<m; j++) { (*v++) *= x;}
1200     }
1201     ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr);
1202     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
1203   }
1204   PetscFunctionReturn(0);
1205 }
1206 
1207 #undef __FUNCT__
1208 #define __FUNCT__ "MatNorm_SeqDense"
1209 PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm)
1210 {
1211   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1212   PetscScalar  *v = mat->v;
1213   PetscReal    sum = 0.0;
1214   PetscInt     lda=mat->lda,m=A->rmap.n,i,j;
1215   PetscErrorCode ierr;
1216 
1217   PetscFunctionBegin;
1218   if (type == NORM_FROBENIUS) {
1219     if (lda>m) {
1220       for (j=0; j<A->cmap.n; j++) {
1221 	v = mat->v+j*lda;
1222 	for (i=0; i<m; i++) {
1223 #if defined(PETSC_USE_COMPLEX)
1224 	  sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1225 #else
1226 	  sum += (*v)*(*v); v++;
1227 #endif
1228 	}
1229       }
1230     } else {
1231       for (i=0; i<A->cmap.n*A->rmap.n; i++) {
1232 #if defined(PETSC_USE_COMPLEX)
1233 	sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1234 #else
1235 	sum += (*v)*(*v); v++;
1236 #endif
1237       }
1238     }
1239     *nrm = sqrt(sum);
1240     ierr = PetscLogFlops(2*A->cmap.n*A->rmap.n);CHKERRQ(ierr);
1241   } else if (type == NORM_1) {
1242     *nrm = 0.0;
1243     for (j=0; j<A->cmap.n; j++) {
1244       v = mat->v + j*mat->lda;
1245       sum = 0.0;
1246       for (i=0; i<A->rmap.n; i++) {
1247         sum += PetscAbsScalar(*v);  v++;
1248       }
1249       if (sum > *nrm) *nrm = sum;
1250     }
1251     ierr = PetscLogFlops(A->cmap.n*A->rmap.n);CHKERRQ(ierr);
1252   } else if (type == NORM_INFINITY) {
1253     *nrm = 0.0;
1254     for (j=0; j<A->rmap.n; j++) {
1255       v = mat->v + j;
1256       sum = 0.0;
1257       for (i=0; i<A->cmap.n; i++) {
1258         sum += PetscAbsScalar(*v); v += mat->lda;
1259       }
1260       if (sum > *nrm) *nrm = sum;
1261     }
1262     ierr = PetscLogFlops(A->cmap.n*A->rmap.n);CHKERRQ(ierr);
1263   } else {
1264     SETERRQ(PETSC_ERR_SUP,"No two norm");
1265   }
1266   PetscFunctionReturn(0);
1267 }
1268 
1269 #undef __FUNCT__
1270 #define __FUNCT__ "MatSetOption_SeqDense"
1271 PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op,PetscTruth flg)
1272 {
1273   Mat_SeqDense   *aij = (Mat_SeqDense*)A->data;
1274   PetscErrorCode ierr;
1275 
1276   PetscFunctionBegin;
1277   switch (op) {
1278   case MAT_ROW_ORIENTED:
1279     aij->roworiented = flg;
1280     break;
1281   case MAT_NEW_NONZERO_LOCATIONS:
1282   case MAT_NEW_NONZERO_LOCATION_ERR:
1283   case MAT_NEW_NONZERO_ALLOCATION_ERR:
1284   case MAT_NEW_DIAGONALS:
1285   case MAT_IGNORE_OFF_PROC_ENTRIES:
1286   case MAT_USE_HASH_TABLE:
1287   case MAT_SYMMETRIC:
1288   case MAT_STRUCTURALLY_SYMMETRIC:
1289   case MAT_HERMITIAN:
1290   case MAT_SYMMETRY_ETERNAL:
1291   case MAT_IGNORE_LOWER_TRIANGULAR:
1292     ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr);
1293     break;
1294   default:
1295     SETERRQ1(PETSC_ERR_SUP,"unknown option %s",MatOptions[op]);
1296   }
1297   PetscFunctionReturn(0);
1298 }
1299 
1300 #undef __FUNCT__
1301 #define __FUNCT__ "MatZeroEntries_SeqDense"
1302 PetscErrorCode MatZeroEntries_SeqDense(Mat A)
1303 {
1304   Mat_SeqDense   *l = (Mat_SeqDense*)A->data;
1305   PetscErrorCode ierr;
1306   PetscInt       lda=l->lda,m=A->rmap.n,j;
1307 
1308   PetscFunctionBegin;
1309   if (lda>m) {
1310     for (j=0; j<A->cmap.n; j++) {
1311       ierr = PetscMemzero(l->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr);
1312     }
1313   } else {
1314     ierr = PetscMemzero(l->v,A->rmap.n*A->cmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
1315   }
1316   PetscFunctionReturn(0);
1317 }
1318 
1319 #undef __FUNCT__
1320 #define __FUNCT__ "MatZeroRows_SeqDense"
1321 PetscErrorCode MatZeroRows_SeqDense(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag)
1322 {
1323   Mat_SeqDense   *l = (Mat_SeqDense*)A->data;
1324   PetscInt       n = A->cmap.n,i,j;
1325   PetscScalar    *slot;
1326 
1327   PetscFunctionBegin;
1328   for (i=0; i<N; i++) {
1329     slot = l->v + rows[i];
1330     for (j=0; j<n; j++) { *slot = 0.0; slot += n;}
1331   }
1332   if (diag != 0.0) {
1333     for (i=0; i<N; i++) {
1334       slot = l->v + (n+1)*rows[i];
1335       *slot = diag;
1336     }
1337   }
1338   PetscFunctionReturn(0);
1339 }
1340 
1341 #undef __FUNCT__
1342 #define __FUNCT__ "MatGetArray_SeqDense"
1343 PetscErrorCode MatGetArray_SeqDense(Mat A,PetscScalar *array[])
1344 {
1345   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1346 
1347   PetscFunctionBegin;
1348   if (mat->lda != A->rmap.n) SETERRQ(PETSC_ERR_SUP,"Cannot get array for Dense matrices with LDA different from number of rows");
1349   *array = mat->v;
1350   PetscFunctionReturn(0);
1351 }
1352 
1353 #undef __FUNCT__
1354 #define __FUNCT__ "MatRestoreArray_SeqDense"
1355 PetscErrorCode MatRestoreArray_SeqDense(Mat A,PetscScalar *array[])
1356 {
1357   PetscFunctionBegin;
1358   *array = 0; /* user cannot accidently use the array later */
1359   PetscFunctionReturn(0);
1360 }
1361 
1362 #undef __FUNCT__
1363 #define __FUNCT__ "MatGetSubMatrix_SeqDense"
1364 static PetscErrorCode MatGetSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B)
1365 {
1366   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1367   PetscErrorCode ierr;
1368   PetscInt       i,j,*irow,*icol,nrows,ncols;
1369   PetscScalar    *av,*bv,*v = mat->v;
1370   Mat            newmat;
1371 
1372   PetscFunctionBegin;
1373   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1374   ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1375   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1376   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1377 
1378   /* Check submatrixcall */
1379   if (scall == MAT_REUSE_MATRIX) {
1380     PetscInt n_cols,n_rows;
1381     ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1382     if (n_rows != nrows || n_cols != ncols) {
1383       /* resize the result result matrix to match number of requested rows/columns */
1384       ierr = MatSetSizes(*B,nrows,nrows,nrows,nrows);CHKERRQ(ierr);
1385     }
1386     newmat = *B;
1387   } else {
1388     /* Create and fill new matrix */
1389     ierr = MatCreate(((PetscObject)A)->comm,&newmat);CHKERRQ(ierr);
1390     ierr = MatSetSizes(newmat,nrows,ncols,nrows,ncols);CHKERRQ(ierr);
1391     ierr = MatSetType(newmat,((PetscObject)A)->type_name);CHKERRQ(ierr);
1392     ierr = MatSeqDenseSetPreallocation(newmat,PETSC_NULL);CHKERRQ(ierr);
1393   }
1394 
1395   /* Now extract the data pointers and do the copy,column at a time */
1396   bv = ((Mat_SeqDense*)newmat->data)->v;
1397 
1398   for (i=0; i<ncols; i++) {
1399     av = v + mat->lda*icol[i];
1400     for (j=0; j<nrows; j++) {
1401       *bv++ = av[irow[j]];
1402     }
1403   }
1404 
1405   /* Assemble the matrices so that the correct flags are set */
1406   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1407   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1408 
1409   /* Free work space */
1410   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1411   ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1412   *B = newmat;
1413   PetscFunctionReturn(0);
1414 }
1415 
1416 #undef __FUNCT__
1417 #define __FUNCT__ "MatGetSubMatrices_SeqDense"
1418 PetscErrorCode MatGetSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1419 {
1420   PetscErrorCode ierr;
1421   PetscInt       i;
1422 
1423   PetscFunctionBegin;
1424   if (scall == MAT_INITIAL_MATRIX) {
1425     ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr);
1426   }
1427 
1428   for (i=0; i<n; i++) {
1429     ierr = MatGetSubMatrix_SeqDense(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1430   }
1431   PetscFunctionReturn(0);
1432 }
1433 
1434 #undef __FUNCT__
1435 #define __FUNCT__ "MatAssemblyBegin_SeqDense"
1436 PetscErrorCode MatAssemblyBegin_SeqDense(Mat mat,MatAssemblyType mode)
1437 {
1438   PetscFunctionBegin;
1439   PetscFunctionReturn(0);
1440 }
1441 
1442 #undef __FUNCT__
1443 #define __FUNCT__ "MatAssemblyEnd_SeqDense"
1444 PetscErrorCode MatAssemblyEnd_SeqDense(Mat mat,MatAssemblyType mode)
1445 {
1446   PetscFunctionBegin;
1447   PetscFunctionReturn(0);
1448 }
1449 
1450 #undef __FUNCT__
1451 #define __FUNCT__ "MatCopy_SeqDense"
1452 PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str)
1453 {
1454   Mat_SeqDense   *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense *)B->data;
1455   PetscErrorCode ierr;
1456   PetscInt       lda1=a->lda,lda2=b->lda, m=A->rmap.n,n=A->cmap.n, j;
1457 
1458   PetscFunctionBegin;
1459   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
1460   if (A->ops->copy != B->ops->copy) {
1461     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1462     PetscFunctionReturn(0);
1463   }
1464   if (m != B->rmap.n || n != B->cmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"size(B) != size(A)");
1465   if (lda1>m || lda2>m) {
1466     for (j=0; j<n; j++) {
1467       ierr = PetscMemcpy(b->v+j*lda2,a->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr);
1468     }
1469   } else {
1470     ierr = PetscMemcpy(b->v,a->v,A->rmap.n*A->cmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
1471   }
1472   PetscFunctionReturn(0);
1473 }
1474 
1475 #undef __FUNCT__
1476 #define __FUNCT__ "MatSetUpPreallocation_SeqDense"
1477 PetscErrorCode MatSetUpPreallocation_SeqDense(Mat A)
1478 {
1479   PetscErrorCode ierr;
1480 
1481   PetscFunctionBegin;
1482   ierr =  MatSeqDenseSetPreallocation(A,0);CHKERRQ(ierr);
1483   PetscFunctionReturn(0);
1484 }
1485 
1486 #undef __FUNCT__
1487 #define __FUNCT__ "MatSetSizes_SeqDense"
1488 PetscErrorCode MatSetSizes_SeqDense(Mat A,PetscInt m,PetscInt n,PetscInt M,PetscInt N)
1489 {
1490   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1491   PetscErrorCode ierr;
1492   PetscFunctionBegin;
1493   /* this will not be called before lda, Mmax,  and Nmax have been set */
1494   m = PetscMax(m,M);
1495   n = PetscMax(n,N);
1496   if (m > a->Mmax) SETERRQ2(PETSC_ERR_SUP,"Cannot yet resize number rows of dense matrix larger then its initial size %d, requested %d",a->lda,(int)m);
1497   if (n > a->Nmax) SETERRQ2(PETSC_ERR_SUP,"Cannot yet resize number columns of dense matrix larger then its initial size %d, requested %d",a->Nmax,(int)n);
1498   A->rmap.n = A->rmap.n = m;
1499   A->cmap.n = A->cmap.N = n;
1500   if (a->changelda) a->lda = m;
1501   ierr = PetscMemzero(a->v,m*n*sizeof(PetscScalar));CHKERRQ(ierr);
1502   PetscFunctionReturn(0);
1503 }
1504 
1505 
1506 /* ----------------------------------------------------------------*/
1507 #undef __FUNCT__
1508 #define __FUNCT__ "MatMatMult_SeqDense_SeqDense"
1509 PetscErrorCode MatMatMult_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
1510 {
1511   PetscErrorCode ierr;
1512 
1513   PetscFunctionBegin;
1514   if (scall == MAT_INITIAL_MATRIX){
1515     ierr = MatMatMultSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr);
1516   }
1517   ierr = MatMatMultNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr);
1518   PetscFunctionReturn(0);
1519 }
1520 
1521 #undef __FUNCT__
1522 #define __FUNCT__ "MatMatMultSymbolic_SeqDense_SeqDense"
1523 PetscErrorCode MatMatMultSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
1524 {
1525   PetscErrorCode ierr;
1526   PetscInt       m=A->rmap.n,n=B->cmap.n;
1527   Mat            Cmat;
1528 
1529   PetscFunctionBegin;
1530   if (A->cmap.n != B->rmap.n) SETERRQ2(PETSC_ERR_ARG_SIZ,"A->cmap.n %d != B->rmap.n %d\n",A->cmap.n,B->rmap.n);
1531   ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr);
1532   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
1533   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
1534   ierr = MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr);
1535   Cmat->assembled = PETSC_TRUE;
1536   *C = Cmat;
1537   PetscFunctionReturn(0);
1538 }
1539 
1540 #undef __FUNCT__
1541 #define __FUNCT__ "MatMatMultNumeric_SeqDense_SeqDense"
1542 PetscErrorCode MatMatMultNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
1543 {
1544   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1545   Mat_SeqDense   *b = (Mat_SeqDense*)B->data;
1546   Mat_SeqDense   *c = (Mat_SeqDense*)C->data;
1547   PetscBLASInt   m,n,k;
1548   PetscScalar    _DOne=1.0,_DZero=0.0;
1549 
1550   PetscFunctionBegin;
1551   m = PetscBLASIntCast(A->rmap.n);
1552   n = PetscBLASIntCast(B->cmap.n);
1553   k = PetscBLASIntCast(A->cmap.n);
1554   BLASgemm_("N","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda);
1555   PetscFunctionReturn(0);
1556 }
1557 
1558 #undef __FUNCT__
1559 #define __FUNCT__ "MatMatMultTranspose_SeqDense_SeqDense"
1560 PetscErrorCode MatMatMultTranspose_SeqDense_SeqDense(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C)
1561 {
1562   PetscErrorCode ierr;
1563 
1564   PetscFunctionBegin;
1565   if (scall == MAT_INITIAL_MATRIX){
1566     ierr = MatMatMultTransposeSymbolic_SeqDense_SeqDense(A,B,fill,C);CHKERRQ(ierr);
1567   }
1568   ierr = MatMatMultTransposeNumeric_SeqDense_SeqDense(A,B,*C);CHKERRQ(ierr);
1569   PetscFunctionReturn(0);
1570 }
1571 
1572 #undef __FUNCT__
1573 #define __FUNCT__ "MatMatMultTransposeSymbolic_SeqDense_SeqDense"
1574 PetscErrorCode MatMatMultTransposeSymbolic_SeqDense_SeqDense(Mat A,Mat B,PetscReal fill,Mat *C)
1575 {
1576   PetscErrorCode ierr;
1577   PetscInt       m=A->cmap.n,n=B->cmap.n;
1578   Mat            Cmat;
1579 
1580   PetscFunctionBegin;
1581   if (A->rmap.n != B->rmap.n) SETERRQ2(PETSC_ERR_ARG_SIZ,"A->rmap.n %d != B->rmap.n %d\n",A->rmap.n,B->rmap.n);
1582   ierr = MatCreate(PETSC_COMM_SELF,&Cmat);CHKERRQ(ierr);
1583   ierr = MatSetSizes(Cmat,m,n,m,n);CHKERRQ(ierr);
1584   ierr = MatSetType(Cmat,MATSEQDENSE);CHKERRQ(ierr);
1585   ierr = MatSeqDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr);
1586   Cmat->assembled = PETSC_TRUE;
1587   *C = Cmat;
1588   PetscFunctionReturn(0);
1589 }
1590 
1591 #undef __FUNCT__
1592 #define __FUNCT__ "MatMatMultTransposeNumeric_SeqDense_SeqDense"
1593 PetscErrorCode MatMatMultTransposeNumeric_SeqDense_SeqDense(Mat A,Mat B,Mat C)
1594 {
1595   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1596   Mat_SeqDense   *b = (Mat_SeqDense*)B->data;
1597   Mat_SeqDense   *c = (Mat_SeqDense*)C->data;
1598   PetscBLASInt   m,n,k;
1599   PetscScalar    _DOne=1.0,_DZero=0.0;
1600 
1601   PetscFunctionBegin;
1602   m = PetscBLASIntCast(A->cmap.n);
1603   n = PetscBLASIntCast(B->cmap.n);
1604   k = PetscBLASIntCast(A->rmap.n);
1605   /*
1606      Note the m and n arguments below are the number rows and columns of A', not A!
1607   */
1608   BLASgemm_("T","N",&m,&n,&k,&_DOne,a->v,&a->lda,b->v,&b->lda,&_DZero,c->v,&c->lda);
1609   PetscFunctionReturn(0);
1610 }
1611 
1612 #undef __FUNCT__
1613 #define __FUNCT__ "MatGetRowMax_SeqDense"
1614 PetscErrorCode MatGetRowMax_SeqDense(Mat A,Vec v,PetscInt idx[])
1615 {
1616   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1617   PetscErrorCode ierr;
1618   PetscInt       i,j,m = A->rmap.n,n = A->cmap.n,p;
1619   PetscScalar    *x;
1620   MatScalar      *aa = a->v;
1621 
1622   PetscFunctionBegin;
1623   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1624 
1625   ierr = VecSet(v,0.0);CHKERRQ(ierr);
1626   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1627   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
1628   if (p != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1629   for (i=0; i<m; i++) {
1630     x[i] = aa[i]; if (idx) idx[i] = 0;
1631     for (j=1; j<n; j++){
1632       if (PetscRealPart(x[i]) < PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
1633     }
1634   }
1635   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1636   PetscFunctionReturn(0);
1637 }
1638 
1639 #undef __FUNCT__
1640 #define __FUNCT__ "MatGetRowMaxAbs_SeqDense"
1641 PetscErrorCode MatGetRowMaxAbs_SeqDense(Mat A,Vec v,PetscInt idx[])
1642 {
1643   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1644   PetscErrorCode ierr;
1645   PetscInt       i,j,m = A->rmap.n,n = A->cmap.n,p;
1646   PetscScalar    *x;
1647   PetscReal      atmp;
1648   MatScalar      *aa = a->v;
1649 
1650   PetscFunctionBegin;
1651   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1652 
1653   ierr = VecSet(v,0.0);CHKERRQ(ierr);
1654   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1655   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
1656   if (p != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1657   for (i=0; i<m; i++) {
1658     x[i] = PetscAbsScalar(aa[i]); if (idx) idx[i] = 0;
1659     for (j=1; j<n; j++){
1660       atmp = PetscAbsScalar(aa[i+m*j]);
1661       if (PetscAbsScalar(x[i]) < atmp) {x[i] = atmp; if (idx) idx[i] = j;}
1662     }
1663   }
1664   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1665   PetscFunctionReturn(0);
1666 }
1667 
1668 #undef __FUNCT__
1669 #define __FUNCT__ "MatGetRowMin_SeqDense"
1670 PetscErrorCode MatGetRowMin_SeqDense(Mat A,Vec v,PetscInt idx[])
1671 {
1672   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1673   PetscErrorCode ierr;
1674   PetscInt       i,j,m = A->rmap.n,n = A->cmap.n,p;
1675   PetscScalar    *x;
1676   MatScalar      *aa = a->v;
1677 
1678   PetscFunctionBegin;
1679   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1680 
1681   ierr = VecSet(v,0.0);CHKERRQ(ierr);
1682   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1683   ierr = VecGetLocalSize(v,&p);CHKERRQ(ierr);
1684   if (p != A->rmap.n) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming matrix and vector");
1685   for (i=0; i<m; i++) {
1686     x[i] = aa[i]; if (idx) idx[i] = 0;
1687     for (j=1; j<n; j++){
1688       if (PetscRealPart(x[i]) > PetscRealPart(aa[i+m*j])) {x[i] = aa[i + m*j]; if (idx) idx[i] = j;}
1689     }
1690   }
1691   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1692   PetscFunctionReturn(0);
1693 }
1694 
1695 #undef __FUNCT__
1696 #define __FUNCT__ "MatGetColumnVector_SeqDense"
1697 PetscErrorCode MatGetColumnVector_SeqDense(Mat A,Vec v,PetscInt col)
1698 {
1699   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
1700   PetscErrorCode ierr;
1701   PetscScalar    *x;
1702 
1703   PetscFunctionBegin;
1704   if (A->factor) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix");
1705 
1706   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1707   ierr = PetscMemcpy(x,a->v+col*a->lda,A->rmap.n*sizeof(PetscScalar));CHKERRQ(ierr);
1708   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1709   PetscFunctionReturn(0);
1710 }
1711 
1712 /* -------------------------------------------------------------------*/
1713 static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
1714        MatGetRow_SeqDense,
1715        MatRestoreRow_SeqDense,
1716        MatMult_SeqDense,
1717 /* 4*/ MatMultAdd_SeqDense,
1718        MatMultTranspose_SeqDense,
1719        MatMultTransposeAdd_SeqDense,
1720        MatSolve_SeqDense,
1721        MatSolveAdd_SeqDense,
1722        MatSolveTranspose_SeqDense,
1723 /*10*/ MatSolveTransposeAdd_SeqDense,
1724        MatLUFactor_SeqDense,
1725        MatCholeskyFactor_SeqDense,
1726        MatRelax_SeqDense,
1727        MatTranspose_SeqDense,
1728 /*15*/ MatGetInfo_SeqDense,
1729        MatEqual_SeqDense,
1730        MatGetDiagonal_SeqDense,
1731        MatDiagonalScale_SeqDense,
1732        MatNorm_SeqDense,
1733 /*20*/ MatAssemblyBegin_SeqDense,
1734        MatAssemblyEnd_SeqDense,
1735        0,
1736        MatSetOption_SeqDense,
1737        MatZeroEntries_SeqDense,
1738 /*25*/ MatZeroRows_SeqDense,
1739        MatLUFactorSymbolic_SeqDense,
1740        MatLUFactorNumeric_SeqDense,
1741        MatCholeskyFactorSymbolic_SeqDense,
1742        MatCholeskyFactorNumeric_SeqDense,
1743 /*30*/ MatSetUpPreallocation_SeqDense,
1744        0,
1745        0,
1746        MatGetArray_SeqDense,
1747        MatRestoreArray_SeqDense,
1748 /*35*/ MatDuplicate_SeqDense,
1749        0,
1750        0,
1751        0,
1752        0,
1753 /*40*/ MatAXPY_SeqDense,
1754        MatGetSubMatrices_SeqDense,
1755        0,
1756        MatGetValues_SeqDense,
1757        MatCopy_SeqDense,
1758 /*45*/ MatGetRowMax_SeqDense,
1759        MatScale_SeqDense,
1760        0,
1761        0,
1762        0,
1763 /*50*/ 0,
1764        0,
1765        0,
1766        0,
1767        0,
1768 /*55*/ 0,
1769        0,
1770        0,
1771        0,
1772        0,
1773 /*60*/ 0,
1774        MatDestroy_SeqDense,
1775        MatView_SeqDense,
1776        0,
1777        0,
1778 /*65*/ 0,
1779        0,
1780        0,
1781        0,
1782        0,
1783 /*70*/ MatGetRowMaxAbs_SeqDense,
1784        0,
1785        0,
1786        0,
1787        0,
1788 /*75*/ 0,
1789        0,
1790        0,
1791        0,
1792        0,
1793 /*80*/ 0,
1794        0,
1795        0,
1796        0,
1797 /*84*/ MatLoad_SeqDense,
1798        0,
1799        MatIsHermitian_SeqDense,
1800        0,
1801        0,
1802        0,
1803 /*90*/ MatMatMult_SeqDense_SeqDense,
1804        MatMatMultSymbolic_SeqDense_SeqDense,
1805        MatMatMultNumeric_SeqDense_SeqDense,
1806        0,
1807        0,
1808 /*95*/ 0,
1809        MatMatMultTranspose_SeqDense_SeqDense,
1810        MatMatMultTransposeSymbolic_SeqDense_SeqDense,
1811        MatMatMultTransposeNumeric_SeqDense_SeqDense,
1812        0,
1813 /*100*/0,
1814        0,
1815        0,
1816        0,
1817        MatSetSizes_SeqDense,
1818        0,
1819        0,
1820        0,
1821        0,
1822        0,
1823 /*110*/0,
1824        0,
1825        MatGetRowMin_SeqDense,
1826        MatGetColumnVector_SeqDense
1827 };
1828 
1829 #undef __FUNCT__
1830 #define __FUNCT__ "MatCreateSeqDense"
1831 /*@C
1832    MatCreateSeqDense - Creates a sequential dense matrix that
1833    is stored in column major order (the usual Fortran 77 manner). Many
1834    of the matrix operations use the BLAS and LAPACK routines.
1835 
1836    Collective on MPI_Comm
1837 
1838    Input Parameters:
1839 +  comm - MPI communicator, set to PETSC_COMM_SELF
1840 .  m - number of rows
1841 .  n - number of columns
1842 -  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
1843    to control all matrix memory allocation.
1844 
1845    Output Parameter:
1846 .  A - the matrix
1847 
1848    Notes:
1849    The data input variable is intended primarily for Fortran programmers
1850    who wish to allocate their own matrix memory space.  Most users should
1851    set data=PETSC_NULL.
1852 
1853    Level: intermediate
1854 
1855 .keywords: dense, matrix, LAPACK, BLAS
1856 
1857 .seealso: MatCreate(), MatCreateMPIDense(), MatSetValues()
1858 @*/
1859 PetscErrorCode PETSCMAT_DLLEXPORT MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A)
1860 {
1861   PetscErrorCode ierr;
1862 
1863   PetscFunctionBegin;
1864   ierr = MatCreate(comm,A);CHKERRQ(ierr);
1865   ierr = MatSetSizes(*A,m,n,m,n);CHKERRQ(ierr);
1866   ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr);
1867   ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr);
1868   PetscFunctionReturn(0);
1869 }
1870 
1871 #undef __FUNCT__
1872 #define __FUNCT__ "MatSeqDenseSetPreallocation"
1873 /*@C
1874    MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements
1875 
1876    Collective on MPI_Comm
1877 
1878    Input Parameters:
1879 +  A - the matrix
1880 -  data - the array (or PETSC_NULL)
1881 
1882    Notes:
1883    The data input variable is intended primarily for Fortran programmers
1884    who wish to allocate their own matrix memory space.  Most users should
1885    need not call this routine.
1886 
1887    Level: intermediate
1888 
1889 .keywords: dense, matrix, LAPACK, BLAS
1890 
1891 .seealso: MatCreate(), MatCreateMPIDense(), MatSetValues()
1892 @*/
1893 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqDenseSetPreallocation(Mat B,PetscScalar data[])
1894 {
1895   PetscErrorCode ierr,(*f)(Mat,PetscScalar[]);
1896 
1897   PetscFunctionBegin;
1898   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
1899   if (f) {
1900     ierr = (*f)(B,data);CHKERRQ(ierr);
1901   }
1902   PetscFunctionReturn(0);
1903 }
1904 
1905 EXTERN_C_BEGIN
1906 #undef __FUNCT__
1907 #define __FUNCT__ "MatSeqDenseSetPreallocation_SeqDense"
1908 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data)
1909 {
1910   Mat_SeqDense   *b;
1911   PetscErrorCode ierr;
1912 
1913   PetscFunctionBegin;
1914   B->preallocated = PETSC_TRUE;
1915   b               = (Mat_SeqDense*)B->data;
1916   if (!data) { /* petsc-allocated storage */
1917     if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); }
1918     ierr = PetscMalloc((b->lda*b->Nmax+1)*sizeof(PetscScalar),&b->v);CHKERRQ(ierr);
1919     ierr = PetscMemzero(b->v,b->lda*b->Nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1920     ierr = PetscLogObjectMemory(B,b->lda*b->Nmax*sizeof(PetscScalar));CHKERRQ(ierr);
1921     b->user_alloc = PETSC_FALSE;
1922   } else { /* user-allocated storage */
1923     if (!b->user_alloc) { ierr = PetscFree(b->v);CHKERRQ(ierr); }
1924     b->v          = data;
1925     b->user_alloc = PETSC_TRUE;
1926   }
1927   PetscFunctionReturn(0);
1928 }
1929 EXTERN_C_END
1930 
1931 #undef __FUNCT__
1932 #define __FUNCT__ "MatSeqDenseSetLDA"
1933 /*@C
1934   MatSeqDenseSetLDA - Declare the leading dimension of the user-provided array
1935 
1936   Input parameter:
1937 + A - the matrix
1938 - lda - the leading dimension
1939 
1940   Notes:
1941   This routine is to be used in conjunction with MatSeqDenseSetPreallocation;
1942   it asserts that the preallocation has a leading dimension (the LDA parameter
1943   of Blas and Lapack fame) larger than M, the first dimension of the matrix.
1944 
1945   Level: intermediate
1946 
1947 .keywords: dense, matrix, LAPACK, BLAS
1948 
1949 .seealso: MatCreate(), MatCreateSeqDense(), MatSeqDenseSetPreallocation(), MatSetMaximumSize()
1950 @*/
1951 PetscErrorCode PETSCMAT_DLLEXPORT MatSeqDenseSetLDA(Mat B,PetscInt lda)
1952 {
1953   Mat_SeqDense *b = (Mat_SeqDense*)B->data;
1954 
1955   PetscFunctionBegin;
1956   if (lda < B->rmap.n) SETERRQ2(PETSC_ERR_ARG_SIZ,"LDA %D must be at least matrix dimension %D",lda,B->rmap.n);
1957   b->lda       = lda;
1958   b->changelda = PETSC_FALSE;
1959   b->Mmax      = PetscMax(b->Mmax,lda);
1960   PetscFunctionReturn(0);
1961 }
1962 
1963 /*MC
1964    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
1965 
1966    Options Database Keys:
1967 . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions()
1968 
1969   Level: beginner
1970 
1971 .seealso: MatCreateSeqDense()
1972 
1973 M*/
1974 
1975 EXTERN_C_BEGIN
1976 #undef __FUNCT__
1977 #define __FUNCT__ "MatCreate_SeqDense"
1978 PetscErrorCode PETSCMAT_DLLEXPORT MatCreate_SeqDense(Mat B)
1979 {
1980   Mat_SeqDense   *b;
1981   PetscErrorCode ierr;
1982   PetscMPIInt    size;
1983 
1984   PetscFunctionBegin;
1985   ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr);
1986   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1987 
1988   B->rmap.bs = B->cmap.bs = 1;
1989   ierr = PetscMapSetUp(&B->rmap);CHKERRQ(ierr);
1990   ierr = PetscMapSetUp(&B->cmap);CHKERRQ(ierr);
1991 
1992   ierr            = PetscNewLog(B,Mat_SeqDense,&b);CHKERRQ(ierr);
1993   ierr            = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1994   B->factor       = 0;
1995   B->mapping      = 0;
1996   B->data         = (void*)b;
1997 
1998 
1999   b->pivots       = 0;
2000   b->roworiented  = PETSC_TRUE;
2001   b->v            = 0;
2002   b->lda          = B->rmap.n;
2003   b->changelda    = PETSC_FALSE;
2004   b->Mmax         = B->rmap.n;
2005   b->Nmax         = B->cmap.n;
2006 
2007   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqDenseSetPreallocation_C",
2008                                     "MatSeqDenseSetPreallocation_SeqDense",
2009                                      MatSeqDenseSetPreallocation_SeqDense);CHKERRQ(ierr);
2010   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_seqaij_seqdense_C",
2011                                      "MatMatMult_SeqAIJ_SeqDense",
2012                                       MatMatMult_SeqAIJ_SeqDense);CHKERRQ(ierr);
2013   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_seqaij_seqdense_C",
2014                                      "MatMatMultSymbolic_SeqAIJ_SeqDense",
2015                                       MatMatMultSymbolic_SeqAIJ_SeqDense);CHKERRQ(ierr);
2016   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_seqaij_seqdense_C",
2017                                      "MatMatMultNumeric_SeqAIJ_SeqDense",
2018                                       MatMatMultNumeric_SeqAIJ_SeqDense);CHKERRQ(ierr);
2019   ierr = PetscObjectChangeTypeName((PetscObject)B,MATSEQDENSE);CHKERRQ(ierr);
2020   PetscFunctionReturn(0);
2021 }
2022 
2023 
2024 EXTERN_C_END
2025