xref: /petsc/src/mat/impls/dense/seq/dense.c (revision efee365b5c5892804fae87af7964fc14342744e2)
1 /*
2      Defines the basic matrix operations for sequential dense.
3 */
4 
5 #include "src/mat/impls/dense/seq/dense.h"
6 #include "petscblaslapack.h"
7 
8 #undef __FUNCT__
9 #define __FUNCT__ "MatAXPY_SeqDense"
10 PetscErrorCode MatAXPY_SeqDense(const PetscScalar *alpha,Mat X,Mat Y,MatStructure str)
11 {
12   Mat_SeqDense *x = (Mat_SeqDense*)X->data,*y = (Mat_SeqDense*)Y->data;
13   PetscInt     j;
14   PetscBLASInt N = (PetscBLASInt)X->m*X->n,m=(PetscBLASInt)X->m,ldax = x->lda,lday=y->lda,one = 1;
15   PetscErrorCode ierr;
16 
17   PetscFunctionBegin;
18   if (X->m != Y->m || X->n != Y->n) SETERRQ(PETSC_ERR_ARG_SIZ,"size(B) != size(A)");
19   if (ldax>m || lday>m) {
20     for (j=0; j<X->n; j++) {
21       BLASaxpy_(&m,(PetscScalar*)alpha,x->v+j*ldax,&one,y->v+j*lday,&one);
22     }
23   } else {
24     BLASaxpy_(&N,(PetscScalar*)alpha,x->v,&one,y->v,&one);
25   }
26   ierr = PetscLogFlops(2*N-1);CHKERRQ(ierr);
27   PetscFunctionReturn(0);
28 }
29 
30 #undef __FUNCT__
31 #define __FUNCT__ "MatGetInfo_SeqDense"
32 PetscErrorCode MatGetInfo_SeqDense(Mat A,MatInfoType flag,MatInfo *info)
33 {
34   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
35   PetscInt     i,N = A->m*A->n,count = 0;
36   PetscScalar  *v = a->v;
37 
38   PetscFunctionBegin;
39   for (i=0; i<N; i++) {if (*v != 0.0) count++; v++;}
40 
41   info->rows_global       = (double)A->m;
42   info->columns_global    = (double)A->n;
43   info->rows_local        = (double)A->m;
44   info->columns_local     = (double)A->n;
45   info->block_size        = 1.0;
46   info->nz_allocated      = (double)N;
47   info->nz_used           = (double)count;
48   info->nz_unneeded       = (double)(N-count);
49   info->assemblies        = (double)A->num_ass;
50   info->mallocs           = 0;
51   info->memory            = A->mem;
52   info->fill_ratio_given  = 0;
53   info->fill_ratio_needed = 0;
54   info->factor_mallocs    = 0;
55 
56   PetscFunctionReturn(0);
57 }
58 
59 #undef __FUNCT__
60 #define __FUNCT__ "MatScale_SeqDense"
61 PetscErrorCode MatScale_SeqDense(const PetscScalar *alpha,Mat A)
62 {
63   Mat_SeqDense *a = (Mat_SeqDense*)A->data;
64   PetscBLASInt one = 1,lda = a->lda,j,nz;
65   PetscErrorCode ierr;
66 
67   PetscFunctionBegin;
68   if (lda>A->m) {
69     nz = (PetscBLASInt)A->m;
70     for (j=0; j<A->n; j++) {
71       BLASscal_(&nz,(PetscScalar*)alpha,a->v+j*lda,&one);
72     }
73   } else {
74     nz = (PetscBLASInt)A->m*A->n;
75     BLASscal_(&nz,(PetscScalar*)alpha,a->v,&one);
76   }
77   ierr = PetscLogFlops(nz);CHKERRQ(ierr);
78   PetscFunctionReturn(0);
79 }
80 
81 /* ---------------------------------------------------------------*/
82 /* COMMENT: I have chosen to hide row permutation in the pivots,
83    rather than put it in the Mat->row slot.*/
84 #undef __FUNCT__
85 #define __FUNCT__ "MatLUFactor_SeqDense"
86 PetscErrorCode MatLUFactor_SeqDense(Mat A,IS row,IS col,MatFactorInfo *minfo)
87 {
88 #if defined(PETSC_MISSING_LAPACK_GETRF)
89   PetscFunctionBegin;
90   SETERRQ(PETSC_ERR_SUP,"GETRF - Lapack routine is unavailable.");
91 #else
92   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
93   PetscErrorCode ierr;
94   PetscBLASInt   n = (PetscBLASInt)A->n,m = (PetscBLASInt)A->m,info;
95 
96   PetscFunctionBegin;
97   if (!mat->pivots) {
98     ierr = PetscMalloc((A->m+1)*sizeof(PetscBLASInt),&mat->pivots);CHKERRQ(ierr);
99     ierr = PetscLogObjectMemory(A,A->m*sizeof(PetscBLASInt));CHKERRQ(ierr);
100   }
101   A->factor = FACTOR_LU;
102   if (!A->m || !A->n) PetscFunctionReturn(0);
103   LAPACKgetrf_(&m,&n,mat->v,&mat->lda,mat->pivots,&info);
104   if (info<0) SETERRQ(PETSC_ERR_LIB,"Bad argument to LU factorization");
105   if (info>0) SETERRQ(PETSC_ERR_MAT_LU_ZRPVT,"Bad LU factorization");
106   ierr = PetscLogFlops((2*A->n*A->n*A->n)/3);CHKERRQ(ierr);
107 #endif
108   PetscFunctionReturn(0);
109 }
110 
111 #undef __FUNCT__
112 #define __FUNCT__ "MatDuplicate_SeqDense"
113 PetscErrorCode MatDuplicate_SeqDense(Mat A,MatDuplicateOption cpvalues,Mat *newmat)
114 {
115   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data,*l;
116   PetscErrorCode ierr;
117   PetscInt       lda = (PetscInt)mat->lda,j,m;
118   Mat            newi;
119 
120   PetscFunctionBegin;
121   ierr = MatCreate(A->comm,A->m,A->n,A->m,A->n,&newi);CHKERRQ(ierr);
122   ierr = MatSetType(newi,A->type_name);CHKERRQ(ierr);
123   ierr = MatSeqDenseSetPreallocation(newi,PETSC_NULL);CHKERRQ(ierr);
124   if (cpvalues == MAT_COPY_VALUES) {
125     l = (Mat_SeqDense*)newi->data;
126     if (lda>A->m) {
127       m = A->m;
128       for (j=0; j<A->n; j++) {
129 	ierr = PetscMemcpy(l->v+j*m,mat->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr);
130       }
131     } else {
132       ierr = PetscMemcpy(l->v,mat->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr);
133     }
134   }
135   newi->assembled = PETSC_TRUE;
136   *newmat = newi;
137   PetscFunctionReturn(0);
138 }
139 
140 #undef __FUNCT__
141 #define __FUNCT__ "MatLUFactorSymbolic_SeqDense"
142 PetscErrorCode MatLUFactorSymbolic_SeqDense(Mat A,IS row,IS col,MatFactorInfo *info,Mat *fact)
143 {
144   PetscErrorCode ierr;
145 
146   PetscFunctionBegin;
147   ierr = MatDuplicate_SeqDense(A,MAT_DO_NOT_COPY_VALUES,fact);CHKERRQ(ierr);
148   PetscFunctionReturn(0);
149 }
150 
151 #undef __FUNCT__
152 #define __FUNCT__ "MatLUFactorNumeric_SeqDense"
153 PetscErrorCode MatLUFactorNumeric_SeqDense(Mat A,MatFactorInfo *info_dummy,Mat *fact)
154 {
155   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data,*l = (Mat_SeqDense*)(*fact)->data;
156   PetscErrorCode ierr;
157   PetscInt       lda1=mat->lda,lda2=l->lda, m=A->m,n=A->n, j;
158   MatFactorInfo  info;
159 
160   PetscFunctionBegin;
161   /* copy the numerical values */
162   if (lda1>m || lda2>m ) {
163     for (j=0; j<n; j++) {
164       ierr = PetscMemcpy(l->v+j*lda2,mat->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr);
165     }
166   } else {
167     ierr = PetscMemcpy(l->v,mat->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr);
168   }
169   (*fact)->factor = 0;
170   ierr = MatLUFactor(*fact,0,0,&info);CHKERRQ(ierr);
171   PetscFunctionReturn(0);
172 }
173 
174 #undef __FUNCT__
175 #define __FUNCT__ "MatCholeskyFactorSymbolic_SeqDense"
176 PetscErrorCode MatCholeskyFactorSymbolic_SeqDense(Mat A,IS row,MatFactorInfo *info,Mat *fact)
177 {
178   PetscErrorCode ierr;
179 
180   PetscFunctionBegin;
181   ierr = MatConvert(A,MATSAME,MAT_INITIAL_MATRIX,fact);CHKERRQ(ierr);
182   PetscFunctionReturn(0);
183 }
184 
185 #undef __FUNCT__
186 #define __FUNCT__ "MatCholeskyFactor_SeqDense"
187 PetscErrorCode MatCholeskyFactor_SeqDense(Mat A,IS perm,MatFactorInfo *factinfo)
188 {
189 #if defined(PETSC_MISSING_LAPACK_POTRF)
190   PetscFunctionBegin;
191   SETERRQ(PETSC_ERR_SUP,"POTRF - Lapack routine is unavailable.");
192 #else
193   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
194   PetscErrorCode ierr;
195   PetscBLASInt   n = (PetscBLASInt)A->n,info;
196 
197   PetscFunctionBegin;
198   if (mat->pivots) {
199     ierr = PetscFree(mat->pivots);CHKERRQ(ierr);
200     ierr = PetscLogObjectMemory(A,-A->m*sizeof(PetscInt));CHKERRQ(ierr);
201     mat->pivots = 0;
202   }
203   if (!A->m || !A->n) PetscFunctionReturn(0);
204   LAPACKpotrf_("L",&n,mat->v,&mat->lda,&info);
205   if (info) SETERRQ1(PETSC_ERR_MAT_CH_ZRPVT,"Bad factorization: zero pivot in row %D",(PetscInt)info-1);
206   A->factor = FACTOR_CHOLESKY;
207   ierr = PetscLogFlops((A->n*A->n*A->n)/3);CHKERRQ(ierr);
208 #endif
209   PetscFunctionReturn(0);
210 }
211 
212 #undef __FUNCT__
213 #define __FUNCT__ "MatCholeskyFactorNumeric_SeqDense"
214 PetscErrorCode MatCholeskyFactorNumeric_SeqDense(Mat A,MatFactorInfo *info_dummy,Mat *fact)
215 {
216   PetscErrorCode ierr;
217   MatFactorInfo  info;
218 
219   PetscFunctionBegin;
220   info.fill = 1.0;
221   ierr = MatCholeskyFactor_SeqDense(*fact,0,&info);CHKERRQ(ierr);
222   PetscFunctionReturn(0);
223 }
224 
225 #undef __FUNCT__
226 #define __FUNCT__ "MatSolve_SeqDense"
227 PetscErrorCode MatSolve_SeqDense(Mat A,Vec xx,Vec yy)
228 {
229   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
230   PetscErrorCode ierr;
231   PetscBLASInt   m = (PetscBLASInt)A->m, one = 1,info;
232   PetscScalar    *x,*y;
233 
234   PetscFunctionBegin;
235   if (!A->m || !A->n) PetscFunctionReturn(0);
236   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
237   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
238   ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr);
239   if (A->factor == FACTOR_LU) {
240 #if defined(PETSC_MISSING_LAPACK_GETRS)
241     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
242 #else
243     LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
244     if (info) SETERRQ(PETSC_ERR_LIB,"GETRS - Bad solve");
245 #endif
246   } else if (A->factor == FACTOR_CHOLESKY){
247 #if defined(PETSC_MISSING_LAPACK_POTRS)
248     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
249 #else
250     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
251     if (info) SETERRQ(PETSC_ERR_LIB,"POTRS Bad solve");
252 #endif
253   }
254   else SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Matrix must be factored to solve");
255   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
256   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
257   ierr = PetscLogFlops(2*A->n*A->n - A->n);CHKERRQ(ierr);
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "MatSolveTranspose_SeqDense"
263 PetscErrorCode MatSolveTranspose_SeqDense(Mat A,Vec xx,Vec yy)
264 {
265   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
266   PetscErrorCode ierr;
267   PetscBLASInt   m = (PetscBLASInt) A->m,one = 1,info;
268   PetscScalar    *x,*y;
269 
270   PetscFunctionBegin;
271   if (!A->m || !A->n) PetscFunctionReturn(0);
272   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
273   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
274   ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr);
275   /* assume if pivots exist then use LU; else Cholesky */
276   if (mat->pivots) {
277 #if defined(PETSC_MISSING_LAPACK_GETRS)
278     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
279 #else
280     LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
281     if (info) SETERRQ(PETSC_ERR_LIB,"POTRS - Bad solve");
282 #endif
283   } else {
284 #if defined(PETSC_MISSING_LAPACK_POTRS)
285     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
286 #else
287     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
288     if (info) SETERRQ(PETSC_ERR_LIB,"POTRS - Bad solve");
289 #endif
290   }
291   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
292   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
293   ierr = PetscLogFlops(2*A->n*A->n - A->n);CHKERRQ(ierr);
294   PetscFunctionReturn(0);
295 }
296 
297 #undef __FUNCT__
298 #define __FUNCT__ "MatSolveAdd_SeqDense"
299 PetscErrorCode MatSolveAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
300 {
301   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
302   PetscErrorCode ierr;
303   PetscBLASInt   m = (PetscBLASInt)A->m,one = 1,info;
304   PetscScalar    *x,*y,sone = 1.0;
305   Vec            tmp = 0;
306 
307   PetscFunctionBegin;
308   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
309   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
310   if (!A->m || !A->n) PetscFunctionReturn(0);
311   if (yy == zz) {
312     ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr);
313     ierr = PetscLogObjectParent(A,tmp);CHKERRQ(ierr);
314     ierr = VecCopy(yy,tmp);CHKERRQ(ierr);
315   }
316   ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr);
317   /* assume if pivots exist then use LU; else Cholesky */
318   if (mat->pivots) {
319 #if defined(PETSC_MISSING_LAPACK_GETRS)
320     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
321 #else
322     LAPACKgetrs_("N",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
323     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
324 #endif
325   } else {
326 #if defined(PETSC_MISSING_LAPACK_POTRS)
327     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
328 #else
329     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
330     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
331 #endif
332   }
333   if (tmp) {ierr = VecAXPY(&sone,tmp,yy);CHKERRQ(ierr); ierr = VecDestroy(tmp);CHKERRQ(ierr);}
334   else     {ierr = VecAXPY(&sone,zz,yy);CHKERRQ(ierr);}
335   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
336   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
337   ierr = PetscLogFlops(2*A->n*A->n);CHKERRQ(ierr);
338   PetscFunctionReturn(0);
339 }
340 
341 #undef __FUNCT__
342 #define __FUNCT__ "MatSolveTransposeAdd_SeqDense"
343 PetscErrorCode MatSolveTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
344 {
345   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
346   PetscErrorCode ierr;
347   PetscBLASInt   m = (PetscBLASInt)A->m,one = 1,info;
348   PetscScalar    *x,*y,sone = 1.0;
349   Vec            tmp;
350 
351   PetscFunctionBegin;
352   if (!A->m || !A->n) PetscFunctionReturn(0);
353   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
354   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
355   if (yy == zz) {
356     ierr = VecDuplicate(yy,&tmp);CHKERRQ(ierr);
357     ierr = PetscLogObjectParent(A,tmp);CHKERRQ(ierr);
358     ierr = VecCopy(yy,tmp);CHKERRQ(ierr);
359   }
360   ierr = PetscMemcpy(y,x,A->m*sizeof(PetscScalar));CHKERRQ(ierr);
361   /* assume if pivots exist then use LU; else Cholesky */
362   if (mat->pivots) {
363 #if defined(PETSC_MISSING_LAPACK_GETRS)
364     SETERRQ(PETSC_ERR_SUP,"GETRS - Lapack routine is unavailable.");
365 #else
366     LAPACKgetrs_("T",&m,&one,mat->v,&mat->lda,mat->pivots,y,&m,&info);
367     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
368 #endif
369   } else {
370 #if defined(PETSC_MISSING_LAPACK_POTRS)
371     SETERRQ(PETSC_ERR_SUP,"POTRS - Lapack routine is unavailable.");
372 #else
373     LAPACKpotrs_("L",&m,&one,mat->v,&mat->lda,y,&m,&info);
374     if (info) SETERRQ(PETSC_ERR_LIB,"Bad solve");
375 #endif
376   }
377   if (tmp) {
378     ierr = VecAXPY(&sone,tmp,yy);CHKERRQ(ierr);
379     ierr = VecDestroy(tmp);CHKERRQ(ierr);
380   } else {
381     ierr = VecAXPY(&sone,zz,yy);CHKERRQ(ierr);
382   }
383   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
384   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
385   ierr = PetscLogFlops(2*A->n*A->n);CHKERRQ(ierr);
386   PetscFunctionReturn(0);
387 }
388 /* ------------------------------------------------------------------*/
389 #undef __FUNCT__
390 #define __FUNCT__ "MatRelax_SeqDense"
391 PetscErrorCode MatRelax_SeqDense(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal shift,PetscInt its,PetscInt lits,Vec xx)
392 {
393   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
394   PetscScalar    *x,*b,*v = mat->v,zero = 0.0,xt;
395   PetscErrorCode ierr;
396   PetscInt       m = A->m,i;
397 #if !defined(PETSC_USE_COMPLEX)
398   PetscBLASInt   bm = (PetscBLASInt)m, o = 1;
399 #endif
400 
401   PetscFunctionBegin;
402   if (flag & SOR_ZERO_INITIAL_GUESS) {
403     /* this is a hack fix, should have another version without the second BLASdot */
404     ierr = VecSet(&zero,xx);CHKERRQ(ierr);
405   }
406   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
407   ierr = VecGetArray(bb,&b);CHKERRQ(ierr);
408   its  = its*lits;
409   if (its <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %D and local its %D both positive",its,lits);
410   while (its--) {
411     if (flag & SOR_FORWARD_SWEEP){
412       for (i=0; i<m; i++) {
413 #if defined(PETSC_USE_COMPLEX)
414         /* cannot use BLAS dot for complex because compiler/linker is
415            not happy about returning a double complex */
416         PetscInt         _i;
417         PetscScalar sum = b[i];
418         for (_i=0; _i<m; _i++) {
419           sum -= PetscConj(v[i+_i*m])*x[_i];
420         }
421         xt = sum;
422 #else
423         xt = b[i] - BLASdot_(&bm,v+i,&bm,x,&o);
424 #endif
425         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
426       }
427     }
428     if (flag & SOR_BACKWARD_SWEEP) {
429       for (i=m-1; i>=0; i--) {
430 #if defined(PETSC_USE_COMPLEX)
431         /* cannot use BLAS dot for complex because compiler/linker is
432            not happy about returning a double complex */
433         PetscInt         _i;
434         PetscScalar sum = b[i];
435         for (_i=0; _i<m; _i++) {
436           sum -= PetscConj(v[i+_i*m])*x[_i];
437         }
438         xt = sum;
439 #else
440         xt = b[i] - BLASdot_(&bm,v+i,&bm,x,&o);
441 #endif
442         x[i] = (1. - omega)*x[i] + omega*(xt+v[i + i*m]*x[i])/(v[i + i*m]+shift);
443       }
444     }
445   }
446   ierr = VecRestoreArray(bb,&b);CHKERRQ(ierr);
447   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
448   PetscFunctionReturn(0);
449 }
450 
451 /* -----------------------------------------------------------------*/
452 #undef __FUNCT__
453 #define __FUNCT__ "MatMultTranspose_SeqDense"
454 PetscErrorCode MatMultTranspose_SeqDense(Mat A,Vec xx,Vec yy)
455 {
456   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
457   PetscScalar    *v = mat->v,*x,*y;
458   PetscErrorCode ierr;
459   PetscBLASInt   m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n,_One=1;
460   PetscScalar    _DOne=1.0,_DZero=0.0;
461 
462   PetscFunctionBegin;
463   if (!A->m || !A->n) PetscFunctionReturn(0);
464   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
465   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
466   BLASgemv_("T",&m,&n,&_DOne,v,&mat->lda,x,&_One,&_DZero,y,&_One);
467   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
468   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
469   ierr = PetscLogFlops(2*A->m*A->n - A->n);CHKERRQ(ierr);
470   PetscFunctionReturn(0);
471 }
472 
473 #undef __FUNCT__
474 #define __FUNCT__ "MatMult_SeqDense"
475 PetscErrorCode MatMult_SeqDense(Mat A,Vec xx,Vec yy)
476 {
477   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
478   PetscScalar    *v = mat->v,*x,*y,_DOne=1.0,_DZero=0.0;
479   PetscErrorCode ierr;
480   PetscBLASInt   m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n, _One=1;
481 
482   PetscFunctionBegin;
483   if (!A->m || !A->n) PetscFunctionReturn(0);
484   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
485   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
486   BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DZero,y,&_One);
487   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
488   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
489   ierr = PetscLogFlops(2*A->m*A->n - A->m);CHKERRQ(ierr);
490   PetscFunctionReturn(0);
491 }
492 
493 #undef __FUNCT__
494 #define __FUNCT__ "MatMultAdd_SeqDense"
495 PetscErrorCode MatMultAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
496 {
497   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
498   PetscScalar    *v = mat->v,*x,*y,_DOne=1.0;
499   PetscErrorCode ierr;
500   PetscBLASInt   m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n, _One=1;
501 
502   PetscFunctionBegin;
503   if (!A->m || !A->n) PetscFunctionReturn(0);
504   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
505   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
506   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
507   BLASgemv_("N",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One);
508   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
509   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
510   ierr = PetscLogFlops(2*A->m*A->n);CHKERRQ(ierr);
511   PetscFunctionReturn(0);
512 }
513 
514 #undef __FUNCT__
515 #define __FUNCT__ "MatMultTransposeAdd_SeqDense"
516 PetscErrorCode MatMultTransposeAdd_SeqDense(Mat A,Vec xx,Vec zz,Vec yy)
517 {
518   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
519   PetscScalar    *v = mat->v,*x,*y;
520   PetscErrorCode ierr;
521   PetscBLASInt   m = (PetscBLASInt)A->m, n = (PetscBLASInt)A->n, _One=1;
522   PetscScalar    _DOne=1.0;
523 
524   PetscFunctionBegin;
525   if (!A->m || !A->n) PetscFunctionReturn(0);
526   if (zz != yy) {ierr = VecCopy(zz,yy);CHKERRQ(ierr);}
527   ierr = VecGetArray(xx,&x);CHKERRQ(ierr);
528   ierr = VecGetArray(yy,&y);CHKERRQ(ierr);
529   BLASgemv_("T",&m,&n,&_DOne,v,&(mat->lda),x,&_One,&_DOne,y,&_One);
530   ierr = VecRestoreArray(xx,&x);CHKERRQ(ierr);
531   ierr = VecRestoreArray(yy,&y);CHKERRQ(ierr);
532   ierr = PetscLogFlops(2*A->m*A->n);CHKERRQ(ierr);
533   PetscFunctionReturn(0);
534 }
535 
536 /* -----------------------------------------------------------------*/
537 #undef __FUNCT__
538 #define __FUNCT__ "MatGetRow_SeqDense"
539 PetscErrorCode MatGetRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
540 {
541   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
542   PetscScalar    *v;
543   PetscErrorCode ierr;
544   PetscInt       i;
545 
546   PetscFunctionBegin;
547   *ncols = A->n;
548   if (cols) {
549     ierr = PetscMalloc((A->n+1)*sizeof(PetscInt),cols);CHKERRQ(ierr);
550     for (i=0; i<A->n; i++) (*cols)[i] = i;
551   }
552   if (vals) {
553     ierr = PetscMalloc((A->n+1)*sizeof(PetscScalar),vals);CHKERRQ(ierr);
554     v    = mat->v + row;
555     for (i=0; i<A->n; i++) {(*vals)[i] = *v; v += mat->lda;}
556   }
557   PetscFunctionReturn(0);
558 }
559 
560 #undef __FUNCT__
561 #define __FUNCT__ "MatRestoreRow_SeqDense"
562 PetscErrorCode MatRestoreRow_SeqDense(Mat A,PetscInt row,PetscInt *ncols,PetscInt **cols,PetscScalar **vals)
563 {
564   PetscErrorCode ierr;
565   PetscFunctionBegin;
566   if (cols) {ierr = PetscFree(*cols);CHKERRQ(ierr);}
567   if (vals) {ierr = PetscFree(*vals);CHKERRQ(ierr); }
568   PetscFunctionReturn(0);
569 }
570 /* ----------------------------------------------------------------*/
571 #undef __FUNCT__
572 #define __FUNCT__ "MatSetValues_SeqDense"
573 PetscErrorCode MatSetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],const PetscScalar v[],InsertMode addv)
574 {
575   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
576   PetscInt     i,j,idx=0;
577 
578   PetscFunctionBegin;
579   if (!mat->roworiented) {
580     if (addv == INSERT_VALUES) {
581       for (j=0; j<n; j++) {
582         if (indexn[j] < 0) {idx += m; continue;}
583 #if defined(PETSC_USE_DEBUG)
584         if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1);
585 #endif
586         for (i=0; i<m; i++) {
587           if (indexm[i] < 0) {idx++; continue;}
588 #if defined(PETSC_USE_DEBUG)
589           if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1);
590 #endif
591           mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
592         }
593       }
594     } else {
595       for (j=0; j<n; j++) {
596         if (indexn[j] < 0) {idx += m; continue;}
597 #if defined(PETSC_USE_DEBUG)
598         if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1);
599 #endif
600         for (i=0; i<m; i++) {
601           if (indexm[i] < 0) {idx++; continue;}
602 #if defined(PETSC_USE_DEBUG)
603           if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1);
604 #endif
605           mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
606         }
607       }
608     }
609   } else {
610     if (addv == INSERT_VALUES) {
611       for (i=0; i<m; i++) {
612         if (indexm[i] < 0) { idx += n; continue;}
613 #if defined(PETSC_USE_DEBUG)
614         if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1);
615 #endif
616         for (j=0; j<n; j++) {
617           if (indexn[j] < 0) { idx++; continue;}
618 #if defined(PETSC_USE_DEBUG)
619           if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1);
620 #endif
621           mat->v[indexn[j]*mat->lda + indexm[i]] = v[idx++];
622         }
623       }
624     } else {
625       for (i=0; i<m; i++) {
626         if (indexm[i] < 0) { idx += n; continue;}
627 #if defined(PETSC_USE_DEBUG)
628         if (indexm[i] >= A->m) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",indexm[i],A->m-1);
629 #endif
630         for (j=0; j<n; j++) {
631           if (indexn[j] < 0) { idx++; continue;}
632 #if defined(PETSC_USE_DEBUG)
633           if (indexn[j] >= A->n) SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",indexn[j],A->n-1);
634 #endif
635           mat->v[indexn[j]*mat->lda + indexm[i]] += v[idx++];
636         }
637       }
638     }
639   }
640   PetscFunctionReturn(0);
641 }
642 
643 #undef __FUNCT__
644 #define __FUNCT__ "MatGetValues_SeqDense"
645 PetscErrorCode MatGetValues_SeqDense(Mat A,PetscInt m,const PetscInt indexm[],PetscInt n,const PetscInt indexn[],PetscScalar v[])
646 {
647   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
648   PetscInt     i,j;
649   PetscScalar  *vpt = v;
650 
651   PetscFunctionBegin;
652   /* row-oriented output */
653   for (i=0; i<m; i++) {
654     for (j=0; j<n; j++) {
655       *vpt++ = mat->v[indexn[j]*mat->lda + indexm[i]];
656     }
657   }
658   PetscFunctionReturn(0);
659 }
660 
661 /* -----------------------------------------------------------------*/
662 
663 #include "petscsys.h"
664 
665 #undef __FUNCT__
666 #define __FUNCT__ "MatLoad_SeqDense"
667 PetscErrorCode MatLoad_SeqDense(PetscViewer viewer,const MatType type,Mat *A)
668 {
669   Mat_SeqDense   *a;
670   Mat            B;
671   PetscErrorCode ierr;
672   PetscInt       *scols,i,j,nz,header[4];
673   int            fd;
674   PetscMPIInt    size;
675   PetscInt       *rowlengths = 0,M,N,*cols;
676   PetscScalar    *vals,*svals,*v,*w;
677   MPI_Comm       comm = ((PetscObject)viewer)->comm;
678 
679   PetscFunctionBegin;
680   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
681   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"view must have one processor");
682   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
683   ierr = PetscBinaryRead(fd,header,4,PETSC_INT);CHKERRQ(ierr);
684   if (header[0] != MAT_FILE_COOKIE) SETERRQ(PETSC_ERR_FILE_UNEXPECTED,"Not matrix object");
685   M = header[1]; N = header[2]; nz = header[3];
686 
687   if (nz == MATRIX_BINARY_FORMAT_DENSE) { /* matrix in file is dense */
688     ierr = MatCreate(comm,M,N,M,N,A);CHKERRQ(ierr);
689     ierr = MatSetType(*A,type);CHKERRQ(ierr);
690     ierr = MatSeqDenseSetPreallocation(*A,PETSC_NULL);CHKERRQ(ierr);
691     B    = *A;
692     a    = (Mat_SeqDense*)B->data;
693     v    = a->v;
694     /* Allocate some temp space to read in the values and then flip them
695        from row major to column major */
696     ierr = PetscMalloc((M*N > 0 ? M*N : 1)*sizeof(PetscScalar),&w);CHKERRQ(ierr);
697     /* read in nonzero values */
698     ierr = PetscBinaryRead(fd,w,M*N,PETSC_SCALAR);CHKERRQ(ierr);
699     /* now flip the values and store them in the matrix*/
700     for (j=0; j<N; j++) {
701       for (i=0; i<M; i++) {
702         *v++ =w[i*N+j];
703       }
704     }
705     ierr = PetscFree(w);CHKERRQ(ierr);
706     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
707     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
708   } else {
709     /* read row lengths */
710     ierr = PetscMalloc((M+1)*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr);
711     ierr = PetscBinaryRead(fd,rowlengths,M,PETSC_INT);CHKERRQ(ierr);
712 
713     /* create our matrix */
714     ierr = MatCreate(comm,M,N,M,N,A);CHKERRQ(ierr);
715     ierr = MatSetType(*A,type);CHKERRQ(ierr);
716     ierr = MatSeqDenseSetPreallocation(*A,PETSC_NULL);CHKERRQ(ierr);
717     B = *A;
718     a = (Mat_SeqDense*)B->data;
719     v = a->v;
720 
721     /* read column indices and nonzeros */
722     ierr = PetscMalloc((nz+1)*sizeof(PetscInt),&scols);CHKERRQ(ierr);
723     cols = scols;
724     ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr);
725     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&svals);CHKERRQ(ierr);
726     vals = svals;
727     ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr);
728 
729     /* insert into matrix */
730     for (i=0; i<M; i++) {
731       for (j=0; j<rowlengths[i]; j++) v[i+M*scols[j]] = svals[j];
732       svals += rowlengths[i]; scols += rowlengths[i];
733     }
734     ierr = PetscFree(vals);CHKERRQ(ierr);
735     ierr = PetscFree(cols);CHKERRQ(ierr);
736     ierr = PetscFree(rowlengths);CHKERRQ(ierr);
737 
738     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
739     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
740   }
741   PetscFunctionReturn(0);
742 }
743 
744 #include "petscsys.h"
745 
746 #undef __FUNCT__
747 #define __FUNCT__ "MatView_SeqDense_ASCII"
748 static PetscErrorCode MatView_SeqDense_ASCII(Mat A,PetscViewer viewer)
749 {
750   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
751   PetscErrorCode    ierr;
752   PetscInt          i,j;
753   char              *name;
754   PetscScalar       *v;
755   PetscViewerFormat format;
756 
757   PetscFunctionBegin;
758   ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
759   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
760   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
761     PetscFunctionReturn(0);  /* do nothing for now */
762   } else if (format == PETSC_VIEWER_ASCII_COMMON) {
763     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
764     for (i=0; i<A->m; i++) {
765       v = a->v + i;
766       ierr = PetscViewerASCIIPrintf(viewer,"row %D:",i);CHKERRQ(ierr);
767       for (j=0; j<A->n; j++) {
768 #if defined(PETSC_USE_COMPLEX)
769         if (PetscRealPart(*v) != 0.0 && PetscImaginaryPart(*v) != 0.0) {
770           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g + %g i) ",j,PetscRealPart(*v),PetscImaginaryPart(*v));CHKERRQ(ierr);
771         } else if (PetscRealPart(*v)) {
772           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,PetscRealPart(*v));CHKERRQ(ierr);
773         }
774 #else
775         if (*v) {
776           ierr = PetscViewerASCIIPrintf(viewer," (%D, %g) ",j,*v);CHKERRQ(ierr);
777         }
778 #endif
779         v += a->lda;
780       }
781       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
782     }
783     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
784   } else {
785     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_NO);CHKERRQ(ierr);
786 #if defined(PETSC_USE_COMPLEX)
787     PetscTruth allreal = PETSC_TRUE;
788     /* determine if matrix has all real values */
789     v = a->v;
790     for (i=0; i<A->m*A->n; i++) {
791 	if (PetscImaginaryPart(v[i])) { allreal = PETSC_FALSE; break ;}
792     }
793 #endif
794     if (format == PETSC_VIEWER_ASCII_MATLAB) {
795       ierr = PetscObjectGetName((PetscObject)A,&name);CHKERRQ(ierr);
796       ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D \n",A->m,A->n);CHKERRQ(ierr);
797       ierr = PetscViewerASCIIPrintf(viewer,"%s = zeros(%D,%D);\n",name,A->m,A->n);CHKERRQ(ierr);
798       ierr = PetscViewerASCIIPrintf(viewer,"%s = [\n",name);CHKERRQ(ierr);
799     }
800 
801     for (i=0; i<A->m; i++) {
802       v = a->v + i;
803       for (j=0; j<A->n; j++) {
804 #if defined(PETSC_USE_COMPLEX)
805         if (allreal) {
806           ierr = PetscViewerASCIIPrintf(viewer,"%6.4e ",PetscRealPart(*v));CHKERRQ(ierr);
807         } else {
808           ierr = PetscViewerASCIIPrintf(viewer,"%6.4e + %6.4e i ",PetscRealPart(*v),PetscImaginaryPart(*v));CHKERRQ(ierr);
809         }
810 #else
811         ierr = PetscViewerASCIIPrintf(viewer,"%6.4e ",*v);CHKERRQ(ierr);
812 #endif
813 	v += a->lda;
814       }
815       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
816     }
817     if (format == PETSC_VIEWER_ASCII_MATLAB) {
818       ierr = PetscViewerASCIIPrintf(viewer,"];\n");CHKERRQ(ierr);
819     }
820     ierr = PetscViewerASCIIUseTabs(viewer,PETSC_YES);CHKERRQ(ierr);
821   }
822   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
823   PetscFunctionReturn(0);
824 }
825 
826 #undef __FUNCT__
827 #define __FUNCT__ "MatView_SeqDense_Binary"
828 static PetscErrorCode MatView_SeqDense_Binary(Mat A,PetscViewer viewer)
829 {
830   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
831   PetscErrorCode    ierr;
832   int               fd;
833   PetscInt          ict,j,n = A->n,m = A->m,i,*col_lens,nz = m*n;
834   PetscScalar       *v,*anonz,*vals;
835   PetscViewerFormat format;
836 
837   PetscFunctionBegin;
838   ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr);
839 
840   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
841   if (format == PETSC_VIEWER_BINARY_NATIVE) {
842     /* store the matrix as a dense matrix */
843     ierr = PetscMalloc(4*sizeof(PetscInt),&col_lens);CHKERRQ(ierr);
844     col_lens[0] = MAT_FILE_COOKIE;
845     col_lens[1] = m;
846     col_lens[2] = n;
847     col_lens[3] = MATRIX_BINARY_FORMAT_DENSE;
848     ierr = PetscBinaryWrite(fd,col_lens,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
849     ierr = PetscFree(col_lens);CHKERRQ(ierr);
850 
851     /* write out matrix, by rows */
852     ierr = PetscMalloc((m*n+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr);
853     v    = a->v;
854     for (i=0; i<m; i++) {
855       for (j=0; j<n; j++) {
856         vals[i + j*m] = *v++;
857       }
858     }
859     ierr = PetscBinaryWrite(fd,vals,n*m,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
860     ierr = PetscFree(vals);CHKERRQ(ierr);
861   } else {
862     ierr = PetscMalloc((4+nz)*sizeof(PetscInt),&col_lens);CHKERRQ(ierr);
863     col_lens[0] = MAT_FILE_COOKIE;
864     col_lens[1] = m;
865     col_lens[2] = n;
866     col_lens[3] = nz;
867 
868     /* store lengths of each row and write (including header) to file */
869     for (i=0; i<m; i++) col_lens[4+i] = n;
870     ierr = PetscBinaryWrite(fd,col_lens,4+m,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr);
871 
872     /* Possibly should write in smaller increments, not whole matrix at once? */
873     /* store column indices (zero start index) */
874     ict = 0;
875     for (i=0; i<m; i++) {
876       for (j=0; j<n; j++) col_lens[ict++] = j;
877     }
878     ierr = PetscBinaryWrite(fd,col_lens,nz,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr);
879     ierr = PetscFree(col_lens);CHKERRQ(ierr);
880 
881     /* store nonzero values */
882     ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&anonz);CHKERRQ(ierr);
883     ict  = 0;
884     for (i=0; i<m; i++) {
885       v = a->v + i;
886       for (j=0; j<n; j++) {
887         anonz[ict++] = *v; v += a->lda;
888       }
889     }
890     ierr = PetscBinaryWrite(fd,anonz,nz,PETSC_SCALAR,PETSC_FALSE);CHKERRQ(ierr);
891     ierr = PetscFree(anonz);CHKERRQ(ierr);
892   }
893   PetscFunctionReturn(0);
894 }
895 
896 #undef __FUNCT__
897 #define __FUNCT__ "MatView_SeqDense_Draw_Zoom"
898 PetscErrorCode MatView_SeqDense_Draw_Zoom(PetscDraw draw,void *Aa)
899 {
900   Mat               A = (Mat) Aa;
901   Mat_SeqDense      *a = (Mat_SeqDense*)A->data;
902   PetscErrorCode    ierr;
903   PetscInt          m = A->m,n = A->n,color,i,j;
904   PetscScalar       *v = a->v;
905   PetscViewer       viewer;
906   PetscDraw         popup;
907   PetscReal         xl,yl,xr,yr,x_l,x_r,y_l,y_r,scale,maxv = 0.0;
908   PetscViewerFormat format;
909 
910   PetscFunctionBegin;
911 
912   ierr = PetscObjectQuery((PetscObject)A,"Zoomviewer",(PetscObject*)&viewer);CHKERRQ(ierr);
913   ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
914   ierr = PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);CHKERRQ(ierr);
915 
916   /* Loop over matrix elements drawing boxes */
917   if (format != PETSC_VIEWER_DRAW_CONTOUR) {
918     /* Blue for negative and Red for positive */
919     color = PETSC_DRAW_BLUE;
920     for(j = 0; j < n; j++) {
921       x_l = j;
922       x_r = x_l + 1.0;
923       for(i = 0; i < m; i++) {
924         y_l = m - i - 1.0;
925         y_r = y_l + 1.0;
926 #if defined(PETSC_USE_COMPLEX)
927         if (PetscRealPart(v[j*m+i]) >  0.) {
928           color = PETSC_DRAW_RED;
929         } else if (PetscRealPart(v[j*m+i]) <  0.) {
930           color = PETSC_DRAW_BLUE;
931         } else {
932           continue;
933         }
934 #else
935         if (v[j*m+i] >  0.) {
936           color = PETSC_DRAW_RED;
937         } else if (v[j*m+i] <  0.) {
938           color = PETSC_DRAW_BLUE;
939         } else {
940           continue;
941         }
942 #endif
943         ierr = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
944       }
945     }
946   } else {
947     /* use contour shading to indicate magnitude of values */
948     /* first determine max of all nonzero values */
949     for(i = 0; i < m*n; i++) {
950       if (PetscAbsScalar(v[i]) > maxv) maxv = PetscAbsScalar(v[i]);
951     }
952     scale = (245.0 - PETSC_DRAW_BASIC_COLORS)/maxv;
953     ierr  = PetscDrawGetPopup(draw,&popup);CHKERRQ(ierr);
954     if (popup) {ierr  = PetscDrawScalePopup(popup,0.0,maxv);CHKERRQ(ierr);}
955     for(j = 0; j < n; j++) {
956       x_l = j;
957       x_r = x_l + 1.0;
958       for(i = 0; i < m; i++) {
959         y_l   = m - i - 1.0;
960         y_r   = y_l + 1.0;
961         color = PETSC_DRAW_BASIC_COLORS + (int)(scale*PetscAbsScalar(v[j*m+i]));
962         ierr  = PetscDrawRectangle(draw,x_l,y_l,x_r,y_r,color,color,color,color);CHKERRQ(ierr);
963       }
964     }
965   }
966   PetscFunctionReturn(0);
967 }
968 
969 #undef __FUNCT__
970 #define __FUNCT__ "MatView_SeqDense_Draw"
971 PetscErrorCode MatView_SeqDense_Draw(Mat A,PetscViewer viewer)
972 {
973   PetscDraw      draw;
974   PetscTruth     isnull;
975   PetscReal      xr,yr,xl,yl,h,w;
976   PetscErrorCode ierr;
977 
978   PetscFunctionBegin;
979   ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr);
980   ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr);
981   if (isnull) PetscFunctionReturn(0);
982 
983   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",(PetscObject)viewer);CHKERRQ(ierr);
984   xr  = A->n; yr = A->m; h = yr/10.0; w = xr/10.0;
985   xr += w;    yr += h;  xl = -w;     yl = -h;
986   ierr = PetscDrawSetCoordinates(draw,xl,yl,xr,yr);CHKERRQ(ierr);
987   ierr = PetscDrawZoom(draw,MatView_SeqDense_Draw_Zoom,A);CHKERRQ(ierr);
988   ierr = PetscObjectCompose((PetscObject)A,"Zoomviewer",PETSC_NULL);CHKERRQ(ierr);
989   PetscFunctionReturn(0);
990 }
991 
992 #undef __FUNCT__
993 #define __FUNCT__ "MatView_SeqDense"
994 PetscErrorCode MatView_SeqDense(Mat A,PetscViewer viewer)
995 {
996   Mat_SeqDense   *a = (Mat_SeqDense*)A->data;
997   PetscErrorCode ierr;
998   PetscTruth     issocket,iascii,isbinary,isdraw;
999 
1000   PetscFunctionBegin;
1001   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_SOCKET,&issocket);CHKERRQ(ierr);
1002   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&iascii);CHKERRQ(ierr);
1003   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_BINARY,&isbinary);CHKERRQ(ierr);
1004   ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_DRAW,&isdraw);CHKERRQ(ierr);
1005 
1006   if (issocket) {
1007     if (a->lda>A->m) SETERRQ(PETSC_ERR_SUP,"Case can not handle LDA");
1008     ierr = PetscViewerSocketPutScalar(viewer,A->m,A->n,a->v);CHKERRQ(ierr);
1009   } else if (iascii) {
1010     ierr = MatView_SeqDense_ASCII(A,viewer);CHKERRQ(ierr);
1011   } else if (isbinary) {
1012     ierr = MatView_SeqDense_Binary(A,viewer);CHKERRQ(ierr);
1013   } else if (isdraw) {
1014     ierr = MatView_SeqDense_Draw(A,viewer);CHKERRQ(ierr);
1015   } else {
1016     SETERRQ1(PETSC_ERR_SUP,"Viewer type %s not supported by dense matrix",((PetscObject)viewer)->type_name);
1017   }
1018   PetscFunctionReturn(0);
1019 }
1020 
1021 #undef __FUNCT__
1022 #define __FUNCT__ "MatDestroy_SeqDense"
1023 PetscErrorCode MatDestroy_SeqDense(Mat mat)
1024 {
1025   Mat_SeqDense   *l = (Mat_SeqDense*)mat->data;
1026   PetscErrorCode ierr;
1027 
1028   PetscFunctionBegin;
1029 #if defined(PETSC_USE_LOG)
1030   PetscLogObjectState((PetscObject)mat,"Rows %D Cols %D",mat->m,mat->n);
1031 #endif
1032   if (l->pivots) {ierr = PetscFree(l->pivots);CHKERRQ(ierr);}
1033   if (!l->user_alloc) {ierr = PetscFree(l->v);CHKERRQ(ierr);}
1034   ierr = PetscFree(l);CHKERRQ(ierr);
1035   ierr = PetscObjectComposeFunctionDynamic((PetscObject)mat,"MatSeqDenseSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr);
1036   PetscFunctionReturn(0);
1037 }
1038 
1039 #undef __FUNCT__
1040 #define __FUNCT__ "MatTranspose_SeqDense"
1041 PetscErrorCode MatTranspose_SeqDense(Mat A,Mat *matout)
1042 {
1043   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1044   PetscErrorCode ierr;
1045   PetscInt       k,j,m,n,M;
1046   PetscScalar    *v,tmp;
1047 
1048   PetscFunctionBegin;
1049   v = mat->v; m = A->m; M = mat->lda; n = A->n;
1050   if (!matout) { /* in place transpose */
1051     if (m != n) {
1052       SETERRQ(PETSC_ERR_SUP,"Can not transpose non-square matrix in place");
1053     } else {
1054       for (j=0; j<m; j++) {
1055         for (k=0; k<j; k++) {
1056           tmp = v[j + k*M];
1057           v[j + k*M] = v[k + j*M];
1058           v[k + j*M] = tmp;
1059         }
1060       }
1061     }
1062   } else { /* out-of-place transpose */
1063     Mat          tmat;
1064     Mat_SeqDense *tmatd;
1065     PetscScalar  *v2;
1066 
1067     ierr  = MatCreate(A->comm,A->n,A->m,A->n,A->m,&tmat);CHKERRQ(ierr);
1068     ierr  = MatSetType(tmat,A->type_name);CHKERRQ(ierr);
1069     ierr  = MatSeqDenseSetPreallocation(tmat,PETSC_NULL);CHKERRQ(ierr);
1070     tmatd = (Mat_SeqDense*)tmat->data;
1071     v = mat->v; v2 = tmatd->v;
1072     for (j=0; j<n; j++) {
1073       for (k=0; k<m; k++) v2[j + k*n] = v[k + j*M];
1074     }
1075     ierr = MatAssemblyBegin(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1076     ierr = MatAssemblyEnd(tmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1077     *matout = tmat;
1078   }
1079   PetscFunctionReturn(0);
1080 }
1081 
1082 #undef __FUNCT__
1083 #define __FUNCT__ "MatEqual_SeqDense"
1084 PetscErrorCode MatEqual_SeqDense(Mat A1,Mat A2,PetscTruth *flg)
1085 {
1086   Mat_SeqDense *mat1 = (Mat_SeqDense*)A1->data;
1087   Mat_SeqDense *mat2 = (Mat_SeqDense*)A2->data;
1088   PetscInt     i,j;
1089   PetscScalar  *v1 = mat1->v,*v2 = mat2->v;
1090 
1091   PetscFunctionBegin;
1092   if (A1->m != A2->m) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1093   if (A1->n != A2->n) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1094   for (i=0; i<A1->m; i++) {
1095     v1 = mat1->v+i; v2 = mat2->v+i;
1096     for (j=0; j<A1->n; j++) {
1097       if (*v1 != *v2) {*flg = PETSC_FALSE; PetscFunctionReturn(0);}
1098       v1 += mat1->lda; v2 += mat2->lda;
1099     }
1100   }
1101   *flg = PETSC_TRUE;
1102   PetscFunctionReturn(0);
1103 }
1104 
1105 #undef __FUNCT__
1106 #define __FUNCT__ "MatGetDiagonal_SeqDense"
1107 PetscErrorCode MatGetDiagonal_SeqDense(Mat A,Vec v)
1108 {
1109   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1110   PetscErrorCode ierr;
1111   PetscInt       i,n,len;
1112   PetscScalar    *x,zero = 0.0;
1113 
1114   PetscFunctionBegin;
1115   ierr = VecSet(&zero,v);CHKERRQ(ierr);
1116   ierr = VecGetSize(v,&n);CHKERRQ(ierr);
1117   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1118   len = PetscMin(A->m,A->n);
1119   if (n != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Nonconforming mat and vec");
1120   for (i=0; i<len; i++) {
1121     x[i] = mat->v[i*mat->lda + i];
1122   }
1123   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1124   PetscFunctionReturn(0);
1125 }
1126 
1127 #undef __FUNCT__
1128 #define __FUNCT__ "MatDiagonalScale_SeqDense"
1129 PetscErrorCode MatDiagonalScale_SeqDense(Mat A,Vec ll,Vec rr)
1130 {
1131   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1132   PetscScalar    *l,*r,x,*v;
1133   PetscErrorCode ierr;
1134   PetscInt       i,j,m = A->m,n = A->n;
1135 
1136   PetscFunctionBegin;
1137   if (ll) {
1138     ierr = VecGetSize(ll,&m);CHKERRQ(ierr);
1139     ierr = VecGetArray(ll,&l);CHKERRQ(ierr);
1140     if (m != A->m) SETERRQ(PETSC_ERR_ARG_SIZ,"Left scaling vec wrong size");
1141     for (i=0; i<m; i++) {
1142       x = l[i];
1143       v = mat->v + i;
1144       for (j=0; j<n; j++) { (*v) *= x; v+= m;}
1145     }
1146     ierr = VecRestoreArray(ll,&l);CHKERRQ(ierr);
1147     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
1148   }
1149   if (rr) {
1150     ierr = VecGetSize(rr,&n);CHKERRQ(ierr);
1151     ierr = VecGetArray(rr,&r);CHKERRQ(ierr);
1152     if (n != A->n) SETERRQ(PETSC_ERR_ARG_SIZ,"Right scaling vec wrong size");
1153     for (i=0; i<n; i++) {
1154       x = r[i];
1155       v = mat->v + i*m;
1156       for (j=0; j<m; j++) { (*v++) *= x;}
1157     }
1158     ierr = VecRestoreArray(rr,&r);CHKERRQ(ierr);
1159     ierr = PetscLogFlops(n*m);CHKERRQ(ierr);
1160   }
1161   PetscFunctionReturn(0);
1162 }
1163 
1164 #undef __FUNCT__
1165 #define __FUNCT__ "MatNorm_SeqDense"
1166 PetscErrorCode MatNorm_SeqDense(Mat A,NormType type,PetscReal *nrm)
1167 {
1168   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1169   PetscScalar  *v = mat->v;
1170   PetscReal    sum = 0.0;
1171   PetscInt     lda=mat->lda,m=A->m,i,j;
1172   PetscErrorCode ierr;
1173 
1174   PetscFunctionBegin;
1175   if (type == NORM_FROBENIUS) {
1176     if (lda>m) {
1177       for (j=0; j<A->n; j++) {
1178 	v = mat->v+j*lda;
1179 	for (i=0; i<m; i++) {
1180 #if defined(PETSC_USE_COMPLEX)
1181 	  sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1182 #else
1183 	  sum += (*v)*(*v); v++;
1184 #endif
1185 	}
1186       }
1187     } else {
1188       for (i=0; i<A->n*A->m; i++) {
1189 #if defined(PETSC_USE_COMPLEX)
1190 	sum += PetscRealPart(PetscConj(*v)*(*v)); v++;
1191 #else
1192 	sum += (*v)*(*v); v++;
1193 #endif
1194       }
1195     }
1196     *nrm = sqrt(sum);
1197     ierr = PetscLogFlops(2*A->n*A->m);CHKERRQ(ierr);
1198   } else if (type == NORM_1) {
1199     *nrm = 0.0;
1200     for (j=0; j<A->n; j++) {
1201       v = mat->v + j*mat->lda;
1202       sum = 0.0;
1203       for (i=0; i<A->m; i++) {
1204         sum += PetscAbsScalar(*v);  v++;
1205       }
1206       if (sum > *nrm) *nrm = sum;
1207     }
1208     ierr = PetscLogFlops(A->n*A->m);CHKERRQ(ierr);
1209   } else if (type == NORM_INFINITY) {
1210     *nrm = 0.0;
1211     for (j=0; j<A->m; j++) {
1212       v = mat->v + j;
1213       sum = 0.0;
1214       for (i=0; i<A->n; i++) {
1215         sum += PetscAbsScalar(*v); v += mat->lda;
1216       }
1217       if (sum > *nrm) *nrm = sum;
1218     }
1219     ierr = PetscLogFlops(A->n*A->m);CHKERRQ(ierr);
1220   } else {
1221     SETERRQ(PETSC_ERR_SUP,"No two norm");
1222   }
1223   PetscFunctionReturn(0);
1224 }
1225 
1226 #undef __FUNCT__
1227 #define __FUNCT__ "MatSetOption_SeqDense"
1228 PetscErrorCode MatSetOption_SeqDense(Mat A,MatOption op)
1229 {
1230   Mat_SeqDense *aij = (Mat_SeqDense*)A->data;
1231 
1232   PetscFunctionBegin;
1233   switch (op) {
1234   case MAT_ROW_ORIENTED:
1235     aij->roworiented = PETSC_TRUE;
1236     break;
1237   case MAT_COLUMN_ORIENTED:
1238     aij->roworiented = PETSC_FALSE;
1239     break;
1240   case MAT_ROWS_SORTED:
1241   case MAT_ROWS_UNSORTED:
1242   case MAT_COLUMNS_SORTED:
1243   case MAT_COLUMNS_UNSORTED:
1244   case MAT_NO_NEW_NONZERO_LOCATIONS:
1245   case MAT_YES_NEW_NONZERO_LOCATIONS:
1246   case MAT_NEW_NONZERO_LOCATION_ERR:
1247   case MAT_NO_NEW_DIAGONALS:
1248   case MAT_YES_NEW_DIAGONALS:
1249   case MAT_IGNORE_OFF_PROC_ENTRIES:
1250   case MAT_USE_HASH_TABLE:
1251     PetscLogInfo(A,"MatSetOption_SeqDense:Option ignored\n");
1252     break;
1253   case MAT_SYMMETRIC:
1254   case MAT_STRUCTURALLY_SYMMETRIC:
1255   case MAT_NOT_SYMMETRIC:
1256   case MAT_NOT_STRUCTURALLY_SYMMETRIC:
1257   case MAT_HERMITIAN:
1258   case MAT_NOT_HERMITIAN:
1259   case MAT_SYMMETRY_ETERNAL:
1260   case MAT_NOT_SYMMETRY_ETERNAL:
1261     break;
1262   default:
1263     SETERRQ(PETSC_ERR_SUP,"unknown option");
1264   }
1265   PetscFunctionReturn(0);
1266 }
1267 
1268 #undef __FUNCT__
1269 #define __FUNCT__ "MatZeroEntries_SeqDense"
1270 PetscErrorCode MatZeroEntries_SeqDense(Mat A)
1271 {
1272   Mat_SeqDense   *l = (Mat_SeqDense*)A->data;
1273   PetscErrorCode ierr;
1274   PetscInt       lda=l->lda,m=A->m,j;
1275 
1276   PetscFunctionBegin;
1277   if (lda>m) {
1278     for (j=0; j<A->n; j++) {
1279       ierr = PetscMemzero(l->v+j*lda,m*sizeof(PetscScalar));CHKERRQ(ierr);
1280     }
1281   } else {
1282     ierr = PetscMemzero(l->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr);
1283   }
1284   PetscFunctionReturn(0);
1285 }
1286 
1287 #undef __FUNCT__
1288 #define __FUNCT__ "MatZeroRows_SeqDense"
1289 PetscErrorCode MatZeroRows_SeqDense(Mat A,IS is,const PetscScalar *diag)
1290 {
1291   Mat_SeqDense   *l = (Mat_SeqDense*)A->data;
1292   PetscErrorCode ierr;
1293   PetscInt       n = A->n,i,j,N,*rows;
1294   PetscScalar    *slot;
1295 
1296   PetscFunctionBegin;
1297   ierr = ISGetLocalSize(is,&N);CHKERRQ(ierr);
1298   ierr = ISGetIndices(is,&rows);CHKERRQ(ierr);
1299   for (i=0; i<N; i++) {
1300     slot = l->v + rows[i];
1301     for (j=0; j<n; j++) { *slot = 0.0; slot += n;}
1302   }
1303   if (diag) {
1304     for (i=0; i<N; i++) {
1305       slot = l->v + (n+1)*rows[i];
1306       *slot = *diag;
1307     }
1308   }
1309   ISRestoreIndices(is,&rows);
1310   PetscFunctionReturn(0);
1311 }
1312 
1313 #undef __FUNCT__
1314 #define __FUNCT__ "MatGetArray_SeqDense"
1315 PetscErrorCode MatGetArray_SeqDense(Mat A,PetscScalar *array[])
1316 {
1317   Mat_SeqDense *mat = (Mat_SeqDense*)A->data;
1318 
1319   PetscFunctionBegin;
1320   *array = mat->v;
1321   PetscFunctionReturn(0);
1322 }
1323 
1324 #undef __FUNCT__
1325 #define __FUNCT__ "MatRestoreArray_SeqDense"
1326 PetscErrorCode MatRestoreArray_SeqDense(Mat A,PetscScalar *array[])
1327 {
1328   PetscFunctionBegin;
1329   *array = 0; /* user cannot accidently use the array later */
1330   PetscFunctionReturn(0);
1331 }
1332 
1333 #undef __FUNCT__
1334 #define __FUNCT__ "MatGetSubMatrix_SeqDense"
1335 static PetscErrorCode MatGetSubMatrix_SeqDense(Mat A,IS isrow,IS iscol,PetscInt cs,MatReuse scall,Mat *B)
1336 {
1337   Mat_SeqDense   *mat = (Mat_SeqDense*)A->data;
1338   PetscErrorCode ierr;
1339   PetscInt       i,j,m = A->m,*irow,*icol,nrows,ncols;
1340   PetscScalar    *av,*bv,*v = mat->v;
1341   Mat            newmat;
1342 
1343   PetscFunctionBegin;
1344   ierr = ISGetIndices(isrow,&irow);CHKERRQ(ierr);
1345   ierr = ISGetIndices(iscol,&icol);CHKERRQ(ierr);
1346   ierr = ISGetLocalSize(isrow,&nrows);CHKERRQ(ierr);
1347   ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr);
1348 
1349   /* Check submatrixcall */
1350   if (scall == MAT_REUSE_MATRIX) {
1351     PetscInt n_cols,n_rows;
1352     ierr = MatGetSize(*B,&n_rows,&n_cols);CHKERRQ(ierr);
1353     if (n_rows != nrows || n_cols != ncols) SETERRQ(PETSC_ERR_ARG_SIZ,"Reused submatrix wrong size");
1354     newmat = *B;
1355   } else {
1356     /* Create and fill new matrix */
1357     ierr = MatCreate(A->comm,nrows,ncols,nrows,ncols,&newmat);CHKERRQ(ierr);
1358     ierr = MatSetType(newmat,A->type_name);CHKERRQ(ierr);
1359     ierr = MatSeqDenseSetPreallocation(newmat,PETSC_NULL);CHKERRQ(ierr);
1360   }
1361 
1362   /* Now extract the data pointers and do the copy,column at a time */
1363   bv = ((Mat_SeqDense*)newmat->data)->v;
1364 
1365   for (i=0; i<ncols; i++) {
1366     av = v + m*icol[i];
1367     for (j=0; j<nrows; j++) {
1368       *bv++ = av[irow[j]];
1369     }
1370   }
1371 
1372   /* Assemble the matrices so that the correct flags are set */
1373   ierr = MatAssemblyBegin(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1374   ierr = MatAssemblyEnd(newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1375 
1376   /* Free work space */
1377   ierr = ISRestoreIndices(isrow,&irow);CHKERRQ(ierr);
1378   ierr = ISRestoreIndices(iscol,&icol);CHKERRQ(ierr);
1379   *B = newmat;
1380   PetscFunctionReturn(0);
1381 }
1382 
1383 #undef __FUNCT__
1384 #define __FUNCT__ "MatGetSubMatrices_SeqDense"
1385 PetscErrorCode MatGetSubMatrices_SeqDense(Mat A,PetscInt n,const IS irow[],const IS icol[],MatReuse scall,Mat *B[])
1386 {
1387   PetscErrorCode ierr;
1388   PetscInt       i;
1389 
1390   PetscFunctionBegin;
1391   if (scall == MAT_INITIAL_MATRIX) {
1392     ierr = PetscMalloc((n+1)*sizeof(Mat),B);CHKERRQ(ierr);
1393   }
1394 
1395   for (i=0; i<n; i++) {
1396     ierr = MatGetSubMatrix_SeqDense(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(ierr);
1397   }
1398   PetscFunctionReturn(0);
1399 }
1400 
1401 #undef __FUNCT__
1402 #define __FUNCT__ "MatCopy_SeqDense"
1403 PetscErrorCode MatCopy_SeqDense(Mat A,Mat B,MatStructure str)
1404 {
1405   Mat_SeqDense   *a = (Mat_SeqDense*)A->data,*b = (Mat_SeqDense *)B->data;
1406   PetscErrorCode ierr;
1407   PetscInt       lda1=a->lda,lda2=b->lda, m=A->m,n=A->n, j;
1408 
1409   PetscFunctionBegin;
1410   /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */
1411   if (A->ops->copy != B->ops->copy) {
1412     ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr);
1413     PetscFunctionReturn(0);
1414   }
1415   if (m != B->m || n != B->n) SETERRQ(PETSC_ERR_ARG_SIZ,"size(B) != size(A)");
1416   if (lda1>m || lda2>m) {
1417     for (j=0; j<n; j++) {
1418       ierr = PetscMemcpy(b->v+j*lda2,a->v+j*lda1,m*sizeof(PetscScalar));CHKERRQ(ierr);
1419     }
1420   } else {
1421     ierr = PetscMemcpy(b->v,a->v,A->m*A->n*sizeof(PetscScalar));CHKERRQ(ierr);
1422   }
1423   PetscFunctionReturn(0);
1424 }
1425 
1426 #undef __FUNCT__
1427 #define __FUNCT__ "MatSetUpPreallocation_SeqDense"
1428 PetscErrorCode MatSetUpPreallocation_SeqDense(Mat A)
1429 {
1430   PetscErrorCode ierr;
1431 
1432   PetscFunctionBegin;
1433   ierr =  MatSeqDenseSetPreallocation(A,0);CHKERRQ(ierr);
1434   PetscFunctionReturn(0);
1435 }
1436 
1437 /* -------------------------------------------------------------------*/
1438 static struct _MatOps MatOps_Values = {MatSetValues_SeqDense,
1439        MatGetRow_SeqDense,
1440        MatRestoreRow_SeqDense,
1441        MatMult_SeqDense,
1442 /* 4*/ MatMultAdd_SeqDense,
1443        MatMultTranspose_SeqDense,
1444        MatMultTransposeAdd_SeqDense,
1445        MatSolve_SeqDense,
1446        MatSolveAdd_SeqDense,
1447        MatSolveTranspose_SeqDense,
1448 /*10*/ MatSolveTransposeAdd_SeqDense,
1449        MatLUFactor_SeqDense,
1450        MatCholeskyFactor_SeqDense,
1451        MatRelax_SeqDense,
1452        MatTranspose_SeqDense,
1453 /*15*/ MatGetInfo_SeqDense,
1454        MatEqual_SeqDense,
1455        MatGetDiagonal_SeqDense,
1456        MatDiagonalScale_SeqDense,
1457        MatNorm_SeqDense,
1458 /*20*/ 0,
1459        0,
1460        0,
1461        MatSetOption_SeqDense,
1462        MatZeroEntries_SeqDense,
1463 /*25*/ MatZeroRows_SeqDense,
1464        MatLUFactorSymbolic_SeqDense,
1465        MatLUFactorNumeric_SeqDense,
1466        MatCholeskyFactorSymbolic_SeqDense,
1467        MatCholeskyFactorNumeric_SeqDense,
1468 /*30*/ MatSetUpPreallocation_SeqDense,
1469        0,
1470        0,
1471        MatGetArray_SeqDense,
1472        MatRestoreArray_SeqDense,
1473 /*35*/ MatDuplicate_SeqDense,
1474        0,
1475        0,
1476        0,
1477        0,
1478 /*40*/ MatAXPY_SeqDense,
1479        MatGetSubMatrices_SeqDense,
1480        0,
1481        MatGetValues_SeqDense,
1482        MatCopy_SeqDense,
1483 /*45*/ 0,
1484        MatScale_SeqDense,
1485        0,
1486        0,
1487        0,
1488 /*50*/ 0,
1489        0,
1490        0,
1491        0,
1492        0,
1493 /*55*/ 0,
1494        0,
1495        0,
1496        0,
1497        0,
1498 /*60*/ 0,
1499        MatDestroy_SeqDense,
1500        MatView_SeqDense,
1501        MatGetPetscMaps_Petsc,
1502        0,
1503 /*65*/ 0,
1504        0,
1505        0,
1506        0,
1507        0,
1508 /*70*/ 0,
1509        0,
1510        0,
1511        0,
1512        0,
1513 /*75*/ 0,
1514        0,
1515        0,
1516        0,
1517        0,
1518 /*80*/ 0,
1519        0,
1520        0,
1521        0,
1522 /*84*/ MatLoad_SeqDense,
1523        0,
1524        0,
1525        0,
1526        0,
1527        0,
1528 /*90*/ 0,
1529        0,
1530        0,
1531        0,
1532        0,
1533 /*95*/ 0,
1534        0,
1535        0,
1536        0};
1537 
1538 #undef __FUNCT__
1539 #define __FUNCT__ "MatCreateSeqDense"
1540 /*@C
1541    MatCreateSeqDense - Creates a sequential dense matrix that
1542    is stored in column major order (the usual Fortran 77 manner). Many
1543    of the matrix operations use the BLAS and LAPACK routines.
1544 
1545    Collective on MPI_Comm
1546 
1547    Input Parameters:
1548 +  comm - MPI communicator, set to PETSC_COMM_SELF
1549 .  m - number of rows
1550 .  n - number of columns
1551 -  data - optional location of matrix data.  Set data=PETSC_NULL for PETSc
1552    to control all matrix memory allocation.
1553 
1554    Output Parameter:
1555 .  A - the matrix
1556 
1557    Notes:
1558    The data input variable is intended primarily for Fortran programmers
1559    who wish to allocate their own matrix memory space.  Most users should
1560    set data=PETSC_NULL.
1561 
1562    Level: intermediate
1563 
1564 .keywords: dense, matrix, LAPACK, BLAS
1565 
1566 .seealso: MatCreate(), MatCreateMPIDense(), MatSetValues()
1567 @*/
1568 PetscErrorCode MatCreateSeqDense(MPI_Comm comm,PetscInt m,PetscInt n,PetscScalar *data,Mat *A)
1569 {
1570   PetscErrorCode ierr;
1571 
1572   PetscFunctionBegin;
1573   ierr = MatCreate(comm,m,n,m,n,A);CHKERRQ(ierr);
1574   ierr = MatSetType(*A,MATSEQDENSE);CHKERRQ(ierr);
1575   ierr = MatSeqDenseSetPreallocation(*A,data);CHKERRQ(ierr);
1576   PetscFunctionReturn(0);
1577 }
1578 
1579 #undef __FUNCT__
1580 #define __FUNCT__ "MatSeqDensePreallocation"
1581 /*@C
1582    MatSeqDenseSetPreallocation - Sets the array used for storing the matrix elements
1583 
1584    Collective on MPI_Comm
1585 
1586    Input Parameters:
1587 +  A - the matrix
1588 -  data - the array (or PETSC_NULL)
1589 
1590    Notes:
1591    The data input variable is intended primarily for Fortran programmers
1592    who wish to allocate their own matrix memory space.  Most users should
1593    set data=PETSC_NULL.
1594 
1595    Level: intermediate
1596 
1597 .keywords: dense, matrix, LAPACK, BLAS
1598 
1599 .seealso: MatCreate(), MatCreateMPIDense(), MatSetValues()
1600 @*/
1601 PetscErrorCode MatSeqDenseSetPreallocation(Mat B,PetscScalar data[])
1602 {
1603   PetscErrorCode ierr,(*f)(Mat,PetscScalar[]);
1604 
1605   PetscFunctionBegin;
1606   ierr = PetscObjectQueryFunction((PetscObject)B,"MatSeqDenseSetPreallocation_C",(void (**)(void))&f);CHKERRQ(ierr);
1607   if (f) {
1608     ierr = (*f)(B,data);CHKERRQ(ierr);
1609   }
1610   PetscFunctionReturn(0);
1611 }
1612 
1613 EXTERN_C_BEGIN
1614 #undef __FUNCT__
1615 #define __FUNCT__ "MatSeqDensePreallocation_SeqDense"
1616 PetscErrorCode MatSeqDenseSetPreallocation_SeqDense(Mat B,PetscScalar *data)
1617 {
1618   Mat_SeqDense   *b;
1619   PetscErrorCode ierr;
1620 
1621   PetscFunctionBegin;
1622   B->preallocated = PETSC_TRUE;
1623   b               = (Mat_SeqDense*)B->data;
1624   if (!data) {
1625     ierr          = PetscMalloc((B->m*B->n+1)*sizeof(PetscScalar),&b->v);CHKERRQ(ierr);
1626     ierr          = PetscMemzero(b->v,B->m*B->n*sizeof(PetscScalar));CHKERRQ(ierr);
1627     b->user_alloc = PETSC_FALSE;
1628     ierr = PetscLogObjectMemory(B,B->n*B->m*sizeof(PetscScalar));CHKERRQ(ierr);
1629   } else { /* user-allocated storage */
1630     b->v          = data;
1631     b->user_alloc = PETSC_TRUE;
1632   }
1633   PetscFunctionReturn(0);
1634 }
1635 EXTERN_C_END
1636 
1637 #undef __FUNCT__
1638 #define __FUNCT__ "MatSeqDenseSetLDA"
1639 /*@C
1640   MatSeqDenseSetLDA - Declare the leading dimension of the user-provided array
1641 
1642   Input parameter:
1643 + A - the matrix
1644 - lda - the leading dimension
1645 
1646   Notes:
1647   This routine is to be used in conjunction with MatSeqDenseSetPreallocation;
1648   it asserts that the preallocation has a leading dimension (the LDA parameter
1649   of Blas and Lapack fame) larger than M, the first dimension of the matrix.
1650 
1651   Level: intermediate
1652 
1653 .keywords: dense, matrix, LAPACK, BLAS
1654 
1655 .seealso: MatCreate(), MatCreateSeqDense(), MatSeqDenseSetPreallocation()
1656 @*/
1657 PetscErrorCode MatSeqDenseSetLDA(Mat B,PetscInt lda)
1658 {
1659   Mat_SeqDense *b = (Mat_SeqDense*)B->data;
1660   PetscFunctionBegin;
1661   if (lda < B->m) SETERRQ2(PETSC_ERR_ARG_SIZ,"LDA %D must be at least matrix dimension %D",lda,B->m);
1662   b->lda = lda;
1663   PetscFunctionReturn(0);
1664 }
1665 
1666 /*MC
1667    MATSEQDENSE - MATSEQDENSE = "seqdense" - A matrix type to be used for sequential dense matrices.
1668 
1669    Options Database Keys:
1670 . -mat_type seqdense - sets the matrix type to "seqdense" during a call to MatSetFromOptions()
1671 
1672   Level: beginner
1673 
1674 .seealso: MatCreateSeqDense
1675 M*/
1676 
1677 EXTERN_C_BEGIN
1678 #undef __FUNCT__
1679 #define __FUNCT__ "MatCreate_SeqDense"
1680 PetscErrorCode MatCreate_SeqDense(Mat B)
1681 {
1682   Mat_SeqDense   *b;
1683   PetscErrorCode ierr;
1684   PetscMPIInt    size;
1685 
1686   PetscFunctionBegin;
1687   ierr = MPI_Comm_size(B->comm,&size);CHKERRQ(ierr);
1688   if (size > 1) SETERRQ(PETSC_ERR_ARG_WRONG,"Comm must be of size 1");
1689 
1690   B->m = B->M = PetscMax(B->m,B->M);
1691   B->n = B->N = PetscMax(B->n,B->N);
1692 
1693   ierr            = PetscNew(Mat_SeqDense,&b);CHKERRQ(ierr);
1694   ierr            = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr);
1695   B->factor       = 0;
1696   B->mapping      = 0;
1697   ierr = PetscLogObjectMemory(B,sizeof(struct _p_Mat));CHKERRQ(ierr);
1698   B->data         = (void*)b;
1699 
1700   ierr = PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);CHKERRQ(ierr);
1701   ierr = PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);CHKERRQ(ierr);
1702 
1703   b->pivots       = 0;
1704   b->roworiented  = PETSC_TRUE;
1705   b->v            = 0;
1706   b->lda          = B->m;
1707 
1708   ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSeqDenseSetPreallocation_C",
1709                                     "MatSeqDenseSetPreallocation_SeqDense",
1710                                      MatSeqDenseSetPreallocation_SeqDense);CHKERRQ(ierr);
1711   PetscFunctionReturn(0);
1712 }
1713 EXTERN_C_END
1714