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