xref: /petsc/src/mat/impls/dense/seq/dense.c (revision f09e8eb94a771781a812a8d81a9ca3d36ec35eba)
1 #ifndef lint
2 static char vcid[] = "$Id: dense.c,v 1.127 1997/04/10 00:02:31 bsmith Exp balay $";
3 #endif
4 /*
5      Defines the basic matrix operations for sequential dense.
6 */
7 
8 #include "src/mat/impls/dense/seq/dense.h"
9 #include "pinclude/plapack.h"
10 #include "pinclude/pviewer.h"
11 
12 #undef __FUNC__
13 #define __FUNC__ "MatAXPY_SeqDense"
14 int MatAXPY_SeqDense(Scalar *alpha,Mat X,Mat Y)
15 {
16   Mat_SeqDense *x = (Mat_SeqDense*) X->data,*y = (Mat_SeqDense*) Y->data;
17   int          N = x->m*x->n, one = 1;
18   BLaxpy_( &N, alpha, x->v, &one, y->v, &one );
19   PLogFlops(2*N-1);
20   return 0;
21 }
22 
23 #undef __FUNC__
24 #define __FUNC__ "MatGetInfo_SeqDense"
25 int MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info)
26 {
27   Mat_SeqDense *a = (Mat_SeqDense *) A->data;
28   int          i,N = a->m*a->n,count = 0;
29   Scalar       *v = a->v;
30   for ( i=0; i<N; i++ ) {if (*v != 0.0) count++; v++;}
31 
32   info->rows_global       = (double)a->m;
33   info->columns_global    = (double)a->n;
34   info->rows_local        = (double)a->m;
35   info->columns_local     = (double)a->n;
36   info->block_size        = 1.0;
37   info->nz_allocated      = (double)N;
38   info->nz_used           = (double)count;
39   info->nz_unneeded       = (double)(N-count);
40   info->assemblies        = (double)A->num_ass;
41   info->mallocs           = 0;
42   info->memory            = A->mem;
43   info->fill_ratio_given  = 0;
44   info->fill_ratio_needed = 0;
45   info->factor_mallocs    = 0;
46 
47   return 0;
48 }
49 
50 #undef __FUNC__
51 #define __FUNC__ "MatScale_SeqDense"
52 int MatScale_SeqDense(Scalar *alpha,Mat inA)
53 {
54   Mat_SeqDense *a = (Mat_SeqDense *) inA->data;
55   int          one = 1, nz;
56 
57   nz = a->m*a->n;
58   BLscal_( &nz, alpha, a->v, &one );
59   PLogFlops(nz);
60   return 0;
61 }
62 
63 /* ---------------------------------------------------------------*/
64 /* COMMENT: I have chosen to hide column permutation in the pivots,
65    rather than put it in the Mat->col slot.*/
66 #undef __FUNC__
67 #define __FUNC__ "MatLUFactor_SeqDense"
68 int MatLUFactor_SeqDense(Mat A,IS row,IS col,double f)
69 {
70   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
71   int          info;
72 
73   if (!mat->pivots) {
74     mat->pivots = (int *) PetscMalloc((mat->m+1)*sizeof(int));CHKPTRQ(mat->pivots);
75     PLogObjectMemory(A,mat->m*sizeof(int));
76   }
77   LAgetrf_(&mat->m,&mat->n,mat->v,&mat->m,mat->pivots,&info);
78   if (info<0) SETERRQ(1,0,"Bad argument to LU factorization");
79   if (info>0) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,0,"Bad LU factorization");
80   A->factor = FACTOR_LU;
81   PLogFlops((2*mat->n*mat->n*mat->n)/3);
82   return 0;
83 }
84 
85 #undef __FUNC__
86 #define __FUNC__ "MatConvertSameType_SeqDense"
87 int MatConvertSameType_SeqDense(Mat A,Mat *newmat,int cpvalues)
88 {
89   Mat_SeqDense *mat = (Mat_SeqDense *) A->data, *l;
90   int          ierr;
91   Mat          newi;
92 
93   ierr = MatCreateSeqDense(A->comm,mat->m,mat->n,PETSC_NULL,&newi); CHKERRQ(ierr);
94   l = (Mat_SeqDense *) newi->data;
95   if (cpvalues == COPY_VALUES) {
96     PetscMemcpy(l->v,mat->v,mat->m*mat->n*sizeof(Scalar));
97   }
98   newi->assembled = PETSC_TRUE;
99   *newmat = newi;
100   return 0;
101 }
102 
103 #undef __FUNC__
104 #define __FUNC__ "MatLUFactorSymbolic_SeqDense"
105 int MatLUFactorSymbolic_SeqDense(Mat A,IS row,IS col,double f,Mat *fact)
106 {
107   return MatConvertSameType_SeqDense(A,fact,PETSC_FALSE);
108 }
109 
110 #undef __FUNC__
111 #define __FUNC__ "MatLUFactorNumeric_SeqDense"
112 int MatLUFactorNumeric_SeqDense(Mat A,Mat *fact)
113 {
114   Mat_SeqDense *mat = (Mat_SeqDense*) A->data, *l = (Mat_SeqDense*) (*fact)->data;
115   /* copy the numerical values */
116   PetscMemcpy(l->v,mat->v,mat->m*mat->n*sizeof(Scalar));
117   (*fact)->factor = 0;
118   return MatLUFactor(*fact,0,0,1.0);
119 }
120 
121 #undef __FUNC__
122 #define __FUNC__ "MatCholeskyFactorSymbolic_SeqDense"
123 int MatCholeskyFactorSymbolic_SeqDense(Mat A,IS row,double f,Mat *fact)
124 {
125   return MatConvert(A,MATSAME,fact);
126 }
127 
128 #undef __FUNC__
129 #define __FUNC__ "MatCholeskyFactorNumeric_SeqDense"
130 int MatCholeskyFactorNumeric_SeqDense(Mat A,Mat *fact)
131 {
132   return MatCholeskyFactor(*fact,0,1.0);
133 }
134 
135 #undef __FUNC__
136 #define __FUNC__ "MatCholeskyFactor_SeqDense"
137 int MatCholeskyFactor_SeqDense(Mat A,IS perm,double f)
138 {
139   Mat_SeqDense  *mat = (Mat_SeqDense *) A->data;
140   int           info;
141 
142   if (mat->pivots) {
143     PetscFree(mat->pivots);
144     PLogObjectMemory(A,-mat->m*sizeof(int));
145     mat->pivots = 0;
146   }
147   LApotrf_("L",&mat->n,mat->v,&mat->m,&info);
148   if (info) SETERRQ(PETSC_ERR_MAT_CH_ZRPVT,0,"Bad factorization");
149   A->factor = FACTOR_CHOLESKY;
150   PLogFlops((mat->n*mat->n*mat->n)/3);
151   return 0;
152 }
153 
154 #undef __FUNC__
155 #define __FUNC__ "MatSolve_SeqDense"
156 int MatSolve_SeqDense(Mat A,Vec xx,Vec yy)
157 {
158   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
159   int          one = 1, info, ierr;
160   Scalar       *x, *y;
161 
162   ierr = VecGetArray(xx,&x); CHKERRQ(ierr); ierr = VecGetArray(yy,&y); CHKERRQ(ierr);
163   PetscMemcpy(y,x,mat->m*sizeof(Scalar));
164   if (A->factor == FACTOR_LU) {
165     LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info );
166   }
167   else if (A->factor == FACTOR_CHOLESKY){
168     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info );
169   }
170   else SETERRQ(1,0,"Matrix must be factored to solve");
171   if (info) SETERRQ(1,0,"MBad solve");
172   PLogFlops(mat->n*mat->n - mat->n);
173   return 0;
174 }
175 
176 #undef __FUNC__
177 #define __FUNC__ "MatSolveTrans_SeqDense"
178 int MatSolveTrans_SeqDense(Mat A,Vec xx,Vec yy)
179 {
180   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
181   int          one = 1, info;
182   Scalar       *x, *y;
183 
184   VecGetArray(xx,&x); VecGetArray(yy,&y);
185   PetscMemcpy(y,x,mat->m*sizeof(Scalar));
186   /* assume if pivots exist then use LU; else Cholesky */
187   if (mat->pivots) {
188     LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info );
189   }
190   else {
191     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info );
192   }
193   if (info) SETERRQ(1,0,"Bad solve");
194   PLogFlops(mat->n*mat->n - mat->n);
195   return 0;
196 }
197 
198 #undef __FUNC__
199 #define __FUNC__ "MatSolveAdd_SeqDense"
200 int MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
201 {
202   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
203   int          one = 1, info,ierr;
204   Scalar       *x, *y, sone = 1.0;
205   Vec          tmp = 0;
206 
207   VecGetArray(xx,&x); VecGetArray(yy,&y);
208   if (yy == zz) {
209     ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr);
210     PLogObjectParent(A,tmp);
211     ierr = VecCopy(yy,tmp); CHKERRQ(ierr);
212   }
213   PetscMemcpy(y,x,mat->m*sizeof(Scalar));
214   /* assume if pivots exist then use LU; else Cholesky */
215   if (mat->pivots) {
216     LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info );
217   }
218   else {
219     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info );
220   }
221   if (info) SETERRQ(1,0,"Bad solve");
222   if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);}
223   else VecAXPY(&sone,zz,yy);
224   PLogFlops(mat->n*mat->n - mat->n);
225   return 0;
226 }
227 
228 #undef __FUNC__
229 #define __FUNC__ "MatSolveTransAdd_SeqDense"
230 int MatSolveTransAdd_SeqDense(Mat A,Vec xx,Vec zz, Vec yy)
231 {
232   Mat_SeqDense  *mat = (Mat_SeqDense *) A->data;
233   int           one = 1, info,ierr;
234   Scalar        *x, *y, sone = 1.0;
235   Vec           tmp;
236 
237   VecGetArray(xx,&x); VecGetArray(yy,&y);
238   if (yy == zz) {
239     ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr);
240     PLogObjectParent(A,tmp);
241     ierr = VecCopy(yy,tmp); CHKERRQ(ierr);
242   }
243   PetscMemcpy(y,x,mat->m*sizeof(Scalar));
244   /* assume if pivots exist then use LU; else Cholesky */
245   if (mat->pivots) {
246     LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,y, &mat->m, &info );
247   }
248   else {
249     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,y, &mat->m, &info );
250   }
251   if (info) SETERRQ(1,0,"Bad solve");
252   if (tmp) {
253     ierr = VecAXPY(&sone,tmp,yy);  CHKERRQ(ierr);
254     ierr = VecDestroy(tmp); CHKERRQ(ierr);
255   }
256   else {
257     ierr = VecAXPY(&sone,zz,yy); CHKERRQ(ierr);
258   }
259   PLogFlops(mat->n*mat->n - mat->n);
260   return 0;
261 }
262 /* ------------------------------------------------------------------*/
263 #undef __FUNC__
264 #define __FUNC__ "MatRelax_SeqDense"
265 int MatRelax_SeqDense(Mat A,Vec bb,double omega,MatSORType flag,
266                           double shift,int its,Vec xx)
267 {
268   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
269   Scalar       *x, *b, *v = mat->v, zero = 0.0, xt;
270   int          o = 1,ierr, m = mat->m, i;
271 
272   if (flag & SOR_ZERO_INITIAL_GUESS) {
273     /* this is a hack fix, should have another version without
274        the second BLdot */
275     ierr = VecSet(&zero,xx); CHKERRQ(ierr);
276   }
277   VecGetArray(xx,&x); VecGetArray(bb,&b);
278   while (its--) {
279     if (flag & SOR_FORWARD_SWEEP){
280       for ( i=0; i<m; i++ ) {
281 #if defined(PETSC_COMPLEX)
282         /* cannot use BLAS dot for complex because compiler/linker is
283            not happy about returning a double complex */
284         int    _i;
285         Scalar sum = b[i];
286         for ( _i=0; _i<m; _i++ ) {
287           sum -= conj(v[i+_i*m])*x[_i];
288         }
289         xt = sum;
290 #else
291         xt = b[i]-BLdot_(&m,v+i,&m,x,&o);
292 #endif
293         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
294       }
295     }
296     if (flag & SOR_BACKWARD_SWEEP) {
297       for ( i=m-1; i>=0; i-- ) {
298 #if defined(PETSC_COMPLEX)
299         /* cannot use BLAS dot for complex because compiler/linker is
300            not happy about returning a double complex */
301         int    _i;
302         Scalar sum = b[i];
303         for ( _i=0; _i<m; _i++ ) {
304           sum -= conj(v[i+_i*m])*x[_i];
305         }
306         xt = sum;
307 #else
308         xt = b[i]-BLdot_(&m,v+i,&m,x,&o);
309 #endif
310         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
311       }
312     }
313   }
314   return 0;
315 }
316 
317 /* -----------------------------------------------------------------*/
318 #undef __FUNC__
319 #define __FUNC__ "MatMultTrans_SeqDense"
320 int MatMultTrans_SeqDense(Mat A,Vec xx,Vec yy)
321 {
322   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
323   Scalar       *v = mat->v, *x, *y;
324   int          _One=1;Scalar _DOne=1.0, _DZero=0.0;
325   VecGetArray(xx,&x), VecGetArray(yy,&y);
326   LAgemv_("T",&(mat->m),&(mat->n),&_DOne,v,&(mat->m),x,&_One,&_DZero,y,&_One);
327   PLogFlops(2*mat->m*mat->n - mat->n);
328   return 0;
329 }
330 
331 #undef __FUNC__
332 #define __FUNC__ "MatMult_SeqDense"
333 int MatMult_SeqDense(Mat A,Vec xx,Vec yy)
334 {
335   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
336   Scalar       *v = mat->v, *x, *y;
337   int          _One=1;Scalar _DOne=1.0, _DZero=0.0;
338   VecGetArray(xx,&x); VecGetArray(yy,&y);
339   LAgemv_( "N", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),x,&_One,&_DZero,y,&_One);
340   PLogFlops(2*mat->m*mat->n - mat->m);
341   return 0;
342 }
343 
344 #undef __FUNC__
345 #define __FUNC__ "MatMultAdd_SeqDense"
346 int MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
347 {
348   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
349   Scalar       *v = mat->v, *x, *y, *z;
350   int          _One=1; Scalar _DOne=1.0;
351   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
352   if (zz != yy) PetscMemcpy(y,z,mat->m*sizeof(Scalar));
353   LAgemv_( "N", &(mat->m), &(mat->n),&_DOne,v,&(mat->m),x,&_One,&_DOne,y,&_One);
354   PLogFlops(2*mat->m*mat->n);
355   return 0;
356 }
357 
358 #undef __FUNC__
359 #define __FUNC__ "MatMultTransAdd_SeqDense"
360 int MatMultTransAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
361 {
362   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
363   Scalar       *v = mat->v, *x, *y, *z;
364   int          _One=1;
365   Scalar       _DOne=1.0;
366   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
367   if (zz != yy) PetscMemcpy(y,z,mat->n*sizeof(Scalar));
368   LAgemv_( "T", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),x,&_One,&_DOne,y,&_One);
369   PLogFlops(2*mat->m*mat->n);
370   return 0;
371 }
372 
373 /* -----------------------------------------------------------------*/
374 #undef __FUNC__
375 #define __FUNC__ "MatGetRow_SeqDense"
376 int MatGetRow_SeqDense(Mat A,int row,int *ncols,int **cols,Scalar **vals)
377 {
378   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
379   Scalar       *v;
380   int          i;
381 
382   *ncols = mat->n;
383   if (cols) {
384     *cols = (int *) PetscMalloc((mat->n+1)*sizeof(int)); CHKPTRQ(*cols);
385     for ( i=0; i<mat->n; i++ ) (*cols)[i] = i;
386   }
387   if (vals) {
388     *vals = (Scalar *) PetscMalloc((mat->n+1)*sizeof(Scalar)); CHKPTRQ(*vals);
389     v = mat->v + row;
390     for ( i=0; i<mat->n; i++ ) {(*vals)[i] = *v; v += mat->m;}
391   }
392   return 0;
393 }
394 
395 #undef __FUNC__
396 #define __FUNC__ "MatRestoreRow_SeqDense"
397 int MatRestoreRow_SeqDense(Mat A,int row,int *ncols,int **cols,Scalar **vals)
398 {
399   if (cols) { PetscFree(*cols); }
400   if (vals) { PetscFree(*vals); }
401   return 0;
402 }
403 /* ----------------------------------------------------------------*/
404 #undef __FUNC__
405 #define __FUNC__ "MatSetValues_SeqDense"
406 int MatSetValues_SeqDense(Mat A,int m,int *indexm,int n,
407                                     int *indexn,Scalar *v,InsertMode addv)
408 {
409   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
410   int          i,j;
411 
412   if (!mat->roworiented) {
413     if (addv == INSERT_VALUES) {
414       for ( j=0; j<n; j++ ) {
415 #if defined(PETSC_BOPT_g)
416         if (indexn[j] < 0) SETERRQ(1,0,"Negative column");
417         if (indexn[j] >= A->n) SETERRQ(1,0,"Column too large");
418 #endif
419         for ( i=0; i<m; i++ ) {
420 #if defined(PETSC_BOPT_g)
421           if (indexm[i] < 0) SETERRQ(1,0,"Negative row");
422           if (indexm[i] >= A->m) SETERRQ(1,0,"Row too large");
423 #endif
424           mat->v[indexn[j]*mat->m + indexm[i]] = *v++;
425         }
426       }
427     }
428     else {
429       for ( j=0; j<n; j++ ) {
430 #if defined(PETSC_BOPT_g)
431         if (indexn[j] < 0) SETERRQ(1,0,"Negative column");
432         if (indexn[j] >= A->n) SETERRQ(1,0,"Column too large");
433 #endif
434         for ( i=0; i<m; i++ ) {
435 #if defined(PETSC_BOPT_g)
436           if (indexm[i] < 0) SETERRQ(1,0,"Negative row");
437           if (indexm[i] >= A->m) SETERRQ(1,0,"Row too large");
438 #endif
439           mat->v[indexn[j]*mat->m + indexm[i]] += *v++;
440         }
441       }
442     }
443   }
444   else {
445     if (addv == INSERT_VALUES) {
446       for ( i=0; i<m; i++ ) {
447 #if defined(PETSC_BOPT_g)
448         if (indexm[i] < 0) SETERRQ(1,0,"Negative row");
449         if (indexm[i] >= A->m) SETERRQ(1,0,"Row too large");
450 #endif
451         for ( j=0; j<n; j++ ) {
452 #if defined(PETSC_BOPT_g)
453           if (indexn[j] < 0) SETERRQ(1,0,"Negative column");
454           if (indexn[j] >= A->n) SETERRQ(1,0,"Column too large");
455 #endif
456           mat->v[indexn[j]*mat->m + indexm[i]] = *v++;
457         }
458       }
459     }
460     else {
461       for ( i=0; i<m; i++ ) {
462 #if defined(PETSC_BOPT_g)
463         if (indexm[i] < 0) SETERRQ(1,0,"Negative row");
464         if (indexm[i] >= A->m) SETERRQ(1,0,"Row too large");
465 #endif
466         for ( j=0; j<n; j++ ) {
467 #if defined(PETSC_BOPT_g)
468           if (indexn[j] < 0) SETERRQ(1,0,"Negative column");
469           if (indexn[j] >= A->n) SETERRQ(1,0,"Column too large");
470 #endif
471           mat->v[indexn[j]*mat->m + indexm[i]] += *v++;
472         }
473       }
474     }
475   }
476   return 0;
477 }
478 
479 #undef __FUNC__
480 #define __FUNC__ "MatGetValues_SeqDense"
481 int MatGetValues_SeqDense(Mat A,int m,int *indexm,int n,int *indexn,Scalar *v)
482 {
483   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
484   int          i, j;
485   Scalar       *vpt = v;
486 
487   /* row-oriented output */
488   for ( i=0; i<m; i++ ) {
489     for ( j=0; j<n; j++ ) {
490       *vpt++ = mat->v[indexn[j]*mat->m + indexm[i]];
491     }
492   }
493   return 0;
494 }
495 
496 /* -----------------------------------------------------------------*/
497 
498 #include "sys.h"
499 
500 #undef __FUNC__
501 #define __FUNC__ "MatLoad_SeqDense"
502 int MatLoad_SeqDense(Viewer viewer,MatType type,Mat *A)
503 {
504   Mat_SeqDense *a;
505   Mat          B;
506   int          *scols, i, j, nz, ierr, fd, header[4], size;
507   int          *rowlengths = 0, M, N, *cols;
508   Scalar       *vals, *svals, *v;
509   MPI_Comm     comm = ((PetscObject)viewer)->comm;
510 
511   MPI_Comm_size(comm,&size);
512   if (size > 1) SETERRQ(1,0,"view must have one processor");
513   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
514   ierr = PetscBinaryRead(fd,header,4,BINARY_INT); CHKERRQ(ierr);
515   if (header[0] != MAT_COOKIE) SETERRQ(1,0,"Not matrix object");
516   M = header[1]; N = header[2]; nz = header[3];
517 
518   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */
519     ierr = MatCreateSeqDense(comm,M,N,PETSC_NULL,A); CHKERRQ(ierr);
520     B = *A;
521     a = (Mat_SeqDense *) B->data;
522 
523     /* read in nonzero values */
524     ierr = PetscBinaryRead(fd,a->v,M*N,BINARY_SCALAR); CHKERRQ(ierr);
525 
526     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
527     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
528     ierr = MatTranspose(B,PETSC_NULL); CHKERRQ(ierr);
529   } else {
530     /* read row lengths */
531     rowlengths = (int*) PetscMalloc( (M+1)*sizeof(int) ); CHKPTRQ(rowlengths);
532     ierr = PetscBinaryRead(fd,rowlengths,M,BINARY_INT); CHKERRQ(ierr);
533 
534     /* create our matrix */
535     ierr = MatCreateSeqDense(comm,M,N,PETSC_NULL,A); CHKERRQ(ierr);
536     B = *A;
537     a = (Mat_SeqDense *) B->data;
538     v = a->v;
539 
540     /* read column indices and nonzeros */
541     cols = scols = (int *) PetscMalloc( (nz+1)*sizeof(int) ); CHKPTRQ(cols);
542     ierr = PetscBinaryRead(fd,cols,nz,BINARY_INT); CHKERRQ(ierr);
543     vals = svals = (Scalar *) PetscMalloc( (nz+1)*sizeof(Scalar) ); CHKPTRQ(vals);
544     ierr = PetscBinaryRead(fd,vals,nz,BINARY_SCALAR); CHKERRQ(ierr);
545 
546     /* insert into matrix */
547     for ( i=0; i<M; i++ ) {
548       for ( j=0; j<rowlengths[i]; j++ ) v[i+M*scols[j]] = svals[j];
549       svals += rowlengths[i]; scols += rowlengths[i];
550     }
551     PetscFree(vals); PetscFree(cols); PetscFree(rowlengths);
552 
553     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
554     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
555   }
556   return 0;
557 }
558 
559 #include "pinclude/pviewer.h"
560 #include "sys.h"
561 
562 #undef __FUNC__
563 #define __FUNC__ "MatView_SeqDense_ASCII"
564 static int MatView_SeqDense_ASCII(Mat A,Viewer viewer)
565 {
566   Mat_SeqDense *a = (Mat_SeqDense *) A->data;
567   int          ierr, i, j, format;
568   FILE         *fd;
569   char         *outputname;
570   Scalar       *v;
571 
572   ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr);
573   ierr = ViewerFileGetOutputname_Private(viewer,&outputname); CHKERRQ(ierr);
574   ierr = ViewerGetFormat(viewer,&format);
575   if (format == VIEWER_FORMAT_ASCII_INFO || format == VIEWER_FORMAT_ASCII_INFO_LONG) {
576     return 0;  /* do nothing for now */
577   }
578   else if (format == VIEWER_FORMAT_ASCII_COMMON) {
579     for ( i=0; i<a->m; i++ ) {
580       v = a->v + i;
581       fprintf(fd,"row %d:",i);
582       for ( j=0; j<a->n; j++ ) {
583 #if defined(PETSC_COMPLEX)
584         if (real(*v) != 0.0 && imag(*v) != 0.0)
585           fprintf(fd," %d %g + %g i",j,real(*v),imag(*v));
586         else if (real(*v)) fprintf(fd," %d %g ",j,real(*v));
587         v += a->m;
588 #else
589         if (*v) fprintf(fd," %d %g ",j,*v);
590         v += a->m;
591 #endif
592       }
593       fprintf(fd,"\n");
594     }
595   }
596   else {
597 #if defined(PETSC_COMPLEX)
598     int allreal = 1;
599     /* determine if matrix has all real values */
600     v = a->v;
601     for ( i=0; i<a->m*a->n; i++ ) {
602       if (imag(v[i])) { allreal = 0; break ;}
603     }
604 #endif
605     for ( i=0; i<a->m; i++ ) {
606       v = a->v + i;
607       for ( j=0; j<a->n; j++ ) {
608 #if defined(PETSC_COMPLEX)
609         if (allreal) {
610           fprintf(fd,"%6.4e ",real(*v)); v += a->m;
611         } else {
612           fprintf(fd,"%6.4e + %6.4e i ",real(*v),imag(*v)); v += a->m;
613         }
614 #else
615         fprintf(fd,"%6.4e ",*v); v += a->m;
616 #endif
617       }
618       fprintf(fd,"\n");
619     }
620   }
621   fflush(fd);
622   return 0;
623 }
624 
625 #undef __FUNC__
626 #define __FUNC__ "MatView_SeqDense_Binary"
627 static int MatView_SeqDense_Binary(Mat A,Viewer viewer)
628 {
629   Mat_SeqDense *a = (Mat_SeqDense *) A->data;
630   int          ict, j, n = a->n, m = a->m, i, fd, *col_lens, ierr, nz = m*n;
631   int          format;
632   Scalar       *v, *anonz,*vals;
633 
634   ierr = ViewerBinaryGetDescriptor(viewer,&fd); CHKERRQ(ierr);
635 
636   ierr = ViewerGetFormat(viewer,&format); CHKERRQ(ierr);
637   if (format == VIEWER_FORMAT_BINARY_NATIVE) {
638     /* store the matrix as a dense matrix */
639     col_lens = (int *) PetscMalloc( 4*sizeof(int) ); CHKPTRQ(col_lens);
640     col_lens[0] = MAT_COOKIE;
641     col_lens[1] = m;
642     col_lens[2] = n;
643     col_lens[3] = MATRIX_BINARY_FORMAT_DENSE;
644     ierr = PetscBinaryWrite(fd,col_lens,4,BINARY_INT,1); CHKERRQ(ierr);
645     PetscFree(col_lens);
646 
647     /* write out matrix, by rows */
648     vals = (Scalar *) PetscMalloc((m*n+1)*sizeof(Scalar)); CHKPTRQ(vals);
649     v    = a->v;
650     for ( i=0; i<m; i++ ) {
651       for ( j=0; j<n; j++ ) {
652         vals[i + j*m] = *v++;
653       }
654     }
655     ierr = PetscBinaryWrite(fd,vals,n*m,BINARY_SCALAR,0); CHKERRQ(ierr);
656     PetscFree(vals);
657   } else {
658     col_lens = (int *) PetscMalloc( (4+nz)*sizeof(int) ); CHKPTRQ(col_lens);
659     col_lens[0] = MAT_COOKIE;
660     col_lens[1] = m;
661     col_lens[2] = n;
662     col_lens[3] = nz;
663 
664     /* store lengths of each row and write (including header) to file */
665     for ( i=0; i<m; i++ ) col_lens[4+i] = n;
666     ierr = PetscBinaryWrite(fd,col_lens,4+m,BINARY_INT,1); CHKERRQ(ierr);
667 
668     /* Possibly should write in smaller increments, not whole matrix at once? */
669     /* store column indices (zero start index) */
670     ict = 0;
671     for ( i=0; i<m; i++ ) {
672       for ( j=0; j<n; j++ ) col_lens[ict++] = j;
673     }
674     ierr = PetscBinaryWrite(fd,col_lens,nz,BINARY_INT,0); CHKERRQ(ierr);
675     PetscFree(col_lens);
676 
677     /* store nonzero values */
678     anonz = (Scalar *) PetscMalloc((nz+1)*sizeof(Scalar)); CHKPTRQ(anonz);
679     ict = 0;
680     for ( i=0; i<m; i++ ) {
681       v = a->v + i;
682       for ( j=0; j<n; j++ ) {
683         anonz[ict++] = *v; v += a->m;
684       }
685     }
686     ierr = PetscBinaryWrite(fd,anonz,nz,BINARY_SCALAR,0); CHKERRQ(ierr);
687     PetscFree(anonz);
688   }
689   return 0;
690 }
691 
692 #undef __FUNC__
693 #define __FUNC__ "MatView_SeqDense"
694 int MatView_SeqDense(PetscObject obj,Viewer viewer)
695 {
696   Mat          A = (Mat) obj;
697   Mat_SeqDense *a = (Mat_SeqDense*) A->data;
698   ViewerType   vtype;
699   int          ierr;
700 
701   ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr);
702 
703   if (vtype == MATLAB_VIEWER) {
704     return ViewerMatlabPutArray_Private(viewer,a->m,a->n,a->v);
705   }
706   else if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) {
707     return MatView_SeqDense_ASCII(A,viewer);
708   }
709   else if (vtype == BINARY_FILE_VIEWER) {
710     return MatView_SeqDense_Binary(A,viewer);
711   }
712   return 0;
713 }
714 
715 #undef __FUNC__
716 #define __FUNC__ "MatDestroy_SeqDense"
717 int MatDestroy_SeqDense(PetscObject obj)
718 {
719   Mat          mat = (Mat) obj;
720   Mat_SeqDense *l = (Mat_SeqDense *) mat->data;
721   int          ierr;
722 
723 #if defined(PETSC_LOG)
724   PLogObjectState(obj,"Rows %d Cols %d",l->m,l->n);
725 #endif
726   if (l->pivots) PetscFree(l->pivots);
727   if (!l->user_alloc) PetscFree(l->v);
728   PetscFree(l);
729   if (mat->mapping) {
730     ierr = ISLocalToGlobalMappingDestroy(mat->mapping); CHKERRQ(ierr);
731   }
732   PLogObjectDestroy(mat);
733   PetscHeaderDestroy(mat);
734   return 0;
735 }
736 
737 #undef __FUNC__
738 #define __FUNC__ "MatTranspose_SeqDense"
739 int MatTranspose_SeqDense(Mat A,Mat *matout)
740 {
741   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
742   int          k, j, m, n;
743   Scalar       *v, tmp;
744 
745   v = mat->v; m = mat->m; n = mat->n;
746   if (matout == PETSC_NULL) { /* in place transpose */
747     if (m != n) SETERRQ(PETSC_ERR_SUP,0,"Supports square matrix only in-place");
748     for ( j=0; j<m; j++ ) {
749       for ( k=0; k<j; k++ ) {
750         tmp = v[j + k*n];
751         v[j + k*n] = v[k + j*n];
752         v[k + j*n] = tmp;
753       }
754     }
755   }
756   else { /* out-of-place transpose */
757     int          ierr;
758     Mat          tmat;
759     Mat_SeqDense *tmatd;
760     Scalar       *v2;
761     ierr = MatCreateSeqDense(A->comm,mat->n,mat->m,PETSC_NULL,&tmat); CHKERRQ(ierr);
762     tmatd = (Mat_SeqDense *) tmat->data;
763     v = mat->v; v2 = tmatd->v;
764     for ( j=0; j<n; j++ ) {
765       for ( k=0; k<m; k++ ) v2[j + k*n] = v[k + j*m];
766     }
767     ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
768     ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
769     *matout = tmat;
770   }
771   return 0;
772 }
773 
774 #undef __FUNC__
775 #define __FUNC__ "MatEqual_SeqDense"
776 int MatEqual_SeqDense(Mat A1,Mat A2, PetscTruth *flg)
777 {
778   Mat_SeqDense *mat1 = (Mat_SeqDense *) A1->data;
779   Mat_SeqDense *mat2 = (Mat_SeqDense *) A2->data;
780   int          i;
781   Scalar       *v1 = mat1->v, *v2 = mat2->v;
782 
783   if (A2->type != MATSEQDENSE) SETERRQ(PETSC_ERR_SUP,0,"Both matrices should be of type  MATSEQDENSE");
784   if (mat1->m != mat2->m) {*flg = PETSC_FALSE; return 0;}
785   if (mat1->n != mat2->n) {*flg = PETSC_FALSE; return 0;}
786   for ( i=0; i<mat1->m*mat1->n; i++ ) {
787     if (*v1 != *v2) {*flg = PETSC_FALSE; return 0;}
788     v1++; v2++;
789   }
790   *flg = PETSC_TRUE;
791   return 0;
792 }
793 
794 #undef __FUNC__
795 #define __FUNC__ "MatGetDiagonal_SeqDense"
796 int MatGetDiagonal_SeqDense(Mat A,Vec v)
797 {
798   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
799   int          i, n, len;
800   Scalar       *x, zero = 0.0;
801 
802   VecSet(&zero,v);
803   VecGetArray(v,&x); VecGetSize(v,&n);
804   len = PetscMin(mat->m,mat->n);
805   if (n != mat->m) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Nonconforming mat and vec");
806   for ( i=0; i<len; i++ ) {
807     x[i] = mat->v[i*mat->m + i];
808   }
809   return 0;
810 }
811 
812 #undef __FUNC__
813 #define __FUNC__ "MatDiagonalScale_SeqDense"
814 int MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr)
815 {
816   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
817   Scalar       *l,*r,x,*v;
818   int          i,j,m = mat->m, n = mat->n;
819 
820   if (ll) {
821     VecGetArray(ll,&l); VecGetSize(ll,&m);
822     if (m != mat->m) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Left scaling vec wrong size");
823     for ( i=0; i<m; i++ ) {
824       x = l[i];
825       v = mat->v + i;
826       for ( j=0; j<n; j++ ) { (*v) *= x; v+= m;}
827     }
828     PLogFlops(n*m);
829   }
830   if (rr) {
831     VecGetArray(rr,&r); VecGetSize(rr,&n);
832     if (n != mat->n) SETERRQ(PETSC_ERR_ARG_SIZ,0,"Right scaling vec wrong size");
833     for ( i=0; i<n; i++ ) {
834       x = r[i];
835       v = mat->v + i*m;
836       for ( j=0; j<m; j++ ) { (*v++) *= x;}
837     }
838     PLogFlops(n*m);
839   }
840   return 0;
841 }
842 
843 #undef __FUNC__
844 #define __FUNC__ "MatNorm_SeqDense"
845 int MatNorm_SeqDense(Mat A,NormType type,double *norm)
846 {
847   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
848   Scalar       *v = mat->v;
849   double       sum = 0.0;
850   int          i, j;
851 
852   if (type == NORM_FROBENIUS) {
853     for (i=0; i<mat->n*mat->m; i++ ) {
854 #if defined(PETSC_COMPLEX)
855       sum += real(conj(*v)*(*v)); v++;
856 #else
857       sum += (*v)*(*v); v++;
858 #endif
859     }
860     *norm = sqrt(sum);
861     PLogFlops(2*mat->n*mat->m);
862   }
863   else if (type == NORM_1) {
864     *norm = 0.0;
865     for ( j=0; j<mat->n; j++ ) {
866       sum = 0.0;
867       for ( i=0; i<mat->m; i++ ) {
868         sum += PetscAbsScalar(*v);  v++;
869       }
870       if (sum > *norm) *norm = sum;
871     }
872     PLogFlops(mat->n*mat->m);
873   }
874   else if (type == NORM_INFINITY) {
875     *norm = 0.0;
876     for ( j=0; j<mat->m; j++ ) {
877       v = mat->v + j;
878       sum = 0.0;
879       for ( i=0; i<mat->n; i++ ) {
880         sum += PetscAbsScalar(*v); v += mat->m;
881       }
882       if (sum > *norm) *norm = sum;
883     }
884     PLogFlops(mat->n*mat->m);
885   }
886   else {
887     SETERRQ(PETSC_ERR_SUP,0,"No two norm");
888   }
889   return 0;
890 }
891 
892 #undef __FUNC__
893 #define __FUNC__ "MatSetOption_SeqDense"
894 int MatSetOption_SeqDense(Mat A,MatOption op)
895 {
896   Mat_SeqDense *aij = (Mat_SeqDense *) A->data;
897 
898   if (op == MAT_ROW_ORIENTED)            aij->roworiented = 1;
899   else if (op == MAT_COLUMN_ORIENTED)    aij->roworiented = 0;
900   else if (op == MAT_ROWS_SORTED ||
901            op == MAT_ROWS_UNSORTED ||
902            op == MAT_COLUMNS_SORTED ||
903            op == MAT_COLUMNS_UNSORTED ||
904            op == MAT_SYMMETRIC ||
905            op == MAT_STRUCTURALLY_SYMMETRIC ||
906            op == MAT_NO_NEW_NONZERO_LOCATIONS ||
907            op == MAT_YES_NEW_NONZERO_LOCATIONS ||
908            op == MAT_NEW_NONZERO_LOCATION_ERROR ||
909            op == MAT_NO_NEW_DIAGONALS ||
910            op == MAT_YES_NEW_DIAGONALS ||
911            op == MAT_IGNORE_OFF_PROC_ENTRIES)
912     PLogInfo(A,"Info:MatSetOption_SeqDense:Option ignored\n");
913   else
914     {SETERRQ(PETSC_ERR_SUP,0,"unknown option");}
915   return 0;
916 }
917 
918 #undef __FUNC__
919 #define __FUNC__ "MatZeroEntries_SeqDense"
920 int MatZeroEntries_SeqDense(Mat A)
921 {
922   Mat_SeqDense *l = (Mat_SeqDense *) A->data;
923   PetscMemzero(l->v,l->m*l->n*sizeof(Scalar));
924   return 0;
925 }
926 
927 #undef __FUNC__
928 #define __FUNC__ "MatGetBlockSize_SeqDense"
929 int MatGetBlockSize_SeqDense(Mat A,int *bs)
930 {
931   *bs = 1;
932   return 0;
933 }
934 
935 #undef __FUNC__
936 #define __FUNC__ "MatZeroRows_SeqDense"
937 int MatZeroRows_SeqDense(Mat A,IS is,Scalar *diag)
938 {
939   Mat_SeqDense *l = (Mat_SeqDense *) A->data;
940   int          n = l->n, i, j,ierr,N, *rows;
941   Scalar       *slot;
942 
943   ierr = ISGetSize(is,&N); CHKERRQ(ierr);
944   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
945   for ( i=0; i<N; i++ ) {
946     slot = l->v + rows[i];
947     for ( j=0; j<n; j++ ) { *slot = 0.0; slot += n;}
948   }
949   if (diag) {
950     for ( i=0; i<N; i++ ) {
951       slot = l->v + (n+1)*rows[i];
952       *slot = *diag;
953     }
954   }
955   ISRestoreIndices(is,&rows);
956   return 0;
957 }
958 
959 #undef __FUNC__
960 #define __FUNC__ "MatGetSize_SeqDense"
961 int MatGetSize_SeqDense(Mat A,int *m,int *n)
962 {
963   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
964   *m = mat->m; *n = mat->n;
965   return 0;
966 }
967 
968 #undef __FUNC__
969 #define __FUNC__ "MatGetOwnershipRange_SeqDense"
970 int MatGetOwnershipRange_SeqDense(Mat A,int *m,int *n)
971 {
972   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
973   *m = 0; *n = mat->m;
974   return 0;
975 }
976 
977 #undef __FUNC__
978 #define __FUNC__ "MatGetArray_SeqDense"
979 int MatGetArray_SeqDense(Mat A,Scalar **array)
980 {
981   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
982   *array = mat->v;
983   return 0;
984 }
985 
986 #undef __FUNC__
987 #define __FUNC__ "MatRestoreArray_SeqDense"
988 int MatRestoreArray_SeqDense(Mat A,Scalar **array)
989 {
990   return 0;
991 }
992 
993 #undef __FUNC__
994 #define __FUNC__ "MatGetSubMatrix_SeqDense"
995 static int MatGetSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,MatGetSubMatrixCall scall,
996                                     Mat *submat)
997 {
998   Mat_SeqDense *mat = (Mat_SeqDense *) A->data;
999   int          nznew, *smap, i, j, ierr, oldcols = mat->n;
1000   int          *irow, *icol, nrows, ncols, *cwork;
1001   Scalar       *vwork, *val;
1002   Mat          newmat;
1003 
1004   ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr);
1005   ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr);
1006   ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr);
1007   ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr);
1008 
1009   smap = (int *) PetscMalloc(oldcols*sizeof(int)); CHKPTRQ(smap);
1010   cwork = (int *) PetscMalloc(ncols*sizeof(int)); CHKPTRQ(cwork);
1011   vwork = (Scalar *) PetscMalloc(ncols*sizeof(Scalar)); CHKPTRQ(vwork);
1012   PetscMemzero((char*)smap,oldcols*sizeof(int));
1013   for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1;
1014 
1015   /* Create and fill new matrix */
1016   ierr = MatCreateSeqDense(A->comm,nrows,ncols,PETSC_NULL,&newmat); CHKERRQ(ierr);
1017   for (i=0; i<nrows; i++) {
1018     nznew = 0;
1019     val   = mat->v + irow[i];
1020     for (j=0; j<oldcols; j++) {
1021       if (smap[j]) {
1022         cwork[nznew]   = smap[j] - 1;
1023         vwork[nznew++] = val[j * mat->m];
1024       }
1025     }
1026     ierr = MatSetValues(newmat,1,&i,nznew,cwork,vwork,INSERT_VALUES);
1027            CHKERRQ(ierr);
1028   }
1029   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1030   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
1031 
1032   /* Free work space */
1033   PetscFree(smap); PetscFree(cwork); PetscFree(vwork);
1034   ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr);
1035   ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr);
1036   *submat = newmat;
1037   return 0;
1038 }
1039 
1040 #undef __FUNC__
1041 #define __FUNC__ "MatGetSubMatrices_SeqDense"
1042 int MatGetSubMatrices_SeqDense(Mat A,int n, IS *irow,IS *icol,MatGetSubMatrixCall scall,
1043                                     Mat **B)
1044 {
1045   int ierr,i;
1046 
1047   if (scall == MAT_INITIAL_MATRIX) {
1048     *B = (Mat *) PetscMalloc( (n+1)*sizeof(Mat) ); CHKPTRQ(*B);
1049   }
1050 
1051   for ( i=0; i<n; i++ ) {
1052     ierr = MatGetSubMatrix_SeqDense(A,irow[i],icol[i],scall,&(*B)[i]);CHKERRQ(ierr);
1053   }
1054   return 0;
1055 }
1056 
1057 #undef __FUNC__
1058 #define __FUNC__ "MatCopy_SeqDense"
1059 int MatCopy_SeqDense(Mat A, Mat B)
1060 {
1061   Mat_SeqDense *a = (Mat_SeqDense *) A->data, *b = (Mat_SeqDense *)B->data;
1062   if (B->type != MATSEQDENSE) return MatCopy_Basic(A,B);
1063   if (a->m != b->m || a->n != b->n) SETERRQ(PETSC_ERR_ARG_SIZ,0,"size(B) != size(A)");
1064   PetscMemcpy(b->v,a->v,a->m*a->n*sizeof(Scalar));
1065   return 0;
1066 }
1067 
1068 /* -------------------------------------------------------------------*/
1069 static struct _MatOps MatOps = {MatSetValues_SeqDense,
1070        MatGetRow_SeqDense,
1071        MatRestoreRow_SeqDense,
1072        MatMult_SeqDense,
1073        MatMultAdd_SeqDense,
1074        MatMultTrans_SeqDense,
1075        MatMultTransAdd_SeqDense,
1076        MatSolve_SeqDense,
1077        MatSolveAdd_SeqDense,
1078        MatSolveTrans_SeqDense,
1079        MatSolveTransAdd_SeqDense,
1080        MatLUFactor_SeqDense,
1081        MatCholeskyFactor_SeqDense,
1082        MatRelax_SeqDense,
1083        MatTranspose_SeqDense,
1084        MatGetInfo_SeqDense,
1085        MatEqual_SeqDense,
1086        MatGetDiagonal_SeqDense,
1087        MatDiagonalScale_SeqDense,
1088        MatNorm_SeqDense,
1089        0,
1090        0,
1091        0,
1092        MatSetOption_SeqDense,
1093        MatZeroEntries_SeqDense,
1094        MatZeroRows_SeqDense,
1095        MatLUFactorSymbolic_SeqDense,
1096        MatLUFactorNumeric_SeqDense,
1097        MatCholeskyFactorSymbolic_SeqDense,
1098        MatCholeskyFactorNumeric_SeqDense,
1099        MatGetSize_SeqDense,
1100        MatGetSize_SeqDense,
1101        MatGetOwnershipRange_SeqDense,
1102        0,
1103        0,
1104        MatGetArray_SeqDense,
1105        MatRestoreArray_SeqDense,
1106        MatConvertSameType_SeqDense,0,0,0,0,
1107        MatAXPY_SeqDense,MatGetSubMatrices_SeqDense,0,
1108        MatGetValues_SeqDense,
1109        MatCopy_SeqDense,0,MatScale_SeqDense,
1110        0,0,0,MatGetBlockSize_SeqDense};
1111 
1112 #undef __FUNC__
1113 #define __FUNC__ "MatCreateSeqDense"
1114 /*@C
1115    MatCreateSeqDense - Creates a sequential dense matrix that
1116    is stored in column major order (the usual Fortran 77 manner). Many
1117    of the matrix operations use the BLAS and LAPACK routines.
1118 
1119    Input Parameters:
1120 .  comm - MPI communicator, set to PETSC_COMM_SELF
1121 .  m - number of rows
1122 .  n - number of columns
1123 .  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
1124    to control all matrix memory allocation.
1125 
1126    Output Parameter:
1127 .  A - the matrix
1128 
1129   Notes:
1130   The data input variable is intended primarily for Fortran programmers
1131   who wish to allocate their own matrix memory space.  Most users should
1132   set data=PETSC_NULL.
1133 
1134 .keywords: dense, matrix, LAPACK, BLAS
1135 
1136 .seealso: MatCreate(), MatSetValues()
1137 @*/
1138 int MatCreateSeqDense(MPI_Comm comm,int m,int n,Scalar *data,Mat *A)
1139 {
1140   Mat          B;
1141   Mat_SeqDense *b;
1142   int          ierr,flg,size;
1143 
1144   MPI_Comm_size(comm,&size);
1145   if (size > 1) SETERRQ(1,0,"Comm must be of size 1");
1146 
1147   *A            = 0;
1148   PetscHeaderCreate(B,_p_Mat,MAT_COOKIE,MATSEQDENSE,comm);
1149   PLogObjectCreate(B);
1150   b             = (Mat_SeqDense *) PetscMalloc(sizeof(Mat_SeqDense)); CHKPTRQ(b);
1151   PetscMemzero(b,sizeof(Mat_SeqDense));
1152   PetscMemcpy(&B->ops,&MatOps,sizeof(struct _MatOps));
1153   B->destroy    = MatDestroy_SeqDense;
1154   B->view       = MatView_SeqDense;
1155   B->factor     = 0;
1156   B->mapping    = 0;
1157   PLogObjectMemory(B,sizeof(struct _p_Mat));
1158   B->data       = (void *) b;
1159 
1160   b->m = m;  B->m = m; B->M = m;
1161   b->n = n;  B->n = n; B->N = n;
1162   b->pivots       = 0;
1163   b->roworiented  = 1;
1164   if (data == PETSC_NULL) {
1165     b->v = (Scalar*) PetscMalloc((m*n+1)*sizeof(Scalar)); CHKPTRQ(b->v);
1166     PetscMemzero(b->v,m*n*sizeof(Scalar));
1167     b->user_alloc = 0;
1168     PLogObjectMemory(B,n*m*sizeof(Scalar));
1169   }
1170   else { /* user-allocated storage */
1171     b->v = data;
1172     b->user_alloc = 1;
1173   }
1174   ierr = OptionsHasName(PETSC_NULL,"-help",&flg); CHKERRQ(ierr);
1175   if (flg) {ierr = MatPrintHelp(B); CHKERRQ(ierr);}
1176 
1177   *A = B;
1178   return 0;
1179 }
1180 
1181 
1182 
1183 
1184 
1185 
1186