xref: /petsc/src/mat/impls/dense/seq/dense.c (revision da3a660d273b912abcae7b3f88d2c9355b68b6f0)
1289bc588SBarry Smith 
2289bc588SBarry Smith /*
3289bc588SBarry Smith     Standard Fortran style matrices
4289bc588SBarry Smith */
5289bc588SBarry Smith #include "ptscimpl.h"
6289bc588SBarry Smith #include "plapack.h"
7289bc588SBarry Smith #include "matimpl.h"
8289bc588SBarry Smith #include "math.h"
9289bc588SBarry Smith #include "vec/vecimpl.h"
10289bc588SBarry Smith 
11289bc588SBarry Smith typedef struct {
12289bc588SBarry Smith   Scalar *v;
13289bc588SBarry Smith   int    roworiented;
14289bc588SBarry Smith   int    m,n,pad;
15289bc588SBarry Smith   int    *pivots;   /* pivots in LU factorization */
16289bc588SBarry Smith } MatiSD;
17289bc588SBarry Smith 
18289bc588SBarry Smith 
19289bc588SBarry Smith static int MatiSDnz(Mat matin,int *nz)
20289bc588SBarry Smith {
21289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
22289bc588SBarry Smith   int    i,N = mat->m*mat->n,count = 0;
23289bc588SBarry Smith   Scalar *v = mat->v;
24289bc588SBarry Smith   for ( i=0; i<N; i++ ) {if (*v != 0.0) count++; v++;}
25289bc588SBarry Smith   *nz = count; return 0;
26289bc588SBarry Smith }
27289bc588SBarry Smith static int MatiSDmemory(Mat matin,int *mem)
28289bc588SBarry Smith {
29289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
30289bc588SBarry Smith   *mem = mat->m*mat->n*sizeof(Scalar); return 0;
31289bc588SBarry Smith }
32289bc588SBarry Smith 
33289bc588SBarry Smith /* ---------------------------------------------------------------*/
34289bc588SBarry Smith /* COMMENT: I have chosen to hide column permutation in the pivots,
35289bc588SBarry Smith    rather than put it in the Mat->col slot.*/
36289bc588SBarry Smith static int MatiSDlufactor(Mat matin,IS row,IS col)
37289bc588SBarry Smith {
38289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
39289bc588SBarry Smith   int    ierr, one  = 1, info;
40289bc588SBarry Smith   if (!mat->pivots) {
41289bc588SBarry Smith     mat->pivots = (int *) MALLOC( mat->m*sizeof(int) );
42289bc588SBarry Smith     CHKPTR(mat->pivots);
43289bc588SBarry Smith   }
44289bc588SBarry Smith   LAgetrf_(&mat->m,&mat->n,mat->v,&mat->m,mat->pivots,&info);
45289bc588SBarry Smith   if (info) SETERR(1,"Bad LU factorization");
46289bc588SBarry Smith   matin->factor = FACTOR_LU;
47289bc588SBarry Smith   return 0;
48289bc588SBarry Smith }
49289bc588SBarry Smith static int MatiSDlufactorsymbolic(Mat matin,IS row,IS col,Mat *fact)
50289bc588SBarry Smith {
51289bc588SBarry Smith   int ierr;
52289bc588SBarry Smith   if (ierr = MatCopy(matin,fact)) SETERR(ierr,0);
53289bc588SBarry Smith   return 0;
54289bc588SBarry Smith }
5520563c6bSBarry Smith static int MatiSDlufactornumeric(Mat matin,Mat *fact)
56289bc588SBarry Smith {
5720563c6bSBarry Smith   return MatLUFactor(*fact,0,0);
58289bc588SBarry Smith }
59289bc588SBarry Smith static int MatiSDchfactorsymbolic(Mat matin,IS row,Mat *fact)
60289bc588SBarry Smith {
61289bc588SBarry Smith   int ierr;
62289bc588SBarry Smith   if (ierr = MatCopy(matin,fact)) SETERR(ierr,0);
63289bc588SBarry Smith   return 0;
64289bc588SBarry Smith }
6520563c6bSBarry Smith static int MatiSDchfactornumeric(Mat matin,Mat *fact)
66289bc588SBarry Smith {
6720563c6bSBarry Smith   return MatCholeskyFactor(*fact,0);
68289bc588SBarry Smith }
69289bc588SBarry Smith static int MatiSDchfactor(Mat matin,IS perm)
70289bc588SBarry Smith {
71289bc588SBarry Smith   MatiSD    *mat = (MatiSD *) matin->data;
72289bc588SBarry Smith   int       ierr, one  = 1, info;
73289bc588SBarry Smith   if (mat->pivots) {FREE(mat->pivots); mat->pivots = 0;}
74289bc588SBarry Smith   LApotrf_("L",&mat->n,mat->v,&mat->m,&info);
75289bc588SBarry Smith   if (info) SETERR(1,"Bad Cholesky factorization");
76289bc588SBarry Smith   matin->factor = FACTOR_CHOLESKY;
77289bc588SBarry Smith   return 0;
78289bc588SBarry Smith }
79289bc588SBarry Smith 
80289bc588SBarry Smith static int MatiSDsolve(Mat matin,Vec xx,Vec yy)
81289bc588SBarry Smith {
82289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
83289bc588SBarry Smith   int i,j, one = 1, info;
84289bc588SBarry Smith   Scalar *v = mat->v, *x, *y;
85289bc588SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
86289bc588SBarry Smith   MEMCPY(y,x,mat->m*sizeof(Scalar));
87289bc588SBarry Smith   /* assume if pivots exist then LU else Cholesky */
88289bc588SBarry Smith   if (mat->pivots) {
89289bc588SBarry Smith     LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,
90289bc588SBarry Smith               y, &mat->m, &info );
91289bc588SBarry Smith   }
92289bc588SBarry Smith   else {
93289bc588SBarry Smith     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
94289bc588SBarry Smith               y, &mat->m, &info );
95289bc588SBarry Smith   }
96289bc588SBarry Smith   if (info) SETERR(1,"Bad solve");
97289bc588SBarry Smith   return 0;
98289bc588SBarry Smith }
99289bc588SBarry Smith static int MatiSDsolvetrans(Mat matin,Vec xx,Vec yy)
100*da3a660dSBarry Smith {
101*da3a660dSBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
102*da3a660dSBarry Smith   int i,j, one = 1, info;
103*da3a660dSBarry Smith   Scalar *v = mat->v, *x, *y;
104*da3a660dSBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
105*da3a660dSBarry Smith   MEMCPY(y,x,mat->m*sizeof(Scalar));
106*da3a660dSBarry Smith   /* assume if pivots exist then LU else Cholesky */
107*da3a660dSBarry Smith   if (mat->pivots) {
108*da3a660dSBarry Smith     LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,
109*da3a660dSBarry Smith               y, &mat->m, &info );
110*da3a660dSBarry Smith   }
111*da3a660dSBarry Smith   else {
112*da3a660dSBarry Smith     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
113*da3a660dSBarry Smith               y, &mat->m, &info );
114*da3a660dSBarry Smith   }
115*da3a660dSBarry Smith   if (info) SETERR(1,"Bad solve");
116*da3a660dSBarry Smith   return 0;
117*da3a660dSBarry Smith }
118*da3a660dSBarry Smith static int MatiSDsolveadd(Mat matin,Vec xx,Vec zz,Vec yy)
119*da3a660dSBarry Smith {
120*da3a660dSBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
121*da3a660dSBarry Smith   int    i,j, one = 1, info,ierr;
122*da3a660dSBarry Smith   Scalar *v = mat->v, *x, *y, sone = 1.0;
123*da3a660dSBarry Smith   Vec    tmp = 0;
124*da3a660dSBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
125*da3a660dSBarry Smith   if (yy == zz) {
126*da3a660dSBarry Smith     ierr = VecCreate(yy,&tmp); CHKERR(ierr);
127*da3a660dSBarry Smith     ierr = VecCopy(yy,tmp); CHKERR(ierr);
128*da3a660dSBarry Smith   }
129*da3a660dSBarry Smith   MEMCPY(y,x,mat->m*sizeof(Scalar));
130*da3a660dSBarry Smith   /* assume if pivots exist then LU else Cholesky */
131*da3a660dSBarry Smith   if (mat->pivots) {
132*da3a660dSBarry Smith     LAgetrs_( "N", &mat->m, &one, mat->v, &mat->m, mat->pivots,
133*da3a660dSBarry Smith               y, &mat->m, &info );
134*da3a660dSBarry Smith   }
135*da3a660dSBarry Smith   else {
136*da3a660dSBarry Smith     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
137*da3a660dSBarry Smith               y, &mat->m, &info );
138*da3a660dSBarry Smith   }
139*da3a660dSBarry Smith   if (info) SETERR(1,"Bad solve");
140*da3a660dSBarry Smith   if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);}
141*da3a660dSBarry Smith   else VecAXPY(&sone,zz,yy);
142*da3a660dSBarry Smith   return 0;
143*da3a660dSBarry Smith }
144*da3a660dSBarry Smith static int MatiSDsolvetransadd(Mat matin,Vec xx,Vec zz, Vec yy)
145*da3a660dSBarry Smith {
146*da3a660dSBarry Smith   MatiSD  *mat = (MatiSD *) matin->data;
147*da3a660dSBarry Smith   int     i,j, one = 1, info,ierr;
148*da3a660dSBarry Smith   Scalar  *v = mat->v, *x, *y, sone = 1.0;
149*da3a660dSBarry Smith   Vec     tmp;
150*da3a660dSBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
151*da3a660dSBarry Smith   if (yy == zz) {
152*da3a660dSBarry Smith     ierr = VecCreate(yy,&tmp); CHKERR(ierr);
153*da3a660dSBarry Smith     ierr = VecCopy(yy,tmp); CHKERR(ierr);
154*da3a660dSBarry Smith   }
155*da3a660dSBarry Smith   MEMCPY(y,x,mat->m*sizeof(Scalar));
156*da3a660dSBarry Smith   /* assume if pivots exist then LU else Cholesky */
157*da3a660dSBarry Smith   if (mat->pivots) {
158*da3a660dSBarry Smith     LAgetrs_( "T", &mat->m, &one, mat->v, &mat->m, mat->pivots,
159*da3a660dSBarry Smith               y, &mat->m, &info );
160*da3a660dSBarry Smith   }
161*da3a660dSBarry Smith   else {
162*da3a660dSBarry Smith     LApotrs_( "L", &mat->m, &one, mat->v, &mat->m,
163*da3a660dSBarry Smith               y, &mat->m, &info );
164*da3a660dSBarry Smith   }
165*da3a660dSBarry Smith   if (info) SETERR(1,"Bad solve");
166*da3a660dSBarry Smith   if (tmp) {VecAXPY(&sone,tmp,yy); VecDestroy(tmp);}
167*da3a660dSBarry Smith   else VecAXPY(&sone,zz,yy);
168*da3a660dSBarry Smith   return 0;
169*da3a660dSBarry Smith }
170289bc588SBarry Smith /* ------------------------------------------------------------------*/
171d6dfbf8fSBarry Smith static int MatiSDrelax(Mat matin,Vec bb,double omega,int flag,double shift,
172289bc588SBarry Smith                        int its,Vec xx)
173289bc588SBarry Smith {
174289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
175289bc588SBarry Smith   Scalar *x, *b, *v = mat->v, zero = 0.0, xt;
176289bc588SBarry Smith   int    o = 1, tmp,n = mat->n,ierr, m = mat->m, i, j;
177289bc588SBarry Smith 
178289bc588SBarry Smith   if (flag & SOR_ZERO_INITIAL_GUESS) {
179289bc588SBarry Smith     /* this is a hack fix, should have another version without
180289bc588SBarry Smith        the second BLdot */
181289bc588SBarry Smith     if (ierr = VecSet(&zero,xx)) SETERR(ierr,0);
182289bc588SBarry Smith   }
183289bc588SBarry Smith   VecGetArray(xx,&x); VecGetArray(bb,&b);
184289bc588SBarry Smith   while (its--) {
185289bc588SBarry Smith     if (flag & SOR_FORWARD_SWEEP){
186289bc588SBarry Smith       for ( i=0; i<m; i++ ) {
187289bc588SBarry Smith         xt = b[i]-BLdot_(&m,v+i,&m,x,&o);
188d6dfbf8fSBarry Smith         x[i] = (1. - omega)*x[i] + omega*(xt/(v[i + i*m]+shift) + x[i]);
189289bc588SBarry Smith       }
190289bc588SBarry Smith     }
191289bc588SBarry Smith     if (flag & SOR_BACKWARD_SWEEP) {
192289bc588SBarry Smith       for ( i=m-1; i>=0; i-- ) {
193289bc588SBarry Smith         xt = b[i]-BLdot_(&m,v+i,&m,x,&o);
194d6dfbf8fSBarry Smith         x[i] = (1. - omega)*x[i] + omega*(xt/(v[i + i*m]+shift) + x[i]);
195289bc588SBarry Smith       }
196289bc588SBarry Smith     }
197289bc588SBarry Smith   }
198289bc588SBarry Smith   return 0;
199289bc588SBarry Smith }
200289bc588SBarry Smith 
201289bc588SBarry Smith /* -----------------------------------------------------------------*/
202289bc588SBarry Smith static int MatiSDmulttrans(Mat matin,Vec xx,Vec yy)
203289bc588SBarry Smith {
204289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
205289bc588SBarry Smith   Scalar *v = mat->v, *x, *y;
206289bc588SBarry Smith   int _One=1;Scalar _DOne=1.0, _DZero=0.0;
207289bc588SBarry Smith   VecGetArray(xx,&x), VecGetArray(yy,&y);
208289bc588SBarry Smith   LAgemv_( "T", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
209289bc588SBarry Smith          x, &_One, &_DZero, y, &_One );
210289bc588SBarry Smith   return 0;
211289bc588SBarry Smith }
212289bc588SBarry Smith static int MatiSDmult(Mat matin,Vec xx,Vec yy)
213289bc588SBarry Smith {
214289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
215289bc588SBarry Smith   Scalar *v = mat->v, *x, *y;
216289bc588SBarry Smith   int _One=1;Scalar _DOne=1.0, _DZero=0.0;
217289bc588SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
218289bc588SBarry Smith   LAgemv_( "N", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
219289bc588SBarry Smith          x, &_One, &_DZero, y, &_One );
220289bc588SBarry Smith   return 0;
221289bc588SBarry Smith }
222289bc588SBarry Smith static int MatiSDmultadd(Mat matin,Vec xx,Vec zz,Vec yy)
223289bc588SBarry Smith {
224289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
225289bc588SBarry Smith   Scalar *v = mat->v, *x, *y, *z;
226289bc588SBarry Smith   int    _One=1; Scalar _DOne=1.0, _DZero=0.0;
227289bc588SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y); VecGetArray(zz,&z);
228289bc588SBarry Smith   if (zz != yy) MEMCPY(y,z,mat->m*sizeof(Scalar));
229289bc588SBarry Smith   LAgemv_( "N", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
230289bc588SBarry Smith          x, &_One, &_DOne, y, &_One );
231289bc588SBarry Smith   return 0;
232289bc588SBarry Smith }
233289bc588SBarry Smith static int MatiSDmulttransadd(Mat matin,Vec xx,Vec zz,Vec yy)
234289bc588SBarry Smith {
235289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
236289bc588SBarry Smith   Scalar *v = mat->v, *x, *y, *z;
237289bc588SBarry Smith   int    _One=1;
238289bc588SBarry Smith   Scalar _DOne=1.0, _DZero=0.0;
239289bc588SBarry Smith   VecGetArray(xx,&x); VecGetArray(yy,&y);
240289bc588SBarry Smith   VecGetArray(zz,&z);
241289bc588SBarry Smith   if (zz != yy) MEMCPY(y,z,mat->m*sizeof(Scalar));
242289bc588SBarry Smith   LAgemv_( "T", &(mat->m), &(mat->n), &_DOne, v, &(mat->m),
243289bc588SBarry Smith          x, &_One, &_DOne, y, &_One );
244289bc588SBarry Smith   return 0;
245289bc588SBarry Smith }
246289bc588SBarry Smith 
247289bc588SBarry Smith /* -----------------------------------------------------------------*/
248289bc588SBarry Smith static int MatiSDgetrow(Mat matin,int row,int *ncols,int **cols,
249289bc588SBarry Smith                         Scalar **vals)
250289bc588SBarry Smith {
251289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
252289bc588SBarry Smith   Scalar *v;
253289bc588SBarry Smith   int    i;
254289bc588SBarry Smith   *ncols = mat->n;
255289bc588SBarry Smith   if (cols) {
256289bc588SBarry Smith     *cols = (int *) MALLOC(mat->n*sizeof(int)); CHKPTR(*cols);
257289bc588SBarry Smith     for ( i=0; i<mat->n; i++ ) *cols[i] = i;
258289bc588SBarry Smith   }
259289bc588SBarry Smith   if (vals) {
260289bc588SBarry Smith     *vals = (Scalar *) MALLOC(mat->n*sizeof(Scalar)); CHKPTR(*vals);
261289bc588SBarry Smith     v = mat->v + row;
262289bc588SBarry Smith     for ( i=0; i<mat->n; i++ ) {*vals[i] = *v; v += mat->m;}
263289bc588SBarry Smith   }
264289bc588SBarry Smith   return 0;
265289bc588SBarry Smith }
266289bc588SBarry Smith static int MatiSDrestorerow(Mat matin,int row,int *ncols,int **cols,
267289bc588SBarry Smith                             Scalar **vals)
268289bc588SBarry Smith {
269289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
270289bc588SBarry Smith   if (cols) { FREE(*cols); }
271289bc588SBarry Smith   if (vals) { FREE(*vals); }
272289bc588SBarry Smith   return 0;
273289bc588SBarry Smith }
274289bc588SBarry Smith /* ----------------------------------------------------------------*/
275e8d4e0b9SBarry Smith static int MatiSDinsert(Mat matin,int m,int *indexm,int n,
276e8d4e0b9SBarry Smith                         int *indexn,Scalar *v,InsertMode addv)
277289bc588SBarry Smith {
278289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
279289bc588SBarry Smith   int    i,j;
280d6dfbf8fSBarry Smith 
281289bc588SBarry Smith   if (!mat->roworiented) {
282e8d4e0b9SBarry Smith     if (addv == InsertValues) {
283289bc588SBarry Smith       for ( j=0; j<n; j++ ) {
284d6dfbf8fSBarry Smith         if (indexn[j] < 0) {*v += m; continue;}
285289bc588SBarry Smith         for ( i=0; i<m; i++ ) {
286d6dfbf8fSBarry Smith           if (indexm[i] < 0) {*v++; continue;}
287289bc588SBarry Smith           mat->v[indexn[j]*mat->m + indexm[i]] = *v++;
288289bc588SBarry Smith         }
289289bc588SBarry Smith       }
290289bc588SBarry Smith     }
291289bc588SBarry Smith     else {
292289bc588SBarry Smith       for ( j=0; j<n; j++ ) {
293d6dfbf8fSBarry Smith         if (indexn[j] < 0) {*v += m; continue;}
294289bc588SBarry Smith         for ( i=0; i<m; i++ ) {
295d6dfbf8fSBarry Smith           if (indexm[i] < 0) {*v++; continue;}
296289bc588SBarry Smith           mat->v[indexn[j]*mat->m + indexm[i]] += *v++;
297289bc588SBarry Smith         }
298289bc588SBarry Smith       }
299289bc588SBarry Smith     }
300e8d4e0b9SBarry Smith   }
301e8d4e0b9SBarry Smith   else {
302e8d4e0b9SBarry Smith     if (addv == InsertValues) {
303e8d4e0b9SBarry Smith       for ( i=0; i<m; i++ ) {
304d6dfbf8fSBarry Smith         if (indexm[i] < 0) {*v += n; continue;}
305e8d4e0b9SBarry Smith         for ( j=0; j<n; j++ ) {
306d6dfbf8fSBarry Smith           if (indexn[j] < 0) {*v++; continue;}
307e8d4e0b9SBarry Smith           mat->v[indexn[j]*mat->m + indexm[i]] = *v++;
308e8d4e0b9SBarry Smith         }
309e8d4e0b9SBarry Smith       }
310e8d4e0b9SBarry Smith     }
311289bc588SBarry Smith     else {
312289bc588SBarry Smith       for ( i=0; i<m; i++ ) {
313d6dfbf8fSBarry Smith         if (indexm[i] < 0) {*v += n; continue;}
314289bc588SBarry Smith         for ( j=0; j<n; j++ ) {
315d6dfbf8fSBarry Smith           if (indexn[j] < 0) {*v++; continue;}
316289bc588SBarry Smith           mat->v[indexn[j]*mat->m + indexm[i]] += *v++;
317289bc588SBarry Smith         }
318289bc588SBarry Smith       }
319289bc588SBarry Smith     }
320e8d4e0b9SBarry Smith   }
321289bc588SBarry Smith   return 0;
322289bc588SBarry Smith }
323e8d4e0b9SBarry Smith 
324289bc588SBarry Smith /* -----------------------------------------------------------------*/
325289bc588SBarry Smith static int MatiSDcopy(Mat matin,Mat *newmat)
326289bc588SBarry Smith {
327289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
328289bc588SBarry Smith   int ierr;
329289bc588SBarry Smith   Mat newi;
330289bc588SBarry Smith   MatiSD *l;
331289bc588SBarry Smith   if (ierr = MatCreateSequentialDense(mat->m,mat->n,&newi)) SETERR(ierr,0);
332289bc588SBarry Smith   l = (MatiSD *) newi->data;
333289bc588SBarry Smith   MEMCPY(l->v,mat->v,mat->m*mat->n*sizeof(Scalar));
334289bc588SBarry Smith   *newmat = newi;
335289bc588SBarry Smith   return 0;
336289bc588SBarry Smith }
337*da3a660dSBarry Smith #include "viewer.h"
338289bc588SBarry Smith 
339289bc588SBarry Smith int MatiSDview(PetscObject obj,Viewer ptr)
340289bc588SBarry Smith {
341289bc588SBarry Smith   Mat         matin = (Mat) obj;
342289bc588SBarry Smith   MatiSD      *mat = (MatiSD *) matin->data;
343289bc588SBarry Smith   Scalar      *v;
344289bc588SBarry Smith   int         i,j;
345*da3a660dSBarry Smith   PetscObject ojb = (PetscObject) ptr;
346*da3a660dSBarry Smith 
347*da3a660dSBarry Smith   if (obj && obj->cookie == VIEWER_COOKIE && obj->type == MATLAB_VIEWER) {
348*da3a660dSBarry Smith     return ViewerMatlabPutArray(ptr,mat->m,mat->n,mat->v);
349*da3a660dSBarry Smith   }
350*da3a660dSBarry Smith   else {
351289bc588SBarry Smith     for ( i=0; i<mat->m; i++ ) {
352289bc588SBarry Smith       v = mat->v + i;
353289bc588SBarry Smith       for ( j=0; j<mat->n; j++ ) {
354289bc588SBarry Smith #if defined(PETSC_COMPLEX)
355289bc588SBarry Smith         printf("%6.4e + %6.4e i ",real(*v),imag(*v)); v += mat->m;
356289bc588SBarry Smith #else
357289bc588SBarry Smith         printf("%6.4e ",*v); v += mat->m;
358289bc588SBarry Smith #endif
359289bc588SBarry Smith       }
360289bc588SBarry Smith       printf("\n");
361289bc588SBarry Smith     }
362*da3a660dSBarry Smith   }
363289bc588SBarry Smith   return 0;
364289bc588SBarry Smith }
365289bc588SBarry Smith 
366289bc588SBarry Smith 
367289bc588SBarry Smith static int MatiSDdestroy(PetscObject obj)
368289bc588SBarry Smith {
369289bc588SBarry Smith   Mat mat = (Mat) obj;
370289bc588SBarry Smith   MatiSD *l = (MatiSD *) mat->data;
371289bc588SBarry Smith   if (l->pivots) FREE(l->pivots);
372289bc588SBarry Smith   FREE(l);
373289bc588SBarry Smith   FREE(mat);
374289bc588SBarry Smith   return 0;
375289bc588SBarry Smith }
376289bc588SBarry Smith 
377289bc588SBarry Smith static int MatiSDtrans(Mat matin)
378289bc588SBarry Smith {
379289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
380289bc588SBarry Smith   int    k,j;
381289bc588SBarry Smith   Scalar *v = mat->v, tmp;
382289bc588SBarry Smith   if (mat->m != mat->n) {
383289bc588SBarry Smith     SETERR(1,"Cannot transpose rectangular dense matrix");
384289bc588SBarry Smith   }
385289bc588SBarry Smith   for ( j=0; j<mat->m; j++ ) {
386289bc588SBarry Smith     for ( k=0; k<j; k++ ) {
387289bc588SBarry Smith       tmp = v[j + k*mat->n];
388289bc588SBarry Smith       v[j + k*mat->n] = v[k + j*mat->n];
389289bc588SBarry Smith       v[k + j*mat->n] = tmp;
390289bc588SBarry Smith     }
391289bc588SBarry Smith   }
392289bc588SBarry Smith   return 0;
393289bc588SBarry Smith }
394289bc588SBarry Smith 
395289bc588SBarry Smith static int MatiSDequal(Mat matin1,Mat matin2)
396289bc588SBarry Smith {
397289bc588SBarry Smith   MatiSD *mat1 = (MatiSD *) matin1->data;
398289bc588SBarry Smith   MatiSD *mat2 = (MatiSD *) matin2->data;
399289bc588SBarry Smith   int    i;
400289bc588SBarry Smith   Scalar *v1 = mat1->v, *v2 = mat2->v;
401289bc588SBarry Smith   if (mat1->m != mat2->m) return 0;
402289bc588SBarry Smith   if (mat1->n != mat2->n) return 0;
403289bc588SBarry Smith   for ( i=0; i<mat1->m*mat1->n; i++ ) {
404289bc588SBarry Smith     if (*v1 != *v2) return 0;
405289bc588SBarry Smith     v1++; v2++;
406289bc588SBarry Smith   }
407289bc588SBarry Smith   return 1;
408289bc588SBarry Smith }
409289bc588SBarry Smith 
410289bc588SBarry Smith static int MatiSDgetdiag(Mat matin,Vec v)
411289bc588SBarry Smith {
412289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
413289bc588SBarry Smith   int    i,j, n;
414289bc588SBarry Smith   Scalar *x, zero = 0.0;
415289bc588SBarry Smith   CHKTYPE(v,SEQVECTOR);
416289bc588SBarry Smith   VecGetArray(v,&x); VecGetSize(v,&n);
417289bc588SBarry Smith   if (n != mat->m) SETERR(1,"Nonconforming matrix and vector");
418289bc588SBarry Smith   for ( i=0; i<mat->m; i++ ) {
419289bc588SBarry Smith     x[i] = mat->v[i*mat->m + i];
420289bc588SBarry Smith   }
421289bc588SBarry Smith   return 0;
422289bc588SBarry Smith }
423289bc588SBarry Smith 
424*da3a660dSBarry Smith static int MatiSDscale(Mat matin,Vec ll,Vec rr)
425289bc588SBarry Smith {
426*da3a660dSBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
427*da3a660dSBarry Smith   Scalar *l,*r,x,*v;
428*da3a660dSBarry Smith   int    i,j,m = mat->m, n = mat->n;
429*da3a660dSBarry Smith   if (l) {
430*da3a660dSBarry Smith     VecGetArray(ll,&l); VecGetSize(ll,&m);
431*da3a660dSBarry Smith     if (m != mat->m) SETERR(1,"Left scaling vector wrong length");
432*da3a660dSBarry Smith     for ( i=0; i<m; i++ ) {
433*da3a660dSBarry Smith       x = l[i];
434*da3a660dSBarry Smith       v = mat->v + i;
435*da3a660dSBarry Smith       for ( j=0; j<n; j++ ) { (*v) *= x; v+= m;}
436*da3a660dSBarry Smith     }
437*da3a660dSBarry Smith   }
438*da3a660dSBarry Smith   if (l) {
439*da3a660dSBarry Smith     VecGetArray(rr,&r); VecGetSize(rr,&n);
440*da3a660dSBarry Smith     if (n != mat->n) SETERR(1,"Right scaling vector wrong length");
441*da3a660dSBarry Smith     for ( i=0; i<n; i++ ) {
442*da3a660dSBarry Smith       x = r[i];
443*da3a660dSBarry Smith       v = mat->v + i*m;
444*da3a660dSBarry Smith       for ( j=0; j<m; j++ ) { (*v++) *= x;}
445*da3a660dSBarry Smith     }
446*da3a660dSBarry Smith   }
447289bc588SBarry Smith   return 0;
448289bc588SBarry Smith }
449289bc588SBarry Smith 
450*da3a660dSBarry Smith 
451289bc588SBarry Smith static int MatiSDnorm(Mat matin,int type,double *norm)
452289bc588SBarry Smith {
453289bc588SBarry Smith   MatiSD *mat = (MatiSD *) matin->data;
454289bc588SBarry Smith   Scalar *v = mat->v;
455289bc588SBarry Smith   double sum = 0.0;
456289bc588SBarry Smith   int    i, j;
457289bc588SBarry Smith   if (type == NORM_FROBENIUS) {
458289bc588SBarry Smith     for (i=0; i<mat->n*mat->m; i++ ) {
459289bc588SBarry Smith #if defined(PETSC_COMPLEX)
460289bc588SBarry Smith       sum += real(conj(*v)*(*v)); v++;
461289bc588SBarry Smith #else
462289bc588SBarry Smith       sum += (*v)*(*v); v++;
463289bc588SBarry Smith #endif
464289bc588SBarry Smith     }
465289bc588SBarry Smith     *norm = sqrt(sum);
466289bc588SBarry Smith   }
467289bc588SBarry Smith   else if (type == NORM_1) {
468289bc588SBarry Smith     *norm = 0.0;
469289bc588SBarry Smith     for ( j=0; j<mat->n; j++ ) {
470289bc588SBarry Smith       sum = 0.0;
471289bc588SBarry Smith       for ( i=0; i<mat->m; i++ ) {
472289bc588SBarry Smith #if defined(PETSC_COMPLEX)
473289bc588SBarry Smith         sum += abs(*v++);
474289bc588SBarry Smith #else
475289bc588SBarry Smith         sum += fabs(*v++);
476289bc588SBarry Smith #endif
477289bc588SBarry Smith       }
478289bc588SBarry Smith       if (sum > *norm) *norm = sum;
479289bc588SBarry Smith     }
480289bc588SBarry Smith   }
481289bc588SBarry Smith   else if (type == NORM_INFINITY) {
482289bc588SBarry Smith     *norm = 0.0;
483289bc588SBarry Smith     for ( j=0; j<mat->m; j++ ) {
484289bc588SBarry Smith       v = mat->v + j;
485289bc588SBarry Smith       sum = 0.0;
486289bc588SBarry Smith       for ( i=0; i<mat->n; i++ ) {
487289bc588SBarry Smith #if defined(PETSC_COMPLEX)
488289bc588SBarry Smith         sum += abs(*v); v += mat->m;
489289bc588SBarry Smith #else
490289bc588SBarry Smith         sum += fabs(*v); v += mat->m;
491289bc588SBarry Smith #endif
492289bc588SBarry Smith       }
493289bc588SBarry Smith       if (sum > *norm) *norm = sum;
494289bc588SBarry Smith     }
495289bc588SBarry Smith   }
496289bc588SBarry Smith   else {
497289bc588SBarry Smith     SETERR(1,"No support for the two norm yet");
498289bc588SBarry Smith   }
499289bc588SBarry Smith   return 0;
500289bc588SBarry Smith }
501289bc588SBarry Smith 
502289bc588SBarry Smith static int MatiDenseinsopt(Mat aijin,int op)
503289bc588SBarry Smith {
504289bc588SBarry Smith   MatiSD *aij = (MatiSD *) aijin->data;
505289bc588SBarry Smith   if (op == ROW_ORIENTED)            aij->roworiented = 1;
506289bc588SBarry Smith   else if (op == COLUMN_ORIENTED)    aij->roworiented = 0;
507289bc588SBarry Smith   /* doesn't care about sorted rows or columns */
508289bc588SBarry Smith   return 0;
509289bc588SBarry Smith }
510289bc588SBarry Smith 
5116f0a148fSBarry Smith static int MatiZero(Mat A)
5126f0a148fSBarry Smith {
5136f0a148fSBarry Smith   MatiSD *l = (MatiSD *) A->data;
5146f0a148fSBarry Smith   MEMSET(l->v,0,l->m*l->n*sizeof(Scalar));
5156f0a148fSBarry Smith   return 0;
5166f0a148fSBarry Smith }
5176f0a148fSBarry Smith 
518260925b8SBarry Smith static int MatiZerorows(Mat A,IS is,Scalar *diag)
5196f0a148fSBarry Smith {
5206f0a148fSBarry Smith   MatiSD *l = (MatiSD *) A->data;
521260925b8SBarry Smith   int     m = l->m, n = l->n, i, j,ierr,N, *rows;
5226f0a148fSBarry Smith   Scalar  *slot;
523260925b8SBarry Smith   ierr = ISGetLocalSize(is,&N); CHKERR(ierr);
524260925b8SBarry Smith   ierr = ISGetIndices(is,&rows); CHKERR(ierr);
5256f0a148fSBarry Smith   for ( i=0; i<N; i++ ) {
5266f0a148fSBarry Smith     slot = l->v + rows[i];
5276f0a148fSBarry Smith     for ( j=0; j<n; j++ ) { *slot = 0.0; slot += n;}
5286f0a148fSBarry Smith   }
5296f0a148fSBarry Smith   if (diag) {
5306f0a148fSBarry Smith     for ( i=0; i<N; i++ ) {
5316f0a148fSBarry Smith       slot = l->v + (n+1)*rows[i];
532260925b8SBarry Smith       *slot = *diag;
5336f0a148fSBarry Smith     }
5346f0a148fSBarry Smith   }
535260925b8SBarry Smith   ISRestoreIndices(is,&rows);
5366f0a148fSBarry Smith   return 0;
5376f0a148fSBarry Smith }
538289bc588SBarry Smith /* -------------------------------------------------------------------*/
539e8d4e0b9SBarry Smith static struct _MatOps MatOps = {MatiSDinsert,
540289bc588SBarry Smith        MatiSDgetrow, MatiSDrestorerow,
541289bc588SBarry Smith        MatiSDmult, MatiSDmultadd, MatiSDmulttrans, MatiSDmulttransadd,
542*da3a660dSBarry Smith        MatiSDsolve,MatiSDsolveadd,MatiSDsolvetrans,MatiSDsolvetransadd,
543289bc588SBarry Smith        MatiSDlufactor,MatiSDchfactor,
544289bc588SBarry Smith        MatiSDrelax,
545289bc588SBarry Smith        MatiSDtrans,
546289bc588SBarry Smith        MatiSDnz,MatiSDmemory,MatiSDequal,
547289bc588SBarry Smith        MatiSDcopy,
548289bc588SBarry Smith        MatiSDgetdiag,MatiSDscale,MatiSDnorm,
549289bc588SBarry Smith        0,0,
5506f0a148fSBarry Smith        0, MatiDenseinsopt,MatiZero,MatiZerorows,0,
551289bc588SBarry Smith        MatiSDlufactorsymbolic,MatiSDlufactornumeric,
552289bc588SBarry Smith        MatiSDchfactorsymbolic,MatiSDchfactornumeric
553289bc588SBarry Smith };
55420563c6bSBarry Smith /*@
55520563c6bSBarry Smith     MatCreateSequentialDense - Creates a sequential dense matrix that
55620563c6bSBarry Smith         is stored in the usual Fortran 77 manner. Many of the matrix
55720563c6bSBarry Smith         operations use the BLAS and LAPACK routines.
558289bc588SBarry Smith 
55920563c6bSBarry Smith   Input Parameters:
56020563c6bSBarry Smith .   m, n - the number of rows and columns in the matrix.
56120563c6bSBarry Smith 
56220563c6bSBarry Smith   Output Parameter:
56320563c6bSBarry Smith .  newmat - the matrix created.
56420563c6bSBarry Smith 
56520563c6bSBarry Smith   Keywords: dense matrix, lapack, blas
56620563c6bSBarry Smith @*/
567289bc588SBarry Smith int MatCreateSequentialDense(int m,int n,Mat *newmat)
568289bc588SBarry Smith {
569289bc588SBarry Smith   int       size = sizeof(MatiSD) + m*n*sizeof(Scalar);
570289bc588SBarry Smith   Mat mat;
571289bc588SBarry Smith   MatiSD    *l;
572289bc588SBarry Smith   *newmat        = 0;
573289bc588SBarry Smith   CREATEHEADER(mat,_Mat);
574289bc588SBarry Smith   l              = (MatiSD *) MALLOC(size); CHKPTR(l);
575289bc588SBarry Smith   mat->cookie    = MAT_COOKIE;
576289bc588SBarry Smith   mat->ops       = &MatOps;
577289bc588SBarry Smith   mat->destroy   = MatiSDdestroy;
578289bc588SBarry Smith   mat->view      = MatiSDview;
579289bc588SBarry Smith   mat->data      = (void *) l;
580289bc588SBarry Smith   mat->type      = MATDENSESEQ;
581289bc588SBarry Smith   mat->factor    = 0;
582289bc588SBarry Smith   mat->col       = 0;
583289bc588SBarry Smith   mat->row       = 0;
584d6dfbf8fSBarry Smith 
585289bc588SBarry Smith   l->m           = m;
586289bc588SBarry Smith   l->n           = n;
587289bc588SBarry Smith   l->v           = (Scalar *) (l + 1);
588289bc588SBarry Smith   l->pivots      = 0;
589289bc588SBarry Smith   l->roworiented = 1;
590d6dfbf8fSBarry Smith 
591289bc588SBarry Smith   MEMSET(l->v,0,m*n*sizeof(Scalar));
592289bc588SBarry Smith   *newmat = mat;
593289bc588SBarry Smith   return 0;
594289bc588SBarry Smith }
595289bc588SBarry Smith 
596289bc588SBarry Smith int MatiSDCreate(Mat matin,Mat *newmat)
597289bc588SBarry Smith {
598289bc588SBarry Smith   MatiSD *m = (MatiSD *) matin->data;
599289bc588SBarry Smith   return MatCreateSequentialDense(m->m,m->n,newmat);
600289bc588SBarry Smith }
601