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