xref: /petsc/src/mat/impls/dense/seq/dense.c (revision 0de55854bfaa60ad6b9e2d93a899f4a8e4f316bb)
1 #ifndef lint
2 static char vcid[] = "$Id: dense.c,v 1.55 1995/09/06 22:51:28 curfman Exp curfman $";
3 #endif
4 
5 /*
6     Standard Fortran style matrices
7 */
8 #include "petsc.h"
9 #include "pinclude/plapack.h"
10 #include "matimpl.h"
11 #include "math.h"
12 #include "vec/vecimpl.h"
13 #include "pinclude/pviewer.h"
14 
15 typedef struct {
16   Scalar *v;
17   int    roworiented;
18   int    m,n,pad;
19   int    *pivots;   /* pivots in LU factorization */
20 } Mat_Dense;
21 
22 static int MatGetInfo_Dense(Mat matin,MatInfoType flag,int *nz,
23                             int *nzalloc,int *mem)
24 {
25   Mat_Dense *mat = (Mat_Dense *) matin->data;
26   int    i,N = mat->m*mat->n,count = 0;
27   Scalar *v = mat->v;
28   for ( i=0; i<N; i++ ) {if (*v != 0.0) count++; v++;}
29   *nz = count; *nzalloc = N; *mem = (int)matin->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_Dense(Mat matin,IS row,IS col,double f)
37 {
38   Mat_Dense *mat = (Mat_Dense *) matin->data;
39   int    info;
40   if (!mat->pivots) {
41     mat->pivots = (int *) PETSCMALLOC(mat->m*sizeof(int));
42     CHKPTRQ(mat->pivots);
43     PLogObjectMemory(matin,mat->m*sizeof(int));
44   }
45   LAgetrf_(&mat->m,&mat->n,mat->v,&mat->m,mat->pivots,&info);
46   if (info) SETERRQ(1,"MatLUFactor_Dense: Bad LU factorization");
47   matin->factor = FACTOR_LU;
48   return 0;
49 }
50 static int MatLUFactorSymbolic_Dense(Mat matin,IS row,IS col,double f,
51                                      Mat *fact)
52 {
53   int ierr;
54   ierr = MatConvert(matin,MATSAME,fact); CHKERRQ(ierr);
55   return 0;
56 }
57 static int MatLUFactorNumeric_Dense(Mat matin,Mat *fact)
58 {
59   return MatLUFactor(*fact,0,0,1.0);
60 }
61 static int MatCholeskyFactorSymbolic_Dense(Mat matin,IS row,double f,Mat *fact)
62 {
63   int ierr;
64   ierr = MatConvert(matin,MATSAME,fact); CHKERRQ(ierr);
65   return 0;
66 }
67 static int MatCholeskyFactorNumeric_Dense(Mat matin,Mat *fact)
68 {
69   return MatCholeskyFactor(*fact,0,1.0);
70 }
71 static int MatCholeskyFactor_Dense(Mat matin,IS perm,double f)
72 {
73   Mat_Dense    *mat = (Mat_Dense *) matin->data;
74   int       info;
75   if (mat->pivots) {
76     PETSCFREE(mat->pivots);
77     PLogObjectMemory(matin,-mat->m*sizeof(int));
78     mat->pivots = 0;
79   }
80   LApotrf_("L",&mat->n,mat->v,&mat->m,&info);
81   if (info) SETERRQ(1,"MatCholeskyFactor_Dense: Bad factorization");
82   matin->factor = FACTOR_CHOLESKY;
83   return 0;
84 }
85 
86 static int MatSolve_Dense(Mat matin,Vec xx,Vec yy)
87 {
88   Mat_Dense *mat = (Mat_Dense *) matin->data;
89   int    one = 1, info;
90   Scalar *x, *y;
91   VecGetArray(xx,&x); VecGetArray(yy,&y);
92   PETSCMEMCPY(y,x,mat->m*sizeof(Scalar));
93   if (matin->factor == FACTOR_LU) {
94     LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,
95               y, &mat->m, &info );
96   }
97   else if (matin->factor == FACTOR_CHOLESKY){
98     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
99               y, &mat->m, &info );
100   }
101   else SETERRQ(1,"MatSolve_Dense: Matrix must be factored to solve");
102   if (info) SETERRQ(1,"MatSolve_Dense: Bad solve");
103   return 0;
104 }
105 static int MatSolveTrans_Dense(Mat matin,Vec xx,Vec yy)
106 {
107   Mat_Dense *mat = (Mat_Dense *) matin->data;
108   int    one = 1, info;
109   Scalar *x, *y;
110   VecGetArray(xx,&x); VecGetArray(yy,&y);
111   PETSCMEMCPY(y,x,mat->m*sizeof(Scalar));
112   /* assume if pivots exist then use LU; else Cholesky */
113   if (mat->pivots) {
114     LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,
115               y, &mat->m, &info );
116   }
117   else {
118     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
119               y, &mat->m, &info );
120   }
121   if (info) SETERRQ(1,"MatSolveTrans_Dense: Bad solve");
122   return 0;
123 }
124 static int MatSolveAdd_Dense(Mat matin,Vec xx,Vec zz,Vec yy)
125 {
126   Mat_Dense *mat = (Mat_Dense *) matin->data;
127   int    one = 1, info,ierr;
128   Scalar *x, *y, sone = 1.0;
129   Vec    tmp = 0;
130   VecGetArray(xx,&x); VecGetArray(yy,&y);
131   if (yy == zz) {
132     ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr);
133     PLogObjectParent(matin,tmp);
134     ierr = VecCopy(yy,tmp); CHKERRQ(ierr);
135   }
136   PETSCMEMCPY(y,x,mat->m*sizeof(Scalar));
137   /* assume if pivots exist then use LU; else Cholesky */
138   if (mat->pivots) {
139     LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,
140               y, &mat->m, &info );
141   }
142   else {
143     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
144               y, &mat->m, &info );
145   }
146   if (info) SETERRQ(1,"MatSolveAdd_Dense: Bad solve");
147   if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);}
148   else VecAXPY(&sone,zz,yy);
149   return 0;
150 }
151 static int MatSolveTransAdd_Dense(Mat matin,Vec xx,Vec zz, Vec yy)
152 {
153   Mat_Dense  *mat = (Mat_Dense *) matin->data;
154   int     one = 1, info,ierr;
155   Scalar  *x, *y, sone = 1.0;
156   Vec     tmp;
157   VecGetArray(xx,&x); VecGetArray(yy,&y);
158   if (yy == zz) {
159     ierr = VecDuplicate(yy,&tmp); CHKERRQ(ierr);
160     PLogObjectParent(matin,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,
167               y, &mat->m, &info );
168   }
169   else {
170     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
171               y, &mat->m, &info );
172   }
173   if (info) SETERRQ(1,"MatSolveTransAdd_Dense: Bad solve");
174   if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);}
175   else VecAXPY(&sone,zz,yy);
176   return 0;
177 }
178 /* ------------------------------------------------------------------*/
179 static int MatRelax_Dense(Mat matin,Vec bb,double omega,MatSORType flag,
180                           double shift,int its,Vec xx)
181 {
182   Mat_Dense *mat = (Mat_Dense *) matin->data;
183   Scalar *x, *b, *v = mat->v, zero = 0.0, xt;
184   int    o = 1,ierr, m = mat->m, i;
185 
186   if (flag & SOR_ZERO_INITIAL_GUESS) {
187     /* this is a hack fix, should have another version without
188        the second BLdot */
189     ierr = VecSet(&zero,xx); CHKERRQ(ierr);
190   }
191   VecGetArray(xx,&x); VecGetArray(bb,&b);
192   while (its--) {
193     if (flag & SOR_FORWARD_SWEEP){
194       for ( i=0; i<m; i++ ) {
195 #if defined(PETSC_COMPLEX)
196         /* cannot use BLAS dot for complex because compiler/linker is
197            not happy about returning a double complex */
198         int    _i;
199         Scalar sum = b[i];
200         for ( _i=0; _i<m; _i++ ) {
201           sum -= conj(v[i+_i*m])*x[_i];
202         }
203         xt = sum;
204 #else
205         xt = b[i]-BLdot_(&m,v+i,&m,x,&o);
206 #endif
207         x[i] = (1. - omega)*x[i] + omega*(xt/(v[i + i*m]+shift) + x[i]);
208       }
209     }
210     if (flag & SOR_BACKWARD_SWEEP) {
211       for ( i=m-1; i>=0; i-- ) {
212 #if defined(PETSC_COMPLEX)
213         /* cannot use BLAS dot for complex because compiler/linker is
214            not happy about returning a double complex */
215         int    _i;
216         Scalar sum = b[i];
217         for ( _i=0; _i<m; _i++ ) {
218           sum -= conj(v[i+_i*m])*x[_i];
219         }
220         xt = sum;
221 #else
222         xt = b[i]-BLdot_(&m,v+i,&m,x,&o);
223 #endif
224         x[i] = (1. - omega)*x[i] + omega*(xt/(v[i + i*m]+shift) + x[i]);
225       }
226     }
227   }
228   return 0;
229 }
230 
231 /* -----------------------------------------------------------------*/
232 static int MatMultTrans_Dense(Mat matin,Vec xx,Vec yy)
233 {
234   Mat_Dense *mat = (Mat_Dense *) matin->data;
235   Scalar *v = mat->v, *x, *y;
236   int _One=1;Scalar _DOne=1.0, _DZero=0.0;
237   VecGetArray(xx,&x), VecGetArray(yy,&y);
238   LAgemv_( "T", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
239          x, &_One, &_DZero, y, &_One );
240   return 0;
241 }
242 static int MatMult_Dense(Mat matin,Vec xx,Vec yy)
243 {
244   Mat_Dense *mat = (Mat_Dense *) matin->data;
245   Scalar *v = mat->v, *x, *y;
246   int _One=1;Scalar _DOne=1.0, _DZero=0.0;
247   VecGetArray(xx,&x); VecGetArray(yy,&y);
248   LAgemv_( "N", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
249          x, &_One, &_DZero, y, &_One );
250   return 0;
251 }
252 static int MatMultAdd_Dense(Mat matin,Vec xx,Vec zz,Vec yy)
253 {
254   Mat_Dense *mat = (Mat_Dense *) matin->data;
255   Scalar *v = mat->v, *x, *y, *z;
256   int    _One=1; Scalar _DOne=1.0;
257   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
258   if (zz != yy) PETSCMEMCPY(y,z,mat->m*sizeof(Scalar));
259   LAgemv_( "N", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
260          x, &_One, &_DOne, y, &_One );
261   return 0;
262 }
263 static int MatMultTransAdd_Dense(Mat matin,Vec xx,Vec zz,Vec yy)
264 {
265   Mat_Dense *mat = (Mat_Dense *) matin->data;
266   Scalar *v = mat->v, *x, *y, *z;
267   int    _One=1;
268   Scalar _DOne=1.0;
269   VecGetArray(xx,&x); VecGetArray(yy,&y);
270   VecGetArray(zz,&z);
271   if (zz != yy) PETSCMEMCPY(y,z,mat->m*sizeof(Scalar));
272   LAgemv_( "T", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
273          x, &_One, &_DOne, y, &_One );
274   return 0;
275 }
276 
277 /* -----------------------------------------------------------------*/
278 static int MatGetRow_Dense(Mat matin,int row,int *ncols,int **cols,
279                         Scalar **vals)
280 {
281   Mat_Dense *mat = (Mat_Dense *) matin->data;
282   Scalar *v;
283   int    i;
284   *ncols = mat->n;
285   if (cols) {
286     *cols = (int *) PETSCMALLOC(mat->n*sizeof(int)); CHKPTRQ(*cols);
287     for ( i=0; i<mat->n; i++ ) *cols[i] = i;
288   }
289   if (vals) {
290     *vals = (Scalar *) PETSCMALLOC(mat->n*sizeof(Scalar)); CHKPTRQ(*vals);
291     v = mat->v + row;
292     for ( i=0; i<mat->n; i++ ) {*vals[i] = *v; v += mat->m;}
293   }
294   return 0;
295 }
296 static int MatRestoreRow_Dense(Mat matin,int row,int *ncols,int **cols,
297                             Scalar **vals)
298 {
299   if (cols) { PETSCFREE(*cols); }
300   if (vals) { PETSCFREE(*vals); }
301   return 0;
302 }
303 /* ----------------------------------------------------------------*/
304 static int MatInsert_Dense(Mat matin,int m,int *indexm,int n,
305                         int *indexn,Scalar *v,InsertMode addv)
306 {
307   Mat_Dense *mat = (Mat_Dense *) matin->data;
308   int    i,j;
309 
310   if (!mat->roworiented) {
311     if (addv == INSERTVALUES) {
312       for ( j=0; j<n; j++ ) {
313         for ( i=0; i<m; i++ ) {
314           mat->v[indexn[j]*mat->m + indexm[i]] = *v++;
315         }
316       }
317     }
318     else {
319       for ( j=0; j<n; j++ ) {
320         for ( i=0; i<m; i++ ) {
321           mat->v[indexn[j]*mat->m + indexm[i]] += *v++;
322         }
323       }
324     }
325   }
326   else {
327     if (addv == INSERTVALUES) {
328       for ( i=0; i<m; i++ ) {
329         for ( j=0; j<n; j++ ) {
330           mat->v[indexn[j]*mat->m + indexm[i]] = *v++;
331         }
332       }
333     }
334     else {
335       for ( i=0; i<m; i++ ) {
336         for ( j=0; j<n; j++ ) {
337           mat->v[indexn[j]*mat->m + indexm[i]] += *v++;
338         }
339       }
340     }
341   }
342   return 0;
343 }
344 
345 /* -----------------------------------------------------------------*/
346 static int MatCopyPrivate_Dense(Mat matin,Mat *newmat)
347 {
348   Mat_Dense *mat = (Mat_Dense *) matin->data;
349   int ierr;
350   Mat newi;
351   Mat_Dense *l;
352   ierr = MatCreateSequentialDense(matin->comm,mat->m,mat->n,&newi);
353   CHKERRQ(ierr);
354   l = (Mat_Dense *) newi->data;
355   PETSCMEMCPY(l->v,mat->v,mat->m*mat->n*sizeof(Scalar));
356   *newmat = newi;
357   return 0;
358 }
359 #include "viewer.h"
360 
361 int MatView_Dense(PetscObject obj,Viewer ptr)
362 {
363   Mat         matin = (Mat) obj;
364   Mat_Dense   *mat = (Mat_Dense *) matin->data;
365   Scalar      *v;
366   int         i,j,ierr;
367   PetscObject vobj = (PetscObject) ptr;
368 
369   if (ptr == 0) {
370     ptr = STDOUT_VIEWER_SELF; vobj = (PetscObject) ptr;
371   }
372   if (vobj->cookie == VIEWER_COOKIE && vobj->type == MATLAB_VIEWER) {
373     return ViewerMatlabPutArray_Private(ptr,mat->m,mat->n,mat->v);
374   }
375   else {
376     FILE *fd;
377     int format;
378     ierr = ViewerFileGetPointer_Private(ptr,&fd); CHKERRQ(ierr);
379     ierr = ViewerFileGetFormat_Private(ptr,&format); CHKERRQ(ierr);
380     if (format == FILE_FORMAT_INFO) {
381       /* do nothing for now */
382     }
383     else {
384       for ( i=0; i<mat->m; i++ ) {
385         v = mat->v + i;
386         for ( j=0; j<mat->n; j++ ) {
387 #if defined(PETSC_COMPLEX)
388           fprintf(fd,"%6.4e + %6.4e i ",real(*v),imag(*v)); v += mat->m;
389 #else
390           fprintf(fd,"%6.4e ",*v); v += mat->m;
391 #endif
392         }
393         fprintf(fd,"\n");
394       }
395     }
396   }
397   return 0;
398 }
399 
400 
401 static int MatDestroy_Dense(PetscObject obj)
402 {
403   Mat    mat = (Mat) obj;
404   Mat_Dense *l = (Mat_Dense *) mat->data;
405 #if defined(PETSC_LOG)
406   PLogObjectState(obj,"Rows %d Cols %d",l->m,l->n);
407 #endif
408   if (l->pivots) PETSCFREE(l->pivots);
409   PETSCFREE(l);
410   PLogObjectDestroy(mat);
411   PETSCHEADERDESTROY(mat);
412   return 0;
413 }
414 
415 static int MatTranspose_Dense(Mat matin,Mat *matout)
416 {
417   Mat_Dense *mat = (Mat_Dense *) matin->data;
418   int       k, j, m, n;
419   Scalar    *v, tmp;
420 
421   v = mat->v; m = mat->m; n = mat->n;
422   if (!matout) { /* in place transpose */
423     if (m != n) SETERRQ(1,
424       "MatTranspose_Dense: Cannot transpose rectangular matrix in place");
425     for ( j=0; j<m; j++ ) {
426       for ( k=0; k<j; k++ ) {
427         tmp = v[j + k*n];
428         v[j + k*n] = v[k + j*n];
429         v[k + j*n] = tmp;
430       }
431     }
432   }
433   else { /* out-of-place transpose */
434     int ierr;
435     Mat tmat;
436     Mat_Dense *tmatd;
437     Scalar *v2;
438     ierr = MatCreateSequentialDense(matin->comm,mat->n,mat->m,&tmat); CHKERRQ(ierr);
439     tmatd = (Mat_Dense *) tmat->data;
440     v = mat->v; v2 = tmatd->v;
441     for ( j=0; j<n; j++ ) {
442       for ( k=0; k<m; k++ ) v2[j + k*n] = v[k + j*m];
443     }
444     ierr = MatAssemblyBegin(tmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
445     ierr = MatAssemblyEnd(tmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
446     *matout = tmat;
447   }
448   return 0;
449 }
450 
451 static int MatEqual_Dense(Mat matin1,Mat matin2)
452 {
453   Mat_Dense *mat1 = (Mat_Dense *) matin1->data;
454   Mat_Dense *mat2 = (Mat_Dense *) matin2->data;
455   int    i;
456   Scalar *v1 = mat1->v, *v2 = mat2->v;
457   if (mat1->m != mat2->m) return 0;
458   if (mat1->n != mat2->n) return 0;
459   for ( i=0; i<mat1->m*mat1->n; i++ ) {
460     if (*v1 != *v2) return 0;
461     v1++; v2++;
462   }
463   return 1;
464 }
465 
466 static int MatGetDiagonal_Dense(Mat matin,Vec v)
467 {
468   Mat_Dense *mat = (Mat_Dense *) matin->data;
469   int       i, n;
470   Scalar    *x;
471   VecGetArray(v,&x); VecGetSize(v,&n);
472   if (n != mat->m) SETERRQ(1,"MatGetDiagonal_Dense:Nonconforming mat and vec");
473   for ( i=0; i<mat->m; i++ ) {
474     x[i] = mat->v[i*mat->m + i];
475   }
476   return 0;
477 }
478 
479 static int MatScale_Dense(Mat matin,Vec ll,Vec rr)
480 {
481   Mat_Dense *mat = (Mat_Dense *) matin->data;
482   Scalar *l,*r,x,*v;
483   int    i,j,m = mat->m, n = mat->n;
484   if (ll) {
485     VecGetArray(ll,&l); VecGetSize(ll,&m);
486     if (m != mat->m) SETERRQ(1,"MatScale_Dense:Left scaling vec wrong size");
487     for ( i=0; i<m; i++ ) {
488       x = l[i];
489       v = mat->v + i;
490       for ( j=0; j<n; j++ ) { (*v) *= x; v+= m;}
491     }
492   }
493   if (rr) {
494     VecGetArray(rr,&r); VecGetSize(rr,&n);
495     if (n != mat->n) SETERRQ(1,"MatScale_Dense:Right scaling vec wrong size");
496     for ( i=0; i<n; i++ ) {
497       x = r[i];
498       v = mat->v + i*m;
499       for ( j=0; j<m; j++ ) { (*v++) *= x;}
500     }
501   }
502   return 0;
503 }
504 
505 static int MatNorm_Dense(Mat matin,MatNormType type,double *norm)
506 {
507   Mat_Dense *mat = (Mat_Dense *) matin->data;
508   Scalar *v = mat->v;
509   double sum = 0.0;
510   int    i, j;
511   if (type == NORM_FROBENIUS) {
512     for (i=0; i<mat->n*mat->m; i++ ) {
513 #if defined(PETSC_COMPLEX)
514       sum += real(conj(*v)*(*v)); v++;
515 #else
516       sum += (*v)*(*v); v++;
517 #endif
518     }
519     *norm = sqrt(sum);
520   }
521   else if (type == NORM_1) {
522     *norm = 0.0;
523     for ( j=0; j<mat->n; j++ ) {
524       sum = 0.0;
525       for ( i=0; i<mat->m; i++ ) {
526 #if defined(PETSC_COMPLEX)
527         sum += abs(*v++);
528 #else
529         sum += fabs(*v++);
530 #endif
531       }
532       if (sum > *norm) *norm = sum;
533     }
534   }
535   else if (type == NORM_INFINITY) {
536     *norm = 0.0;
537     for ( j=0; j<mat->m; j++ ) {
538       v = mat->v + j;
539       sum = 0.0;
540       for ( i=0; i<mat->n; i++ ) {
541 #if defined(PETSC_COMPLEX)
542         sum += abs(*v); v += mat->m;
543 #else
544         sum += fabs(*v); v += mat->m;
545 #endif
546       }
547       if (sum > *norm) *norm = sum;
548     }
549   }
550   else {
551     SETERRQ(1,"MatNorm_Dense:No two norm yet");
552   }
553   return 0;
554 }
555 
556 static int MatSetOption_Dense(Mat aijin,MatOption op)
557 {
558   Mat_Dense *aij = (Mat_Dense *) aijin->data;
559   if (op == ROW_ORIENTED)            aij->roworiented = 1;
560   else if (op == COLUMN_ORIENTED)    aij->roworiented = 0;
561   /* doesn't care about sorted rows or columns */
562   return 0;
563 }
564 
565 static int MatZeroEntries_Dense(Mat A)
566 {
567   Mat_Dense *l = (Mat_Dense *) A->data;
568   PETSCMEMSET(l->v,0,l->m*l->n*sizeof(Scalar));
569   return 0;
570 }
571 
572 static int MatZeroRows_Dense(Mat A,IS is,Scalar *diag)
573 {
574   Mat_Dense *l = (Mat_Dense *) A->data;
575   int    n = l->n, i, j,ierr,N, *rows;
576   Scalar *slot;
577   ierr = ISGetLocalSize(is,&N); CHKERRQ(ierr);
578   ierr = ISGetIndices(is,&rows); CHKERRQ(ierr);
579   for ( i=0; i<N; i++ ) {
580     slot = l->v + rows[i];
581     for ( j=0; j<n; j++ ) { *slot = 0.0; slot += n;}
582   }
583   if (diag) {
584     for ( i=0; i<N; i++ ) {
585       slot = l->v + (n+1)*rows[i];
586       *slot = *diag;
587     }
588   }
589   ISRestoreIndices(is,&rows);
590   return 0;
591 }
592 
593 static int MatGetSize_Dense(Mat matin,int *m,int *n)
594 {
595   Mat_Dense *mat = (Mat_Dense *) matin->data;
596   *m = mat->m; *n = mat->n;
597   return 0;
598 }
599 
600 static int MatGetOwnershipRange_Dense(Mat matin,int *m,int *n)
601 {
602   Mat_Dense *mat = (Mat_Dense *) matin->data;
603   *m = 0; *n = mat->m;
604   return 0;
605 }
606 
607 static int MatGetArray_Dense(Mat matin,Scalar **array)
608 {
609   Mat_Dense *mat = (Mat_Dense *) matin->data;
610   *array = mat->v;
611   return 0;
612 }
613 
614 
615 static int MatGetSubMatrixInPlace_Dense(Mat matin,IS isrow,IS iscol)
616 {
617   SETERRQ(1,"MatGetSubMatrixInPlace_Dense: not done");
618 }
619 
620 static int MatGetSubMatrix_Dense(Mat matin,IS isrow,IS iscol,Mat *submat)
621 {
622   Mat_Dense *mat = (Mat_Dense *) matin->data;
623   int     nznew, *smap, i, j, ierr, oldcols = mat->n;
624   int     *irow, *icol, nrows, ncols, *cwork;
625   Scalar  *vwork, *val;
626   Mat     newmat;
627 
628   ierr = ISGetIndices(isrow,&irow); CHKERRQ(ierr);
629   ierr = ISGetIndices(iscol,&icol); CHKERRQ(ierr);
630   ierr = ISGetSize(isrow,&nrows); CHKERRQ(ierr);
631   ierr = ISGetSize(iscol,&ncols); CHKERRQ(ierr);
632 
633   smap = (int *) PETSCMALLOC(oldcols*sizeof(int)); CHKPTRQ(smap);
634   cwork = (int *) PETSCMALLOC(ncols*sizeof(int)); CHKPTRQ(cwork);
635   vwork = (Scalar *) PETSCMALLOC(ncols*sizeof(Scalar)); CHKPTRQ(vwork);
636   PETSCMEMSET((char*)smap,0,oldcols*sizeof(int));
637   for ( i=0; i<ncols; i++ ) smap[icol[i]] = i+1;
638 
639   /* Create and fill new matrix */
640   ierr = MatCreateSequentialDense(matin->comm,nrows,ncols,&newmat);
641          CHKERRQ(ierr);
642   for (i=0; i<nrows; i++) {
643     nznew = 0;
644     val   = mat->v + irow[i];
645     for (j=0; j<oldcols; j++) {
646       if (smap[j]) {
647         cwork[nznew]   = smap[j] - 1;
648         vwork[nznew++] = val[j * mat->m];
649       }
650     }
651     ierr = MatSetValues(newmat,1,&i,nznew,cwork,vwork,INSERTVALUES);
652            CHKERRQ(ierr);
653   }
654   ierr = MatAssemblyBegin(newmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
655   ierr = MatAssemblyEnd(newmat,FINAL_ASSEMBLY); CHKERRQ(ierr);
656 
657   /* Free work space */
658   PETSCFREE(smap); PETSCFREE(cwork); PETSCFREE(vwork);
659   ierr = ISRestoreIndices(isrow,&irow); CHKERRQ(ierr);
660   ierr = ISRestoreIndices(iscol,&icol); CHKERRQ(ierr);
661   *submat = newmat;
662   return 0;
663 }
664 
665 /* -------------------------------------------------------------------*/
666 static struct _MatOps MatOps = {MatInsert_Dense,
667        MatGetRow_Dense, MatRestoreRow_Dense,
668        MatMult_Dense, MatMultAdd_Dense,
669        MatMultTrans_Dense, MatMultTransAdd_Dense,
670        MatSolve_Dense,MatSolveAdd_Dense,
671        MatSolveTrans_Dense,MatSolveTransAdd_Dense,
672        MatLUFactor_Dense,MatCholeskyFactor_Dense,
673        MatRelax_Dense,
674        MatTranspose_Dense,
675        MatGetInfo_Dense,MatEqual_Dense,
676        MatGetDiagonal_Dense,MatScale_Dense,MatNorm_Dense,
677        0,0,
678        0, MatSetOption_Dense,MatZeroEntries_Dense,MatZeroRows_Dense,0,
679        MatLUFactorSymbolic_Dense,MatLUFactorNumeric_Dense,
680        MatCholeskyFactorSymbolic_Dense,MatCholeskyFactorNumeric_Dense,
681        MatGetSize_Dense,MatGetSize_Dense,MatGetOwnershipRange_Dense,
682        0,0,MatGetArray_Dense,0,0,
683        MatGetSubMatrix_Dense,MatGetSubMatrixInPlace_Dense,
684        MatCopyPrivate_Dense};
685 
686 /*@C
687    MatCreateSequentialDense - Creates a sequential dense matrix that
688    is stored in column major order (the usual Fortran 77 manner). Many
689    of the matrix operations use the BLAS and LAPACK routines.
690 
691    Input Parameters:
692 .  comm - MPI communicator, set to MPI_COMM_SELF
693 .  m - number of rows
694 .  n - number of column
695 
696    Output Parameter:
697 .  newmat - the matrix
698 
699 .keywords: dense, matrix, LAPACK, BLAS
700 
701 .seealso: MatCreate(), MatSetValues()
702 @*/
703 int MatCreateSequentialDense(MPI_Comm comm,int m,int n,Mat *newmat)
704 {
705   int       size = sizeof(Mat_Dense) + m*n*sizeof(Scalar);
706   Mat mat;
707   Mat_Dense    *l;
708   *newmat        = 0;
709   PETSCHEADERCREATE(mat,_Mat,MAT_COOKIE,MATDENSE,comm);
710   PLogObjectCreate(mat);
711   l              = (Mat_Dense *) PETSCMALLOC(size); CHKPTRQ(l);
712   mat->ops       = &MatOps;
713   mat->destroy   = MatDestroy_Dense;
714   mat->view      = MatView_Dense;
715   mat->data      = (void *) l;
716   mat->factor    = 0;
717   PLogObjectMemory(mat,sizeof(struct _Mat) + size);
718 
719   l->m           = m;
720   l->n           = n;
721   l->v           = (Scalar *) (l + 1);
722   l->pivots      = 0;
723   l->roworiented = 1;
724 
725   PETSCMEMSET(l->v,0,m*n*sizeof(Scalar));
726   *newmat = mat;
727   return 0;
728 }
729 
730 int MatCreate_Dense(Mat matin,Mat *newmat)
731 {
732   Mat_Dense *m = (Mat_Dense *) matin->data;
733   return MatCreateSequentialDense(matin->comm,m->m,m->n,newmat);
734 }
735