EVSL  1.1.0
EigenValues Slicing Library
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
evsl_suitesparse.c
Go to the documentation of this file.
1 
2 #include <string.h>
3 #include "def.h"
4 #include "struct.h"
5 #include "internal_proto.h"
6 #include "cholmod.h"
7 #include "umfpack.h"
8 #include "evsl_direct.h"
9 
10 #ifdef CHOLMOD_USE_LONG
11 #define CHOLMOD(name) cholmod_l_ ## name
12 #else
13 #define CHOLMOD(name) cholmod_ ## name
14 #endif
15 
16 typedef struct _BSolDataDirect {
17  cholmod_factor *LB;
18  cholmod_common cm;
20 
34 cholmod_sparse* csrMat_to_cholmod_sparse(csrMat *A, int stype) {
35  cholmod_sparse *B = NULL;
36  Malloc(B, 1, cholmod_sparse);
37  B->nrow = A->nrows;
38  B->ncol = A->ncols;
39  B->nzmax = A->ia[A->nrows];
40 #ifdef CHOLMOD_USE_LONG
41  /* long int version, allocate memory and copy ia, ja */
42  Malloc(B->p, B->nrow+1, SuiteSparse_long);
43  Malloc(B->i, B->nzmax, SuiteSparse_long);
44  int i;
45  for (i=0; i<B->nrow+1; i++) {
46  SuiteSparse_long *ptr = (SuiteSparse_long *) B->p;
47  ptr[i] = A->ia[i];
48  }
49  for (i=0; i<B->nzmax; i++) {
50  SuiteSparse_long *ptr = (SuiteSparse_long *) B->i;
51  ptr[i] = A->ja[i];
52  }
53 #else
54  /* column pointers */
55  B->p = A->ia;
56  /* row indices */
57  B->i = A->ja;
58 #endif
59  B->nz = NULL;
60  B->x = A->a;
61  B->z = NULL;
62  B->stype = stype;
63 #ifdef CHOLMOD_USE_LONG
64  B->itype = CHOLMOD_LONG;
65 #else
66  B->itype = CHOLMOD_INT;
67 #endif
68  B->xtype = CHOLMOD_REAL;
69  B->dtype = CHOLMOD_DOUBLE;
70  B->sorted = 0;
71  B->packed = 1;
72 
73  return B;
74 }
75 
79 void arr_to_cholmod_dense(int m, int n, double *A, cholmod_dense *B) {
80  B->nrow = m;
81  B->ncol = n;
82  B->nzmax = m*n;
83  B->d = m;
84  B->x = A;
85  B->z = NULL;
86  B->xtype = CHOLMOD_REAL;
87  B->dtype = CHOLMOD_DOUBLE;
88 }
89 
90 #if 0
91 
94 cholmod_dense* arr_to_cholmod_dense_alloc(int m, int n, double *A) {
95  cholmod_dense *B = NULL;
96  Malloc(B, 1, cholmod_dense);
97  B->nrow = m;
98  B->ncol = n;
99  B->nzmax = m*n;
100  B->d = m;
101  B->x = A;
102  B->z = NULL;
103  B->xtype = CHOLMOD_REAL;
104  B->dtype = CHOLMOD_DOUBLE;
105 
106  return B;
107 }
108 #endif
109 
110 
112 cholmod_dense cholmod_X, cholmod_B, *cholmod_Y=NULL, *cholmod_E=NULL,
113  *cholmod_W=NULL;
114 
118 void BSolDirect(double *b, double *x, void *data) {
119  //int n;
120 
121  BSolDataDirect *Bsol_data = (BSolDataDirect *) data;
122  cholmod_factor *LB;
123  cholmod_common *cc;
124 
125  LB = Bsol_data->LB;
126  cc = &Bsol_data->cm;
127  //n = LB->n;
128 
129  /* give the wrapper data */
130  cholmod_X.x = x;
131  cholmod_B.x = b;
132 
133  /* XXX is this always safe for cholmod_x ? */
134  cholmod_dense *cholmod_Xp = &cholmod_X;
135  CHOLMOD(solve2)(CHOLMOD_A, LB, &cholmod_B, NULL,
136  &cholmod_Xp, NULL, &cholmod_Y, &cholmod_E, cc);
137 }
138 
144 int SetupBSolDirect(csrMat *B, void **data) {
145  double tms = evsl_timer();
146  BSolDataDirect *Bsol_data;
147  Malloc(Bsol_data, 1, BSolDataDirect);
148  cholmod_sparse *Bcholmod;
149  cholmod_common *cc = &Bsol_data->cm;
150  cholmod_factor *LB;
151 
152  /* start CHOLMOD */
153  CHOLMOD(start)(cc);
154  /* force to have LL factor */
155  cc->final_asis = 0;
156  cc->final_ll = 1;
157  /* convert matrix.
158  * stype=1 means the upper triangular part of B will be accessed */
159  Bcholmod = csrMat_to_cholmod_sparse(B, 1);
160  /* check common and the matrix */
161  CHOLMOD(check_common)(cc);
162  CHOLMOD(check_sparse)(Bcholmod, cc);
163  /* symbolic and numeric fact */
164  //printf("start analysis\n");
165  LB = CHOLMOD(analyze)(Bcholmod, cc);
166  CHOLMOD(check_common)(cc);
167  //printf("cc status %d\n", cc->status);
168  //printf("start factorization\n");
169  CHOLMOD(factorize)(Bcholmod, LB, cc);
170  //printf("done factorization\n");
171  /* check the factor */
172  CHOLMOD(check_factor)(LB, cc);
173  /* save the struct to global variable */
174  Bsol_data->LB = LB;
175  /* check the factor */
176  CHKERR(LB->is_ll == 0);
177  /* free the matrix data and wrapper */
178 #ifdef CHOLMOD_USE_LONG
179  free(Bcholmod->p);
180  free(Bcholmod->i);
181 #endif
182  /* free the wrapper itself */
183  free(Bcholmod);
184  /* space for solve */
185  int n = B->nrows;
186  /* setup the wrapper, no data given yet */
187  arr_to_cholmod_dense(n, 1, NULL, &cholmod_X);
188  arr_to_cholmod_dense(n, 1, NULL, &cholmod_B);
189 
190  *data = (void *) Bsol_data;
191 
192  double tme = evsl_timer();
193  evslstat.t_setBsv += tme - tms;
194 
195  return 0;
196 }
197 
198 void FreeBSolDirectData(void *vdata) {
199  BSolDataDirect *data = (BSolDataDirect *) vdata;
200  cholmod_common *cc = &data->cm;
201  /* free the factor */
202  CHOLMOD(free_factor)(&data->LB, cc);
203  /* free workspace for solve2 */
204  CHOLMOD(free_dense)(&cholmod_Y, cc);
205  CHOLMOD(free_dense)(&cholmod_E, cc);
206  CHOLMOD(free_dense)(&cholmod_W, cc);
207  /* finish cholmod */
208  CHOLMOD(finish)(cc);
209  free(vdata);
210 }
211 
215 void LTSolDirect(double *b, double *x, void *data) {
216  //int n;
217 
218  BSolDataDirect *Bsol_data = (BSolDataDirect *) data;
219  cholmod_factor *LB;
220  cholmod_common *cc;
221 
222  LB = Bsol_data->LB;
223  cc = &Bsol_data->cm;
224  //n = LB->n;
225 
226  /* XXX are these always safe ? */
227  cholmod_B.x = b;
228  CHOLMOD(solve2)(CHOLMOD_Lt, LB, &cholmod_B, NULL,
229  &cholmod_W, NULL, &cholmod_Y, &cholmod_E, cc);
230 
231  cholmod_X.x = x;
232  cholmod_dense *cholmod_Xp = &cholmod_X;
233  CHOLMOD(solve2)(CHOLMOD_Pt, LB, cholmod_W, NULL,
234  &cholmod_Xp, NULL, &cholmod_Y, &cholmod_E, cc);
235 }
236 
249 void ASIGMABSolDirect(int n, double *br, double *bi, double *xr,
250  double *xz, void *data) {
251  void* Numeric = data;
252  double Control[UMFPACK_CONTROL];
253  umfpack_zl_defaults(Control);
254  Control[UMFPACK_IRSTEP] = 0; // no iterative refinement for umfpack
255  umfpack_zl_solve(UMFPACK_A, NULL, NULL, NULL, NULL, xr, xz, br, bi,
256  Numeric, Control, NULL);
257 }
258 
272 int SetupASIGMABSolDirect(csrMat *A, csrMat *BB, int num,
273  complex double *zk, void **data) {
274  int i, j, nrow, ncol, nnzB, nnzC, *map, status;
275  csrMat *B, C, eye;
276  double tms = evsl_timer();
277  /* UMFPACK matrix for the shifted matrix
278  * C = A - s * B */
279  SuiteSparse_long *Cp, *Ci;
280  double *Cx, *Cz, zkr1;
281  void *Symbolic=NULL, *Numeric=NULL;
282 
283  nrow = A->nrows;
284  ncol = A->ncols;
285 
286  if (BB) {
287  B = BB;
288  } else {
289  /* if B==NULL, B=I, standard e.v. prob */
290  speye(nrow, &eye);
291  B = &eye;
292  }
293 
294  nnzB = B->ia[nrow];
295  /* map from nnz in B to nnz in C, useful for multi-poles */
296  Malloc(map, nnzB, int);
297  /* NOTE: SuiteSparse requires that the matrix entries be sorted.
298  * The matadd routine will guarantee this
299  * C = A + 0.0 * B
300  * This actually computes the pattern of A + B
301  * and also can guarantee C has sorted rows
302  * map is the mapping from nnzB to nnzC */
303  matadd(1.0, 0.0, A, B, &C, NULL, map);
304  nnzC = C.ia[nrow];
305  /* malloc and copy to SuiteSparse matrix */
306  Malloc(Cp, nrow+1, SuiteSparse_long);
307  Malloc(Ci, nnzC, SuiteSparse_long);
308  Calloc(Cz, nnzC, double);
309  for (i=0; i<nrow+1; i++) {
310  Cp[i] = C.ia[i];
311  }
312  for (i=0; i<nnzC; i++) {
313  Ci[i] = C.ja[i];
314  }
315  Cx = C.a;
316  /* pole loop
317  * for each pole we shift with B and factorize */
318  zkr1 = 0.0;
319  for (i=0; i<num; i++) {
320  /* the complex shift for pole i */
321  double zkr = creal(zk[i]);
322  double zkc = cimag(zk[i]);
323 
324  // shift B
325  for (j=0; j<nnzB; j++) {
326  int p = map[j];
327  double v = B->a[j];
328  CHKERR(Ci[p] != B->ja[j]);
329  Cx[p] -= (zkr - zkr1) * v;
330  Cz[p] = -zkc * v;
331  }
332  /* only do symbolic factorization once */
333  if (i==0) {
334  /* Symbolic Factorization */
335  status = umfpack_zl_symbolic(nrow, ncol, Cp, Ci, Cx, Cz, &Symbolic,
336  NULL, NULL);
337  if (status < 0) {
338  printf("umfpack_zl_symbolic failed, %d\n", status);
339  return 1;
340  }
341  }
342  /* Numerical Factorization */
343  double Control[UMFPACK_CONTROL], Info[UMFPACK_INFO];
344  Control[UMFPACK_PRL] = 0;
345  status = umfpack_zl_numeric(Cp, Ci, Cx, Cz, Symbolic, &Numeric, Control, Info);
346  umfpack_zl_report_info(Control, Info);
347  if (status < 0) {
348  printf("umfpack_zl_numeric failed and exit, %d\n", status);
349  return 1;
350  }
351  /* save the data */
352  data[i] = Numeric;
353  /* for the next shift */
354  zkr1 = zkr;
355  } /* for (i=...)*/
356 
357  /* free the symbolic fact */
358  if (Symbolic) {
359  umfpack_zl_free_symbolic(&Symbolic);
360  }
361 
362  free(map);
363  free(Cp);
364  free(Ci);
365  free(Cz);
366  free_csr(&C);
367  if (!BB) {
368  free_csr(&eye);
369  }
370 
371  double tme = evsl_timer();
372  evslstat.t_setASigBsv += tme - tms;
373 
374  return 0;
375 }
376 
380 void FreeASIGMABSolDirect(int num, void **data) {
381  int i;
382  for (i=0; i<num; i++) {
383  umfpack_zl_free_numeric(&data[i]);
384  }
385 }
386 
void arr_to_cholmod_dense(int m, int n, double *A, cholmod_dense *B)
wrap an array in cholmod dense (no copying)
void BSolDirect(double *b, double *x, void *data)
Solver function of B.
cholmod_dense * cholmod_W
defs in EVSL
int ncols
Definition: struct.h:32
#define CHKERR(ierr)
Definition: def.h:19
cholmod_dense cholmod_X
void FreeASIGMABSolDirect(int num, void **data)
free the data needed by UMFpack
struct _BSolDataDirect BSolDataDirect
cholmod_sparse * csrMat_to_cholmod_sparse(csrMat *A, int stype)
Create cholmod_sparse matrix just as a wrapper of a csrMat This will be useful for the B matrix...
#define Calloc(base, nmem, type)
Definition: def.h:32
void free_csr(csrMat *csr)
memory deallocation for csr matrix
Definition: spmat.c:91
This file contains function prototypes and constant definitions internally used in EVSL...
cholmod_common cm
int SetupBSolDirect(csrMat *B, void **data)
Setup the B-sol by computing the Cholesky factorization of B.
#define SuiteSparse_long
#define CHOLMOD(name)
int speye(int n, csrMat *A)
return an identity matrix of dimension n
Definition: spmat.c:357
#define Malloc(base, nmem, type)
Definition: def.h:22
void LTSolDirect(double *b, double *x, void *data)
Solver function of L^{T} x = L^{-T}*b.
evslStat evslstat
global statistics of EVSL
Definition: evsl.c:21
cholmod_dense * cholmod_E
structs used in evsl
sparse matrix format: the compressed sparse row (CSR) format, 0-based
Definition: struct.h:31
double * a
Definition: struct.h:37
int SetupASIGMABSolDirect(csrMat *A, csrMat *BB, int num, complex double *zk, void **data)
setup the default solver for A - SIGMA B
int * ia
Definition: struct.h:32
double t_setBsv
Definition: struct.h:198
int matadd(double alp, double bet, csrMat *A, csrMat *B, csrMat *C, int *mapA, int *mapB)
matrix addition C = alp * A + bet * B
Definition: spmat.c:307
cholmod_dense * cholmod_Y
int * ja
Definition: struct.h:32
cholmod_dense cholmod_B
double t_setASigBsv
Definition: struct.h:199
Definitions used for direct solver interface.
int nrows
Definition: struct.h:32
cholmod_factor * LB
void ASIGMABSolDirect(int n, double *br, double *bi, double *xr, double *xz, void *data)
default complex linear solver routine passed to evsl
double evsl_timer()
evsl timer for mac
Definition: mactime.c:14
void FreeBSolDirectData(void *vdata)
Free solver data.