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