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